From 8014f25f6db719fa62336f997963532a14c568f6 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sat, 21 Jan 2012 04:30:10 -0800 Subject: Major restructuring of the code. --- Makefile | 50 +- abcexe.dsp | 4 +- abclib.dsp | 1320 ++-- arch_flags.c | 17 + src/aig/aig/aig.h | 36 +- src/aig/aig/aigCanon.c | 12 +- src/aig/aig/aigCuts.c | 4 +- src/aig/aig/aigDfs.c | 4 +- src/aig/aig/aigDoms.c | 2 +- src/aig/aig/aigDup.c | 68 +- src/aig/aig/aigFact.c | 4 +- src/aig/aig/aigFanout.c | 2 +- src/aig/aig/aigFrames.c | 4 +- src/aig/aig/aigInter.c | 4 +- src/aig/aig/aigJust.c | 6 +- src/aig/aig/aigMan.c | 12 +- src/aig/aig/aigMffc.c | 2 +- src/aig/aig/aigObj.c | 8 +- src/aig/aig/aigPack.c | 28 +- src/aig/aig/aigPart.c | 14 +- src/aig/aig/aigPartSat.c | 4 +- src/aig/aig/aigRepar.c | 8 +- src/aig/aig/aigRepr.c | 4 +- src/aig/aig/aigRet.c | 18 +- src/aig/aig/aigScl.c | 4 +- src/aig/aig/aigSplit.c | 7 +- src/aig/aig/aigTable.c | 2 +- src/aig/aig/aigTiming.c | 2 +- src/aig/aig/aigTruth.c | 2 +- src/aig/aig/aigTsim.c | 18 +- src/aig/aig/aigUtil.c | 78 +- src/aig/bar/bar.c | 187 - src/aig/bar/bar.h | 78 - src/aig/bar/module.make | 1 - src/aig/bbl/bblif.c | 1518 ----- src/aig/bbl/bblif.h | 285 - src/aig/bbl/module.make | 1 - src/aig/bbr/bbr.h | 93 - src/aig/bbr/bbrCex.c | 172 - src/aig/bbr/bbrImage.c | 1327 ---- src/aig/bbr/bbrNtbdd.c | 218 - src/aig/bbr/bbrReach.c | 606 -- src/aig/bbr/bbr_.c | 52 - src/aig/bbr/module.make | 4 - src/aig/bdc/bdc.h | 92 - src/aig/bdc/bdcCore.c | 314 - src/aig/bdc/bdcDec.c | 751 --- src/aig/bdc/bdcInt.h | 165 - src/aig/bdc/bdcSpfd.c | 1176 ---- src/aig/bdc/bdcTable.c | 134 - src/aig/bdc/bdc_.c | 54 - src/aig/bdc/module.make | 5 - src/aig/cec/cec.c | 53 - src/aig/cec/cec.h | 233 - src/aig/cec/cecCec.c | 373 -- src/aig/cec/cecChoice.c | 409 -- src/aig/cec/cecClass.c | 931 --- src/aig/cec/cecCore.c | 542 -- src/aig/cec/cecCorr.c | 1137 ---- src/aig/cec/cecCorr_updated.c | 1027 ---- src/aig/cec/cecInt.h | 225 - src/aig/cec/cecIso.c | 375 -- src/aig/cec/cecMan.c | 297 - src/aig/cec/cecPat.c | 569 -- src/aig/cec/cecSeq.c | 448 -- src/aig/cec/cecSim.c | 53 - src/aig/cec/cecSolve.c | 1023 ---- src/aig/cec/cecSweep.c | 299 - src/aig/cec/cecSynth.c | 380 -- src/aig/cec/module.make | 13 - src/aig/cgt/cgt.h | 86 - src/aig/cgt/cgtAig.c | 601 -- src/aig/cgt/cgtCore.c | 321 - src/aig/cgt/cgtDecide.c | 301 - src/aig/cgt/cgtInt.h | 122 - src/aig/cgt/cgtMan.c | 179 - src/aig/cgt/cgtSat.c | 97 - src/aig/cgt/module.make | 5 - src/aig/cnf/cnf.h | 195 - src/aig/cnf/cnfCore.c | 296 - src/aig/cnf/cnfCut.c | 376 -- src/aig/cnf/cnfData.c | 4789 --------------- src/aig/cnf/cnfFast.c | 697 --- src/aig/cnf/cnfMan.c | 693 --- src/aig/cnf/cnfMap.c | 362 -- src/aig/cnf/cnfPost.c | 238 - src/aig/cnf/cnfUtil.c | 238 - src/aig/cnf/cnfWrite.c | 806 --- src/aig/cnf/cnf_.c | 53 - src/aig/cnf/module.make | 9 - src/aig/csw/csw.h | 69 - src/aig/csw/cswCore.c | 99 - src/aig/csw/cswCut.c | 607 -- src/aig/csw/cswInt.h | 161 - src/aig/csw/cswMan.c | 130 - src/aig/csw/cswTable.c | 166 - src/aig/csw/csw_.c | 53 - src/aig/csw/module.make | 4 - src/aig/dar/dar.h | 116 - src/aig/dar/darBalance.c | 645 -- src/aig/dar/darCore.c | 344 -- src/aig/dar/darCut.c | 752 --- src/aig/dar/darData.c | 11294 ----------------------------------- src/aig/dar/darInt.h | 171 - src/aig/dar/darLib.c | 1339 ----- src/aig/dar/darMan.c | 174 - src/aig/dar/darPrec.c | 394 -- src/aig/dar/darRefact.c | 636 -- src/aig/dar/darResub.c | 53 - src/aig/dar/darScript.c | 927 --- src/aig/dar/dar_.c | 53 - src/aig/dar/module.make | 10 - src/aig/dch/dch.h | 90 - src/aig/dch/dchAig.c | 119 - src/aig/dch/dchChoice.c | 508 -- src/aig/dch/dchClass.c | 611 -- src/aig/dch/dchCnf.c | 334 -- src/aig/dch/dchCore.c | 158 - src/aig/dch/dchInt.h | 170 - src/aig/dch/dchMan.c | 191 - src/aig/dch/dchSat.c | 166 - src/aig/dch/dchSim.c | 297 - src/aig/dch/dchSimSat.c | 258 - src/aig/dch/dchSweep.c | 146 - src/aig/dch/module.make | 10 - src/aig/deco/deco.h | 714 --- src/aig/deco/module.make | 1 - src/aig/fra/fra.h | 389 -- src/aig/fra/fraBmc.c | 451 -- src/aig/fra/fraCec.c | 516 -- src/aig/fra/fraClass.c | 862 --- src/aig/fra/fraClau.c | 763 --- src/aig/fra/fraClaus.c | 1875 ------ src/aig/fra/fraCnf.c | 289 - src/aig/fra/fraCore.c | 490 -- src/aig/fra/fraHot.c | 476 -- src/aig/fra/fraImp.c | 731 --- src/aig/fra/fraInd.c | 709 --- src/aig/fra/fraIndVer.c | 166 - src/aig/fra/fraLcr.c | 709 --- src/aig/fra/fraMan.c | 314 - src/aig/fra/fraPart.c | 268 - src/aig/fra/fraSat.c | 566 -- src/aig/fra/fraSec.c | 696 --- src/aig/fra/fraSim.c | 1023 ---- src/aig/fra/fra_.c | 53 - src/aig/fra/module.make | 17 - src/aig/fsim/fsim.h | 101 - src/aig/fsim/fsimCore.c | 88 - src/aig/fsim/fsimFront.c | 369 -- src/aig/fsim/fsimInt.h | 138 - src/aig/fsim/fsimMan.c | 212 - src/aig/fsim/fsimSim.c | 567 -- src/aig/fsim/fsimSwitch.c | 40 - src/aig/fsim/fsimTsim.c | 415 -- src/aig/fsim/module.make | 6 - src/aig/gia/gia.h | 91 +- src/aig/gia/giaAbs.c | 4 +- src/aig/gia/giaAbs.h | 4 +- src/aig/gia/giaAbsVta.c | 25 +- src/aig/gia/giaAig.c | 42 +- src/aig/gia/giaAig.h | 6 +- src/aig/gia/giaAiger.c | 54 +- src/aig/gia/giaBidec.c | 8 +- src/aig/gia/giaCCof.c | 16 +- src/aig/gia/giaCSat.c | 12 +- src/aig/gia/giaCSatOld.c | 10 +- src/aig/gia/giaCTas.c | 68 +- src/aig/gia/giaCof.c | 30 +- src/aig/gia/giaDup.c | 106 +- src/aig/gia/giaEmbed.c | 32 +- src/aig/gia/giaEnable.c | 16 +- src/aig/gia/giaEquiv.c | 64 +- src/aig/gia/giaEra.c | 18 +- src/aig/gia/giaEra2.c | 42 +- src/aig/gia/giaFanout.c | 2 +- src/aig/gia/giaForce.c | 8 +- src/aig/gia/giaFrames.c | 24 +- src/aig/gia/giaFront.c | 6 +- src/aig/gia/giaGiarf.c | 38 +- src/aig/gia/giaGlitch.c | 8 +- src/aig/gia/giaHash.c | 46 +- src/aig/gia/giaHcd.c | 22 +- src/aig/gia/giaIf.c | 14 +- src/aig/gia/giaMan.c | 15 +- src/aig/gia/giaPat.c | 4 +- src/aig/gia/giaReparam.c | 6 +- src/aig/gia/giaRetime.c | 6 +- src/aig/gia/giaSat.c | 2 +- src/aig/gia/giaScl.c | 2 +- src/aig/gia/giaShrink.c | 8 +- src/aig/gia/giaSim.c | 12 +- src/aig/gia/giaSim2.c | 6 +- src/aig/gia/giaSpeedup.c | 6 +- src/aig/gia/giaSupMin.c | 2 +- src/aig/gia/giaSwitch.c | 8 +- src/aig/gia/giaTsim.c | 22 +- src/aig/gia/giaUtil.c | 46 +- src/aig/hop/cudd2.c | 2 +- src/aig/hop/cudd2.h | 4 +- src/aig/hop/hop.h | 8 +- src/aig/hop/hopDfs.c | 4 +- src/aig/hop/hopTable.c | 38 +- src/aig/int/int.h | 94 - src/aig/int/intCheck.c | 305 - src/aig/int/intContain.c | 341 -- src/aig/int/intCore.c | 389 -- src/aig/int/intCtrex.c | 167 - src/aig/int/intDup.c | 184 - src/aig/int/intFrames.c | 115 - src/aig/int/intInt.h | 142 - src/aig/int/intInter.c | 145 - src/aig/int/intM114.c | 320 - src/aig/int/intM114p.c | 442 -- src/aig/int/intMan.c | 163 - src/aig/int/intUtil.c | 108 - src/aig/int/module.make | 11 - src/aig/ioa/ioa.h | 8 +- src/aig/ioa/ioaReadAig.c | 4 +- src/aig/ioa/ioaUtil.c | 2 +- src/aig/ivy/attr.h | 6 +- src/aig/ivy/ivy.h | 8 +- src/aig/ivy/ivyFraig.c | 10 +- src/aig/ivy/ivyRwr.c | 4 +- src/aig/ivy/ivySeq.c | 4 +- src/aig/ivy/ivyTable.c | 37 +- src/aig/kit/cloud.c | 992 --- src/aig/kit/cloud.h | 255 - src/aig/kit/kit.h | 655 -- src/aig/kit/kitAig.c | 126 - src/aig/kit/kitBdd.c | 236 - src/aig/kit/kitCloud.c | 378 -- src/aig/kit/kitDec.c | 343 -- src/aig/kit/kitDsd.c | 3200 ---------- src/aig/kit/kitFactor.c | 344 -- src/aig/kit/kitGraph.c | 402 -- src/aig/kit/kitHop.c | 155 - src/aig/kit/kitIsop.c | 330 - src/aig/kit/kitPerm.c | 355 -- src/aig/kit/kitPla.c | 535 -- src/aig/kit/kitSop.c | 579 -- src/aig/kit/kitTruth.c | 2222 ------- src/aig/kit/kit_.c | 53 - src/aig/kit/module.make | 11 - src/aig/live/liveness.c | 2575 -------- src/aig/live/liveness_sim.c | 848 --- src/aig/live/ltl_parser.c | 839 --- src/aig/live/module.make | 3 - src/aig/llb/llb.c | 52 - src/aig/llb/llb.h | 96 - src/aig/llb/llb1Cluster.c | 357 -- src/aig/llb/llb1Constr.c | 313 - src/aig/llb/llb1Core.c | 222 - src/aig/llb/llb1Group.c | 474 -- src/aig/llb/llb1Hint.c | 226 - src/aig/llb/llb1Man.c | 218 - src/aig/llb/llb1Matrix.c | 430 -- src/aig/llb/llb1Pivot.c | 254 - src/aig/llb/llb1Reach.c | 899 --- src/aig/llb/llb1Sched.c | 257 - src/aig/llb/llb2Bad.c | 137 - src/aig/llb/llb2Core.c | 775 --- src/aig/llb/llb2Driver.c | 221 - src/aig/llb/llb2Dump.c | 104 - src/aig/llb/llb2Flow.c | 1374 ----- src/aig/llb/llb2Image.c | 478 -- src/aig/llb/llb3Image.c | 1093 ---- src/aig/llb/llb3Nonlin.c | 871 --- src/aig/llb/llb4Cex.c | 320 - src/aig/llb/llb4Cluster.c | 452 -- src/aig/llb/llb4Image.c | 861 --- src/aig/llb/llb4Map.c | 123 - src/aig/llb/llb4Nonlin.c | 1080 ---- src/aig/llb/llb4Sweep.c | 588 -- src/aig/llb/llbInt.h | 212 - src/aig/llb/module.make | 23 - src/aig/mem/mem.c | 605 -- src/aig/mem/mem.h | 75 - src/aig/mem/module.make | 1 - src/aig/mfx/mfx.h | 85 - src/aig/mfx/mfxCore.c | 393 -- src/aig/mfx/mfxDiv.c | 308 - src/aig/mfx/mfxInt.h | 168 - src/aig/mfx/mfxInter.c | 368 -- src/aig/mfx/mfxMan.c | 195 - src/aig/mfx/mfxResub.c | 566 -- src/aig/mfx/mfxSat.c | 145 - src/aig/mfx/mfxStrash.c | 344 -- src/aig/mfx/mfxWin.c | 117 - src/aig/mfx/mfx_.c | 52 - src/aig/mfx/module.make | 8 - src/aig/ntl/module.make | 17 - src/aig/ntl/ntl.h | 426 -- src/aig/ntl/ntlCheck.c | 379 -- src/aig/ntl/ntlCore.c | 152 - src/aig/ntl/ntlEc.c | 370 -- src/aig/ntl/ntlExtract.c | 877 --- src/aig/ntl/ntlFraig.c | 1004 ---- src/aig/ntl/ntlInsert.c | 614 -- src/aig/ntl/ntlMan.c | 1068 ---- src/aig/ntl/ntlMap.c | 346 -- src/aig/ntl/ntlNames.c | 471 -- src/aig/ntl/ntlObj.c | 319 - src/aig/ntl/ntlReadBlif.c | 1446 ----- src/aig/ntl/ntlSweep.c | 214 - src/aig/ntl/ntlTable.c | 554 -- src/aig/ntl/ntlTime.c | 245 - src/aig/ntl/ntlUtil.c | 737 --- src/aig/ntl/ntlWriteBlif.c | 697 --- src/aig/ntl/ntl_.c | 52 - src/aig/ntl/ntlnwk.h | 113 - src/aig/nwk/module.make | 14 - src/aig/nwk/nwk.h | 307 - src/aig/nwk/nwkAig.c | 112 - src/aig/nwk/nwkBidec.c | 177 - src/aig/nwk/nwkCheck.c | 76 - src/aig/nwk/nwkDfs.c | 664 -- src/aig/nwk/nwkFanio.c | 320 - src/aig/nwk/nwkFlow.c | 606 -- src/aig/nwk/nwkFlow_depth.c | 631 -- src/aig/nwk/nwkMan.c | 278 - src/aig/nwk/nwkMap.c | 396 -- src/aig/nwk/nwkMerge.c | 1044 ---- src/aig/nwk/nwkMerge.h | 153 - src/aig/nwk/nwkObj.c | 204 - src/aig/nwk/nwkSpeedup.c | 382 -- src/aig/nwk/nwkStrash.c | 149 - src/aig/nwk/nwkTiming.c | 894 --- src/aig/nwk/nwkUtil.c | 643 -- src/aig/nwk/nwk_.c | 52 - src/aig/rwt/module.make | 3 - src/aig/rwt/rwt.h | 165 - src/aig/rwt/rwtDec.c | 155 - src/aig/rwt/rwtMan.c | 363 -- src/aig/rwt/rwtUtil.c | 662 -- src/aig/saig/saig.h | 8 +- src/aig/saig/saigAbs.c | 4 +- src/aig/saig/saigAbsCba.c | 34 +- src/aig/saig/saigAbsPba.c | 16 +- src/aig/saig/saigAbsStart.c | 8 +- src/aig/saig/saigAbsVfa.c | 4 +- src/aig/saig/saigBmc.c | 8 +- src/aig/saig/saigBmc2.c | 12 +- src/aig/saig/saigBmc3.c | 10 +- src/aig/saig/saigCexMin.c | 60 +- src/aig/saig/saigConstr.c | 12 +- src/aig/saig/saigConstr2.c | 24 +- src/aig/saig/saigDup.c | 24 +- src/aig/saig/saigGlaCba.c | 10 +- src/aig/saig/saigGlaPba.c | 4 +- src/aig/saig/saigGlaPba2.c | 2 +- src/aig/saig/saigHaig.c | 8 +- src/aig/saig/saigInd.c | 6 +- src/aig/saig/saigIoa.c | 14 +- src/aig/saig/saigMiter.c | 34 +- src/aig/saig/saigOutDec.c | 8 +- src/aig/saig/saigPhase.c | 34 +- src/aig/saig/saigRefSat.c | 34 +- src/aig/saig/saigRetMin.c | 16 +- src/aig/saig/saigSimExt.c | 18 +- src/aig/saig/saigSimExt2.c | 22 +- src/aig/saig/saigSimFast.c | 2 +- src/aig/saig/saigSimMv.c | 6 +- src/aig/saig/saigSimSeq.c | 6 +- src/aig/saig/saigStrSim.c | 4 +- src/aig/saig/saigSwitch.c | 2 +- src/aig/saig/saigSynch.c | 4 +- src/aig/saig/saigTempor.c | 4 +- src/aig/saig/saigTrans.c | 2 +- src/aig/saig/saigWnd.c | 8 +- src/aig/ssw/module.make | 20 - src/aig/ssw/ssw.h | 142 - src/aig/ssw/sswAig.c | 259 - src/aig/ssw/sswBmc.c | 224 - src/aig/ssw/sswClass.c | 1170 ---- src/aig/ssw/sswCnf.c | 428 -- src/aig/ssw/sswConstr.c | 714 --- src/aig/ssw/sswCore.c | 522 -- src/aig/ssw/sswDyn.c | 489 -- src/aig/ssw/sswFilter.c | 493 -- src/aig/ssw/sswInt.h | 302 - src/aig/ssw/sswIslands.c | 598 -- src/aig/ssw/sswLcorr.c | 336 -- src/aig/ssw/sswMan.c | 218 - src/aig/ssw/sswPairs.c | 477 -- src/aig/ssw/sswPart.c | 141 - src/aig/ssw/sswRarity.c | 1158 ---- src/aig/ssw/sswRarity2.c | 517 -- src/aig/ssw/sswSat.c | 306 - src/aig/ssw/sswSemi.c | 322 - src/aig/ssw/sswSim.c | 1405 ----- src/aig/ssw/sswSimSat.c | 123 - src/aig/ssw/sswSweep.c | 435 -- src/aig/ssw/sswUnique.c | 197 - src/aig/tim/module.make | 1 - src/aig/tim/tim.c | 996 --- src/aig/tim/tim.h | 110 - src/base/abc/abc.h | 28 +- src/base/abc/abcAig.c | 13 +- src/base/abc/abcBlifMv.c | 16 +- src/base/abc/abcCheck.c | 4 +- src/base/abc/abcDfs.c | 8 +- src/base/abc/abcFunc.c | 5 +- src/base/abc/abcHie.c | 5 +- src/base/abc/abcHieCec.c | 24 +- src/base/abc/abcHieNew.c | 18 +- src/base/abc/abcInt.h | 4 +- src/base/abc/abcLatch.c | 6 +- src/base/abc/abcLib.c | 3 +- src/base/abc/abcMinBase.c | 2 +- src/base/abc/abcNames.c | 19 +- src/base/abc/abcNetlist.c | 2 +- src/base/abc/abcNtk.c | 7 +- src/base/abc/abcObj.c | 5 +- src/base/abc/abcShow.c | 5 +- src/base/abc/abcSop.c | 9 +- src/base/abc/abcUtil.c | 8 +- src/base/abci/abc.c | 3528 +---------- src/base/abci/abcAbc8.c | 280 - src/base/abci/abcAttach.c | 6 +- src/base/abci/abcAuto.c | 4 +- src/base/abci/abcBalance.c | 3 +- src/base/abci/abcBidec.c | 6 +- src/base/abci/abcBm.c | 8 +- src/base/abci/abcBmc.c | 4 +- src/base/abci/abcCas.c | 4 +- src/base/abci/abcCascade.c | 13 +- src/base/abci/abcCollapse.c | 4 +- src/base/abci/abcCut.c | 5 +- src/base/abci/abcDar.c | 46 +- src/base/abci/abcDebug.c | 4 +- src/base/abci/abcDress.c | 4 +- src/base/abci/abcDress2.c | 10 +- src/base/abci/abcDsd.c | 6 +- src/base/abci/abcEspresso.c | 4 +- src/base/abci/abcExtract.c | 2 +- src/base/abci/abcFlop.c | 2 +- src/base/abci/abcFpga.c | 5 +- src/base/abci/abcFpgaFast.c | 4 +- src/base/abci/abcFraig.c | 8 +- src/base/abci/abcFxu.c | 4 +- src/base/abci/abcGen.c | 25 +- src/base/abci/abcHaig.c | 2 +- src/base/abci/abcIf.c | 10 +- src/base/abci/abcIfMux.c | 4 +- src/base/abci/abcIvy.c | 15 +- src/base/abci/abcLog.c | 10 +- src/base/abci/abcLut.c | 11 +- src/base/abci/abcLutmin.c | 8 +- src/base/abci/abcMap.c | 8 +- src/base/abci/abcMeasure.c | 4 +- src/base/abci/abcMerge.c | 6 +- src/base/abci/abcMffc.c | 2 +- src/base/abci/abcMini.c | 2 +- src/base/abci/abcMiter.c | 3 +- src/base/abci/abcMulti.c | 4 +- src/base/abci/abcMv.c | 4 +- src/base/abci/abcNpnSave.c | 15 +- src/base/abci/abcNtbdd.c | 4 +- src/base/abci/abcOdc.c | 3 +- src/base/abci/abcOrder.c | 2 +- src/base/abci/abcPart.c | 8 +- src/base/abci/abcPlace.c | 4 +- src/base/abci/abcPrint.c | 21 +- src/base/abci/abcProve.c | 11 +- src/base/abci/abcQbf.c | 2 +- src/base/abci/abcQuant.c | 3 +- src/base/abci/abcReach.c | 4 +- src/base/abci/abcRec.c | 24 +- src/base/abci/abcReconv.c | 4 +- src/base/abci/abcRefactor.c | 6 +- src/base/abci/abcRenode.c | 9 +- src/base/abci/abcReorder.c | 4 +- src/base/abci/abcRestruct.c | 16 +- src/base/abci/abcResub.c | 9 +- src/base/abci/abcRewrite.c | 7 +- src/base/abci/abcRr.c | 9 +- src/base/abci/abcSat.c | 11 +- src/base/abci/abcScorr.c | 20 +- src/base/abci/abcSense.c | 5 +- src/base/abci/abcSpeedup.c | 8 +- src/base/abci/abcStrash.c | 7 +- src/base/abci/abcSweep.c | 8 +- src/base/abci/abcSymm.c | 6 +- src/base/abci/abcTiming.c | 22 +- src/base/abci/abcUnate.c | 4 +- src/base/abci/abcUnreach.c | 4 +- src/base/abci/abcVerify.c | 18 +- src/base/abci/abcXsim.c | 4 +- src/base/abci/fahout_cut.c | 357 ++ src/base/abci/module.make | 1 - src/base/cmd/cmd.c | 6 +- src/base/cmd/cmd.h | 4 +- src/base/cmd/cmdAlias.c | 2 +- src/base/cmd/cmdApi.c | 4 +- src/base/cmd/cmdFlag.c | 4 +- src/base/cmd/cmdHist.c | 4 +- src/base/cmd/cmdInt.h | 6 +- src/base/cmd/cmdLoad.c | 6 +- src/base/cmd/cmdPlugin.c | 6 +- src/base/cmd/cmdUtils.c | 4 +- src/base/io/io.c | 6 +- src/base/io/ioAbc.h | 8 +- src/base/io/ioInt.h | 4 +- src/base/io/ioReadAiger.c | 6 +- src/base/io/ioReadBblif.c | 4 +- src/base/io/ioReadBlif.c | 4 +- src/base/io/ioReadBlifAig.c | 5 +- src/base/io/ioReadBlifMv.c | 9 +- src/base/io/ioReadDsd.c | 2 +- src/base/io/ioReadPla.c | 4 +- src/base/io/ioReadVerilog.c | 2 +- src/base/io/ioUtil.c | 2 +- src/base/io/ioWriteAiger.c | 12 +- src/base/io/ioWriteBblif.c | 2 +- src/base/io/ioWriteBlif.c | 8 +- src/base/io/ioWriteBlifMv.c | 4 +- src/base/io/ioWriteBook.c | 6 +- src/base/io/ioWriteCnf.c | 2 +- src/base/io/ioWriteDot.c | 4 +- src/base/io/ioWriteVerilog.c | 8 +- src/base/main/libSupport.c | 2 +- src/base/main/main.c | 2 +- src/base/main/main.h | 21 +- src/base/main/mainFrame.c | 5 +- src/base/main/mainInit.c | 2 +- src/base/main/mainInt.h | 29 +- src/base/main/mainLib.c | 2 +- src/base/main/mainMC.c | 8 +- src/base/main/mainUtils.c | 2 +- src/base/seq/module.make | 14 - src/base/seq/seq.h | 105 - src/base/seq/seqAigCore.c | 981 --- src/base/seq/seqAigIter.c | 273 - src/base/seq/seqCreate.c | 487 -- src/base/seq/seqFpgaCore.c | 648 -- src/base/seq/seqFpgaIter.c | 275 - src/base/seq/seqInt.h | 260 - src/base/seq/seqLatch.c | 228 - src/base/seq/seqMan.c | 138 - src/base/seq/seqMapCore.c | 657 -- src/base/seq/seqMapIter.c | 628 -- src/base/seq/seqMaxMeanCycle.c | 572 -- src/base/seq/seqRetCore.c | 498 -- src/base/seq/seqRetIter.c | 408 -- src/base/seq/seqShare.c | 393 -- src/base/seq/seqUtil.c | 602 -- src/base/test/test.c | 2 +- src/base/ver/ver.h | 7 +- src/base/ver/verCore.c | 4 +- src/bdd/cas/cas.h | 4 +- src/bdd/cas/casCore.c | 10 +- src/bdd/cas/casDec.c | 4 +- src/bdd/cudd/cudd.h | 8 +- 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/cuddInt.h | 10 +- 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/dsd/dsd.h | 4 +- src/bdd/dsd/dsdCheck.c | 2 +- src/bdd/dsd/dsdInt.h | 6 +- src/bdd/epd/epd.c | 2 +- src/bdd/epd/epd.h | 4 +- src/bdd/mtr/mtr.h | 4 +- src/bdd/mtr/mtrBasic.c | 2 +- src/bdd/mtr/mtrGroup.c | 2 +- src/bdd/mtr/mtrInt.h | 4 +- src/bdd/parse/parse.h | 4 +- src/bdd/parse/parseEqn.c | 4 +- src/bdd/parse/parseInt.h | 7 +- src/bdd/reo/reo.h | 6 +- src/bool/bdc/bdc.h | 92 + src/bool/bdc/bdcCore.c | 314 + src/bool/bdc/bdcDec.c | 751 +++ src/bool/bdc/bdcInt.h | 165 + src/bool/bdc/bdcSpfd.c | 1176 ++++ src/bool/bdc/bdcTable.c | 134 + src/bool/bdc/bdc_.c | 54 + src/bool/bdc/module.make | 5 + src/bool/dec/dec.h | 725 +++ src/bool/dec/decAbc.c | 358 ++ src/bool/dec/decFactor.c | 399 ++ src/bool/dec/decMan.c | 88 + src/bool/dec/decPrint.c | 289 + src/bool/dec/decUtil.c | 141 + src/bool/dec/module.make | 5 + src/bool/deco/deco.h | 714 +++ src/bool/deco/module.make | 1 + src/bool/kit/cloud.c | 993 +++ src/bool/kit/cloud.h | 255 + src/bool/kit/kit.h | 645 ++ src/bool/kit/kitAig.c | 126 + src/bool/kit/kitBdd.c | 236 + src/bool/kit/kitCloud.c | 378 ++ src/bool/kit/kitDec.c | 343 ++ src/bool/kit/kitDsd.c | 3200 ++++++++++ src/bool/kit/kitFactor.c | 344 ++ src/bool/kit/kitGraph.c | 402 ++ src/bool/kit/kitHop.c | 155 + src/bool/kit/kitIsop.c | 330 + src/bool/kit/kitPerm.c | 355 ++ src/bool/kit/kitPla.c | 535 ++ src/bool/kit/kitSop.c | 579 ++ src/bool/kit/kitTruth.c | 2222 +++++++ src/bool/kit/kit_.c | 53 + src/bool/kit/module.make | 11 + src/generic.h | 4 +- src/map/amap/amap.h | 4 +- src/map/amap/amapCore.c | 2 +- src/map/amap/amapGraph.c | 12 +- src/map/amap/amapInt.h | 33 +- src/map/amap/amapLib.c | 2 +- src/map/amap/amapLiberty.c | 2 +- src/map/amap/amapMatch.c | 12 +- src/map/amap/amapMerge.c | 40 +- src/map/amap/amapParse.c | 8 +- src/map/amap/amapPerm.c | 62 +- src/map/amap/amapRead.c | 2 +- src/map/amap/amapRule.c | 26 +- src/map/amap/amapUniq.c | 14 +- src/map/cov/cov.h | 7 +- src/map/cov/covCore.c | 6 +- src/map/cov/covInt.h | 7 +- src/map/fpga/fpga.c | 2 +- src/map/fpga/fpga.h | 4 +- src/map/fpga/fpgaCreate.c | 6 +- src/map/fpga/fpgaCut.c | 2 +- src/map/fpga/fpgaInt.h | 9 +- src/map/fpga/fpgaTruth.c | 2 +- src/map/if/if.h | 10 +- src/map/if/ifDec07.c | 4 +- src/map/if/ifDec08.c | 4 +- src/map/if/ifDec10.c | 4 +- src/map/if/ifDec16.c | 2 +- src/map/if/ifTime.c | 6 +- src/map/mapper/mapper.c | 6 +- src/map/mapper/mapper.h | 4 +- src/map/mapper/mapperCreate.c | 4 +- src/map/mapper/mapperCut.c | 2 +- src/map/mapper/mapperInt.h | 10 +- src/map/mapper/mapperTable.c | 4 +- src/map/mio/exp.h | 4 +- src/map/mio/mio.c | 6 +- src/map/mio/mio.h | 4 +- src/map/mio/mioForm.c | 2 +- src/map/mio/mioInt.h | 10 +- src/map/mio/mioRead.c | 2 +- src/map/mio/mioUtils.c | 2 +- src/map/super/super.c | 4 +- src/map/super/super.h | 4 +- src/map/super/superInt.h | 14 +- src/misc/avl/avl.h | 4 +- src/misc/bar/bar.c | 187 + src/misc/bar/bar.h | 78 + src/misc/bar/module.make | 1 + src/misc/bbl/bblif.c | 1518 +++++ src/misc/bbl/bblif.h | 285 + src/misc/bbl/module.make | 1 + src/misc/bzlib/bzlib.h | 6 +- src/misc/bzlib/bzlib_private.h | 4 +- src/misc/espresso/espresso.h | 4 +- src/misc/espresso/main.c | 2 +- src/misc/espresso/mincov_int.h | 2 +- src/misc/espresso/sparse.h | 4 +- src/misc/espresso/sparse_int.h | 2 +- src/misc/espresso/util_old.h | 4 +- src/misc/ext/ext.h | 4 +- src/misc/extra/extra.h | 246 +- src/misc/extra/extraBdd.h | 316 + src/misc/extra/extraBddAuto.c | 2 +- src/misc/extra/extraBddCas.c | 4 +- src/misc/extra/extraBddImage.c | 2 +- src/misc/extra/extraBddKmap.c | 2 +- src/misc/extra/extraBddMisc.c | 4 +- src/misc/extra/extraBddSymm.c | 2 +- src/misc/extra/extraBddTime.c | 2 +- src/misc/extra/extraBddUnate.c | 2 +- src/misc/extra/extraUtilFile.c | 2 +- src/misc/extra/extraUtilMisc.c | 78 +- src/misc/extra/extraUtilProgress.c | 2 +- src/misc/extra/extraUtilReader.c | 2 +- src/misc/hash/hash.h | 8 +- src/misc/hash/hashFlt.h | 6 +- src/misc/hash/hashGen.h | 6 +- src/misc/hash/hashInt.h | 6 +- src/misc/hash/hashPtr.h | 6 +- src/misc/mem/mem.c | 605 ++ src/misc/mem/mem.h | 75 + src/misc/mem/module.make | 1 + src/misc/mvc/mvc.h | 7 +- src/misc/nm/nm.h | 4 +- src/misc/nm/nmApi.c | 2 +- src/misc/nm/nmInt.h | 9 +- src/misc/nm/nmTable.c | 37 +- src/misc/st/st.c | 3 +- src/misc/st/st.h | 5 +- src/misc/st/stmm.c | 4 +- src/misc/st/stmm.h | 6 +- src/misc/tim/module.make | 1 + src/misc/tim/tim.c | 996 +++ src/misc/tim/tim.h | 110 + src/misc/util/abc_global.h | 52 +- src/misc/util/utilCex.c | 4 - src/misc/util/utilCex.h | 4 +- src/misc/util/utilMem.h | 4 +- src/misc/util/utilNam.c | 4 +- src/misc/util/utilNam.h | 4 +- src/misc/util/utilSignal.c | 2 + src/misc/util/utilSignal.h | 4 +- src/misc/util/util_hack.h | 4 +- src/misc/vec/vec.h | 6 +- src/misc/vec/vecAtt.h | 4 +- src/misc/vec/vecBit.h | 4 +- src/misc/vec/vecFlt.h | 4 +- src/misc/vec/vecInt.h | 4 +- src/misc/vec/vecPtr.h | 4 +- src/misc/vec/vecStr.h | 4 +- src/misc/vec/vecVec.h | 4 +- src/misc/vec/vecWrd.h | 4 +- src/misc/zlib/adler32.c | 2 +- src/misc/zlib/crc32.c | 2 +- src/misc/zlib/deflate.c | 2 +- src/misc/zlib/gzclose.c | 2 +- src/misc/zlib/gzguts.h | 2 +- src/misc/zlib/gzlib.c | 2 +- src/misc/zlib/gzread.c | 2 +- src/misc/zlib/gzwrite.c | 2 +- src/misc/zlib/infback.c | 2 +- src/misc/zlib/inffast.c | 2 +- src/misc/zlib/inflate.c | 2 +- src/misc/zlib/inftrees.c | 2 +- src/misc/zlib/trees.c | 2 +- src/misc/zlib/uncompr.c | 2 +- src/misc/zlib/zlib.h | 5 +- src/misc/zlib/zutil.c | 2 +- src/opt/cgt/cgt.h | 86 + src/opt/cgt/cgtAig.c | 601 ++ src/opt/cgt/cgtCore.c | 321 + src/opt/cgt/cgtDecide.c | 301 + src/opt/cgt/cgtInt.h | 122 + src/opt/cgt/cgtMan.c | 179 + src/opt/cgt/cgtSat.c | 97 + src/opt/cgt/module.make | 5 + src/opt/csw/csw.h | 69 + src/opt/csw/cswCore.c | 99 + src/opt/csw/cswCut.c | 607 ++ src/opt/csw/cswInt.h | 161 + src/opt/csw/cswMan.c | 130 + src/opt/csw/cswTable.c | 166 + src/opt/csw/csw_.c | 53 + src/opt/csw/module.make | 4 + src/opt/cut/abcCut.c | 2 +- src/opt/cut/cut.h | 4 +- src/opt/cut/cutInt.h | 8 +- src/opt/cut/cutList.h | 4 +- src/opt/cut/cutPre22.c | 2 +- src/opt/dar/dar.h | 116 + src/opt/dar/darBalance.c | 645 ++ src/opt/dar/darCore.c | 344 ++ src/opt/dar/darCut.c | 752 +++ src/opt/dar/darData.c | 11294 +++++++++++++++++++++++++++++++++++ src/opt/dar/darInt.h | 171 + src/opt/dar/darLib.c | 1339 +++++ src/opt/dar/darMan.c | 174 + src/opt/dar/darPrec.c | 394 ++ src/opt/dar/darRefact.c | 636 ++ src/opt/dar/darResub.c | 53 + src/opt/dar/darScript.c | 927 +++ src/opt/dar/dar_.c | 53 + src/opt/dar/module.make | 10 + src/opt/dec/dec.h | 725 --- src/opt/dec/decAbc.c | 358 -- src/opt/dec/decFactor.c | 398 -- src/opt/dec/decMan.c | 88 - src/opt/dec/decPrint.c | 289 - src/opt/dec/decUtil.c | 141 - src/opt/dec/module.make | 5 - src/opt/fret/fretFlow.c | 702 --- src/opt/fret/fretInit.c | 1334 ----- src/opt/fret/fretMain.c | 1385 ----- src/opt/fret/fretTime.c | 768 --- src/opt/fret/fretime.h | 205 - src/opt/fret/module.make | 5 - src/opt/fsim/fsim.h | 101 + src/opt/fsim/fsimCore.c | 88 + src/opt/fsim/fsimFront.c | 369 ++ src/opt/fsim/fsimInt.h | 138 + src/opt/fsim/fsimMan.c | 212 + src/opt/fsim/fsimSim.c | 567 ++ src/opt/fsim/fsimSwitch.c | 40 + src/opt/fsim/fsimTsim.c | 415 ++ src/opt/fsim/module.make | 6 + src/opt/fxu/fxu.h | 6 +- src/opt/fxu/fxuInt.h | 7 +- src/opt/fxu/fxuMatrix.c | 4 +- src/opt/fxu/fxuReduce.c | 2 +- src/opt/fxu/fxuSingle.c | 2 +- src/opt/lpk/lpk.h | 4 +- src/opt/lpk/lpkAbcDsd.c | 10 +- src/opt/lpk/lpkAbcMux.c | 24 +- src/opt/lpk/lpkAbcUtil.c | 2 +- src/opt/lpk/lpkCore.c | 10 +- src/opt/lpk/lpkCut.c | 2 +- src/opt/lpk/lpkInt.h | 10 +- src/opt/lpk/lpkMap.c | 24 +- src/opt/lpk/lpkMulti.c | 10 +- src/opt/lpk/lpkSets.c | 6 +- src/opt/mfs/mfs.h | 4 +- src/opt/mfs/mfsGia.c | 2 +- src/opt/mfs/mfsInt.h | 19 +- src/opt/mfs/mfsInter.c | 2 +- src/opt/mfs/mfsMan.c | 2 +- src/opt/mfs/mfsResub.c | 12 +- src/opt/mfs/mfsSat.c | 6 +- src/opt/mfs/mfsStrash.c | 2 +- src/opt/nwk/module.make | 14 + src/opt/nwk/ntlnwk.h | 113 + src/opt/nwk/nwk.h | 307 + src/opt/nwk/nwkAig.c | 112 + src/opt/nwk/nwkBidec.c | 177 + src/opt/nwk/nwkCheck.c | 76 + src/opt/nwk/nwkDfs.c | 664 ++ src/opt/nwk/nwkFanio.c | 320 + src/opt/nwk/nwkFlow.c | 606 ++ src/opt/nwk/nwkFlow_depth.c | 631 ++ src/opt/nwk/nwkMan.c | 278 + src/opt/nwk/nwkMap.c | 396 ++ src/opt/nwk/nwkMerge.c | 1044 ++++ src/opt/nwk/nwkMerge.h | 153 + src/opt/nwk/nwkObj.c | 204 + src/opt/nwk/nwkSpeedup.c | 382 ++ src/opt/nwk/nwkStrash.c | 149 + src/opt/nwk/nwkTiming.c | 894 +++ src/opt/nwk/nwkUtil.c | 643 ++ src/opt/nwk/nwk_.c | 52 + src/opt/res/res.h | 4 +- src/opt/res/resCore.c | 6 +- src/opt/res/resDivs.c | 2 +- src/opt/res/resFilter.c | 2 +- src/opt/res/resInt.h | 4 +- src/opt/res/resSat.c | 6 +- src/opt/res/resSim.c | 3 +- src/opt/res/resSim_old.c | 2 +- src/opt/res/resStrash.c | 3 +- src/opt/res/resWin.c | 6 +- src/opt/res/res_.c | 2 +- src/opt/ret/retInt.h | 6 +- src/opt/rwr/rwr.h | 8 +- src/opt/rwr/rwrDec.c | 3 +- src/opt/rwr/rwrEva.c | 7 +- src/opt/rwr/rwrExp.c | 1 - src/opt/rwr/rwrLib.c | 3 +- src/opt/rwr/rwrMan.c | 5 +- src/opt/rwr/rwrPrint.c | 1 - src/opt/rwr/rwrTemp.c | 1 - src/opt/rwr/rwrUtil.c | 5 +- src/opt/rwt/module.make | 3 + src/opt/rwt/rwt.h | 165 + src/opt/rwt/rwtDec.c | 155 + src/opt/rwt/rwtMan.c | 363 ++ src/opt/rwt/rwtUtil.c | 662 ++ src/opt/sim/sim.h | 4 +- src/opt/sim/simMan.c | 3 +- src/opt/sim/simSat.c | 3 +- src/opt/sim/simSeq.c | 3 +- src/opt/sim/simSupp.c | 7 +- src/opt/sim/simSwitch.c | 3 +- src/opt/sim/simSym.c | 3 +- src/opt/sim/simSymSat.c | 5 +- src/opt/sim/simSymSim.c | 3 +- src/opt/sim/simSymStr.c | 3 +- src/opt/sim/simUtils.c | 3 +- src/phys/place/libhmetis.h | 4 +- src/phys/place/place_base.h | 4 +- src/phys/place/place_gordian.h | 2 +- src/phys/place/place_qpsolver.h | 2 +- src/proof/bbr/bbr.h | 93 + src/proof/bbr/bbrCex.c | 172 + src/proof/bbr/bbrImage.c | 1327 ++++ src/proof/bbr/bbrNtbdd.c | 218 + src/proof/bbr/bbrReach.c | 606 ++ src/proof/bbr/bbr_.c | 52 + src/proof/bbr/module.make | 4 + src/proof/cec/cec.c | 53 + src/proof/cec/cec.h | 233 + src/proof/cec/cecCec.c | 373 ++ src/proof/cec/cecChoice.c | 409 ++ src/proof/cec/cecClass.c | 931 +++ src/proof/cec/cecCore.c | 542 ++ src/proof/cec/cecCorr.c | 1137 ++++ src/proof/cec/cecCorr_updated.c | 1027 ++++ src/proof/cec/cecInt.h | 225 + src/proof/cec/cecIso.c | 375 ++ src/proof/cec/cecMan.c | 297 + src/proof/cec/cecPat.c | 569 ++ src/proof/cec/cecSeq.c | 448 ++ src/proof/cec/cecSim.c | 53 + src/proof/cec/cecSolve.c | 1023 ++++ src/proof/cec/cecSweep.c | 299 + src/proof/cec/cecSynth.c | 380 ++ src/proof/cec/module.make | 13 + src/proof/dch/dch.h | 90 + src/proof/dch/dchAig.c | 119 + src/proof/dch/dchChoice.c | 508 ++ src/proof/dch/dchClass.c | 611 ++ src/proof/dch/dchCnf.c | 334 ++ src/proof/dch/dchCore.c | 158 + src/proof/dch/dchInt.h | 170 + src/proof/dch/dchMan.c | 191 + src/proof/dch/dchSat.c | 166 + src/proof/dch/dchSim.c | 297 + src/proof/dch/dchSimSat.c | 258 + src/proof/dch/dchSweep.c | 146 + src/proof/dch/module.make | 10 + src/proof/fra/fra.h | 389 ++ src/proof/fra/fraBmc.c | 451 ++ src/proof/fra/fraCec.c | 516 ++ src/proof/fra/fraClass.c | 862 +++ src/proof/fra/fraClau.c | 763 +++ src/proof/fra/fraClaus.c | 1875 ++++++ src/proof/fra/fraCnf.c | 289 + src/proof/fra/fraCore.c | 490 ++ src/proof/fra/fraHot.c | 476 ++ src/proof/fra/fraImp.c | 731 +++ src/proof/fra/fraInd.c | 709 +++ src/proof/fra/fraIndVer.c | 166 + src/proof/fra/fraLcr.c | 709 +++ src/proof/fra/fraMan.c | 314 + src/proof/fra/fraPart.c | 268 + src/proof/fra/fraSat.c | 566 ++ src/proof/fra/fraSec.c | 696 +++ src/proof/fra/fraSim.c | 1023 ++++ src/proof/fra/fra_.c | 53 + src/proof/fra/module.make | 17 + src/proof/fraig/fraig.h | 260 + src/proof/fraig/fraigApi.c | 302 + src/proof/fraig/fraigCanon.c | 223 + src/proof/fraig/fraigChoice.c | 246 + src/proof/fraig/fraigFanout.c | 180 + src/proof/fraig/fraigFeed.c | 913 +++ src/proof/fraig/fraigInt.h | 433 ++ src/proof/fraig/fraigMan.c | 545 ++ src/proof/fraig/fraigMem.c | 251 + src/proof/fraig/fraigNode.c | 318 + src/proof/fraig/fraigPrime.c | 113 + src/proof/fraig/fraigSat.c | 1459 +++++ src/proof/fraig/fraigTable.c | 662 ++ src/proof/fraig/fraigUtil.c | 1039 ++++ src/proof/fraig/fraigVec.c | 550 ++ src/proof/fraig/module.make | 12 + src/proof/int/int.h | 94 + src/proof/int/intCheck.c | 305 + src/proof/int/intContain.c | 341 ++ src/proof/int/intCore.c | 389 ++ src/proof/int/intCtrex.c | 167 + src/proof/int/intDup.c | 184 + src/proof/int/intFrames.c | 115 + src/proof/int/intInt.h | 142 + src/proof/int/intInter.c | 145 + src/proof/int/intM114.c | 320 + src/proof/int/intM114p.c | 442 ++ src/proof/int/intMan.c | 163 + src/proof/int/intUtil.c | 108 + src/proof/int/module.make | 11 + src/proof/live/liveness.c | 2575 ++++++++ src/proof/live/liveness_sim.c | 848 +++ src/proof/live/ltl_parser.c | 839 +++ src/proof/live/module.make | 3 + src/proof/llb/llb.c | 52 + src/proof/llb/llb.h | 96 + src/proof/llb/llb1Cluster.c | 356 ++ src/proof/llb/llb1Constr.c | 313 + src/proof/llb/llb1Core.c | 222 + src/proof/llb/llb1Group.c | 474 ++ src/proof/llb/llb1Hint.c | 226 + src/proof/llb/llb1Man.c | 218 + src/proof/llb/llb1Matrix.c | 430 ++ src/proof/llb/llb1Pivot.c | 254 + src/proof/llb/llb1Reach.c | 898 +++ src/proof/llb/llb1Sched.c | 257 + src/proof/llb/llb2Bad.c | 137 + src/proof/llb/llb2Core.c | 775 +++ src/proof/llb/llb2Driver.c | 221 + src/proof/llb/llb2Dump.c | 104 + src/proof/llb/llb2Flow.c | 1374 +++++ src/proof/llb/llb2Image.c | 478 ++ src/proof/llb/llb3Image.c | 1093 ++++ src/proof/llb/llb3Nonlin.c | 871 +++ src/proof/llb/llb4Cex.c | 320 + src/proof/llb/llb4Cluster.c | 452 ++ src/proof/llb/llb4Image.c | 861 +++ src/proof/llb/llb4Map.c | 123 + src/proof/llb/llb4Nonlin.c | 1080 ++++ src/proof/llb/llb4Sweep.c | 588 ++ src/proof/llb/llbInt.h | 211 + src/proof/llb/module.make | 23 + src/proof/pdr/module.make | 8 + src/proof/pdr/pdr.c | 53 + src/proof/pdr/pdr.h | 79 + src/proof/pdr/pdrClass.c | 223 + src/proof/pdr/pdrCnf.c | 357 ++ src/proof/pdr/pdrCore.c | 722 +++ src/proof/pdr/pdrInt.h | 198 + src/proof/pdr/pdrInv.c | 374 ++ src/proof/pdr/pdrMan.c | 194 + src/proof/pdr/pdrSat.c | 373 ++ src/proof/pdr/pdrTsim.c | 450 ++ src/proof/pdr/pdrUtil.c | 719 +++ src/proof/ssw/module.make | 20 + src/proof/ssw/ssw.h | 142 + src/proof/ssw/sswAig.c | 259 + src/proof/ssw/sswBmc.c | 224 + src/proof/ssw/sswClass.c | 1170 ++++ src/proof/ssw/sswCnf.c | 428 ++ src/proof/ssw/sswConstr.c | 714 +++ src/proof/ssw/sswCore.c | 522 ++ src/proof/ssw/sswDyn.c | 489 ++ src/proof/ssw/sswFilter.c | 493 ++ src/proof/ssw/sswInt.h | 302 + src/proof/ssw/sswIslands.c | 598 ++ src/proof/ssw/sswLcorr.c | 336 ++ src/proof/ssw/sswMan.c | 218 + src/proof/ssw/sswPairs.c | 477 ++ src/proof/ssw/sswPart.c | 141 + src/proof/ssw/sswRarity.c | 1158 ++++ src/proof/ssw/sswRarity2.c | 517 ++ src/proof/ssw/sswSat.c | 306 + src/proof/ssw/sswSemi.c | 322 + src/proof/ssw/sswSim.c | 1405 +++++ src/proof/ssw/sswSimSat.c | 123 + src/proof/ssw/sswSweep.c | 435 ++ src/proof/ssw/sswUnique.c | 197 + src/sat/bsat/satChecker.c | 2 +- src/sat/bsat/satInterA.c | 2 +- src/sat/bsat/satInterB.c | 2 +- src/sat/bsat/satInterP.c | 2 +- src/sat/bsat/satMem.h | 6 +- src/sat/bsat/satProof.c | 6 +- src/sat/bsat/satSolver.h | 4 +- src/sat/bsat/satSolver2.h | 4 +- src/sat/bsat/satSolver_old.h | 4 +- src/sat/bsat/satStore.h | 4 +- src/sat/bsat/satTruth.h | 6 +- src/sat/bsat/satVec.h | 6 +- src/sat/bsat/vecRec.h | 4 +- src/sat/cnf/cnf.h | 195 + src/sat/cnf/cnfCore.c | 296 + src/sat/cnf/cnfCut.c | 376 ++ src/sat/cnf/cnfData.c | 4789 +++++++++++++++ src/sat/cnf/cnfFast.c | 697 +++ src/sat/cnf/cnfMan.c | 693 +++ src/sat/cnf/cnfMap.c | 362 ++ src/sat/cnf/cnfPost.c | 238 + src/sat/cnf/cnfUtil.c | 238 + src/sat/cnf/cnfWrite.c | 806 +++ src/sat/cnf/cnf_.c | 53 + src/sat/cnf/module.make | 9 + src/sat/csat/csat_apis.c | 8 +- src/sat/csat/csat_apis.h | 4 +- src/sat/fraig/fraig.h | 260 - src/sat/fraig/fraigApi.c | 302 - src/sat/fraig/fraigCanon.c | 223 - src/sat/fraig/fraigChoice.c | 246 - src/sat/fraig/fraigFanout.c | 180 - src/sat/fraig/fraigFeed.c | 913 --- src/sat/fraig/fraigInt.h | 434 -- src/sat/fraig/fraigMan.c | 545 -- src/sat/fraig/fraigMem.c | 251 - src/sat/fraig/fraigNode.c | 318 - src/sat/fraig/fraigPrime.c | 149 - src/sat/fraig/fraigSat.c | 1459 ----- src/sat/fraig/fraigTable.c | 662 -- src/sat/fraig/fraigUtil.c | 1039 ---- src/sat/fraig/fraigVec.c | 550 -- src/sat/fraig/module.make | 12 - src/sat/lsat/solver.h | 4 +- src/sat/msat/msat.h | 4 +- src/sat/msat/msatInt.h | 6 +- src/sat/pdr/module.make | 8 - src/sat/pdr/pdr.c | 53 - src/sat/pdr/pdr.h | 79 - src/sat/pdr/pdrClass.c | 223 - src/sat/pdr/pdrCnf.c | 357 -- src/sat/pdr/pdrCore.c | 722 --- src/sat/pdr/pdrInt.h | 198 - src/sat/pdr/pdrInv.c | 376 -- src/sat/pdr/pdrMan.c | 194 - src/sat/pdr/pdrSat.c | 373 -- src/sat/pdr/pdrTsim.c | 450 -- src/sat/pdr/pdrUtil.c | 719 --- src/sat/proof/pr.c | 2 +- src/sat/proof/pr.h | 4 +- src/sat/psat/m114p.h | 4 +- src/sat/psat/m114p_types.h | 4 +- src/template.c | 2 +- 1153 files changed, 130332 insertions(+), 158103 deletions(-) create mode 100644 arch_flags.c 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/bbl/bblif.c delete mode 100644 src/aig/bbl/bblif.h delete mode 100644 src/aig/bbl/module.make delete mode 100644 src/aig/bbr/bbr.h delete mode 100644 src/aig/bbr/bbrCex.c delete mode 100644 src/aig/bbr/bbrImage.c delete mode 100644 src/aig/bbr/bbrNtbdd.c delete mode 100644 src/aig/bbr/bbrReach.c delete mode 100644 src/aig/bbr/bbr_.c delete mode 100644 src/aig/bbr/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/bdcSpfd.c 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/cec/cec.c delete mode 100644 src/aig/cec/cec.h delete mode 100644 src/aig/cec/cecCec.c delete mode 100644 src/aig/cec/cecChoice.c delete mode 100644 src/aig/cec/cecClass.c delete mode 100644 src/aig/cec/cecCore.c delete mode 100644 src/aig/cec/cecCorr.c delete mode 100644 src/aig/cec/cecCorr_updated.c delete mode 100644 src/aig/cec/cecInt.h delete mode 100644 src/aig/cec/cecIso.c delete mode 100644 src/aig/cec/cecMan.c delete mode 100644 src/aig/cec/cecPat.c delete mode 100644 src/aig/cec/cecSeq.c delete mode 100644 src/aig/cec/cecSim.c delete mode 100644 src/aig/cec/cecSolve.c delete mode 100644 src/aig/cec/cecSweep.c delete mode 100644 src/aig/cec/cecSynth.c delete mode 100644 src/aig/cec/module.make delete mode 100644 src/aig/cgt/cgt.h delete mode 100644 src/aig/cgt/cgtAig.c delete mode 100644 src/aig/cgt/cgtCore.c delete mode 100644 src/aig/cgt/cgtDecide.c delete mode 100644 src/aig/cgt/cgtInt.h delete mode 100644 src/aig/cgt/cgtMan.c delete mode 100644 src/aig/cgt/cgtSat.c delete mode 100644 src/aig/cgt/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/cnfFast.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/dch/dch.h delete mode 100644 src/aig/dch/dchAig.c delete mode 100644 src/aig/dch/dchChoice.c delete mode 100644 src/aig/dch/dchClass.c delete mode 100644 src/aig/dch/dchCnf.c delete mode 100644 src/aig/dch/dchCore.c delete mode 100644 src/aig/dch/dchInt.h delete mode 100644 src/aig/dch/dchMan.c delete mode 100644 src/aig/dch/dchSat.c delete mode 100644 src/aig/dch/dchSim.c delete mode 100644 src/aig/dch/dchSimSat.c delete mode 100644 src/aig/dch/dchSweep.c delete mode 100644 src/aig/dch/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/fraHot.c delete mode 100644 src/aig/fra/fraImp.c delete mode 100644 src/aig/fra/fraInd.c delete mode 100644 src/aig/fra/fraIndVer.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/fsim/fsim.h delete mode 100644 src/aig/fsim/fsimCore.c delete mode 100644 src/aig/fsim/fsimFront.c delete mode 100644 src/aig/fsim/fsimInt.h delete mode 100644 src/aig/fsim/fsimMan.c delete mode 100644 src/aig/fsim/fsimSim.c delete mode 100644 src/aig/fsim/fsimSwitch.c delete mode 100644 src/aig/fsim/fsimTsim.c delete mode 100644 src/aig/fsim/module.make delete mode 100644 src/aig/int/int.h delete mode 100644 src/aig/int/intCheck.c delete mode 100644 src/aig/int/intContain.c delete mode 100644 src/aig/int/intCore.c delete mode 100644 src/aig/int/intCtrex.c delete mode 100644 src/aig/int/intDup.c delete mode 100644 src/aig/int/intFrames.c delete mode 100644 src/aig/int/intInt.h delete mode 100644 src/aig/int/intInter.c delete mode 100644 src/aig/int/intM114.c delete mode 100644 src/aig/int/intM114p.c delete mode 100644 src/aig/int/intMan.c delete mode 100644 src/aig/int/intUtil.c delete mode 100644 src/aig/int/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/kitDec.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/kitPerm.c delete mode 100644 src/aig/kit/kitPla.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/live/liveness.c delete mode 100644 src/aig/live/liveness_sim.c delete mode 100644 src/aig/live/ltl_parser.c delete mode 100644 src/aig/live/module.make delete mode 100644 src/aig/llb/llb.c delete mode 100644 src/aig/llb/llb.h delete mode 100644 src/aig/llb/llb1Cluster.c delete mode 100644 src/aig/llb/llb1Constr.c delete mode 100644 src/aig/llb/llb1Core.c delete mode 100644 src/aig/llb/llb1Group.c delete mode 100644 src/aig/llb/llb1Hint.c delete mode 100644 src/aig/llb/llb1Man.c delete mode 100644 src/aig/llb/llb1Matrix.c delete mode 100644 src/aig/llb/llb1Pivot.c delete mode 100644 src/aig/llb/llb1Reach.c delete mode 100644 src/aig/llb/llb1Sched.c delete mode 100644 src/aig/llb/llb2Bad.c delete mode 100644 src/aig/llb/llb2Core.c delete mode 100644 src/aig/llb/llb2Driver.c delete mode 100644 src/aig/llb/llb2Dump.c delete mode 100644 src/aig/llb/llb2Flow.c delete mode 100644 src/aig/llb/llb2Image.c delete mode 100644 src/aig/llb/llb3Image.c delete mode 100644 src/aig/llb/llb3Nonlin.c delete mode 100644 src/aig/llb/llb4Cex.c delete mode 100644 src/aig/llb/llb4Cluster.c delete mode 100644 src/aig/llb/llb4Image.c delete mode 100644 src/aig/llb/llb4Map.c delete mode 100644 src/aig/llb/llb4Nonlin.c delete mode 100644 src/aig/llb/llb4Sweep.c delete mode 100644 src/aig/llb/llbInt.h delete mode 100644 src/aig/llb/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/mfx/mfx.h delete mode 100644 src/aig/mfx/mfxCore.c delete mode 100644 src/aig/mfx/mfxDiv.c delete mode 100644 src/aig/mfx/mfxInt.h delete mode 100644 src/aig/mfx/mfxInter.c delete mode 100644 src/aig/mfx/mfxMan.c delete mode 100644 src/aig/mfx/mfxResub.c delete mode 100644 src/aig/mfx/mfxSat.c delete mode 100644 src/aig/mfx/mfxStrash.c delete mode 100644 src/aig/mfx/mfxWin.c delete mode 100644 src/aig/mfx/mfx_.c delete mode 100644 src/aig/mfx/module.make delete mode 100644 src/aig/ntl/module.make delete mode 100644 src/aig/ntl/ntl.h delete mode 100644 src/aig/ntl/ntlCheck.c delete mode 100644 src/aig/ntl/ntlCore.c delete mode 100644 src/aig/ntl/ntlEc.c delete mode 100644 src/aig/ntl/ntlExtract.c delete mode 100644 src/aig/ntl/ntlFraig.c delete mode 100644 src/aig/ntl/ntlInsert.c delete mode 100644 src/aig/ntl/ntlMan.c delete mode 100644 src/aig/ntl/ntlMap.c delete mode 100644 src/aig/ntl/ntlNames.c delete mode 100644 src/aig/ntl/ntlObj.c delete mode 100644 src/aig/ntl/ntlReadBlif.c delete mode 100644 src/aig/ntl/ntlSweep.c delete mode 100644 src/aig/ntl/ntlTable.c delete mode 100644 src/aig/ntl/ntlTime.c delete mode 100644 src/aig/ntl/ntlUtil.c delete mode 100644 src/aig/ntl/ntlWriteBlif.c delete mode 100644 src/aig/ntl/ntl_.c delete mode 100644 src/aig/ntl/ntlnwk.h delete mode 100644 src/aig/nwk/module.make delete mode 100644 src/aig/nwk/nwk.h delete mode 100644 src/aig/nwk/nwkAig.c delete mode 100644 src/aig/nwk/nwkBidec.c delete mode 100644 src/aig/nwk/nwkCheck.c delete mode 100644 src/aig/nwk/nwkDfs.c delete mode 100644 src/aig/nwk/nwkFanio.c delete mode 100644 src/aig/nwk/nwkFlow.c delete mode 100644 src/aig/nwk/nwkFlow_depth.c delete mode 100644 src/aig/nwk/nwkMan.c delete mode 100644 src/aig/nwk/nwkMap.c delete mode 100644 src/aig/nwk/nwkMerge.c delete mode 100644 src/aig/nwk/nwkMerge.h delete mode 100644 src/aig/nwk/nwkObj.c delete mode 100644 src/aig/nwk/nwkSpeedup.c delete mode 100644 src/aig/nwk/nwkStrash.c delete mode 100644 src/aig/nwk/nwkTiming.c delete mode 100644 src/aig/nwk/nwkUtil.c delete mode 100644 src/aig/nwk/nwk_.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/ssw/module.make delete mode 100644 src/aig/ssw/ssw.h delete mode 100644 src/aig/ssw/sswAig.c delete mode 100644 src/aig/ssw/sswBmc.c delete mode 100644 src/aig/ssw/sswClass.c delete mode 100644 src/aig/ssw/sswCnf.c delete mode 100644 src/aig/ssw/sswConstr.c delete mode 100644 src/aig/ssw/sswCore.c delete mode 100644 src/aig/ssw/sswDyn.c delete mode 100644 src/aig/ssw/sswFilter.c delete mode 100644 src/aig/ssw/sswInt.h delete mode 100644 src/aig/ssw/sswIslands.c delete mode 100644 src/aig/ssw/sswLcorr.c delete mode 100644 src/aig/ssw/sswMan.c delete mode 100644 src/aig/ssw/sswPairs.c delete mode 100644 src/aig/ssw/sswPart.c delete mode 100644 src/aig/ssw/sswRarity.c delete mode 100644 src/aig/ssw/sswRarity2.c delete mode 100644 src/aig/ssw/sswSat.c delete mode 100644 src/aig/ssw/sswSemi.c delete mode 100644 src/aig/ssw/sswSim.c delete mode 100644 src/aig/ssw/sswSimSat.c delete mode 100644 src/aig/ssw/sswSweep.c delete mode 100644 src/aig/ssw/sswUnique.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/abci/abcAbc8.c create mode 100644 src/base/abci/fahout_cut.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 create mode 100644 src/bool/bdc/bdc.h create mode 100644 src/bool/bdc/bdcCore.c create mode 100644 src/bool/bdc/bdcDec.c create mode 100644 src/bool/bdc/bdcInt.h create mode 100644 src/bool/bdc/bdcSpfd.c create mode 100644 src/bool/bdc/bdcTable.c create mode 100644 src/bool/bdc/bdc_.c create mode 100644 src/bool/bdc/module.make create mode 100644 src/bool/dec/dec.h create mode 100644 src/bool/dec/decAbc.c create mode 100644 src/bool/dec/decFactor.c create mode 100644 src/bool/dec/decMan.c create mode 100644 src/bool/dec/decPrint.c create mode 100644 src/bool/dec/decUtil.c create mode 100644 src/bool/dec/module.make create mode 100644 src/bool/deco/deco.h create mode 100644 src/bool/deco/module.make create mode 100644 src/bool/kit/cloud.c create mode 100644 src/bool/kit/cloud.h create mode 100644 src/bool/kit/kit.h create mode 100644 src/bool/kit/kitAig.c create mode 100644 src/bool/kit/kitBdd.c create mode 100644 src/bool/kit/kitCloud.c create mode 100644 src/bool/kit/kitDec.c create mode 100644 src/bool/kit/kitDsd.c create mode 100644 src/bool/kit/kitFactor.c create mode 100644 src/bool/kit/kitGraph.c create mode 100644 src/bool/kit/kitHop.c create mode 100644 src/bool/kit/kitIsop.c create mode 100644 src/bool/kit/kitPerm.c create mode 100644 src/bool/kit/kitPla.c create mode 100644 src/bool/kit/kitSop.c create mode 100644 src/bool/kit/kitTruth.c create mode 100644 src/bool/kit/kit_.c create mode 100644 src/bool/kit/module.make create mode 100644 src/misc/bar/bar.c create mode 100644 src/misc/bar/bar.h create mode 100644 src/misc/bar/module.make create mode 100644 src/misc/bbl/bblif.c create mode 100644 src/misc/bbl/bblif.h create mode 100644 src/misc/bbl/module.make create mode 100644 src/misc/extra/extraBdd.h create mode 100644 src/misc/mem/mem.c create mode 100644 src/misc/mem/mem.h create mode 100644 src/misc/mem/module.make create mode 100644 src/misc/tim/module.make create mode 100644 src/misc/tim/tim.c create mode 100644 src/misc/tim/tim.h create mode 100644 src/opt/cgt/cgt.h create mode 100644 src/opt/cgt/cgtAig.c create mode 100644 src/opt/cgt/cgtCore.c create mode 100644 src/opt/cgt/cgtDecide.c create mode 100644 src/opt/cgt/cgtInt.h create mode 100644 src/opt/cgt/cgtMan.c create mode 100644 src/opt/cgt/cgtSat.c create mode 100644 src/opt/cgt/module.make create mode 100644 src/opt/csw/csw.h create mode 100644 src/opt/csw/cswCore.c create mode 100644 src/opt/csw/cswCut.c create mode 100644 src/opt/csw/cswInt.h create mode 100644 src/opt/csw/cswMan.c create mode 100644 src/opt/csw/cswTable.c create mode 100644 src/opt/csw/csw_.c create mode 100644 src/opt/csw/module.make create mode 100644 src/opt/dar/dar.h create mode 100644 src/opt/dar/darBalance.c create mode 100644 src/opt/dar/darCore.c create mode 100644 src/opt/dar/darCut.c create mode 100644 src/opt/dar/darData.c create mode 100644 src/opt/dar/darInt.h create mode 100644 src/opt/dar/darLib.c create mode 100644 src/opt/dar/darMan.c create mode 100644 src/opt/dar/darPrec.c create mode 100644 src/opt/dar/darRefact.c create mode 100644 src/opt/dar/darResub.c create mode 100644 src/opt/dar/darScript.c create mode 100644 src/opt/dar/dar_.c create mode 100644 src/opt/dar/module.make delete mode 100644 src/opt/dec/dec.h delete mode 100644 src/opt/dec/decAbc.c delete mode 100644 src/opt/dec/decFactor.c delete mode 100644 src/opt/dec/decMan.c delete mode 100644 src/opt/dec/decPrint.c delete mode 100644 src/opt/dec/decUtil.c delete mode 100644 src/opt/dec/module.make delete mode 100644 src/opt/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 create mode 100644 src/opt/fsim/fsim.h create mode 100644 src/opt/fsim/fsimCore.c create mode 100644 src/opt/fsim/fsimFront.c create mode 100644 src/opt/fsim/fsimInt.h create mode 100644 src/opt/fsim/fsimMan.c create mode 100644 src/opt/fsim/fsimSim.c create mode 100644 src/opt/fsim/fsimSwitch.c create mode 100644 src/opt/fsim/fsimTsim.c create mode 100644 src/opt/fsim/module.make create mode 100644 src/opt/nwk/module.make create mode 100644 src/opt/nwk/ntlnwk.h create mode 100644 src/opt/nwk/nwk.h create mode 100644 src/opt/nwk/nwkAig.c create mode 100644 src/opt/nwk/nwkBidec.c create mode 100644 src/opt/nwk/nwkCheck.c create mode 100644 src/opt/nwk/nwkDfs.c create mode 100644 src/opt/nwk/nwkFanio.c create mode 100644 src/opt/nwk/nwkFlow.c create mode 100644 src/opt/nwk/nwkFlow_depth.c create mode 100644 src/opt/nwk/nwkMan.c create mode 100644 src/opt/nwk/nwkMap.c create mode 100644 src/opt/nwk/nwkMerge.c create mode 100644 src/opt/nwk/nwkMerge.h create mode 100644 src/opt/nwk/nwkObj.c create mode 100644 src/opt/nwk/nwkSpeedup.c create mode 100644 src/opt/nwk/nwkStrash.c create mode 100644 src/opt/nwk/nwkTiming.c create mode 100644 src/opt/nwk/nwkUtil.c create mode 100644 src/opt/nwk/nwk_.c create mode 100644 src/opt/rwt/module.make create mode 100644 src/opt/rwt/rwt.h create mode 100644 src/opt/rwt/rwtDec.c create mode 100644 src/opt/rwt/rwtMan.c create mode 100644 src/opt/rwt/rwtUtil.c create mode 100644 src/proof/bbr/bbr.h create mode 100644 src/proof/bbr/bbrCex.c create mode 100644 src/proof/bbr/bbrImage.c create mode 100644 src/proof/bbr/bbrNtbdd.c create mode 100644 src/proof/bbr/bbrReach.c create mode 100644 src/proof/bbr/bbr_.c create mode 100644 src/proof/bbr/module.make create mode 100644 src/proof/cec/cec.c create mode 100644 src/proof/cec/cec.h create mode 100644 src/proof/cec/cecCec.c create mode 100644 src/proof/cec/cecChoice.c create mode 100644 src/proof/cec/cecClass.c create mode 100644 src/proof/cec/cecCore.c create mode 100644 src/proof/cec/cecCorr.c create mode 100644 src/proof/cec/cecCorr_updated.c create mode 100644 src/proof/cec/cecInt.h create mode 100644 src/proof/cec/cecIso.c create mode 100644 src/proof/cec/cecMan.c create mode 100644 src/proof/cec/cecPat.c create mode 100644 src/proof/cec/cecSeq.c create mode 100644 src/proof/cec/cecSim.c create mode 100644 src/proof/cec/cecSolve.c create mode 100644 src/proof/cec/cecSweep.c create mode 100644 src/proof/cec/cecSynth.c create mode 100644 src/proof/cec/module.make create mode 100644 src/proof/dch/dch.h create mode 100644 src/proof/dch/dchAig.c create mode 100644 src/proof/dch/dchChoice.c create mode 100644 src/proof/dch/dchClass.c create mode 100644 src/proof/dch/dchCnf.c create mode 100644 src/proof/dch/dchCore.c create mode 100644 src/proof/dch/dchInt.h create mode 100644 src/proof/dch/dchMan.c create mode 100644 src/proof/dch/dchSat.c create mode 100644 src/proof/dch/dchSim.c create mode 100644 src/proof/dch/dchSimSat.c create mode 100644 src/proof/dch/dchSweep.c create mode 100644 src/proof/dch/module.make create mode 100644 src/proof/fra/fra.h create mode 100644 src/proof/fra/fraBmc.c create mode 100644 src/proof/fra/fraCec.c create mode 100644 src/proof/fra/fraClass.c create mode 100644 src/proof/fra/fraClau.c create mode 100644 src/proof/fra/fraClaus.c create mode 100644 src/proof/fra/fraCnf.c create mode 100644 src/proof/fra/fraCore.c create mode 100644 src/proof/fra/fraHot.c create mode 100644 src/proof/fra/fraImp.c create mode 100644 src/proof/fra/fraInd.c create mode 100644 src/proof/fra/fraIndVer.c create mode 100644 src/proof/fra/fraLcr.c create mode 100644 src/proof/fra/fraMan.c create mode 100644 src/proof/fra/fraPart.c create mode 100644 src/proof/fra/fraSat.c create mode 100644 src/proof/fra/fraSec.c create mode 100644 src/proof/fra/fraSim.c create mode 100644 src/proof/fra/fra_.c create mode 100644 src/proof/fra/module.make create mode 100644 src/proof/fraig/fraig.h create mode 100644 src/proof/fraig/fraigApi.c create mode 100644 src/proof/fraig/fraigCanon.c create mode 100644 src/proof/fraig/fraigChoice.c create mode 100644 src/proof/fraig/fraigFanout.c create mode 100644 src/proof/fraig/fraigFeed.c create mode 100644 src/proof/fraig/fraigInt.h create mode 100644 src/proof/fraig/fraigMan.c create mode 100644 src/proof/fraig/fraigMem.c create mode 100644 src/proof/fraig/fraigNode.c create mode 100644 src/proof/fraig/fraigPrime.c create mode 100644 src/proof/fraig/fraigSat.c create mode 100644 src/proof/fraig/fraigTable.c create mode 100644 src/proof/fraig/fraigUtil.c create mode 100644 src/proof/fraig/fraigVec.c create mode 100644 src/proof/fraig/module.make create mode 100644 src/proof/int/int.h create mode 100644 src/proof/int/intCheck.c create mode 100644 src/proof/int/intContain.c create mode 100644 src/proof/int/intCore.c create mode 100644 src/proof/int/intCtrex.c create mode 100644 src/proof/int/intDup.c create mode 100644 src/proof/int/intFrames.c create mode 100644 src/proof/int/intInt.h create mode 100644 src/proof/int/intInter.c create mode 100644 src/proof/int/intM114.c create mode 100644 src/proof/int/intM114p.c create mode 100644 src/proof/int/intMan.c create mode 100644 src/proof/int/intUtil.c create mode 100644 src/proof/int/module.make create mode 100644 src/proof/live/liveness.c create mode 100644 src/proof/live/liveness_sim.c create mode 100644 src/proof/live/ltl_parser.c create mode 100644 src/proof/live/module.make create mode 100644 src/proof/llb/llb.c create mode 100644 src/proof/llb/llb.h create mode 100644 src/proof/llb/llb1Cluster.c create mode 100644 src/proof/llb/llb1Constr.c create mode 100644 src/proof/llb/llb1Core.c create mode 100644 src/proof/llb/llb1Group.c create mode 100644 src/proof/llb/llb1Hint.c create mode 100644 src/proof/llb/llb1Man.c create mode 100644 src/proof/llb/llb1Matrix.c create mode 100644 src/proof/llb/llb1Pivot.c create mode 100644 src/proof/llb/llb1Reach.c create mode 100644 src/proof/llb/llb1Sched.c create mode 100644 src/proof/llb/llb2Bad.c create mode 100644 src/proof/llb/llb2Core.c create mode 100644 src/proof/llb/llb2Driver.c create mode 100644 src/proof/llb/llb2Dump.c create mode 100644 src/proof/llb/llb2Flow.c create mode 100644 src/proof/llb/llb2Image.c create mode 100644 src/proof/llb/llb3Image.c create mode 100644 src/proof/llb/llb3Nonlin.c create mode 100644 src/proof/llb/llb4Cex.c create mode 100644 src/proof/llb/llb4Cluster.c create mode 100644 src/proof/llb/llb4Image.c create mode 100644 src/proof/llb/llb4Map.c create mode 100644 src/proof/llb/llb4Nonlin.c create mode 100644 src/proof/llb/llb4Sweep.c create mode 100644 src/proof/llb/llbInt.h create mode 100644 src/proof/llb/module.make create mode 100644 src/proof/pdr/module.make create mode 100644 src/proof/pdr/pdr.c create mode 100644 src/proof/pdr/pdr.h create mode 100644 src/proof/pdr/pdrClass.c create mode 100644 src/proof/pdr/pdrCnf.c create mode 100644 src/proof/pdr/pdrCore.c create mode 100644 src/proof/pdr/pdrInt.h create mode 100644 src/proof/pdr/pdrInv.c create mode 100644 src/proof/pdr/pdrMan.c create mode 100644 src/proof/pdr/pdrSat.c create mode 100644 src/proof/pdr/pdrTsim.c create mode 100644 src/proof/pdr/pdrUtil.c create mode 100644 src/proof/ssw/module.make create mode 100644 src/proof/ssw/ssw.h create mode 100644 src/proof/ssw/sswAig.c create mode 100644 src/proof/ssw/sswBmc.c create mode 100644 src/proof/ssw/sswClass.c create mode 100644 src/proof/ssw/sswCnf.c create mode 100644 src/proof/ssw/sswConstr.c create mode 100644 src/proof/ssw/sswCore.c create mode 100644 src/proof/ssw/sswDyn.c create mode 100644 src/proof/ssw/sswFilter.c create mode 100644 src/proof/ssw/sswInt.h create mode 100644 src/proof/ssw/sswIslands.c create mode 100644 src/proof/ssw/sswLcorr.c create mode 100644 src/proof/ssw/sswMan.c create mode 100644 src/proof/ssw/sswPairs.c create mode 100644 src/proof/ssw/sswPart.c create mode 100644 src/proof/ssw/sswRarity.c create mode 100644 src/proof/ssw/sswRarity2.c create mode 100644 src/proof/ssw/sswSat.c create mode 100644 src/proof/ssw/sswSemi.c create mode 100644 src/proof/ssw/sswSim.c create mode 100644 src/proof/ssw/sswSimSat.c create mode 100644 src/proof/ssw/sswSweep.c create mode 100644 src/proof/ssw/sswUnique.c create mode 100644 src/sat/cnf/cnf.h create mode 100644 src/sat/cnf/cnfCore.c create mode 100644 src/sat/cnf/cnfCut.c create mode 100644 src/sat/cnf/cnfData.c create mode 100644 src/sat/cnf/cnfFast.c create mode 100644 src/sat/cnf/cnfMan.c create mode 100644 src/sat/cnf/cnfMap.c create mode 100644 src/sat/cnf/cnfPost.c create mode 100644 src/sat/cnf/cnfUtil.c create mode 100644 src/sat/cnf/cnfWrite.c create mode 100644 src/sat/cnf/cnf_.c create mode 100644 src/sat/cnf/module.make delete mode 100644 src/sat/fraig/fraig.h delete mode 100644 src/sat/fraig/fraigApi.c delete mode 100644 src/sat/fraig/fraigCanon.c delete mode 100644 src/sat/fraig/fraigChoice.c delete mode 100644 src/sat/fraig/fraigFanout.c delete mode 100644 src/sat/fraig/fraigFeed.c delete mode 100644 src/sat/fraig/fraigInt.h delete mode 100644 src/sat/fraig/fraigMan.c delete mode 100644 src/sat/fraig/fraigMem.c delete mode 100644 src/sat/fraig/fraigNode.c delete mode 100644 src/sat/fraig/fraigPrime.c delete mode 100644 src/sat/fraig/fraigSat.c delete mode 100644 src/sat/fraig/fraigTable.c delete mode 100644 src/sat/fraig/fraigUtil.c delete mode 100644 src/sat/fraig/fraigVec.c delete mode 100644 src/sat/fraig/module.make delete mode 100644 src/sat/pdr/module.make delete mode 100644 src/sat/pdr/pdr.c delete mode 100644 src/sat/pdr/pdr.h delete mode 100644 src/sat/pdr/pdrClass.c delete mode 100644 src/sat/pdr/pdrCnf.c delete mode 100644 src/sat/pdr/pdrCore.c delete mode 100644 src/sat/pdr/pdrInt.h delete mode 100644 src/sat/pdr/pdrInv.c delete mode 100644 src/sat/pdr/pdrMan.c delete mode 100644 src/sat/pdr/pdrSat.c delete mode 100644 src/sat/pdr/pdrTsim.c delete mode 100644 src/sat/pdr/pdrUtil.c diff --git a/Makefile b/Makefile index 727d95f0..c5d6989c 100644 --- a/Makefile +++ b/Makefile @@ -8,41 +8,35 @@ PROG := abc MODULES := \ $(wildcard src/ext) src/misc/ext \ - src/base/abc src/base/abci src/base/cmd \ - src/base/io src/base/main src/base/ver src/base/test \ - src/bdd/cudd src/bdd/dsd src/bdd/epd src/bdd/mtr \ - src/bdd/parse src/bdd/reo src/bdd/cas \ - src/map/fpga src/map/mapper src/map/mio src/map/super \ - src/map/if src/map/amap src/map/cov \ - src/misc/extra src/misc/mvc src/misc/st src/misc/util \ - src/misc/nm src/misc/vec src/misc/hash \ - src/misc/bzlib src/misc/zlib \ - src/opt/cut src/opt/dec src/opt/fxu src/opt/rwr src/opt/mfs \ - src/opt/sim src/opt/ret src/opt/res src/opt/lpk \ - src/sat/bsat src/sat/csat src/sat/msat src/sat/fraig \ - src/sat/psat src/sat/pdr \ - 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/nwk \ - src/aig/mfx src/aig/tim src/aig/saig src/aig/bbr \ - src/aig/int src/aig/dch src/aig/ssw src/aig/cgt \ - src/aig/cec src/aig/gia src/aig/bbl src/aig/live \ - src/aig/llb \ + src/base/abc src/base/abci src/base/cmd src/base/io \ + src/base/main src/base/ver src/base/test \ + src/bdd/cudd src/bdd/dsd src/bdd/epd src/bdd/mtr src/bdd/parse \ + src/bdd/reo src/bdd/cas \ + src/map/fpga src/map/mapper src/map/mio src/map/super src/map/if \ + src/map/amap src/map/cov \ + src/misc/extra src/misc/mvc src/misc/st src/misc/util src/misc/nm \ + src/misc/vec src/misc/hash src/misc/tim src/misc/bzlib src/misc/zlib \ + src/misc/mem src/misc/bar src/misc/bbl \ + src/opt/cut src/opt/fxu src/opt/rwr src/opt/mfs src/opt/sim \ + src/opt/ret src/opt/res src/opt/lpk src/opt/nwk src/opt/rwt \ + src/opt/cgt src/opt/csw src/opt/dar \ + src/sat/bsat src/sat/csat src/sat/msat src/sat/psat src/sat/cnf \ + src/bool/bdc src/bool/deco src/bool/dec src/bool/kit \ + src/proof/pdr src/proof/int src/proof/bbr src/proof/llb src/proof/live \ + src/proof/cec src/proof/dch src/proof/fraig src/proof/fra src/proof/ssw \ + src/aig/aig src/aig/saig src/aig/gia src/aig/ioa src/aig/ivy src/aig/hop \ src/python all: $(PROG) default: $(PROG) -# Please note that to compile on 32-bit Linux the following optflags are required: -# -DLIN -DSIZEOF_VOID_P=4 -DSIZEOF_LONG=4 +arch_flags : arch_flags.c + gcc arch_flags.c -o arch_flags -#OPTFLAGS := -DNDEBUG -O3 -DLIN -#OPTFLAGS := -DNDEBUG -O3 -DLIN64 -#OPTFLAGS := -g -O -DLIN -m32 -OPTFLAGS := -g -O -DLIN64 -DSIZEOF_VOID_P=8 -DSIZEOF_LONG=8 -DSIZEOF_INT=4 -DABC_NAMESPACE=xxx +ARCHFLAGS := $(shell gcc arch_flags.c -o arch_flags && ./arch_flags) +OPTFLAGS := -g -O #-DABC_NAMESPACE=xxx -CFLAGS += -Wall -Wno-unused-function $(OPTFLAGS) $(patsubst %, -I%, $(MODULES)) +CFLAGS += -Wall -Wno-unused-function $(OPTFLAGS) $(ARCHFLAGS) -I$(PWD) CXXFLAGS += $(CFLAGS) #LIBS := -m32 -ldl -rdynamic -lreadline -ltermcap diff --git a/abcexe.dsp b/abcexe.dsp index 58aa7c14..ad15afa1 100644 --- a/abcexe.dsp +++ b/abcexe.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 /MD /W3 /GX /O2 /I "src/ext/ext" /I "src/misc/ext" /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/cov" /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/misc/bzlib" /I "src/misc/zlib" /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/sat/nsat" /I "src/sat/psat" /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/nwk" /I "src/aig/tim" /I "src/opt/mfs" /I "src/aig/mfx" /I "src/aig/saig" /I "src/aig/bbr" /I "src/aig/int" /I "src/aig/dch" /I "src/aig/ssw" /I "src/sat/lsat" /I "src/aig/cec" /I "src/aig/cgt" /I "src/aig/sec" /I "src/map/amap" /I "src/aig/fsim" /I "src/aig/gia" /I "src/aig/bbl" /I "src/aig/llb" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D ABC_DLL=ABC_DLLEXPORT /D "_CRT_SECURE_NO_DEPRECATE" /FR /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "C:/_projects/abc_niklas/" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D ABC_DLL=ABC_DLLEXPORT /D "_CRT_SECURE_NO_DEPRECATE" /FR /YX /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -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 /MDd /W3 /Gm /GX /ZI /Od /I "src/ext/ext" /I "src/misc/ext" /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/cov" /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/misc/bzlib" /I "src/misc/zlib" /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/sat/nsat" /I "src/sat/psat" /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/nwk" /I "src/aig/tim" /I "src/opt/mfs" /I "src/aig/mfx" /I "src/aig/saig" /I "src/aig/bbr" /I "src/aig/int" /I "src/aig/dch" /I "src/aig/ssw" /I "src/sat/lsat" /I "src/aig/cec" /I "src/aig/cgt" /I "src/aig/sec" /I "src/map/amap" /I "src/aig/fsim" /I "src/aig/gia" /I "src/aig/bbl" /I "src/aig/llb" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D ABC_DLL=ABC_DLLEXPORT /D "_CRT_SECURE_NO_DEPRECATE" /FR /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "C:/_projects/abc_niklas/" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D ABC_DLL=ABC_DLLEXPORT /D "_CRT_SECURE_NO_DEPRECATE" /FR /YX /FD /GZ /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe diff --git a/abclib.dsp b/abclib.dsp index 064206a3..41b1c77d 100644 --- a/abclib.dsp +++ b/abclib.dsp @@ -41,7 +41,7 @@ RSC=rc.exe # PROP Intermediate_Dir "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 /MD /W3 /GX /O2 /I "src/sat/pdr" /I "src/ext/ext" /I "src/misc/ext" /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/cov" /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/misc/bzlib" /I "src/misc/zlib" /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/sat/nsat" /I "src/sat/psat" /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/nwk" /I "src/aig/tim" /I "src/opt/mfs" /I "src/aig/mfx" /I "src/aig/saig" /I "src/aig/bbr" /I "src/aig/int" /I "src/aig/dch" /I "src/aig/ssw" /I "src/sat/lsat" /I "src/aig/cec" /I "src/aig/cgt" /I "src/aig/sec" /I "src/map/amap" /I "src/aig/fsim" /I "src/aig/gia" /I "src/aig/bbl" /I "src/aig/llb" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D ABC_DLL=ABC_DLLEXPORT /D "_CRT_SECURE_NO_DEPRECATE" /FR /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "C:/_projects/abc_niklas/" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D ABC_DLL=ABC_DLLEXPORT /D "_CRT_SECURE_NO_DEPRECATE" /FR /YX /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -64,7 +64,7 @@ LIB32=link.exe -lib # PROP Intermediate_Dir "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 /MDd /W3 /Gm /GX /ZI /Od /I "src/sat/pdr" /I "src/ext/ext" /I "src/misc/ext" /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/cov" /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/misc/bzlib" /I "src/misc/zlib" /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/sat/nsat" /I "src/sat/psat" /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/nwk" /I "src/aig/tim" /I "src/opt/mfs" /I "src/aig/mfx" /I "src/aig/saig" /I "src/aig/bbr" /I "src/aig/int" /I "src/aig/dch" /I "src/aig/ssw" /I "src/sat/lsat" /I "src/aig/cec" /I "src/aig/cgt" /I "src/aig/sec" /I "src/map/amap" /I "src/aig/fsim" /I "src/aig/gia" /I "src/aig/bbl" /I "src/aig/llb" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D ABC_DLL=ABC_DLLEXPORT /D "_CRT_SECURE_NO_DEPRECATE" /FR /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "C:/_projects/abc_niklas/" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D ABC_DLL=ABC_DLLEXPORT /D "_CRT_SECURE_NO_DEPRECATE" /FR /YX /FD /GZ /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe @@ -187,10 +187,6 @@ SOURCE=.\src\base\abci\abc.c # End Source File # Begin Source File -SOURCE=.\src\base\abci\abcAbc8.c -# End Source File -# Begin Source File - SOURCE=.\src\base\abci\abcAttach.c # End Source File # Begin Source File @@ -1174,70 +1170,6 @@ SOURCE=.\src\sat\msat\msatSort.c 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 "" @@ -1362,48 +1294,48 @@ SOURCE=.\src\sat\psat\m114p_types.h SOURCE=.\src\sat\lsat\solver.h # End Source File # End Group -# Begin Group "pdr" +# Begin Group "cnf" # PROP Default_Filter "" # Begin Source File -SOURCE=.\src\sat\pdr\pdr.h +SOURCE=.\src\sat\cnf\cnf.h # End Source File # Begin Source File -SOURCE=.\src\sat\pdr\pdrClass.c +SOURCE=.\src\sat\cnf\cnfCore.c # End Source File # Begin Source File -SOURCE=.\src\sat\pdr\pdrCnf.c +SOURCE=.\src\sat\cnf\cnfCut.c # End Source File # Begin Source File -SOURCE=.\src\sat\pdr\pdrCore.c +SOURCE=.\src\sat\cnf\cnfData.c # End Source File # Begin Source File -SOURCE=.\src\sat\pdr\pdrInt.h +SOURCE=.\src\sat\cnf\cnfFast.c # End Source File # Begin Source File -SOURCE=.\src\sat\pdr\pdrInv.c +SOURCE=.\src\sat\cnf\cnfMan.c # End Source File # Begin Source File -SOURCE=.\src\sat\pdr\pdrMan.c +SOURCE=.\src\sat\cnf\cnfMap.c # End Source File # Begin Source File -SOURCE=.\src\sat\pdr\pdrSat.c +SOURCE=.\src\sat\cnf\cnfPost.c # End Source File # Begin Source File -SOURCE=.\src\sat\pdr\pdrTsim.c +SOURCE=.\src\sat\cnf\cnfUtil.c # End Source File # Begin Source File -SOURCE=.\src\sat\pdr\pdrUtil.c +SOURCE=.\src\sat\cnf\cnfWrite.c # End Source File # End Group # End Group @@ -1566,34 +1498,6 @@ SOURCE=.\src\opt\cut\cutSeq.c 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 "" @@ -1774,10 +1678,6 @@ SOURCE=.\src\opt\lpk\lpkMux.c SOURCE=.\src\opt\lpk\lpkSets.c # End Source File # End Group -# Begin Group "fret" - -# PROP Default_Filter "" -# End Group # Begin Group "mfs" # PROP Default_Filter "" @@ -1822,6 +1722,214 @@ SOURCE=.\src\opt\mfs\mfsStrash.c SOURCE=.\src\opt\mfs\mfsWin.c # End Source File # End Group +# Begin Group "cgt" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\cgt\cgt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cgt\cgtAig.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cgt\cgtCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cgt\cgtDecide.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cgt\cgtInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cgt\cgtMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cgt\cgtSat.c +# End Source File +# End Group +# Begin Group "csw" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\csw\csw.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\csw\cswCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\csw\cswCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\csw\cswInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\csw\cswMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\csw\cswTable.c +# End Source File +# End Group +# Begin Group "dar" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\dar\dar.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dar\darBalance.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dar\darCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dar\darCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dar\darData.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dar\darInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dar\darLib.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dar\darMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dar\darPrec.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dar\darRefact.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dar\darResub.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dar\darScript.c +# End Source File +# End Group +# Begin Group "rwt" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\rwt\rwt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwt\rwtDec.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwt\rwtMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwt\rwtUtil.c +# End Source File +# End Group +# Begin Group "nwk" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\nwk\ntlnwk.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwk.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwk_.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkAig.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkBidec.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkCheck.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkDfs.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkFanio.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkFlow.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkMap.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkMerge.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkMerge.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkObj.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkSpeedup.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkStrash.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkTiming.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkUtil.c +# End Source File +# End Group # End Group # Begin Group "map" @@ -2227,6 +2335,10 @@ SOURCE=.\src\misc\extra\extra.h # End Source File # Begin Source File +SOURCE=.\src\misc\extra\extraBdd.h +# End Source File +# Begin Source File + SOURCE=.\src\misc\extra\extraBddAuto.c # End Source File # Begin Source File @@ -2399,6 +2511,10 @@ SOURCE=.\src\misc\vec\vecAtt.h # End Source File # Begin Source File +SOURCE=.\src\misc\vec\vecBit.h +# End Source File +# Begin Source File + SOURCE=.\src\misc\vec\vecFlt.h # End Source File # Begin Source File @@ -2467,6 +2583,10 @@ SOURCE=.\src\misc\util\utilSignal.c # End Source File # Begin Source File +SOURCE=.\src\misc\util\utilSignal.h +# End Source File +# Begin Source File + SOURCE=.\src\misc\util\utilSort.c # End Source File # End Group @@ -2658,16 +2778,64 @@ SOURCE=.\src\misc\zlib\zutil.c SOURCE=.\src\misc\zlib\zutil.h # End Source File # End Group -# End Group -# Begin Group "ai" - -# PROP Default_Filter "" -# Begin Group "hop" +# Begin Group "bar" # PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\hop\hop.h +SOURCE=.\src\misc\bar\bar.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\bar\bar.h +# End Source File +# End Group +# Begin Group "bbl" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\bbl\bblif.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\bbl\bblif.h +# End Source File +# End Group +# Begin Group "mem" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\mem\mem.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mem\mem.h +# End Source File +# End Group +# Begin Group "tim" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\tim\tim.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\tim\tim.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 @@ -2806,46 +2974,6 @@ SOURCE=.\src\aig\ivy\ivyTable.c 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 "" @@ -2866,892 +2994,728 @@ SOURCE=.\src\aig\ioa\ioaUtil.c 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\fraClau.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\fra\fraClaus.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\fraHot.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\fraIndVer.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" +# Begin Group "aig" # PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\cnf\cnf.h -# End Source File -# Begin Source File - -SOURCE=.\src\aig\cnf\cnfCore.c +SOURCE=.\src\aig\aig\aig.h # End Source File # Begin Source File -SOURCE=.\src\aig\cnf\cnfCut.c +SOURCE=.\src\aig\aig\aigCanon.c # End Source File # Begin Source File -SOURCE=.\src\aig\cnf\cnfData.c +SOURCE=.\src\aig\aig\aigCheck.c # End Source File # Begin Source File -SOURCE=.\src\aig\cnf\cnfFast.c +SOURCE=.\src\aig\aig\aigCuts.c # End Source File # Begin Source File -SOURCE=.\src\aig\cnf\cnfMan.c +SOURCE=.\src\aig\aig\aigDfs.c # End Source File # Begin Source File -SOURCE=.\src\aig\cnf\cnfMap.c +SOURCE=.\src\aig\aig\aigDoms.c # End Source File # Begin Source File -SOURCE=.\src\aig\cnf\cnfPost.c +SOURCE=.\src\aig\aig\aigDup.c # End Source File # Begin Source File -SOURCE=.\src\aig\cnf\cnfUtil.c +SOURCE=.\src\aig\aig\aigFact.c # End Source File # Begin Source File -SOURCE=.\src\aig\cnf\cnfWrite.c +SOURCE=.\src\aig\aig\aigFanout.c # End Source File -# End Group -# Begin Group "csw" - -# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\csw\csw.h +SOURCE=.\src\aig\aig\aigFrames.c # End Source File # Begin Source File -SOURCE=.\src\aig\csw\cswCore.c +SOURCE=.\src\aig\aig\aigInter.c # End Source File # Begin Source File -SOURCE=.\src\aig\csw\cswCut.c +SOURCE=.\src\aig\aig\aigJust.c # End Source File # Begin Source File -SOURCE=.\src\aig\csw\cswInt.h +SOURCE=.\src\aig\aig\aigMan.c # End Source File # Begin Source File -SOURCE=.\src\aig\csw\cswMan.c +SOURCE=.\src\aig\aig\aigMem.c # End Source File # Begin Source File -SOURCE=.\src\aig\csw\cswTable.c +SOURCE=.\src\aig\aig\aigMffc.c # End Source File -# End Group -# Begin Group "kit" - -# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\kit\cloud.c +SOURCE=.\src\aig\aig\aigObj.c # End Source File # Begin Source File -SOURCE=.\src\aig\kit\cloud.h +SOURCE=.\src\aig\aig\aigOper.c # End Source File # Begin Source File -SOURCE=.\src\aig\kit\kit.h +SOURCE=.\src\aig\aig\aigOrder.c # End Source File # Begin Source File -SOURCE=.\src\aig\kit\kitAig.c +SOURCE=.\src\aig\aig\aigPack.c # End Source File # Begin Source File -SOURCE=.\src\aig\kit\kitBdd.c +SOURCE=.\src\aig\aig\aigPart.c # End Source File # Begin Source File -SOURCE=.\src\aig\kit\kitCloud.c +SOURCE=.\src\aig\aig\aigPartReg.c # End Source File # Begin Source File -SOURCE=.\src\aig\kit\kitDsd.c +SOURCE=.\src\aig\aig\aigPartSat.c # End Source File # Begin Source File -SOURCE=.\src\aig\kit\kitFactor.c +SOURCE=.\src\aig\aig\aigRepar.c # End Source File # Begin Source File -SOURCE=.\src\aig\kit\kitGraph.c +SOURCE=.\src\aig\aig\aigRepr.c # End Source File # Begin Source File -SOURCE=.\src\aig\kit\kitHop.c +SOURCE=.\src\aig\aig\aigRet.c # End Source File # Begin Source File -SOURCE=.\src\aig\kit\kitIsop.c +SOURCE=.\src\aig\aig\aigRetF.c # End Source File # Begin Source File -SOURCE=.\src\aig\kit\kitPerm.c +SOURCE=.\src\aig\aig\aigScl.c # End Source File # Begin Source File -SOURCE=.\src\aig\kit\kitPla.c +SOURCE=.\src\aig\aig\aigShow.c # End Source File # Begin Source File -SOURCE=.\src\aig\kit\kitSop.c +SOURCE=.\src\aig\aig\aigSplit.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 +SOURCE=.\src\aig\aig\aigTable.c # End Source File # Begin Source File -SOURCE=.\src\aig\bdc\bdcCore.c +SOURCE=.\src\aig\aig\aigTiming.c # End Source File # Begin Source File -SOURCE=.\src\aig\bdc\bdcDec.c +SOURCE=.\src\aig\aig\aigTruth.c # End Source File # Begin Source File -SOURCE=.\src\aig\bdc\bdcInt.h +SOURCE=.\src\aig\aig\aigTsim.c # End Source File # Begin Source File -SOURCE=.\src\aig\bdc\bdcSpfd.c +SOURCE=.\src\aig\aig\aigUtil.c # End Source File # Begin Source File -SOURCE=.\src\aig\bdc\bdcTable.c +SOURCE=.\src\aig\aig\aigWin.c # End Source File # End Group -# Begin Group "aig" +# Begin Group "saig" # PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\aig\aig.h -# End Source File -# Begin Source File - -SOURCE=.\src\aig\aig\aigCanon.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\aig\aigCheck.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\aig\aigCuts.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\aig\aigDfs.c +SOURCE=.\src\aig\saig\saig.h # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigDoms.c +SOURCE=.\src\aig\saig\saigAbs.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigDup.c +SOURCE=.\src\aig\saig\saigAbsCba.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigFact.c +SOURCE=.\src\aig\saig\saigAbsPba.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigFanout.c +SOURCE=.\src\aig\saig\saigAbsStart.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigFrames.c +SOURCE=.\src\aig\saig\saigAbsVfa.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigInter.c +SOURCE=.\src\aig\saig\saigBmc.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigJust.c +SOURCE=.\src\aig\saig\saigBmc2.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigMan.c +SOURCE=.\src\aig\saig\saigBmc3.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigMem.c +SOURCE=.\src\aig\saig\saigCexMin.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigMffc.c +SOURCE=.\src\aig\saig\saigCone.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigObj.c +SOURCE=.\src\aig\saig\saigConstr.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigOper.c +SOURCE=.\src\aig\saig\saigConstr2.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigOrder.c +SOURCE=.\src\aig\saig\saigDup.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigPack.c +SOURCE=.\src\aig\saig\saigGlaCba.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigPart.c +SOURCE=.\src\aig\saig\saigGlaPba.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigPartReg.c +SOURCE=.\src\aig\saig\saigGlaPba2.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigPartSat.c +SOURCE=.\src\aig\saig\saigHaig.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigRepar.c +SOURCE=.\src\aig\saig\saigInd.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigRepr.c +SOURCE=.\src\aig\saig\saigIoa.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigRet.c +SOURCE=.\src\aig\saig\saigMiter.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigRetF.c +SOURCE=.\src\aig\saig\saigOutDec.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigScl.c +SOURCE=.\src\aig\saig\saigPhase.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigShow.c +SOURCE=.\src\aig\saig\saigRefSat.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigSplit.c +SOURCE=.\src\aig\saig\saigRetFwd.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigTable.c +SOURCE=.\src\aig\saig\saigRetMin.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigTiming.c +SOURCE=.\src\aig\saig\saigRetStep.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigTruth.c +SOURCE=.\src\aig\saig\saigScl.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigTsim.c +SOURCE=.\src\aig\saig\saigSimExt.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigUtil.c +SOURCE=.\src\aig\saig\saigSimExt2.c # End Source File # Begin Source File -SOURCE=.\src\aig\aig\aigWin.c +SOURCE=.\src\aig\saig\saigSimFast.c # End Source File -# End Group -# Begin Group "bar" - -# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\bar\bar.c +SOURCE=.\src\aig\saig\saigSimMv.c # End Source File # Begin Source File -SOURCE=.\src\aig\bar\bar.h +SOURCE=.\src\aig\saig\saigSimSeq.c # End Source File -# End Group -# Begin Group "ntl" - -# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\ntl\ntl.h +SOURCE=.\src\aig\saig\saigStrSim.c # End Source File # Begin Source File -SOURCE=.\src\aig\ntl\ntlCheck.c +SOURCE=.\src\aig\saig\saigSwitch.c # End Source File # Begin Source File -SOURCE=.\src\aig\ntl\ntlCore.c +SOURCE=.\src\aig\saig\saigSynch.c # End Source File # Begin Source File -SOURCE=.\src\aig\ntl\ntlEc.c +SOURCE=.\src\aig\saig\saigTempor.c # End Source File # Begin Source File -SOURCE=.\src\aig\ntl\ntlExtract.c +SOURCE=.\src\aig\saig\saigTrans.c # End Source File # Begin Source File -SOURCE=.\src\aig\ntl\ntlFraig.c +SOURCE=.\src\aig\saig\saigWnd.c # End Source File +# End Group +# Begin Group "gia" + +# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\ntl\ntlInsert.c +SOURCE=.\src\aig\gia\gia.c # End Source File # Begin Source File -SOURCE=.\src\aig\ntl\ntlMan.c +SOURCE=.\src\aig\gia\gia.h # End Source File # Begin Source File -SOURCE=.\src\aig\ntl\ntlMap.c +SOURCE=.\src\aig\gia\giaAbs.c # End Source File # Begin Source File -SOURCE=.\src\aig\ntl\ntlNames.c +SOURCE=.\src\aig\gia\giaAbs.h # End Source File # Begin Source File -SOURCE=.\src\aig\ntl\ntlnwk.h +SOURCE=.\src\aig\gia\giaAbsVta.c # End Source File # Begin Source File -SOURCE=.\src\aig\ntl\ntlObj.c +SOURCE=.\src\aig\gia\giaAig.c # End Source File # Begin Source File -SOURCE=.\src\aig\ntl\ntlReadBlif.c +SOURCE=.\src\aig\gia\giaAig.h # End Source File # Begin Source File -SOURCE=.\src\aig\ntl\ntlSweep.c +SOURCE=.\src\aig\gia\giaAiger.c # End Source File # Begin Source File -SOURCE=.\src\aig\ntl\ntlTable.c +SOURCE=.\src\aig\gia\giaBidec.c # End Source File # Begin Source File -SOURCE=.\src\aig\ntl\ntlTime.c +SOURCE=.\src\aig\gia\giaCCof.c # End Source File # Begin Source File -SOURCE=.\src\aig\ntl\ntlUtil.c +SOURCE=.\src\aig\gia\giaCof.c # End Source File # Begin Source File -SOURCE=.\src\aig\ntl\ntlWriteBlif.c +SOURCE=.\src\aig\gia\giaCSat.c # End Source File -# End Group -# Begin Group "tim" - -# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\tim\tim.c +SOURCE=.\src\aig\gia\giaCSatOld.c # End Source File # Begin Source File -SOURCE=.\src\aig\tim\tim.h +SOURCE=.\src\aig\gia\giaCTas.c # End Source File -# End Group -# Begin Group "nwk" - -# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\nwk\nwk.h +SOURCE=.\src\aig\gia\giaDfs.c # End Source File # Begin Source File -SOURCE=.\src\aig\nwk\nwkAig.c +SOURCE=.\src\aig\gia\giaDup.c # End Source File # Begin Source File -SOURCE=.\src\aig\nwk\nwkBidec.c +SOURCE=.\src\aig\gia\giaEmbed.c # End Source File # Begin Source File -SOURCE=.\src\aig\nwk\nwkCheck.c +SOURCE=.\src\aig\gia\giaEnable.c # End Source File # Begin Source File -SOURCE=.\src\aig\nwk\nwkDfs.c +SOURCE=.\src\aig\gia\giaEquiv.c # End Source File # Begin Source File -SOURCE=.\src\aig\nwk\nwkFanio.c +SOURCE=.\src\aig\gia\giaEra.c # End Source File # Begin Source File -SOURCE=.\src\aig\nwk\nwkFlow.c +SOURCE=.\src\aig\gia\giaEra2.c # End Source File # Begin Source File -SOURCE=.\src\aig\nwk\nwkMan.c +SOURCE=.\src\aig\gia\giaFanout.c # End Source File # Begin Source File -SOURCE=.\src\aig\nwk\nwkMap.c +SOURCE=.\src\aig\gia\giaForce.c # End Source File # Begin Source File -SOURCE=.\src\aig\nwk\nwkMerge.c +SOURCE=.\src\aig\gia\giaFrames.c # End Source File # Begin Source File -SOURCE=.\src\aig\nwk\nwkMerge.h +SOURCE=.\src\aig\gia\giaFront.c # End Source File # Begin Source File -SOURCE=.\src\aig\nwk\nwkObj.c +SOURCE=.\src\aig\gia\giaGiarf.c # End Source File # Begin Source File -SOURCE=.\src\aig\nwk\nwkSpeedup.c +SOURCE=.\src\aig\gia\giaGlitch.c # End Source File # Begin Source File -SOURCE=.\src\aig\nwk\nwkStrash.c +SOURCE=.\src\aig\gia\giaHash.c # End Source File # Begin Source File -SOURCE=.\src\aig\nwk\nwkTiming.c +SOURCE=.\src\aig\gia\giaHcd.c # End Source File # Begin Source File -SOURCE=.\src\aig\nwk\nwkUtil.c +SOURCE=.\src\aig\gia\giaIf.c # End Source File -# End Group -# Begin Group "mfx" - -# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\mfx\mfx.h +SOURCE=.\src\aig\gia\giaMan.c # End Source File # Begin Source File -SOURCE=.\src\aig\mfx\mfxCore.c +SOURCE=.\src\aig\gia\giaMem.c # End Source File # Begin Source File -SOURCE=.\src\aig\mfx\mfxDiv.c +SOURCE=.\src\aig\gia\giaPat.c # End Source File # Begin Source File -SOURCE=.\src\aig\mfx\mfxInt.h +SOURCE=.\src\aig\gia\giaReparam.c # End Source File # Begin Source File -SOURCE=.\src\aig\mfx\mfxInter.c +SOURCE=.\src\aig\gia\giaRetime.c # End Source File # Begin Source File -SOURCE=.\src\aig\mfx\mfxMan.c +SOURCE=.\src\aig\gia\giaScl.c # End Source File # Begin Source File -SOURCE=.\src\aig\mfx\mfxResub.c +SOURCE=.\src\aig\gia\giaShrink.c # End Source File # Begin Source File -SOURCE=.\src\aig\mfx\mfxSat.c +SOURCE=.\src\aig\gia\giaSim.c # End Source File # Begin Source File -SOURCE=.\src\aig\mfx\mfxStrash.c +SOURCE=.\src\aig\gia\giaSim2.c # End Source File # Begin Source File -SOURCE=.\src\aig\mfx\mfxWin.c +SOURCE=.\src\aig\gia\giaSort.c # End Source File -# End Group -# Begin Group "bbr" - -# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\bbr\bbr.h +SOURCE=.\src\aig\gia\giaSpeedup.c # End Source File # Begin Source File -SOURCE=.\src\aig\bbr\bbrCex.c +SOURCE=.\src\aig\gia\giaSupMin.c # End Source File # Begin Source File -SOURCE=.\src\aig\bbr\bbrImage.c +SOURCE=.\src\aig\gia\giaSwitch.c # End Source File # Begin Source File -SOURCE=.\src\aig\bbr\bbrNtbdd.c +SOURCE=.\src\aig\gia\giaTsim.c # End Source File # Begin Source File -SOURCE=.\src\aig\bbr\bbrReach.c +SOURCE=.\src\aig\gia\giaUtil.c # End Source File # End Group -# Begin Group "saig" +# End Group +# Begin Group "bool" # PROP Default_Filter "" -# Begin Source File +# Begin Group "bdc" -SOURCE=.\src\aig\saig\saig.h -# End Source File +# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\saig\saigAbs.c +SOURCE=.\src\bool\bdc\bdc.h # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigAbsCba.c +SOURCE=.\src\bool\bdc\bdcCore.c # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigAbsPba.c +SOURCE=.\src\bool\bdc\bdcDec.c # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigAbsStart.c +SOURCE=.\src\bool\bdc\bdcInt.h # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigAbsVfa.c +SOURCE=.\src\bool\bdc\bdcSpfd.c # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigBmc.c +SOURCE=.\src\bool\bdc\bdcTable.c # End Source File +# End Group +# Begin Group "dec" + +# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\saig\saigBmc2.c +SOURCE=.\src\bool\dec\dec.h # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigBmc3.c +SOURCE=.\src\bool\dec\decAbc.c # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigCexMin.c +SOURCE=.\src\bool\dec\decFactor.c # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigCone.c +SOURCE=.\src\bool\dec\decMan.c # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigConstr.c +SOURCE=.\src\bool\dec\decPrint.c # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigConstr2.c +SOURCE=.\src\bool\dec\decUtil.c # End Source File +# End Group +# Begin Group "deco" + +# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\saig\saigDup.c +SOURCE=.\src\bool\deco\deco.h # End Source File +# End Group +# Begin Group "kit" + +# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\saig\saigGlaCba.c +SOURCE=.\src\bool\kit\cloud.c # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigGlaPba.c +SOURCE=.\src\bool\kit\cloud.h # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigGlaPba2.c +SOURCE=.\src\bool\kit\kit.h # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigHaig.c +SOURCE=.\src\bool\kit\kit_.c # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigInd.c +SOURCE=.\src\bool\kit\kitAig.c # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigIoa.c +SOURCE=.\src\bool\kit\kitBdd.c # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigMiter.c +SOURCE=.\src\bool\kit\kitCloud.c # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigOutDec.c +SOURCE=.\src\bool\kit\kitDec.c # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigPhase.c +SOURCE=.\src\bool\kit\kitDsd.c # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigRefSat.c +SOURCE=.\src\bool\kit\kitFactor.c # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigRetFwd.c +SOURCE=.\src\bool\kit\kitGraph.c # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigRetMin.c +SOURCE=.\src\bool\kit\kitHop.c # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigRetStep.c +SOURCE=.\src\bool\kit\kitIsop.c # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigScl.c +SOURCE=.\src\bool\kit\kitPerm.c # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigSimExt.c +SOURCE=.\src\bool\kit\kitPla.c # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigSimExt2.c +SOURCE=.\src\bool\kit\kitSop.c # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigSimFast.c +SOURCE=.\src\bool\kit\kitTruth.c # End Source File +# End Group +# End Group +# Begin Group "prove" + +# PROP Default_Filter "" +# Begin Group "bbr" + +# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\saig\saigSimMv.c +SOURCE=.\src\proof\bbr\bbr.h # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigSimSeq.c +SOURCE=.\src\proof\bbr\bbrCex.c # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigStrSim.c +SOURCE=.\src\proof\bbr\bbrImage.c # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigSwitch.c +SOURCE=.\src\proof\bbr\bbrNtbdd.c # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigSynch.c +SOURCE=.\src\proof\bbr\bbrReach.c # End Source File +# End Group +# Begin Group "cec" + +# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\saig\saigTempor.c +SOURCE=.\src\proof\cec\cec.c # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigTrans.c +SOURCE=.\src\proof\cec\cec.h # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigWnd.c +SOURCE=.\src\proof\cec\cecCec.c # End Source File -# End Group -# Begin Group "int" - -# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\int\int.h +SOURCE=.\src\proof\cec\cecChoice.c # End Source File # Begin Source File -SOURCE=.\src\aig\int\intCheck.c +SOURCE=.\src\proof\cec\cecClass.c # End Source File # Begin Source File -SOURCE=.\src\aig\int\intContain.c +SOURCE=.\src\proof\cec\cecCore.c # End Source File # Begin Source File -SOURCE=.\src\aig\int\intCore.c +SOURCE=.\src\proof\cec\cecCorr.c # End Source File # Begin Source File -SOURCE=.\src\aig\int\intCtrex.c +SOURCE=.\src\proof\cec\cecInt.h # End Source File # Begin Source File -SOURCE=.\src\aig\int\intDup.c +SOURCE=.\src\proof\cec\cecIso.c # End Source File # Begin Source File -SOURCE=.\src\aig\int\intFrames.c +SOURCE=.\src\proof\cec\cecMan.c # End Source File # Begin Source File -SOURCE=.\src\aig\int\intInt.h +SOURCE=.\src\proof\cec\cecPat.c # End Source File # Begin Source File -SOURCE=.\src\aig\int\intInter.c +SOURCE=.\src\proof\cec\cecSeq.c # End Source File # Begin Source File -SOURCE=.\src\aig\int\intM114.c +SOURCE=.\src\proof\cec\cecSim.c # End Source File # Begin Source File -SOURCE=.\src\aig\int\intM114p.c +SOURCE=.\src\proof\cec\cecSolve.c # End Source File # Begin Source File -SOURCE=.\src\aig\int\intMan.c +SOURCE=.\src\proof\cec\cecSweep.c # End Source File # Begin Source File -SOURCE=.\src\aig\int\intUtil.c +SOURCE=.\src\proof\cec\cecSynth.c # End Source File # End Group # Begin Group "dch" @@ -3759,551 +3723,523 @@ SOURCE=.\src\aig\int\intUtil.c # PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\dch\dch.h +SOURCE=.\src\proof\dch\dch.h # End Source File # Begin Source File -SOURCE=.\src\aig\dch\dchAig.c +SOURCE=.\src\proof\dch\dchAig.c # End Source File # Begin Source File -SOURCE=.\src\aig\dch\dchChoice.c +SOURCE=.\src\proof\dch\dchChoice.c # End Source File # Begin Source File -SOURCE=.\src\aig\dch\dchClass.c +SOURCE=.\src\proof\dch\dchClass.c # End Source File # Begin Source File -SOURCE=.\src\aig\dch\dchCnf.c +SOURCE=.\src\proof\dch\dchCnf.c # End Source File # Begin Source File -SOURCE=.\src\aig\dch\dchCore.c +SOURCE=.\src\proof\dch\dchCore.c # End Source File # Begin Source File -SOURCE=.\src\aig\dch\dchInt.h +SOURCE=.\src\proof\dch\dchInt.h # End Source File # Begin Source File -SOURCE=.\src\aig\dch\dchMan.c +SOURCE=.\src\proof\dch\dchMan.c # End Source File # Begin Source File -SOURCE=.\src\aig\dch\dchSat.c +SOURCE=.\src\proof\dch\dchSat.c # End Source File # Begin Source File -SOURCE=.\src\aig\dch\dchSim.c +SOURCE=.\src\proof\dch\dchSim.c # End Source File # Begin Source File -SOURCE=.\src\aig\dch\dchSimSat.c +SOURCE=.\src\proof\dch\dchSimSat.c # End Source File # Begin Source File -SOURCE=.\src\aig\dch\dchSweep.c +SOURCE=.\src\proof\dch\dchSweep.c # End Source File # End Group -# Begin Group "ssw" +# Begin Group "fra" # PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\ssw\ssw.h -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ssw\sswAig.c +SOURCE=.\src\proof\fra\fra.h # End Source File # Begin Source File -SOURCE=.\src\aig\ssw\sswBmc.c +SOURCE=.\src\proof\fra\fra_.c # End Source File # Begin Source File -SOURCE=.\src\aig\ssw\sswClass.c +SOURCE=.\src\proof\fra\fraBmc.c # End Source File # Begin Source File -SOURCE=.\src\aig\ssw\sswCnf.c +SOURCE=.\src\proof\fra\fraCec.c # End Source File # Begin Source File -SOURCE=.\src\aig\ssw\sswConstr.c +SOURCE=.\src\proof\fra\fraClass.c # End Source File # Begin Source File -SOURCE=.\src\aig\ssw\sswCore.c +SOURCE=.\src\proof\fra\fraClau.c # End Source File # Begin Source File -SOURCE=.\src\aig\ssw\sswDyn.c +SOURCE=.\src\proof\fra\fraClaus.c # End Source File # Begin Source File -SOURCE=.\src\aig\ssw\sswFilter.c +SOURCE=.\src\proof\fra\fraCnf.c # End Source File # Begin Source File -SOURCE=.\src\aig\ssw\sswInt.h +SOURCE=.\src\proof\fra\fraCore.c # End Source File # Begin Source File -SOURCE=.\src\aig\ssw\sswIslands.c +SOURCE=.\src\proof\fra\fraHot.c # End Source File # Begin Source File -SOURCE=.\src\aig\ssw\sswLcorr.c +SOURCE=.\src\proof\fra\fraImp.c # End Source File # Begin Source File -SOURCE=.\src\aig\ssw\sswMan.c +SOURCE=.\src\proof\fra\fraInd.c # End Source File # Begin Source File -SOURCE=.\src\aig\ssw\sswPairs.c +SOURCE=.\src\proof\fra\fraIndVer.c # End Source File # Begin Source File -SOURCE=.\src\aig\ssw\sswPart.c +SOURCE=.\src\proof\fra\fraLcr.c # End Source File # Begin Source File -SOURCE=.\src\aig\ssw\sswRarity.c +SOURCE=.\src\proof\fra\fraMan.c # End Source File # Begin Source File -SOURCE=.\src\aig\ssw\sswSat.c +SOURCE=.\src\proof\fra\fraPart.c # End Source File # Begin Source File -SOURCE=.\src\aig\ssw\sswSemi.c +SOURCE=.\src\proof\fra\fraSat.c # End Source File # Begin Source File -SOURCE=.\src\aig\ssw\sswSim.c +SOURCE=.\src\proof\fra\fraSec.c # End Source File # Begin Source File -SOURCE=.\src\aig\ssw\sswSimSat.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ssw\sswSweep.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ssw\sswUnique.c +SOURCE=.\src\proof\fra\fraSim.c # End Source File # End Group -# Begin Group "cec" +# Begin Group "fraig" # PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\cec\cec.c +SOURCE=.\src\proof\fraig\fraig.h # End Source File # Begin Source File -SOURCE=.\src\aig\cec\cec.h +SOURCE=.\src\proof\fraig\fraigApi.c # End Source File # Begin Source File -SOURCE=.\src\aig\cec\cecCec.c +SOURCE=.\src\proof\fraig\fraigCanon.c # End Source File # Begin Source File -SOURCE=.\src\aig\cec\cecChoice.c +SOURCE=.\src\proof\fraig\fraigChoice.c # End Source File # Begin Source File -SOURCE=.\src\aig\cec\cecClass.c +SOURCE=.\src\proof\fraig\fraigFanout.c # End Source File # Begin Source File -SOURCE=.\src\aig\cec\cecCore.c +SOURCE=.\src\proof\fraig\fraigFeed.c # End Source File # Begin Source File -SOURCE=.\src\aig\cec\cecCorr.c +SOURCE=.\src\proof\fraig\fraigInt.h # End Source File # Begin Source File -SOURCE=.\src\aig\cec\cecInt.h +SOURCE=.\src\proof\fraig\fraigMan.c # End Source File # Begin Source File -SOURCE=.\src\aig\cec\cecIso.c +SOURCE=.\src\proof\fraig\fraigMem.c # End Source File # Begin Source File -SOURCE=.\src\aig\cec\cecMan.c +SOURCE=.\src\proof\fraig\fraigNode.c # End Source File # Begin Source File -SOURCE=.\src\aig\cec\cecPat.c +SOURCE=.\src\proof\fraig\fraigPrime.c # End Source File # Begin Source File -SOURCE=.\src\aig\cec\cecSeq.c +SOURCE=.\src\proof\fraig\fraigSat.c # End Source File # Begin Source File -SOURCE=.\src\aig\cec\cecSim.c +SOURCE=.\src\proof\fraig\fraigTable.c # End Source File # Begin Source File -SOURCE=.\src\aig\cec\cecSolve.c +SOURCE=.\src\proof\fraig\fraigUtil.c # End Source File # Begin Source File -SOURCE=.\src\aig\cec\cecSweep.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\cec\cecSynth.c +SOURCE=.\src\proof\fraig\fraigVec.c # End Source File # End Group -# Begin Group "cgt" +# Begin Group "int" # PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\cgt\cgt.h +SOURCE=.\src\proof\int\int.h # End Source File # Begin Source File -SOURCE=.\src\aig\cgt\cgtAig.c +SOURCE=.\src\proof\int\intCheck.c # End Source File # Begin Source File -SOURCE=.\src\aig\cgt\cgtCore.c +SOURCE=.\src\proof\int\intContain.c # End Source File # Begin Source File -SOURCE=.\src\aig\cgt\cgtDecide.c +SOURCE=.\src\proof\int\intCore.c # End Source File # Begin Source File -SOURCE=.\src\aig\cgt\cgtInt.h +SOURCE=.\src\proof\int\intCtrex.c # End Source File # Begin Source File -SOURCE=.\src\aig\cgt\cgtMan.c +SOURCE=.\src\proof\int\intDup.c # End Source File # Begin Source File -SOURCE=.\src\aig\cgt\cgtSat.c +SOURCE=.\src\proof\int\intFrames.c # End Source File -# End Group -# Begin Group "gia" - -# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\gia\gia.c +SOURCE=.\src\proof\int\intInt.h # End Source File # Begin Source File -SOURCE=.\src\aig\gia\gia.h +SOURCE=.\src\proof\int\intInter.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaAbs.c +SOURCE=.\src\proof\int\intM114.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaAbsVta.c +SOURCE=.\src\proof\int\intM114p.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaAig.c +SOURCE=.\src\proof\int\intMan.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaAig.h +SOURCE=.\src\proof\int\intUtil.c # End Source File -# Begin Source File +# End Group +# Begin Group "live" -SOURCE=.\src\aig\gia\giaAiger.c -# End Source File +# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\gia\giaBidec.c +SOURCE=.\src\proof\live\liveness.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaCCof.c +SOURCE=.\src\proof\live\liveness_sim.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaCof.c +SOURCE=.\src\proof\live\ltl_parser.c # End Source File -# Begin Source File +# End Group +# Begin Group "llb" -SOURCE=.\src\aig\gia\giaCSat.c -# End Source File +# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\gia\giaCSatOld.c +SOURCE=.\src\proof\llb\llb.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaCTas.c +SOURCE=.\src\proof\llb\llb.h # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaDfs.c +SOURCE=.\src\proof\llb\llb1Cluster.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaDup.c +SOURCE=.\src\proof\llb\llb1Constr.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaEmbed.c +SOURCE=.\src\proof\llb\llb1Core.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaEnable.c +SOURCE=.\src\proof\llb\llb1Group.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaEquiv.c +SOURCE=.\src\proof\llb\llb1Hint.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaEra.c +SOURCE=.\src\proof\llb\llb1Man.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaEra2.c +SOURCE=.\src\proof\llb\llb1Matrix.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaFanout.c +SOURCE=.\src\proof\llb\llb1Pivot.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaForce.c +SOURCE=.\src\proof\llb\llb1Reach.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaFrames.c +SOURCE=.\src\proof\llb\llb1Sched.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaFront.c +SOURCE=.\src\proof\llb\llb2Bad.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaGiarf.c +SOURCE=.\src\proof\llb\llb2Core.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaGlitch.c +SOURCE=.\src\proof\llb\llb2Driver.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaHash.c +SOURCE=.\src\proof\llb\llb2Dump.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaHcd.c +SOURCE=.\src\proof\llb\llb2Flow.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaIf.c +SOURCE=.\src\proof\llb\llb2Image.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaMan.c +SOURCE=.\src\proof\llb\llb3Image.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaMem.c +SOURCE=.\src\proof\llb\llb3Nonlin.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaPat.c +SOURCE=.\src\proof\llb\llb4Cex.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaReparam.c +SOURCE=.\src\proof\llb\llb4Cluster.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaRetime.c +SOURCE=.\src\proof\llb\llb4Image.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaScl.c +SOURCE=.\src\proof\llb\llb4Map.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaShrink.c +SOURCE=.\src\proof\llb\llb4Nonlin.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaSim.c +SOURCE=.\src\proof\llb\llb4Sweep.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaSim2.c +SOURCE=.\src\proof\llb\llbInt.h # End Source File +# End Group +# Begin Group "pdr" + +# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\gia\giaSort.c +SOURCE=.\src\proof\pdr\pdr.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaSpeedup.c +SOURCE=.\src\proof\pdr\pdr.h # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaSupMin.c +SOURCE=.\src\proof\pdr\pdrClass.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaSwitch.c +SOURCE=.\src\proof\pdr\pdrCnf.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaTsim.c +SOURCE=.\src\proof\pdr\pdrCore.c # End Source File # Begin Source File -SOURCE=.\src\aig\gia\giaUtil.c +SOURCE=.\src\proof\pdr\pdrInt.h # End Source File -# End Group -# Begin Group "bbl" - -# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\bbl\bblif.c +SOURCE=.\src\proof\pdr\pdrInv.c # End Source File # Begin Source File -SOURCE=.\src\aig\bbl\bblif.h +SOURCE=.\src\proof\pdr\pdrMan.c # End Source File -# End Group -# Begin Group "live" - -# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\live\liveness.c +SOURCE=.\src\proof\pdr\pdrSat.c # End Source File # Begin Source File -SOURCE=.\src\aig\live\liveness_sim.c +SOURCE=.\src\proof\pdr\pdrTsim.c # End Source File # Begin Source File -SOURCE=.\src\aig\live\ltl_parser.c +SOURCE=.\src\proof\pdr\pdrUtil.c # End Source File # End Group -# Begin Group "llb" +# Begin Group "ssw" # PROP Default_Filter "" # Begin Source File -SOURCE=.\src\aig\llb\llb.h -# End Source File -# Begin Source File - -SOURCE=.\src\aig\llb\llb1Cluster.c +SOURCE=.\src\proof\ssw\ssw.h # End Source File # Begin Source File -SOURCE=.\src\aig\llb\llb1Constr.c +SOURCE=.\src\proof\ssw\sswAig.c # End Source File # Begin Source File -SOURCE=.\src\aig\llb\llb1Core.c +SOURCE=.\src\proof\ssw\sswBmc.c # End Source File # Begin Source File -SOURCE=.\src\aig\llb\llb1Group.c +SOURCE=.\src\proof\ssw\sswClass.c # End Source File # Begin Source File -SOURCE=.\src\aig\llb\llb1Hint.c +SOURCE=.\src\proof\ssw\sswCnf.c # End Source File # Begin Source File -SOURCE=.\src\aig\llb\llb1Man.c +SOURCE=.\src\proof\ssw\sswConstr.c # End Source File # Begin Source File -SOURCE=.\src\aig\llb\llb1Matrix.c +SOURCE=.\src\proof\ssw\sswCore.c # End Source File # Begin Source File -SOURCE=.\src\aig\llb\llb1Pivot.c +SOURCE=.\src\proof\ssw\sswDyn.c # End Source File # Begin Source File -SOURCE=.\src\aig\llb\llb1Reach.c +SOURCE=.\src\proof\ssw\sswFilter.c # End Source File # Begin Source File -SOURCE=.\src\aig\llb\llb1Sched.c +SOURCE=.\src\proof\ssw\sswInt.h # End Source File # Begin Source File -SOURCE=.\src\aig\llb\llb2Bad.c +SOURCE=.\src\proof\ssw\sswIslands.c # End Source File # Begin Source File -SOURCE=.\src\aig\llb\llb2Core.c +SOURCE=.\src\proof\ssw\sswLcorr.c # End Source File # Begin Source File -SOURCE=.\src\aig\llb\llb2Driver.c +SOURCE=.\src\proof\ssw\sswMan.c # End Source File # Begin Source File -SOURCE=.\src\aig\llb\llb2Dump.c +SOURCE=.\src\proof\ssw\sswPairs.c # End Source File # Begin Source File -SOURCE=.\src\aig\llb\llb2Flow.c +SOURCE=.\src\proof\ssw\sswPart.c # End Source File # Begin Source File -SOURCE=.\src\aig\llb\llb2Image.c +SOURCE=.\src\proof\ssw\sswRarity.c # End Source File # Begin Source File -SOURCE=.\src\aig\llb\llb3Image.c +SOURCE=.\src\proof\ssw\sswRarity2.c # End Source File # Begin Source File -SOURCE=.\src\aig\llb\llb3Nonlin.c +SOURCE=.\src\proof\ssw\sswSat.c # End Source File # Begin Source File -SOURCE=.\src\aig\llb\llb4Cex.c +SOURCE=.\src\proof\ssw\sswSemi.c # End Source File # Begin Source File -SOURCE=.\src\aig\llb\llb4Image.c +SOURCE=.\src\proof\ssw\sswSim.c # End Source File # Begin Source File -SOURCE=.\src\aig\llb\llb4Nonlin.c +SOURCE=.\src\proof\ssw\sswSimSat.c # End Source File # Begin Source File -SOURCE=.\src\aig\llb\llb4Sweep.c +SOURCE=.\src\proof\ssw\sswSweep.c # End Source File # Begin Source File -SOURCE=.\src\aig\llb\llbInt.h +SOURCE=.\src\proof\ssw\sswUnique.c # End Source File # End Group # End Group diff --git a/arch_flags.c b/arch_flags.c new file mode 100644 index 00000000..a2945ae0 --- /dev/null +++ b/arch_flags.c @@ -0,0 +1,17 @@ +#include + +int main() +{ + if (sizeof(void*) == 8) // Assume 64-bit Linux if pointers are 8 bytes. + printf("-DLIN64 "); + else + printf("-DLIN "); + + printf("-DSIZEOF_VOID_P=%d -DSIZEOF_LONG=%d -DSIZEOF_INT=%d\n", + (int)sizeof(void*), + (int)sizeof(long), + (int)sizeof(int) ); + + + return 0; +} diff --git a/src/aig/aig/aig.h b/src/aig/aig/aig.h index 2ed3c130..ad8ce927 100644 --- a/src/aig/aig/aig.h +++ b/src/aig/aig/aig.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __AIG_H__ -#define __AIG_H__ +#ifndef ABC__aig__aig__aig_h +#define ABC__aig__aig__aig_h //////////////////////////////////////////////////////////////////////// @@ -32,8 +32,8 @@ #include #include -#include "vec.h" -#include "utilCex.h" +#include "src/misc/vec/vec.h" +#include "src/misc/util/utilCex.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// @@ -222,20 +222,6 @@ static inline Aig_Cut_t * Aig_CutNext( Aig_Cut_t * pCut ) { return /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// -static inline int Aig_IntAbs( int n ) { return (n < 0)? -n : n; } -//static inline int Aig_Float2Int( float Val ) { return *((int *)&Val); } -//static inline float Aig_Int2Float( int Num ) { return *((float *)&Num); } -static inline int Aig_Float2Int( float Val ) { union { int x; float y; } v; v.y = Val; return v.x; } -static inline float Aig_Int2Float( int Num ) { union { int x; float y; } v; v.x = Num; return v.y; } -static inline int Aig_Base2Log( unsigned n ) { int r; if ( n < 2 ) return n; for ( r = 0, n--; n; n >>= 1, r++ ); return r; } -static inline int Aig_Base10Log( unsigned n ) { int r; 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(ABC_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 ) { @@ -254,13 +240,6 @@ static inline int Aig_WordFindFirstBit( unsigned uWord ) return -1; } -static inline int Aig_Var2Lit( int Var, int fCompl ) { return Var + Var + fCompl; } -static inline int Aig_Lit2Var( int Lit ) { return Lit >> 1; } -static inline int Aig_LitIsCompl( int Lit ) { return Lit & 1; } -static inline int Aig_LitNot( int Lit ) { return Lit ^ 1; } -static inline int Aig_LitNotCond( int Lit, int c ) { return Lit ^ (int)(c > 0); } -static inline int Aig_LitRegular( int Lit ) { return Lit & ~01; } - static inline Aig_Obj_t * Aig_Regular( Aig_Obj_t * p ) { return (Aig_Obj_t *)((ABC_PTRUINT_T)(p) & ~01); } static inline Aig_Obj_t * Aig_Not( Aig_Obj_t * p ) { return (Aig_Obj_t *)((ABC_PTRUINT_T)(p) ^ 01); } static inline Aig_Obj_t * Aig_NotCond( Aig_Obj_t * p, int c ) { return (Aig_Obj_t *)((ABC_PTRUINT_T)(p) ^ (c)); } @@ -335,10 +314,10 @@ static inline void Aig_ObjChild1Flip( Aig_Obj_t * pObj ) { assert( !Aig static inline Aig_Obj_t * Aig_ObjCopy( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return (Aig_Obj_t *)pObj->pData; } static inline void Aig_ObjSetCopy( Aig_Obj_t * pObj, Aig_Obj_t * pCopy ) { assert( !Aig_IsComplement(pObj) ); pObj->pData = pCopy; } static inline Aig_Obj_t * Aig_ObjRealCopy( Aig_Obj_t * pObj ) { return Aig_NotCond((Aig_Obj_t *)Aig_Regular(pObj)->pData, Aig_IsComplement(pObj));} -static inline int Aig_ObjToLit( Aig_Obj_t * pObj ) { return Aig_Var2Lit( Aig_ObjId(Aig_Regular(pObj)), Aig_IsComplement(pObj) ); } -static inline Aig_Obj_t * Aig_ObjFromLit( Aig_Man_t * p,int iLit){ return Aig_NotCond( Aig_ManObj(p, Aig_Lit2Var(iLit)), Aig_LitIsCompl(iLit) ); } +static inline int Aig_ObjToLit( Aig_Obj_t * pObj ) { return Abc_Var2Lit( Aig_ObjId(Aig_Regular(pObj)), Aig_IsComplement(pObj) ); } +static inline Aig_Obj_t * Aig_ObjFromLit( Aig_Man_t * p,int iLit){ return Aig_NotCond( Aig_ManObj(p, Abc_Lit2Var(iLit)), Abc_LitIsCompl(iLit) ); } 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) + ABC_MAX(Aig_ObjFanin0(pObj)->Level, Aig_ObjFanin1(pObj)->Level) : Aig_ObjFanin0(pObj)->Level; } +static inline int Aig_ObjLevelNew( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? 1 + Aig_ObjIsExor(pObj) + Abc_MaxInt(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); } @@ -653,7 +632,6 @@ extern unsigned * Aig_ManCutTruth( Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, /*=== aigTsim.c ========================================================*/ extern Aig_Man_t * Aig_ManConstReduce( Aig_Man_t * p, int fUseMvSweep, int nFramesSymb, int nFramesSatur, int fVerbose, int fVeryVerbose ); /*=== aigUtil.c =========================================================*/ -extern unsigned Aig_PrimeCudd( unsigned p ); extern void Aig_ManIncrementTravId( Aig_Man_t * p ); extern char * Aig_TimeStamp(); extern int Aig_ManHasNoGaps( Aig_Man_t * p ); diff --git a/src/aig/aig/aigCanon.c b/src/aig/aig/aigCanon.c index 706a9c61..2c5e4d17 100644 --- a/src/aig/aig/aigCanon.c +++ b/src/aig/aig/aigCanon.c @@ -19,9 +19,9 @@ ***********************************************************************/ #include "aig.h" -#include "kit.h" -#include "bdc.h" -#include "ioa.h" +#include "src/bool/kit/kit.h" +#include "src/bool/bdc/bdc.h" +#include "src/aig/ioa/ioa.h" ABC_NAMESPACE_IMPL_START @@ -106,7 +106,7 @@ Aig_RMan_t * Aig_RManStart() p->pAig = Aig_ManStart( 1000000 ); Aig_IthVar( p->pAig, p->nVars-1 ); // create hash table - p->nBins = Aig_PrimeCudd(5000); + p->nBins = Abc_PrimeCudd(5000); p->pBins = ABC_CALLOC( Aig_Tru_t *, p->nBins ); p->pMemTrus = Aig_MmFlexStart(); // bi-decomposition manager @@ -182,7 +182,7 @@ clk = clock(); pBinsOld = p->pBins; nBinsOld = p->nBins; // get the new Bins - p->nBins = Aig_PrimeCudd( 3 * nBinsOld ); + p->nBins = Abc_PrimeCudd( 3 * nBinsOld ); p->pBins = ABC_CALLOC( Aig_Tru_t *, p->nBins ); // rehash the entries from the old table Counter = 0; @@ -628,7 +628,7 @@ void Aig_RManRecord( unsigned * pTruth, int nVarsInit ) else s_pRMan->nTtDsdNot++; // compute the number of words - nWords = Aig_TruthWordNum( nVars ); + nWords = Abc_TruthWordNum( nVars ); // copy the function memcpy( s_pRMan->pTruthInit, Kit_DsdObjTruth(pObj), 4*nWords ); Kit_DsdNtkFree( pNtk ); diff --git a/src/aig/aig/aigCuts.c b/src/aig/aig/aigCuts.c index 1bcf69ce..acff77d2 100644 --- a/src/aig/aig/aigCuts.c +++ b/src/aig/aig/aigCuts.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "aig.h" -#include "kit.h" +#include "src/bool/kit/kit.h" ABC_NAMESPACE_IMPL_START @@ -58,7 +58,7 @@ Aig_ManCut_t * Aig_ManCutStart( Aig_Man_t * pMan, int nCutsMax, int nLeafMax, in p->pAig = pMan; p->pCuts = ABC_CALLOC( Aig_Cut_t *, Aig_ManObjNumMax(pMan) ); // allocate memory manager - p->nTruthWords = Aig_TruthWordNum(nLeafMax); + p->nTruthWords = Abc_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 diff --git a/src/aig/aig/aigDfs.c b/src/aig/aig/aigDfs.c index 0c2989d8..2da609f3 100644 --- a/src/aig/aig/aigDfs.c +++ b/src/aig/aig/aigDfs.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "aig.h" -#include "tim.h" +#include "src/misc/tim/tim.h" ABC_NAMESPACE_IMPL_START @@ -477,7 +477,7 @@ int Aig_ManLevelNum( Aig_Man_t * p ) int i, LevelsMax; LevelsMax = 0; Aig_ManForEachPo( p, pObj, i ) - LevelsMax = ABC_MAX( LevelsMax, (int)Aig_ObjFanin0(pObj)->Level ); + LevelsMax = Abc_MaxInt( LevelsMax, (int)Aig_ObjFanin0(pObj)->Level ); return LevelsMax; } diff --git a/src/aig/aig/aigDoms.c b/src/aig/aig/aigDoms.c index 0ac2b358..b81279b2 100644 --- a/src/aig/aig/aigDoms.c +++ b/src/aig/aig/aigDoms.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "aig.h" -#include "saig.h" +#include "src/aig/saig/saig.h" ABC_NAMESPACE_IMPL_START diff --git a/src/aig/aig/aigDup.c b/src/aig/aig/aigDup.c index 94eaf497..c2127262 100644 --- a/src/aig/aig/aigDup.c +++ b/src/aig/aig/aigDup.c @@ -18,8 +18,8 @@ ***********************************************************************/ -#include "saig.h" -#include "tim.h" +#include "src/aig/saig/saig.h" +#include "src/misc/tim/tim.h" ABC_NAMESPACE_IMPL_START @@ -52,8 +52,8 @@ Aig_Man_t * Aig_ManDupSimple( Aig_Man_t * p ) assert( p->pManHaig == NULL || Aig_ManBufNum(p) == 0 ); // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->pSpec = Aig_UtilStrsav( p->pSpec ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nAsserts = p->nAsserts; pNew->nConstrs = p->nConstrs; if ( p->vFlopNums ) @@ -124,7 +124,7 @@ Aig_Man_t * Aig_ManDupSimpleWithHints( Aig_Man_t * p, Vec_Int_t * vHints ) assert( p->nAsserts == 0 || p->nConstrs == 0 ); // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); // create the PIs Aig_ManCleanData( p ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); @@ -203,8 +203,8 @@ Aig_Man_t * Aig_ManDupSimpleDfs( Aig_Man_t * p ) assert( p->pManHaig == NULL || Aig_ManBufNum(p) == 0 ); // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->pSpec = Aig_UtilStrsav( p->pSpec ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nAsserts = p->nAsserts; pNew->nConstrs = p->nConstrs; if ( p->vFlopNums ) @@ -303,8 +303,8 @@ Aig_Man_t * Aig_ManDupOrdered( Aig_Man_t * p ) int i, nNodes; // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->pSpec = Aig_UtilStrsav( p->pSpec ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nAsserts = p->nAsserts; pNew->nConstrs = p->nConstrs; if ( p->vFlopNums ) @@ -379,8 +379,8 @@ Aig_Man_t * Aig_ManDupCof( Aig_Man_t * p, int iInput, int Value ) assert( p->pManHaig == NULL || Aig_ManBufNum(p) == 0 ); // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->pSpec = Aig_UtilStrsav( p->pSpec ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nAsserts = p->nAsserts; pNew->nConstrs = p->nConstrs; if ( p->vFlopNums ) @@ -456,8 +456,8 @@ Aig_Man_t * Aig_ManDupTrim( Aig_Man_t * p ) int i, nNodes; // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->pSpec = Aig_UtilStrsav( p->pSpec ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nConstrs = p->nConstrs; // create the PIs Aig_ManCleanData( p ); @@ -505,8 +505,8 @@ Aig_Man_t * Aig_ManDupExor( Aig_Man_t * p ) // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->fCatchExor = 1; - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->pSpec = Aig_UtilStrsav( p->pSpec ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nAsserts = p->nAsserts; pNew->nConstrs = p->nConstrs; if ( p->vFlopNums ) @@ -608,8 +608,8 @@ Aig_Man_t * Aig_ManDupDfs( Aig_Man_t * p ) int i, nNodes; // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->pSpec = Aig_UtilStrsav( p->pSpec ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nAsserts = p->nAsserts; pNew->nConstrs = p->nConstrs; if ( p->vFlopNums ) @@ -749,8 +749,8 @@ Aig_Man_t * Aig_ManDupDfsGuided( Aig_Man_t * p, Vec_Ptr_t * vPios ) int i, nNodes; // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->pSpec = Aig_UtilStrsav( p->pSpec ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nAsserts = p->nAsserts; pNew->nConstrs = p->nConstrs; if ( p->vFlopNums ) @@ -821,8 +821,8 @@ Aig_Man_t * Aig_ManDupLevelized( Aig_Man_t * p ) int i, k; // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->pSpec = Aig_UtilStrsav( p->pSpec ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nAsserts = p->nAsserts; pNew->nConstrs = p->nConstrs; if ( p->vFlopNums ) @@ -895,8 +895,8 @@ Aig_Man_t * Aig_ManDupWithoutPos( Aig_Man_t * p ) int i; // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->pSpec = Aig_UtilStrsav( p->pSpec ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // create the PIs Aig_ManCleanData( p ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); @@ -980,8 +980,8 @@ Aig_Man_t * Aig_ManDupRepres( Aig_Man_t * p ) int i; // start the HOP package pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->pSpec = Aig_UtilStrsav( p->pSpec ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nConstrs = p->nConstrs; if ( p->vFlopNums ) pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); @@ -1054,8 +1054,8 @@ Aig_Man_t * Aig_ManDupRepresDfs( Aig_Man_t * p ) int i; // start the HOP package pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->pSpec = Aig_UtilStrsav( p->pSpec ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nConstrs = p->nConstrs; if ( p->vFlopNums ) pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); @@ -1163,8 +1163,8 @@ Aig_Man_t * Aig_ManDupOrpos( Aig_Man_t * p, int fAddRegs ) } // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->pSpec = Aig_UtilStrsav( p->pSpec ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // create the PIs Aig_ManCleanData( p ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); @@ -1212,8 +1212,8 @@ Aig_Man_t * Aig_ManDupOneOutput( Aig_Man_t * p, int iPoNum, int fAddRegs ) assert( iPoNum < Aig_ManPoNum(p)-Aig_ManRegNum(p) ); // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->pSpec = Aig_UtilStrsav( p->pSpec ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // create the PIs Aig_ManCleanData( p ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); @@ -1263,8 +1263,8 @@ Aig_Man_t * Aig_ManDupUnsolvedOutputs( Aig_Man_t * p, int fAddRegs ) } // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->pSpec = Aig_UtilStrsav( p->pSpec ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // create the PIs Aig_ManCleanData( p ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); @@ -1321,7 +1321,7 @@ Aig_Man_t * Aig_ManDupArray( Vec_Ptr_t * vArray ) } // create the new manager pNew = Aig_ManStart( 10000 ); - pNew->pName = Aig_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Aig_ManForEachPi( p, pObj, i ) Aig_ObjCreatePi(pNew); // create the PIs diff --git a/src/aig/aig/aigFact.c b/src/aig/aig/aigFact.c index 9c4e5689..40885365 100644 --- a/src/aig/aig/aigFact.c +++ b/src/aig/aig/aigFact.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "aig.h" -#include "kit.h" +#include "src/bool/kit/kit.h" ABC_NAMESPACE_IMPL_START @@ -289,7 +289,7 @@ Vec_Ptr_t * Aig_SuppMinPerform( Aig_Man_t * p, Vec_Ptr_t * vOrGate, Vec_Ptr_t * Aig_Obj_t * pObj; Vec_Ptr_t * vTrSupp, * vTrNode, * vCofs; unsigned * uFunc, * uCare, * uFunc0, * uFunc1, * uCof; - int i, nWords = Aig_TruthWordNum( Vec_PtrSize(vSupp) ); + int i, nWords = Abc_TruthWordNum( Vec_PtrSize(vSupp) ); // assign support nodes vTrSupp = Vec_PtrAllocTruthTables( Vec_PtrSize(vSupp) ); Vec_PtrForEachEntry( Aig_Obj_t *, vSupp, pObj, i ) diff --git a/src/aig/aig/aigFanout.c b/src/aig/aig/aigFanout.c index d6317f43..d2fc1fe3 100644 --- a/src/aig/aig/aigFanout.c +++ b/src/aig/aig/aigFanout.c @@ -112,7 +112,7 @@ void Aig_ObjAddFanout( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFanout ) assert( pFanout->Id > 0 ); if ( pObj->Id >= p->nFansAlloc || pFanout->Id >= p->nFansAlloc ) { - int nFansAlloc = 2 * ABC_MAX( pObj->Id, pFanout->Id ); + int nFansAlloc = 2 * Abc_MaxInt( pObj->Id, pFanout->Id ); p->pFanData = ABC_REALLOC( int, p->pFanData, 5 * nFansAlloc ); memset( p->pFanData + 5 * p->nFansAlloc, 0, sizeof(int) * 5 * (nFansAlloc - p->nFansAlloc) ); p->nFansAlloc = nFansAlloc; diff --git a/src/aig/aig/aigFrames.c b/src/aig/aig/aigFrames.c index fdcd14aa..6840aadf 100644 --- a/src/aig/aig/aigFrames.c +++ b/src/aig/aig/aigFrames.c @@ -61,8 +61,8 @@ Aig_Man_t * Aig_ManFrames( Aig_Man_t * pAig, int nFs, int fInit, int fOuts, int // start the fraig package pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFs ); - pFrames->pName = Aig_UtilStrsav( pAig->pName ); - pFrames->pSpec = Aig_UtilStrsav( pAig->pSpec ); + pFrames->pName = Abc_UtilStrsav( pAig->pName ); + pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec ); // map constant nodes for ( f = 0; f < nFs; f++ ) Aig_ObjSetFrames( pObjMap, nFs, Aig_ManConst1(pAig), f, Aig_ManConst1(pFrames) ); diff --git a/src/aig/aig/aigInter.c b/src/aig/aig/aigInter.c index aa019191..bb6cf987 100644 --- a/src/aig/aig/aigInter.c +++ b/src/aig/aig/aigInter.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "aig.h" -#include "cnf.h" -#include "satStore.h" +#include "src/sat/cnf/cnf.h" +#include "src/sat/bsat/satStore.h" ABC_NAMESPACE_IMPL_START diff --git a/src/aig/aig/aigJust.c b/src/aig/aig/aigJust.c index eca17d40..bff2baed 100644 --- a/src/aig/aig/aigJust.c +++ b/src/aig/aig/aigJust.c @@ -114,7 +114,7 @@ int Aig_NtkFindSatAssign_rec( Aig_Man_t * pAig, Aig_Obj_t * pNode, int Value, Ve // if ( Aig_ObjId(pNode) % 1000 == 0 ) // Value ^= 1; if ( vSuppLits ) - Vec_IntPush( vSuppLits, Aig_Var2Lit( Aig_ObjPioNum(pNode), !Value ) ); + Vec_IntPush( vSuppLits, Abc_Var2Lit( Aig_ObjPioNum(pNode), !Value ) ); return 1; } assert( Aig_ObjIsNode(pNode) ); @@ -221,8 +221,8 @@ int Aig_ObjTerSimulate( Aig_Man_t * pAig, Aig_Obj_t * pNode, Vec_Int_t * vSuppLi Aig_ManIncrementTravId( pAig ); Vec_IntForEachEntry( vSuppLits, Entry, i ) { - pObj = Aig_ManPi( pAig, Aig_Lit2Var(Entry) ); - Aig_ObjSetTerValue( pObj, Aig_LitIsCompl(Entry) ? AIG_VAL0 : AIG_VAL1 ); + pObj = Aig_ManPi( pAig, Abc_Lit2Var(Entry) ); + Aig_ObjSetTerValue( pObj, Abc_LitIsCompl(Entry) ? AIG_VAL0 : AIG_VAL1 ); Aig_ObjSetTravIdCurrent( pAig, pObj ); //printf( "%d ", Entry ); } diff --git a/src/aig/aig/aigMan.c b/src/aig/aig/aigMan.c index b0544c90..814e5248 100644 --- a/src/aig/aig/aigMan.c +++ b/src/aig/aig/aigMan.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "aig.h" -#include "tim.h" +#include "src/misc/tim/tim.h" ABC_NAMESPACE_IMPL_START @@ -68,7 +68,7 @@ Aig_Man_t * Aig_ManStart( int nNodesMax ) p->pConst1->fPhase = 1; p->nObjs[AIG_OBJ_CONST1]++; // start the table - p->nTableSize = Aig_PrimeCudd( nNodesMax ); + p->nTableSize = Abc_PrimeCudd( nNodesMax ); p->pTable = ABC_ALLOC( Aig_Obj_t *, p->nTableSize ); memset( p->pTable, 0, sizeof(Aig_Obj_t *) * p->nTableSize ); return p; @@ -92,8 +92,8 @@ Aig_Man_t * Aig_ManStartFrom( Aig_Man_t * p ) int i; // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->pSpec = Aig_UtilStrsav( p->pSpec ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // create the PIs Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Aig_ManForEachPi( p, pObj, i ) @@ -149,8 +149,8 @@ Aig_Man_t * Aig_ManExtractMiter( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * int i; // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->pSpec = Aig_UtilStrsav( p->pSpec ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // create the PIs Aig_ManCleanData( p ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); diff --git a/src/aig/aig/aigMffc.c b/src/aig/aig/aigMffc.c index 2f51e442..ed0015ac 100644 --- a/src/aig/aig/aigMffc.c +++ b/src/aig/aig/aigMffc.c @@ -269,7 +269,7 @@ int Aig_NodeMffcExtendCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves // dereference the current cut LevelMax = 0; Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i ) - LevelMax = ABC_MAX( LevelMax, (int)pObj->Level ); + LevelMax = Abc_MaxInt( LevelMax, (int)pObj->Level ); if ( LevelMax == 0 ) return 0; // dereference the cut diff --git a/src/aig/aig/aigObj.c b/src/aig/aig/aigObj.c index 36578d35..71796993 100644 --- a/src/aig/aig/aigObj.c +++ b/src/aig/aig/aigObj.c @@ -122,11 +122,11 @@ Aig_Obj_t * Aig_ObjCreate( Aig_Man_t * p, Aig_Obj_t * pGhost ) // create the power counter if ( p->vProbs ) { - float Prob0 = Aig_Int2Float( Vec_IntEntry( p->vProbs, Aig_ObjFaninId0(pObj) ) ); - float Prob1 = Aig_Int2Float( Vec_IntEntry( p->vProbs, Aig_ObjFaninId1(pObj) ) ); + float Prob0 = Abc_Int2Float( Vec_IntEntry( p->vProbs, Aig_ObjFaninId0(pObj) ) ); + float Prob1 = Abc_Int2Float( Vec_IntEntry( p->vProbs, Aig_ObjFaninId1(pObj) ) ); Prob0 = Aig_ObjFaninC0(pObj)? 1.0 - Prob0 : Prob0; Prob1 = Aig_ObjFaninC1(pObj)? 1.0 - Prob1 : Prob1; - Vec_IntSetEntry( p->vProbs, pObj->Id, Aig_Float2Int(Prob0 * Prob1) ); + Vec_IntSetEntry( p->vProbs, pObj->Id, Abc_Float2Int(Prob0 * Prob1) ); } return pObj; } @@ -563,7 +563,7 @@ void Aig_ObjReplace( Aig_Man_t * p, Aig_Obj_t * pObjOld, Aig_Obj_t * pObjNew, in if ( p->pFanData && Aig_ObjIsBuf(pObjOld) ) { Vec_PtrPush( p->vBufs, pObjOld ); - p->nBufMax = ABC_MAX( p->nBufMax, Vec_PtrSize(p->vBufs) ); + p->nBufMax = Abc_MaxInt( p->nBufMax, Vec_PtrSize(p->vBufs) ); Aig_ManPropagateBuffers( p, fUpdateLevel ); } } diff --git a/src/aig/aig/aigPack.c b/src/aig/aig/aigPack.c index 0ecbf533..b89d6077 100644 --- a/src/aig/aig/aigPack.c +++ b/src/aig/aig/aigPack.c @@ -295,19 +295,19 @@ int Aig_ManPackAddPatternTry( Aig_ManPack_t * p, int iBit, Vec_Int_t * vLits ) int i, Lit; Vec_IntForEachEntry( vLits, Lit, i ) { - pInfo = Vec_WrdEntryP( p->vPiPats, Aig_Lit2Var(Lit) ); - pPres = Vec_WrdEntryP( p->vPiCare, Aig_Lit2Var(Lit) ); - if ( Aig_InfoHasBit( (unsigned *)pPres, iBit ) && - Aig_InfoHasBit( (unsigned *)pInfo, iBit ) == Aig_LitIsCompl(Lit) ) + pInfo = Vec_WrdEntryP( p->vPiPats, Abc_Lit2Var(Lit) ); + pPres = Vec_WrdEntryP( p->vPiCare, Abc_Lit2Var(Lit) ); + if ( Abc_InfoHasBit( (unsigned *)pPres, iBit ) && + Abc_InfoHasBit( (unsigned *)pInfo, iBit ) == Abc_LitIsCompl(Lit) ) return 0; } Vec_IntForEachEntry( vLits, Lit, i ) { - pInfo = Vec_WrdEntryP( p->vPiPats, Aig_Lit2Var(Lit) ); - pPres = Vec_WrdEntryP( p->vPiCare, Aig_Lit2Var(Lit) ); - Aig_InfoSetBit( (unsigned *)pPres, iBit ); - if ( Aig_InfoHasBit( (unsigned *)pInfo, iBit ) == Aig_LitIsCompl(Lit) ) - Aig_InfoXorBit( (unsigned *)pInfo, iBit ); + pInfo = Vec_WrdEntryP( p->vPiPats, Abc_Lit2Var(Lit) ); + pPres = Vec_WrdEntryP( p->vPiCare, Abc_Lit2Var(Lit) ); + Abc_InfoSetBit( (unsigned *)pPres, iBit ); + if ( Abc_InfoHasBit( (unsigned *)pInfo, iBit ) == Abc_LitIsCompl(Lit) ) + Abc_InfoXorBit( (unsigned *)pInfo, iBit ); } return 1; } @@ -335,16 +335,16 @@ void Aig_ManPackAddPattern( Aig_ManPack_t * p, Vec_Int_t * vLits ) word * pInfo, * pPres; int i, Lit; Vec_IntForEachEntry( vLits, Lit, i ) - printf( "%d", Aig_LitIsCompl(Lit) ); + printf( "%d", Abc_LitIsCompl(Lit) ); printf( "\n\n" ); for ( k = 1; k < 64; k++ ) { Vec_IntForEachEntry( vLits, Lit, i ) { - pInfo = Vec_WrdEntryP( p->vPiPats, Aig_Lit2Var(Lit) ); - pPres = Vec_WrdEntryP( p->vPiCare, Aig_Lit2Var(Lit) ); - if ( Aig_InfoHasBit( (unsigned *)pPres, k ) ) - printf( "%d", Aig_InfoHasBit( (unsigned *)pInfo, k ) ); + pInfo = Vec_WrdEntryP( p->vPiPats, Abc_Lit2Var(Lit) ); + pPres = Vec_WrdEntryP( p->vPiCare, Abc_Lit2Var(Lit) ); + if ( Abc_InfoHasBit( (unsigned *)pPres, k ) ) + printf( "%d", Abc_InfoHasBit( (unsigned *)pInfo, k ) ); else printf( "-" ); } diff --git a/src/aig/aig/aigPart.c b/src/aig/aig/aigPart.c index 6ee3930b..1510ddc7 100644 --- a/src/aig/aig/aigPart.c +++ b/src/aig/aig/aigPart.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "aig.h" -#include "tim.h" -#include "fra.h" +#include "src/misc/tim/tim.h" +#include "src/proof/fra/fra.h" ABC_NAMESPACE_IMPL_START @@ -471,13 +471,13 @@ unsigned * Aig_ManSuppCharStart( Vec_Int_t * vOne, int nPis ) { unsigned * pBuffer; int i, Entry; - int nWords = Aig_BitWordNum(nPis); + int nWords = Abc_BitWordNum(nPis); pBuffer = ABC_ALLOC( unsigned, nWords ); memset( pBuffer, 0, sizeof(unsigned) * nWords ); Vec_IntForEachEntry( vOne, Entry, i ) { assert( Entry < nPis ); - Aig_InfoSetBit( pBuffer, Entry ); + Abc_InfoSetBit( pBuffer, Entry ); } return pBuffer; } @@ -499,7 +499,7 @@ void Aig_ManSuppCharAdd( unsigned * pBuffer, Vec_Int_t * vOne, int nPis ) Vec_IntForEachEntry( vOne, Entry, i ) { assert( Entry < nPis ); - Aig_InfoSetBit( pBuffer, Entry ); + Abc_InfoSetBit( pBuffer, Entry ); } } @@ -518,7 +518,7 @@ int Aig_ManSuppCharCommon( unsigned * pBuffer, Vec_Int_t * vOne ) { int i, Entry, nCommon = 0; Vec_IntForEachEntry( vOne, Entry, i ) - nCommon += Aig_InfoHasBit(pBuffer, Entry); + nCommon += Abc_InfoHasBit(pBuffer, Entry); return nCommon; } @@ -558,7 +558,7 @@ int Aig_ManPartitionSmartFindPart( Vec_Ptr_t * vPartSuppsAll, Vec_Ptr_t * vParts if ( Vec_IntSize(vPartSupp) < 100 ) Repulse = 1; else - Repulse = 1+Aig_Base2Log(Vec_IntSize(vPartSupp)-100); + Repulse = 1+Abc_Base2Log(Vec_IntSize(vPartSupp)-100); Value = Attract/Repulse; if ( ValueBest < Value ) { diff --git a/src/aig/aig/aigPartSat.c b/src/aig/aig/aigPartSat.c index 48e5cf80..52fbe2e2 100644 --- a/src/aig/aig/aigPartSat.c +++ b/src/aig/aig/aigPartSat.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "aig.h" -#include "satSolver.h" -#include "cnf.h" +#include "src/sat/bsat/satSolver.h" +#include "src/sat/cnf/cnf.h" ABC_NAMESPACE_IMPL_START diff --git a/src/aig/aig/aigRepar.c b/src/aig/aig/aigRepar.c index 03155e91..e0fe4cb1 100644 --- a/src/aig/aig/aigRepar.c +++ b/src/aig/aig/aigRepar.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "aig.h" -#include "cnf.h" -#include "satSolver2.h" +#include "src/sat/cnf/cnf.h" +#include "src/sat/bsat/satSolver2.h" ABC_NAMESPACE_IMPL_START @@ -313,7 +313,7 @@ Aig_Man_t * Aig_ManInterRepar( Aig_Man_t * pMan, int fVerbose ) // start the interpolant pBase = Aig_ManStart( 1000 ); - pBase->pName = Aig_UtilStrsav( "repar" ); + pBase->pName = Abc_UtilStrsav( "repar" ); for ( k = 0; k < 2*nOuts; k++ ) Aig_IthVar(pBase, i); @@ -338,7 +338,7 @@ Aig_Man_t * Aig_ManInterRepar( Aig_Man_t * pMan, int fVerbose ) Sat_Solver2PrintStats( stdout, pSat ); // derive interpolant - pInter = Sat_ProofInterpolant( pSat, vVars ); + pInter = (Aig_Man_t *)Sat_ProofInterpolant( pSat, vVars ); Aig_ManPrintStats( pInter ); // make sure interpolant does not depend on useless vars Aig_ManForEachPi( pInter, pObj, i ) diff --git a/src/aig/aig/aigRepr.c b/src/aig/aig/aigRepr.c index 9966174f..d08b6553 100644 --- a/src/aig/aig/aigRepr.c +++ b/src/aig/aig/aigRepr.c @@ -271,8 +271,8 @@ Aig_Man_t * Aig_ManDupRepr( Aig_Man_t * p, int fOrdered ) int i; // start the HOP package pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->pSpec = Aig_UtilStrsav( p->pSpec ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nConstrs = p->nConstrs; if ( p->vFlopNums ) pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); diff --git a/src/aig/aig/aigRet.c b/src/aig/aig/aigRet.c index f7774d22..acc5b6ec 100644 --- a/src/aig/aig/aigRet.c +++ b/src/aig/aig/aigRet.c @@ -176,7 +176,7 @@ void Rtm_ObjTransferToBig( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) assert( pEdge->nLats == 10 ); if ( p->nExtraCur + 1 > p->nExtraAlloc ) { - int nExtraAllocNew = ABC_MAX( 2 * p->nExtraAlloc, 1024 ); + int nExtraAllocNew = Abc_MaxInt( 2 * p->nExtraAlloc, 1024 ); p->pExtra = ABC_REALLOC( unsigned, p->pExtra, nExtraAllocNew ); p->nExtraAlloc = nExtraAllocNew; } @@ -202,7 +202,7 @@ void Rtm_ObjTransferToBigger( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) nWords = (pEdge->nLats + 1) >> 4; if ( p->nExtraCur + nWords + 1 > p->nExtraAlloc ) { - int nExtraAllocNew = ABC_MAX( 2 * p->nExtraAlloc, 1024 ); + int nExtraAllocNew = Abc_MaxInt( 2 * p->nExtraAlloc, 1024 ); p->pExtra = ABC_REALLOC( unsigned, p->pExtra, nExtraAllocNew ); p->nExtraAlloc = nExtraAllocNew; } @@ -360,7 +360,7 @@ int Rtm_ManLatchMax( Rtm_Man_t * p ) assert( Val == 1 || Val == 2 ); } */ - nLatchMax = ABC_MAX( nLatchMax, (int)pEdge->nLats ); + nLatchMax = Abc_MaxInt( nLatchMax, (int)pEdge->nLats ); } return nLatchMax; } @@ -477,7 +477,7 @@ int Rtm_ObjGetDegreeFwd( Rtm_Obj_t * pObj ) Rtm_Obj_t * pFanin; int i, Degree = 0; Rtm_ObjForEachFanin( pObj, pFanin, i ) - Degree = ABC_MAX( Degree, (int)pFanin->Num ); + Degree = Abc_MaxInt( Degree, (int)pFanin->Num ); return Degree + 1; } @@ -497,7 +497,7 @@ int Rtm_ObjGetDegreeBwd( Rtm_Obj_t * pObj ) Rtm_Obj_t * pFanout; int i, Degree = 0; Rtm_ObjForEachFanout( pObj, pFanout, i ) - Degree = ABC_MAX( Degree, (int)pFanout->Num ); + Degree = Abc_MaxInt( Degree, (int)pFanout->Num ); return Degree + 1; } @@ -910,7 +910,7 @@ clk = clock(); if ( !Rtm_ObjCheckRetimeFwd( pNext ) ) // skip non-retimable continue; Degree = Rtm_ObjGetDegreeFwd( pNext ); - DegreeMax = ABC_MAX( DegreeMax, Degree ); + DegreeMax = Abc_MaxInt( DegreeMax, Degree ); if ( Degree > nStepsMax ) // skip nodes with high degree continue; pNext->fMark = 1; @@ -931,7 +931,7 @@ clk = clock(); if ( !Rtm_ObjCheckRetimeBwd( pNext ) ) // skip non-retimable continue; Degree = Rtm_ObjGetDegreeBwd( pNext ); - DegreeMax = ABC_MAX( DegreeMax, Degree ); + DegreeMax = Abc_MaxInt( DegreeMax, Degree ); if ( Degree > nStepsMax ) // skip nodes with high degree continue; pNext->fMark = 1; @@ -952,8 +952,8 @@ clk = clock(); // get the new manager pNew = Rtm_ManToAig( pRtm ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->pSpec = Aig_UtilStrsav( p->pSpec ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Rtm_ManFree( pRtm ); // group the registers clk = clock(); diff --git a/src/aig/aig/aigScl.c b/src/aig/aig/aigScl.c index 2bc7f8ea..74b56bcf 100644 --- a/src/aig/aig/aigScl.c +++ b/src/aig/aig/aigScl.c @@ -50,8 +50,8 @@ Aig_Man_t * Aig_ManRemap( Aig_Man_t * p, Vec_Ptr_t * vMap ) int i, nTruePis; // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->pSpec = Aig_UtilStrsav( p->pSpec ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nAsserts = p->nAsserts; pNew->nConstrs = p->nConstrs; assert( p->vFlopNums == NULL || Vec_IntSize(p->vFlopNums) == p->nRegs ); diff --git a/src/aig/aig/aigSplit.c b/src/aig/aig/aigSplit.c index 51b4f982..82f60e2d 100644 --- a/src/aig/aig/aigSplit.c +++ b/src/aig/aig/aigSplit.c @@ -19,9 +19,8 @@ ***********************************************************************/ #include "aig.h" -#include "saig.h" -#include "cuddInt.h" -#include "extra.h" +#include "src/aig/saig/saig.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START @@ -84,7 +83,7 @@ Aig_Man_t * Aig_ManConvertBddsToAigs( Aig_Man_t * p, DdManager * dd, Vec_Ptr_t * Aig_ManCleanData( p ); // generate AIG for BDD pNew = Aig_ManStart( Aig_ManObjNum(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Aig_ManForEachPi( p, pObj, i ) pObj->pData = Aig_ObjCreatePi( pNew ); diff --git a/src/aig/aig/aigTable.c b/src/aig/aig/aigTable.c index 13826065..ec2531c7 100644 --- a/src/aig/aig/aigTable.c +++ b/src/aig/aig/aigTable.c @@ -77,7 +77,7 @@ clk = clock(); pTableOld = p->pTable; nTableSizeOld = p->nTableSize; // get the new table - p->nTableSize = Aig_PrimeCudd( 2 * Aig_ManNodeNum(p) ); + p->nTableSize = Abc_PrimeCudd( 2 * Aig_ManNodeNum(p) ); p->pTable = ABC_ALLOC( Aig_Obj_t *, p->nTableSize ); memset( p->pTable, 0, sizeof(Aig_Obj_t *) * p->nTableSize ); // rehash the entries from the old table diff --git a/src/aig/aig/aigTiming.c b/src/aig/aig/aigTiming.c index 4ea93e29..e855e012 100644 --- a/src/aig/aig/aigTiming.c +++ b/src/aig/aig/aigTiming.c @@ -121,7 +121,7 @@ int Aig_ObjReverseLevelNew( Aig_Man_t * p, Aig_Obj_t * pObj ) Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) { LevelCur = Aig_ObjReverseLevel( p, pFanout ); - Level = ABC_MAX( Level, LevelCur ); + Level = Abc_MaxInt( Level, LevelCur ); } return Level + 1; } diff --git a/src/aig/aig/aigTruth.c b/src/aig/aig/aigTruth.c index ddcb8736..5115c4f4 100644 --- a/src/aig/aig/aigTruth.c +++ b/src/aig/aig/aigTruth.c @@ -88,7 +88,7 @@ unsigned * Aig_ManCutTruth( Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i ) pObj->pData = Vec_PtrEntry( vTruthElem, i ); // compute truths for other nodes - nWords = Aig_TruthWordNum( Vec_PtrSize(vLeaves) ); + nWords = Abc_TruthWordNum( Vec_PtrSize(vLeaves) ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) pObj->pData = Aig_ManCutTruthOne( pObj, (unsigned *)Vec_PtrEntry(vTruthStore, i), nWords ); return (unsigned *)pRoot->pData; diff --git a/src/aig/aig/aigTsim.c b/src/aig/aig/aigTsim.c index 5e711ff6..99aa5c64 100644 --- a/src/aig/aig/aigTsim.c +++ b/src/aig/aig/aigTsim.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "aig.h" -#include "saig.h" +#include "src/aig/saig/saig.h" ABC_NAMESPACE_IMPL_START @@ -133,10 +133,10 @@ Aig_Tsi_t * Aig_TsiStart( Aig_Man_t * pAig ) p = ABC_ALLOC( Aig_Tsi_t, 1 ); memset( p, 0, sizeof(Aig_Tsi_t) ); p->pAig = pAig; - p->nWords = Aig_BitWordNum( 2*Aig_ManRegNum(pAig) ); + p->nWords = Abc_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->nBins = Abc_PrimeCudd(TSI_MAX_ROUNDS/2); p->pBins = ABC_ALLOC( unsigned *, p->nBins ); memset( p->pBins, 0, sizeof(unsigned *) * p->nBins ); return p; @@ -274,7 +274,7 @@ 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 ); + Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i ); if ( Value == 1 ) printf( "0" ), nZeros++; else if ( Value == 2 ) @@ -304,7 +304,7 @@ int Aig_TsiStateCount( Aig_Tsi_t * p, unsigned * pState ) int i, Value, nCounter = 0; Aig_ManForEachLiLoSeq( p->pAig, pObjLi, pObjLo, i ) { - Value = (Aig_InfoHasBit( pState, 2 * i + 1 ) << 1) | Aig_InfoHasBit( pState, 2 * i ); + Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i ); nCounter += (Value == 1 || Value == 2); } return nCounter; @@ -369,9 +369,9 @@ Vec_Ptr_t * Aig_ManTernarySimulate( Aig_Man_t * p, int fVerbose, int fVeryVerbos { Value = Aig_ObjGetXsim(pObjLo); if ( Value & 1 ) - Aig_InfoSetBit( pState, 2 * i ); + Abc_InfoSetBit( pState, 2 * i ); if ( Value & 2 ) - Aig_InfoSetBit( pState, 2 * i + 1 ); + Abc_InfoSetBit( pState, 2 * i + 1 ); } // printf( "%d ", Aig_TsiStateCount(pTsi, pState) ); @@ -446,7 +446,7 @@ Aig_TsiStatePrint( pTsi, pState ); 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) ) ) + if ( pState[i] != Abc_InfoMask( 2*Aig_ManRegNum(p) - 32*(pTsi->nWords-1) ) ) fConstants = 1; } if ( fConstants == 0 ) @@ -465,7 +465,7 @@ Aig_TsiStatePrint( pTsi, pState ); nCounter = 0; Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) { - Value = (Aig_InfoHasBit( pState, 2 * i + 1 ) << 1) | Aig_InfoHasBit( pState, 2 * i ); + Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i ); nCounter += (Value == 1 || Value == 2); if ( Value == 1 ) Vec_PtrPush( vMap, Aig_ManConst0(p) ); diff --git a/src/aig/aig/aigUtil.c b/src/aig/aig/aigUtil.c index 8cbaa63b..5546c776 100644 --- a/src/aig/aig/aigUtil.c +++ b/src/aig/aig/aigUtil.c @@ -30,42 +30,6 @@ ABC_NAMESPACE_IMPL_START /// 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.] @@ -140,7 +104,7 @@ int Aig_ManLevels( Aig_Man_t * p ) Aig_Obj_t * pObj; int i, LevelMax = 0; Aig_ManForEachPo( p, pObj, i ) - LevelMax = ABC_MAX( LevelMax, (int)Aig_ObjFanin0(pObj)->Level ); + LevelMax = Abc_MaxInt( LevelMax, (int)Aig_ObjFanin0(pObj)->Level ); return LevelMax; } @@ -791,7 +755,7 @@ void Aig_ManDumpBlif( Aig_Man_t * p, char * pFileName, Vec_Ptr_t * vPiNames, Vec pObj->iData = Counter++; Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) pObj->iData = Counter++; - nDigits = Aig_Base10Log( Counter ); + nDigits = Abc_Base10Log( Counter ); // write the file pFile = fopen( pFileName, "w" ); fprintf( pFile, "# BLIF file written by procedure Aig_ManDumpBlif()\n" ); @@ -906,7 +870,7 @@ void Aig_ManDumpVerilog( Aig_Man_t * p, char * pFileName ) pObj->iData = Counter++; Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) pObj->iData = Counter++; - nDigits = Aig_Base10Log( Counter ); + nDigits = Abc_Base10Log( Counter ); // write the file pFile = fopen( pFileName, "w" ); fprintf( pFile, "// Verilog file written by procedure Aig_ManDumpVerilog()\n" ); @@ -1299,7 +1263,7 @@ void Aig_NodeIntersectLists( Vec_Ptr_t * vArr1, Vec_Ptr_t * vArr2, Vec_Ptr_t * v Aig_Obj_t ** pBeg2 = (Aig_Obj_t **)vArr2->pArray; Aig_Obj_t ** pEnd1 = (Aig_Obj_t **)vArr1->pArray + vArr1->nSize; Aig_Obj_t ** pEnd2 = (Aig_Obj_t **)vArr2->pArray + vArr2->nSize; - Vec_PtrGrow( vArr, ABC_MAX( Vec_PtrSize(vArr1), Vec_PtrSize(vArr2) ) ); + Vec_PtrGrow( vArr, Abc_MaxInt( Vec_PtrSize(vArr1), Vec_PtrSize(vArr2) ) ); pBeg = (Aig_Obj_t **)vArr->pArray; while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) { @@ -1324,8 +1288,8 @@ void Aig_NodeIntersectLists( Vec_Ptr_t * vArr1, Vec_Ptr_t * vArr2, Vec_Ptr_t * v ABC_NAMESPACE_IMPL_END -#include "fra.h" -#include "saig.h" +#include "src/proof/fra/fra.h" +#include "src/aig/saig/saig.h" ABC_NAMESPACE_IMPL_START @@ -1353,45 +1317,45 @@ void Aig_ManCounterExampleValueStart( Aig_Man_t * pAig, Abc_Cex_t * pCex ) assert( Aig_ManRegNum(pAig) > 0 ); // makes sense only for sequential AIGs assert( pAig->pData2 == NULL ); // if this fail, there may be a memory leak // allocate memory to store simulation bits for internal nodes - pAig->pData2 = ABC_CALLOC( unsigned, Aig_BitWordNum( (pCex->iFrame + 1) * Aig_ManObjNum(pAig) ) ); + pAig->pData2 = ABC_CALLOC( unsigned, Abc_BitWordNum( (pCex->iFrame + 1) * Aig_ManObjNum(pAig) ) ); // the register values in the counter-example should be zero Saig_ManForEachLo( pAig, pObj, k ) - assert( Aig_InfoHasBit(pCex->pData, iBit++) == 0 ); + assert( Abc_InfoHasBit(pCex->pData, iBit++) == 0 ); // iterate through the timeframes nObjs = Aig_ManObjNum(pAig); for ( i = 0; i <= pCex->iFrame; i++ ) { // set constant 1 node - Aig_InfoSetBit( (unsigned *)pAig->pData2, nObjs * i + 0 ); + Abc_InfoSetBit( (unsigned *)pAig->pData2, nObjs * i + 0 ); // set primary inputs according to the counter-example Saig_ManForEachPi( pAig, pObj, k ) - if ( Aig_InfoHasBit(pCex->pData, iBit++) ) - Aig_InfoSetBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjId(pObj) ); + if ( Abc_InfoHasBit(pCex->pData, iBit++) ) + Abc_InfoSetBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjId(pObj) ); // compute values for each node Aig_ManForEachNode( pAig, pObj, k ) { - Val0 = Aig_InfoHasBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjFaninId0(pObj) ); - Val1 = Aig_InfoHasBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjFaninId1(pObj) ); + Val0 = Abc_InfoHasBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjFaninId0(pObj) ); + Val1 = Abc_InfoHasBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjFaninId1(pObj) ); if ( (Val0 ^ Aig_ObjFaninC0(pObj)) & (Val1 ^ Aig_ObjFaninC1(pObj)) ) - Aig_InfoSetBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjId(pObj) ); + Abc_InfoSetBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjId(pObj) ); } // derive values for combinational outputs Aig_ManForEachPo( pAig, pObj, k ) { - Val0 = Aig_InfoHasBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjFaninId0(pObj) ); + Val0 = Abc_InfoHasBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjFaninId0(pObj) ); if ( Val0 ^ Aig_ObjFaninC0(pObj) ) - Aig_InfoSetBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjId(pObj) ); + Abc_InfoSetBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjId(pObj) ); } if ( i == pCex->iFrame ) continue; // transfer values to the register output of the next frame Saig_ManForEachLiLo( pAig, pObjRi, pObjRo, k ) - if ( Aig_InfoHasBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjId(pObjRi) ) ) - Aig_InfoSetBit( (unsigned *)pAig->pData2, nObjs * (i+1) + Aig_ObjId(pObjRo) ); + if ( Abc_InfoHasBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjId(pObjRi) ) ) + Abc_InfoSetBit( (unsigned *)pAig->pData2, nObjs * (i+1) + Aig_ObjId(pObjRo) ); } assert( iBit == pCex->nBits ); // check that the counter-example is correct, that is, the corresponding output is asserted - assert( Aig_InfoHasBit( (unsigned *)pAig->pData2, nObjs * pCex->iFrame + Aig_ObjId(Aig_ManPo(pAig, pCex->iPo)) ) ); + assert( Abc_InfoHasBit( (unsigned *)pAig->pData2, nObjs * pCex->iFrame + Aig_ObjId(Aig_ManPo(pAig, pCex->iPo)) ) ); } /**Function************************************************************* @@ -1428,7 +1392,7 @@ void Aig_ManCounterExampleValueStop( Aig_Man_t * pAig ) int Aig_ManCounterExampleValueLookup( Aig_Man_t * pAig, int Id, int iFrame ) { assert( Id >= 0 && Id < Aig_ManObjNum(pAig) ); - return Aig_InfoHasBit( (unsigned *)pAig->pData2, Aig_ManObjNum(pAig) * iFrame + Id ); + return Abc_InfoHasBit( (unsigned *)pAig->pData2, Aig_ManObjNum(pAig) * iFrame + Id ); } /**Function************************************************************* @@ -1445,7 +1409,7 @@ int Aig_ManCounterExampleValueLookup( Aig_Man_t * pAig, int Id, int iFrame ) void Aig_ManCounterExampleValueTest( Aig_Man_t * pAig, Abc_Cex_t * pCex ) { Aig_Obj_t * pObj = Aig_ManObj( pAig, Aig_ManObjNum(pAig)/2 ); - int iFrame = ABC_MAX( 0, pCex->iFrame - 1 ); + int iFrame = Abc_MaxInt( 0, pCex->iFrame - 1 ); printf( "\nUsing counter-example, which asserts output %d in frame %d.\n", pCex->iPo, pCex->iFrame ); Aig_ManCounterExampleValueStart( pAig, pCex ); printf( "Value of object %d in frame %d is %d.\n", Aig_ObjId(pObj), iFrame, diff --git a/src/aig/bar/bar.c b/src/aig/bar/bar.c deleted file mode 100644 index b5c31779..00000000 --- a/src/aig/bar/bar.c +++ /dev/null @@ -1,187 +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 "abc_global.h" -#include "main.h" -#include "bar.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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; - Abc_Frame_t * pFrame; - pFrame = Abc_FrameReadGlobalFrame(); - if ( pFrame == NULL ) - return NULL; - if ( !Abc_FrameShowProgress(pFrame) ) return NULL; - p = ABC_ALLOC( Bar_Progress_t, 1 ); - 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 ); - ABC_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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/bar/bar.h b/src/aig/bar/bar.h deleted file mode 100644 index 65c9ec6a..00000000 --- a/src/aig/bar/bar.h +++ /dev/null @@ -1,78 +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 _WIN32 -#define inline __inline // compatible with MS VS 6.0 -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -#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); } - - - - -ABC_NAMESPACE_HEADER_END - - - -#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/bbl/bblif.c b/src/aig/bbl/bblif.c deleted file mode 100644 index e68258d9..00000000 --- a/src/aig/bbl/bblif.c +++ /dev/null @@ -1,1518 +0,0 @@ -/**CFile**************************************************************** - - FileName [bblif.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Binary BLIF representation for logic networks.] - - Synopsis [Main implementation module.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 28, 2009.] - - Revision [$Id: bblif.c,v 1.00 2009/02/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include -#include -#include -#include -#include - -#include "abc_global.h" -#include "bblif.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// vector of integers -typedef struct Vec_Int_t_ Vec_Int_t; -struct Vec_Int_t_ -{ - int nCap; - int nSize; - int * pArray; -}; - -// vector of characters -typedef struct Vec_Str_t_ Vec_Str_t; -struct Vec_Str_t_ -{ - int nCap; - int nSize; - char * pArray; -}; - -// network object -struct Bbl_Obj_t_ -{ - int Id; // user ID - int Fnc; // functionality - unsigned fCi : 1; // combinational input - unsigned fCo : 1; // combinational output - unsigned fBox : 1; // subcircuit - unsigned fMark : 1; // temporary mark - unsigned nFanins : 28; // fanin number - int pFanins[0]; // fanin array -}; - -// object function -typedef struct Bbl_Fnc_t_ Bbl_Fnc_t; -struct Bbl_Fnc_t_ -{ - int nWords; // word number - int pWords[0]; // word array -}; - -// object function -typedef struct Bbl_Ent_t_ Bbl_Ent_t; -struct Bbl_Ent_t_ -{ - int iFunc; // function handle - int iNext; // next entry handle -}; - -// data manager -struct Bbl_Man_t_ -{ - // data pool - Vec_Str_t * pName; // design name - Vec_Str_t * pObjs; // vector of objects - Vec_Str_t * pFncs; // vector of functions - // construction - Vec_Int_t * vId2Obj; // mapping user IDs into objects - Vec_Int_t * vObj2Id; // mapping objects into user IDs - Vec_Int_t * vFaninNums; // mapping user IDs into fanin number - // file contents - int nFileSize; // file size - char * pFileData; // file contents - // other data - Vec_Str_t * pEnts; // vector of entries - int SopMap[17][17]; // mapping vars x cubes into entry handles -}; - -static inline int Bbl_ObjIsCi( Bbl_Obj_t * pObj ) { return pObj->fCi; } -static inline int Bbl_ObjIsCo( Bbl_Obj_t * pObj ) { return pObj->fCo; } -static inline int Bbl_ObjIsNode( Bbl_Obj_t * pObj ) { return!pObj->fCi && !pObj->fCo; } - -static inline int Bbl_ObjFaninNum( Bbl_Obj_t * pObj ) { return pObj->nFanins; } -static inline Bbl_Obj_t * Bbl_ObjFanin( Bbl_Obj_t * pObj, int i ) { return (Bbl_Obj_t *)(((char *)pObj) - pObj->pFanins[i]); } - -static inline int Bbl_ObjSize( Bbl_Obj_t * pObj ) { return sizeof(Bbl_Obj_t) + sizeof(int) * pObj->nFanins; } -static inline int Bbl_FncSize( Bbl_Fnc_t * pFnc ) { return sizeof(Bbl_Fnc_t) + sizeof(int) * pFnc->nWords; } - -static inline Bbl_Obj_t * Bbl_VecObj( Vec_Str_t * p, int h ) { return (Bbl_Obj_t *)(p->pArray + h); } -static inline Bbl_Fnc_t * Bbl_VecFnc( Vec_Str_t * p, int h ) { return (Bbl_Fnc_t *)(p->pArray + h); } -static inline Bbl_Ent_t * Bbl_VecEnt( Vec_Str_t * p, int h ) { return (Bbl_Ent_t *)(p->pArray + h); } - -static inline char * Bbl_ManSop( Bbl_Man_t * p, int h ) { return (char *)Bbl_VecFnc(p->pFncs, h)->pWords; } -static inline Bbl_Obj_t * Bbl_ManObj( Bbl_Man_t * p, int Id ) { return Bbl_VecObj(p->pObjs, p->vId2Obj->pArray[Id]); } - -#define Bbl_ManForEachObj_int( p, pObj, h ) \ - for ( h = 0; (h < p->nSize) && (pObj = Bbl_VecObj(p,h)); h += Bbl_ObjSize(pObj) ) -#define Bbl_ManForEachFnc_int( p, pObj, h ) \ - for ( h = 0; (h < p->nSize) && (pObj = Bbl_VecFnc(p,h)); h += Bbl_FncSize(pObj) ) -#define Bbl_ObjForEachFanin_int( pObj, pFanin, i ) \ - for ( i = 0; (i < (int)pObj->nFanins) && (pFanin = Bbl_ObjFanin(pObj,i)); i++ ) - -#define BBLIF_ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) -#define BBLIF_CALLOC(type, num) ((type *) calloc((num), sizeof(type))) -#define BBLIF_FALLOC(type, num) ((type *) memset(malloc(sizeof(type) * (num)), 0xff, sizeof(type) * (num))) -#define BBLIF_FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) -#define BBLIF_REALLOC(type, obj, num) \ - ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ - ((type *) malloc(sizeof(type) * (num)))) - -//////////////////////////////////////////////////////////////////////// -/// 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 = BBLIF_ALLOC( Vec_Int_t, 1 ); - if ( nCap > 0 && nCap < 16 ) - nCap = 16; - p->nSize = 0; - p->nCap = nCap; - p->pArray = p->nCap? BBLIF_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 = BBLIF_ALLOC( Vec_Int_t, 1 ); - p->nSize = nSize; - p->nCap = nSize; - p->pArray = pArray; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntFree( Vec_Int_t * p ) -{ - BBLIF_FREE( p->pArray ); - BBLIF_FREE( p ); -} - -/**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 = BBLIF_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 Fill ) -{ - int i; - Vec_IntGrow( p, nSize ); - for ( i = 0; i < nSize; i++ ) - p->pArray[i] = Fill; - 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 Fill ) -{ - int i; - if ( p->nSize >= nSize ) - return; - if ( nSize > 2 * p->nCap ) - Vec_IntGrow( p, nSize ); - else if ( nSize > p->nCap ) - Vec_IntGrow( p, 2 * p->nCap ); - for ( i = p->nSize; i < nSize; i++ ) - p->pArray[i] = Fill; - p->nSize = nSize; -} - -/**Function************************************************************* - - Synopsis [Returns the entry even if the place not exist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_IntGetEntry( Vec_Int_t * p, int i ) -{ - Vec_IntFillExtra( p, i + 1, 0 ); - return Vec_IntEntry( p, i ); -} - -/**Function************************************************************* - - Synopsis [Inserts the entry even if the place does not exist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntSetEntry( Vec_Int_t * p, int i, int Entry ) -{ - Vec_IntFillExtra( p, i + 1, 0 ); - Vec_IntWriteEntry( p, i, Entry ); -} - -/**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 [Allocates a vector with the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Str_t * Vec_StrAlloc( int nCap ) -{ - Vec_Str_t * p; - p = BBLIF_ALLOC( Vec_Str_t, 1 ); - if ( nCap > 0 && nCap < 16 ) - nCap = 16; - p->nSize = 0; - p->nCap = nCap; - p->pArray = p->nCap? BBLIF_ALLOC( char, p->nCap ) : NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [Creates the vector from an array of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Str_t * Vec_StrAllocArray( char * pArray, int nSize ) -{ - Vec_Str_t * p; - p = BBLIF_ALLOC( Vec_Str_t, 1 ); - p->nSize = nSize; - p->nCap = nSize; - p->pArray = pArray; - return p; -} - -/**Fnction************************************************************* - - Synopsis [Returns a piece of memory.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Vec_StrFetch( Vec_Str_t * p, int nBytes ) -{ - while ( p->nSize + nBytes > p->nCap ) - { - p->pArray = BBLIF_REALLOC( char, p->pArray, 3 * p->nCap ); - p->nCap *= 3; - } - p->nSize += nBytes; - return p->pArray + p->nSize - nBytes; -} - -/**Fnction************************************************************* - - Synopsis [Write vector into file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Vec_StrWrite( FILE * pFile, Vec_Str_t * p ) -{ - fwrite( &p->nSize, sizeof(int), 1, pFile ); - fwrite( p->pArray, sizeof(char), p->nSize, pFile ); -} - -/**Fnction************************************************************* - - Synopsis [Write vector into file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Str_t * Vec_StrRead( char ** ppStr ) -{ - Vec_Str_t * p; - char * pStr = *ppStr; - p = Vec_StrAlloc( 0 ); - p->nSize = *(int *)pStr; - p->pArray = pStr + sizeof(int); - *ppStr = pStr + sizeof(int) + p->nSize * sizeof(char); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_StrSize( Vec_Str_t * p ) -{ - return p->nSize; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_StrFree( Vec_Str_t * p ) -{ - BBLIF_FREE( p->pArray ); - BBLIF_FREE( p ); -} - - - - - -/**Fnction************************************************************* - - Synopsis [Returns the file size.] - - Description [The file should be closed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Bbl_ManFileSize( char * pFileName ) -{ - FILE * pFile; - int nFileSize; - pFile = fopen( pFileName, "r" ); - if ( pFile == NULL ) - { - printf( "Bbl_ManFileSize(): The file is unavailable (absent or open).\n" ); - return 0; - } - fseek( pFile, 0, SEEK_END ); - nFileSize = ftell( pFile ); - fclose( pFile ); - return nFileSize; -} - -/**Fnction************************************************************* - - Synopsis [Read data from file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Bbl_ManFileRead( char * pFileName ) -{ - FILE * pFile; - char * pContents; - int nFileSize; - nFileSize = Bbl_ManFileSize( pFileName ); - pFile = fopen( pFileName, "rb" ); - pContents = BBLIF_ALLOC( char, nFileSize ); - fread( pContents, nFileSize, 1, pFile ); - fclose( pFile ); - return pContents; -} - - - -/**Fnction************************************************************* - - Synopsis [Writes data into file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbl_ManDumpBinaryBlif( Bbl_Man_t * p, char * pFileName ) -{ - FILE * pFile; - pFile = fopen( pFileName, "wb" ); - Vec_StrWrite( pFile, p->pName ); - Vec_StrWrite( pFile, p->pObjs ); - Vec_StrWrite( pFile, p->pFncs ); - fclose( pFile ); -} - -/**Fnction************************************************************* - - Synopsis [Creates manager after reading.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bbl_Man_t * Bbl_ManReadBinaryBlif( char * pFileName ) -{ - Bbl_Man_t * p; - Bbl_Obj_t * pObj; - char * pBuffer; - int h; - p = BBLIF_ALLOC( Bbl_Man_t, 1 ); - memset( p, 0, sizeof(Bbl_Man_t) ); - p->nFileSize = Bbl_ManFileSize( pFileName ); - p->pFileData = Bbl_ManFileRead( pFileName ); - // extract three managers - pBuffer = p->pFileData; - p->pName = Vec_StrRead( &pBuffer ); - p->pObjs = Vec_StrRead( &pBuffer ); - p->pFncs = Vec_StrRead( &pBuffer ); - assert( pBuffer - p->pFileData == p->nFileSize ); - // remember original IDs in the objects - p->vObj2Id = Vec_IntAlloc( 1000 ); - Bbl_ManForEachObj_int( p->pObjs, pObj, h ) - { - Vec_IntPush( p->vObj2Id, pObj->Id ); - pObj->Id = Vec_IntSize(p->vObj2Id) - 1; - } - return p; -} - -/**Fnction************************************************************* - - Synopsis [Prints stats of the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbl_ManPrintStats( Bbl_Man_t * p ) -{ - Bbl_Obj_t * pObj; - Bbl_Fnc_t * pFnc; - int h, nFuncs = 0, nNodes = 0, nObjs = 0; - Bbl_ManForEachObj_int( p->pObjs, pObj, h ) - nObjs++, nNodes += Bbl_ObjIsNode(pObj); - Bbl_ManForEachFnc_int( p->pFncs, pFnc, h ) - nFuncs++; - printf( "Total objects = %7d. Total nodes = %7d. Unique functions = %7d.\n", nObjs, nNodes, nFuncs ); - printf( "Name manager = %5.2f Mb\n", 1.0*Vec_StrSize(p->pName)/(1 << 20) ); - printf( "Objs manager = %5.2f Mb\n", 1.0*Vec_StrSize(p->pObjs)/(1 << 20) ); - printf( "Fncs manager = %5.2f Mb\n", 1.0*Vec_StrSize(p->pFncs)/(1 << 20) ); -} - -/**Fnction************************************************************* - - Synopsis [Deletes the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbl_ManStop( Bbl_Man_t * p ) -{ - if ( p->vId2Obj ) Vec_IntFree( p->vId2Obj ); - if ( p->vObj2Id ) Vec_IntFree( p->vObj2Id ); - if ( p->vFaninNums ) Vec_IntFree( p->vFaninNums ); - if ( p->pFileData ) - { - BBLIF_FREE( p->pFileData ); - p->pName->pArray = NULL; - p->pObjs->pArray = NULL; - p->pFncs->pArray = NULL; - } - if ( p->pEnts ) - Vec_StrFree( p->pEnts ); - Vec_StrFree( p->pName ); - Vec_StrFree( p->pObjs ); - Vec_StrFree( p->pFncs ); - BBLIF_FREE( p ); -} - -/**Fnction************************************************************* - - Synopsis [Creates manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bbl_Man_t * Bbl_ManStart( char * pName ) -{ - Bbl_Man_t * p; - int nLength; - p = BBLIF_ALLOC( Bbl_Man_t, 1 ); - memset( p, 0, sizeof(Bbl_Man_t) ); - nLength = pName? 4 * ((strlen(pName) + 1) / 4 + 1) : 0; - p->pName = Vec_StrAlloc( nLength ); - p->pName->nSize = p->pName->nCap; - if ( pName ) - strcpy( p->pName->pArray, pName ); - p->pObjs = Vec_StrAlloc( 1 << 16 ); - p->pFncs = Vec_StrAlloc( 1 << 16 ); - p->pEnts = Vec_StrAlloc( 1 << 16 ); p->pEnts->nSize = 1; - p->vId2Obj = Vec_IntStart( 1 << 10 ); - p->vFaninNums = Vec_IntStart( 1 << 10 ); - return p; -} - - - - -/**Function************************************************************* - - Synopsis [Performs selection sort on the array of cubes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbl_ManSortCubes( char ** pCubes, int nCubes, int nVars ) -{ - char * pTemp; - int i, j, best_i; - for ( i = 0; i < nCubes-1; i++ ) - { - best_i = i; - for (j = i+1; j < nCubes; j++) - if ( memcmp( pCubes[j], pCubes[best_i], nVars ) < 0 ) - best_i = j; - pTemp = pCubes[i]; pCubes[i] = pCubes[best_i]; pCubes[best_i] = pTemp; - } -} - -/**Function************************************************************* - - Synopsis [Sorts the cubes in the SOP to uniqify them to some extent.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Bbl_ManSortSop( char * pSop, int nVars ) -{ - char ** pCubes, * pSopNew; - int c, Length, nCubes; - Length = strlen(pSop); - assert( Length % (nVars + 3) == 0 ); - nCubes = Length / (nVars + 3); - if ( nCubes < 2 ) - { - pSopNew = BBLIF_ALLOC( char, Length + 1 ); - memcpy( pSopNew, pSop, Length + 1 ); - return pSopNew; - } - pCubes = BBLIF_ALLOC( char *, nCubes ); - for ( c = 0; c < nCubes; c++ ) - pCubes[c] = pSop + c * (nVars + 3); - if ( nCubes < 300 ) - Bbl_ManSortCubes( pCubes, nCubes, nVars ); - pSopNew = BBLIF_ALLOC( char, Length + 1 ); - for ( c = 0; c < nCubes; c++ ) - memcpy( pSopNew + c * (nVars + 3), pCubes[c], nVars + 3 ); - BBLIF_FREE( pCubes ); - pSopNew[nCubes * (nVars + 3)] = 0; - return pSopNew; -} - -/**Fnction************************************************************* - - Synopsis [Saves one entry.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Bbl_ManCreateEntry( Bbl_Man_t * p, int iFunc, int iNext ) -{ - Bbl_Ent_t * pEnt; - pEnt = (Bbl_Ent_t *)Vec_StrFetch( p->pEnts, 2 * sizeof(int) ); - pEnt->iFunc = iFunc; - pEnt->iNext = iNext; - return (char *)pEnt - p->pEnts->pArray; -} - -/**Function************************************************************* - - Synopsis [Sorts the cubes in the SOP to uniqify them to some extent.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Bbl_ManSopCheckUnique( Bbl_Man_t * p, char * pSop, int nVars, int nCubes, int iFunc ) -{ - Bbl_Fnc_t * pFnc; - Bbl_Ent_t * pEnt; - int h, Length = strlen(pSop) + 1; - int nWords = (Length / 4 + (Length % 4 > 0)); - if ( nVars > 16 ) nVars = 16; - if ( nCubes > 16 ) nCubes = 16; -// if ( nVars == 16 && nCubes == 16 ) -// return iFunc; - for ( h = p->SopMap[nVars][nCubes]; h; h = pEnt->iNext ) - { - pEnt = Bbl_VecEnt( p->pEnts, h ); - pFnc = Bbl_VecFnc( p->pFncs, pEnt->iFunc ); - assert( nVars == 16 || nCubes == 16 || pFnc->nWords == nWords ); - if ( pFnc->nWords == nWords && memcmp( pFnc->pWords, pSop, Length ) == 0 ) - return pEnt->iFunc; - } - p->SopMap[nVars][nCubes] = Bbl_ManCreateEntry( p, iFunc, p->SopMap[nVars][nCubes] ); - return iFunc; -} - -/**Fnction************************************************************* - - Synopsis [Saves one SOP.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Bbl_ManSaveSop( Bbl_Man_t * p, char * pSop, int nVars ) -{ - Bbl_Fnc_t * pFnc; - char * pSopNew; - int iFunc, Length = strlen(pSop) + 1; - int nWords = Length / 4 + (Length % 4 > 0); - // reorder cubes to semi-canicize SOPs - pSopNew = Bbl_ManSortSop( pSop, nVars ); - // get the candidate location - iFunc = Bbl_ManSopCheckUnique( p, pSopNew, nVars, Length / (nVars + 3), Vec_StrSize(p->pFncs) ); -// iFunc = Vec_StrSize(p->pFncs); - if ( iFunc == Vec_StrSize(p->pFncs) ) - { // store this SOP - pFnc = (Bbl_Fnc_t *)Vec_StrFetch( p->pFncs, sizeof(Bbl_Fnc_t) + nWords * sizeof(int) ); - pFnc->pWords[nWords-1] = 0; - pFnc->nWords = nWords; - strcpy( (char *)pFnc->pWords, pSopNew ); - assert( iFunc == (char *)pFnc - p->pFncs->pArray ); - } - BBLIF_FREE( pSopNew ); - return iFunc; -} - -/**Fnction************************************************************* - - Synopsis [Adds one object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbl_ManCreateObject( Bbl_Man_t * p, Bbl_Type_t Type, int ObjId, int nFanins, char * pSop ) -{ - Bbl_Obj_t * pObj; - if ( Type == BBL_OBJ_CI && nFanins != 0 ) - { - printf( "Attempting to create a combinational input with %d fanins (should be 0).\n", nFanins ); - return; - } - if ( Type == BBL_OBJ_CO && nFanins != 1 ) - { - printf( "Attempting to create a combinational output with %d fanins (should be 1).\n", nFanins ); - return; - } - pObj = (Bbl_Obj_t *)Vec_StrFetch( p->pObjs, sizeof(Bbl_Obj_t) + nFanins * sizeof(int) ); - memset( pObj, 0, sizeof(Bbl_Obj_t) ); - Vec_IntSetEntry( p->vId2Obj, ObjId, (char *)pObj - p->pObjs->pArray ); - Vec_IntSetEntry( p->vFaninNums, ObjId, 0 ); - pObj->fCi = (Type == BBL_OBJ_CI); - pObj->fCo = (Type == BBL_OBJ_CO); - pObj->Id = ObjId; - pObj->Fnc = pSop? Bbl_ManSaveSop(p, pSop, nFanins) : -1; - pObj->nFanins = nFanins; -} - -/**Fnction************************************************************* - - Synopsis [Creates fanin/fanout relationship between two objects.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbl_ManAddFanin( Bbl_Man_t * p, int ObjId, int FaninId ) -{ - Bbl_Obj_t * pObj, * pFanin; - int iFanin; - pObj = Bbl_ManObj( p, ObjId ); - if ( Bbl_ObjIsCi(pObj) ) - { - printf( "Bbl_ManAddFanin(): Cannot add fanin of the combinational input (Id = %d).\n", ObjId ); - return; - } - pFanin = Bbl_ManObj( p, FaninId ); - if ( Bbl_ObjIsCo(pFanin) ) - { - printf( "Bbl_ManAddFanin(): Cannot add fanout of the combinational output (Id = %d).\n", FaninId ); - return; - } - iFanin = Vec_IntEntry( p->vFaninNums, ObjId ); - if ( iFanin >= (int)pObj->nFanins ) - { - printf( "Bbl_ManAddFanin(): Trying to add more fanins to object (Id = %d) than declared (%d).\n", ObjId, pObj->nFanins ); - return; - } - assert( iFanin < (int)pObj->nFanins ); - Vec_IntWriteEntry( p->vFaninNums, ObjId, iFanin+1 ); - pObj->pFanins[iFanin] = (char *)pObj - (char *)pFanin; -} - - -/**Fnction************************************************************* - - Synopsis [Returns 1 if the manager was created correctly.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Bbl_ManCheck( Bbl_Man_t * p ) -{ - Bbl_Obj_t * pObj; - int h, RetValue = 1; - Bbl_ManForEachObj_int( p->pObjs, pObj, h ) - { - if ( Bbl_ObjIsNode(pObj) && pObj->Fnc == -1 ) - RetValue = 0, printf( "Bbl_ManCheck(): Node %d does not have function specified.\n", pObj->Id ); - if ( Bbl_ObjIsCi(pObj) && pObj->Fnc != -1 ) - RetValue = 0, printf( "Bbl_ManCheck(): CI with %d has function specified.\n", pObj->Id ); - if ( Bbl_ObjIsCo(pObj) && pObj->Fnc != -1 ) - RetValue = 0, printf( "Bbl_ManCheck(): CO with %d has function specified.\n", pObj->Id ); - if ( Vec_IntEntry(p->vFaninNums, pObj->Id) != (int)pObj->nFanins ) - RetValue = 0, printf( "Bbl_ManCheck(): Object %d has less fanins (%d) than declared (%d).\n", - pObj->Id, Vec_IntEntry(p->vFaninNums, pObj->Id), pObj->nFanins ); - } - return RetValue; -} - - -/**Fnction************************************************************* - - Synopsis [Misc APIs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Bbl_ObjIsInput( Bbl_Obj_t * p ) { return Bbl_ObjIsCi(p); } -int Bbl_ObjIsOutput( Bbl_Obj_t * p ) { return Bbl_ObjIsCo(p); } -int Bbl_ObjIsLut( Bbl_Obj_t * p ) { return Bbl_ObjIsNode(p); } -int Bbl_ObjId( Bbl_Obj_t * p ) { return p->Id; } -int Bbl_ObjIdOriginal( Bbl_Man_t * pMan, Bbl_Obj_t * p ) { assert(0); return Vec_IntEntry(pMan->vObj2Id, p->Id); } -int Bbl_ObjFaninNumber( Bbl_Obj_t * p ) { return Bbl_ObjFaninNum(p); } -char * Bbl_ObjSop( Bbl_Man_t * pMan, Bbl_Obj_t * p ) { return Bbl_ManSop(pMan, p->Fnc); } -int Bbl_ObjIsMarked( Bbl_Obj_t * p ) { return p->fMark; } -void Bbl_ObjMark( Bbl_Obj_t * p ) { p->fMark = 1; } -int Bbl_ObjFncHandle( Bbl_Obj_t * p ) { return p->Fnc; } - -/**Fnction************************************************************* - - Synopsis [Returns the name of the design.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Bbl_ManName( Bbl_Man_t * p ) -{ - return p->pName->pArray; -} - -/**Fnction************************************************************* - - Synopsis [Returns the maximum handle of the SOP.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Bbl_ManFncSize( Bbl_Man_t * p ) -{ - return p->pFncs->nSize; -} - -/**Fnction************************************************************* - - Synopsis [Returns the first object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bbl_Obj_t * Bbl_ManObjFirst( Bbl_Man_t * p ) -{ - return Bbl_VecObj( p->pObjs, 0 ); -} - -/**Fnction************************************************************* - - Synopsis [Returns the next object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bbl_Obj_t * Bbl_ManObjNext( Bbl_Man_t * p, Bbl_Obj_t * pObj ) -{ - char * pNext = (char *)pObj + Bbl_ObjSize(pObj); - char * pEdge = p->pObjs->pArray + p->pObjs->nSize; - return (Bbl_Obj_t *)(pNext < pEdge ? pNext : NULL); -} - -/**Fnction************************************************************* - - Synopsis [Returns the first fanin.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bbl_Obj_t * Bbl_ObjFaninFirst( Bbl_Obj_t * p ) -{ - return Bbl_ObjFaninNum(p) ? Bbl_ObjFanin( p, 0 ) : NULL; -} - -/**Fnction************************************************************* - - Synopsis [Returns the next fanin.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bbl_Obj_t * Bbl_ObjFaninNext( Bbl_Obj_t * p, Bbl_Obj_t * pPrev ) -{ - Bbl_Obj_t * pFanin; - int i; - Bbl_ObjForEachFanin_int( p, pFanin, i ) - if ( pFanin == pPrev ) - break; - return i < Bbl_ObjFaninNum(p) - 1 ? Bbl_ObjFanin( p, i+1 ) : NULL; -} - -/**Fnction************************************************************* - - Synopsis [Drives text BLIF file for debugging.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbl_ManDumpBlif( Bbl_Man_t * p, char * pFileName ) -{ - FILE * pFile; - Bbl_Obj_t * pObj, * pFanin; - pFile = fopen( pFileName, "w" ); - fprintf( pFile, "# Test file written by Bbl_ManDumpBlif() in ABC.\n" ); - fprintf( pFile, ".model %s\n", Bbl_ManName(p) ); - // write objects - Bbl_ManForEachObj( p, pObj ) - { - if ( Bbl_ObjIsInput(pObj) ) - fprintf( pFile, ".inputs %d\n", Bbl_ObjId(pObj) ); - else if ( Bbl_ObjIsOutput(pObj) ) - fprintf( pFile, ".outputs %d\n", Bbl_ObjId(pObj) ); - else if ( Bbl_ObjIsLut(pObj) ) - { - fprintf( pFile, ".names" ); - Bbl_ObjForEachFanin( pObj, pFanin ) - fprintf( pFile, " %d", Bbl_ObjId(pFanin) ); - fprintf( pFile, " %d\n", Bbl_ObjId(pObj) ); - fprintf( pFile, "%s", Bbl_ObjSop(p, pObj) ); - } - else assert( 0 ); - } - // write output drivers - Bbl_ManForEachObj( p, pObj ) - { - if ( !Bbl_ObjIsOutput(pObj) ) - continue; - fprintf( pFile, ".names" ); - Bbl_ObjForEachFanin( pObj, pFanin ) - fprintf( pFile, " %d", Bbl_ObjId(pFanin) ); - fprintf( pFile, " %d\n", Bbl_ObjId(pObj) ); - fprintf( pFile, "1 1\n" ); - } - fprintf( pFile, ".end\n" ); - fclose( pFile ); -} - -/**Fnction************************************************************* - - Synopsis [Converting truth table into an SOP.] - - Description [The truth table is given as a bit-string pTruth - composed of 2^nVars bits. The result is an SOP derived by - collecting minterms appearing in the truth table. The SOP is - represented as a C-string, as documented in file "bblif.h". - It is recommended to limit the use of this procedure to Boolean - functions up to 6 inputs.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Bbl_ManTruthToSop( unsigned * pTruth, int nVars ) -{ - char * pResult, * pTemp; - int nMints, nOnes, b, v; - assert( nVars >= 0 && nVars <= 16 ); - nMints = (1 << nVars); - // count the number of ones - nOnes = 0; - for ( b = 0; b < nMints; b++ ) - nOnes += ((pTruth[b>>5] >> (b&31)) & 1); - // handle constants - if ( nOnes == 0 || nOnes == nMints ) - { - pResult = pTemp = BBLIF_ALLOC( char, nVars + 4 ); - for ( v = 0; v < nVars; v++ ) - *pTemp++ = '-'; - *pTemp++ = ' '; - *pTemp++ = nOnes? '1' : '0'; - *pTemp++ = '\n'; - *pTemp++ = 0; - assert( pTemp - pResult == nVars + 4 ); - return pResult; - } - pResult = pTemp = BBLIF_ALLOC( char, nOnes * (nVars + 3) + 1 ); - for ( b = 0; b < nMints; b++ ) - { - if ( ((pTruth[b>>5] >> (b&31)) & 1) == 0 ) - continue; - for ( v = 0; v < nVars; v++ ) - *pTemp++ = ((b >> v) & 1)? '1' : '0'; - *pTemp++ = ' '; - *pTemp++ = '1'; - *pTemp++ = '\n'; - } - *pTemp++ = 0; - assert( pTemp - pResult == nOnes * (nVars + 3) + 1 ); - return pResult; -} - -/**Function************************************************************* - - Synopsis [Allocates the array of truth tables for the given number of vars.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Bbl_ManSopToTruthElem( int nVars, unsigned ** pVars ) -{ - unsigned Masks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; - int i, k, nWords; - nWords = (nVars <= 5 ? 1 : (1 << (nVars - 5))); - for ( i = 0; i < nVars; i++ ) - { - if ( i < 5 ) - { - for ( k = 0; k < nWords; k++ ) - pVars[i][k] = Masks[i]; - } - else - { - for ( k = 0; k < nWords; k++ ) - if ( k & (1 << (i-5)) ) - pVars[i][k] = ~(unsigned)0; - else - pVars[i][k] = 0; - } - } -} - -/**Fnction************************************************************* - - Synopsis [Converting SOP into a truth table.] - - Description [The SOP is represented as a C-string, as documented in - file "bblif.h". The truth table is returned as a bit-string composed - of 2^nVars bits. For functions of less than 6 variables, the full - machine word is returned. (The truth table looks as if the function - had 5 variables.) The use of this procedure should be limited to - Boolean functions with no more than 16 inputs.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Bbl_ManSopToTruth( char * pSop, int nVars ) -{ - unsigned * pTruth, * pCube, * pVars[16]; - int nWords = nVars <= 5 ? 1 : (1 << (nVars - 5)); - int v, c, w, nCubes, fCompl = 0; - if ( pSop == NULL ) - return NULL; - if ( strlen(pSop) % (nVars + 3) != 0 ) - { - printf( "Bbl_ManSopToTruth(): SOP is represented incorrectly.\n" ); - return NULL; - } - // create storage for TTs of the result, elementary variables and the temp cube - pTruth = BBLIF_ALLOC( unsigned, nWords ); - pVars[0] = BBLIF_ALLOC( unsigned, nWords * (nVars+1) ); - for ( v = 1; v < nVars; v++ ) - pVars[v] = pVars[v-1] + nWords; - pCube = pVars[v-1] + nWords; - Bbl_ManSopToTruthElem( nVars, pVars ); - // iterate through the cubes - memset( pTruth, 0, sizeof(unsigned) * nWords ); - nCubes = strlen(pSop) / (nVars + 3); - for ( c = 0; c < nCubes; c++ ) - { - fCompl = (pSop[nVars+1] == '0'); - memset( pCube, 0xff, sizeof(unsigned) * nWords ); - // iterate through the literals of the cube - for ( v = 0; v < nVars; v++ ) - if ( pSop[v] == '1' ) - for ( w = 0; w < nWords; w++ ) - pCube[w] &= pVars[v][w]; - else if ( pSop[v] == '0' ) - for ( w = 0; w < nWords; w++ ) - pCube[w] &= ~pVars[v][w]; - // add cube to storage - for ( w = 0; w < nWords; w++ ) - pTruth[w] |= pCube[w]; - // go to the next cube - pSop += (nVars + 3); - } - BBLIF_FREE( pVars[0] ); - if ( fCompl ) - for ( w = 0; w < nWords; w++ ) - pTruth[w] = ~pTruth[w]; - return pTruth; -} - - -/**Fnction************************************************************* - - Synopsis [Checks the truth table computation.] - - Description [We construct the logic network for the half-adder represnted - using the BLIF file below] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbl_ManTestTruth( char * pSop, int nVars ) -{ - unsigned * pTruth; - char * pSopNew; - pTruth = Bbl_ManSopToTruth( pSop, nVars ); - pSopNew = Bbl_ManTruthToSop( pTruth, nVars ); - printf( "Old SOP:\n%s\n", pSop ); - printf( "New SOP:\n%s\n", pSopNew ); - BBLIF_FREE( pSopNew ); - BBLIF_FREE( pTruth ); -} - -/**Fnction************************************************************* - - Synopsis [This demo shows using the internal to construct a half-adder.] - - Description [We construct the logic network for the half-adder represnted - using the BLIF file below] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbl_ManSimpleDemo() -{ -/* - # There are contents of a BLIF file representing a half-adder: - .model hadder - .inputs a // ID = 1 - .inputs b // ID = 2 - .inputs cin // ID = 3 - .outputs s // ID = 4 - .outputs cout // ID = 5 - .names a b cin s_driver // ID = 6 - 100 1 - 010 1 - 001 1 - 111 1 - .names a b cin cout_driver // ID = 7 - -11 1 - 1-1 1 - 11- 1 - .names s_driver s - 1 1 - .names cout_driver cout - 1 1 - .end -*/ - Bbl_Man_t * p; - // start the data manager - p = Bbl_ManStart( "hadder" ); - // create CIs - Bbl_ManCreateObject( p, BBL_OBJ_CI, 1, 0, NULL ); // a - Bbl_ManCreateObject( p, BBL_OBJ_CI, 2, 0, NULL ); // b - Bbl_ManCreateObject( p, BBL_OBJ_CI, 3, 0, NULL ); // cin - // create COs - Bbl_ManCreateObject( p, BBL_OBJ_CO, 4, 1, NULL ); // s - Bbl_ManCreateObject( p, BBL_OBJ_CO, 5, 1, NULL ); // cout - // create internal nodes - Bbl_ManCreateObject( p, BBL_OBJ_NODE, 6, 3, "100 1\n010 1\n001 1\n111 1\n" ); // s_driver - Bbl_ManCreateObject( p, BBL_OBJ_NODE, 7, 3, "-11 1\n1-1 1\n11- 1\n" ); // cout_driver - // add fanins of node 6 - Bbl_ManAddFanin( p, 6, 1 ); // s_driver <- a - Bbl_ManAddFanin( p, 6, 2 ); // s_driver <- b - Bbl_ManAddFanin( p, 6, 3 ); // s_driver <- cin - // add fanins of node 7 - Bbl_ManAddFanin( p, 7, 1 ); // cout_driver <- a - Bbl_ManAddFanin( p, 7, 2 ); // cout_driver <- b - Bbl_ManAddFanin( p, 7, 3 ); // cout_driver <- cin - // add fanins of COs - Bbl_ManAddFanin( p, 4, 6 ); // s <- s_driver - Bbl_ManAddFanin( p, 5, 7 ); // cout <- cout_driver - // sanity check - Bbl_ManCheck( p ); - // write BLIF file as a sanity check - Bbl_ManDumpBlif( p, "hadder.blif" ); - // write binary BLIF file - Bbl_ManDumpBinaryBlif( p, "hadder.bblif" ); - // remove the manager - Bbl_ManStop( p ); - - -// Bbl_ManTestTruth( "100 1\n010 1\n001 1\n111 1\n", 3 ); -// Bbl_ManTestTruth( "-11 0\n1-1 0\n11- 0\n", 3 ); -// Bbl_ManTestTruth( "--- 1\n", 3 ); -} - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/bbl/bblif.h b/src/aig/bbl/bblif.h deleted file mode 100644 index 787d649f..00000000 --- a/src/aig/bbl/bblif.h +++ /dev/null @@ -1,285 +0,0 @@ -/**CFile**************************************************************** - - FileName [bblif.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Binary BLIF representation for logic networks.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 28, 2009.] - - Revision [$Id: bblif.h,v 1.00 2009/02/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __BBLIF_H__ -#define __BBLIF_H__ - - -/* - This file (taken together with "bblif.c") implements a stand-alone - interface between ABC and an application that uses ABC. - - The interface is designed to pass a combinational logic network - from the calling application to ABC using a binary BLIF format (BBLIF) - and return the network after synthesis/mapping/verification in ABC - back to the caller. - - The interface can do the following: - (1) accept a combinational logic network via a set of APIs - (2) write the logic network into a binary BLIF file readable by ABC - (3) read a binary BLIF file with a mapped network produced by ABC - (4) return the mapped network to the caller through a set of APIs - - It should be noted that the BBLIF interface can be used to pass - the network from the calling application into ABC without writing it - into a file. In this case, ABC should be compiled as a library and - linked to the calling application. The BBLIF manager can be given - directly to the procedure Bbl_ManToAbc() to convert it into an AIG. - Similarly, the resulting mapped network can be converted into - BBLIF manager and passed back after the call to Bbl_ManFromAbc(). - - Here these steps are described in more detail: - - (1) The BBLIF manager is allocated by calling Bbl_ManStart() and - deallocated by calling Bbl_ManStop(). - - The combinational network is composed of three types of objects: - (a) combinational inputs (CIs), (b) combinational outputs (COs), - (c) internal logic nodes represented using Sum-of-Products (SOPs) - similar to the way logic nodes are represented in SIS. Sequential - elements (flops) are currently not supported. A CI has no fanins. - A CO has exactly one fanin and no fanouts. Internal nodes can - have any number of fanins and fanouts. Only an internal node can - have a logic function. - - Before constructing the BBLIF manager, each object should be - assigned a unique non-negative (0-based) integer ID. The sequence - of ID numbers may have gaps in it (for example, 0, 1, 2, 5, 6, etc) - but care should be taken that the ID numbers do not grow too large - because internally they are used to index the objects. So if - the largest given ID has value N, an array of 4*N bytes will be - allocated internally by the BBLIF manager. Obviously if N = 1M, - the array will use 4Mb, but if N = 100M, it will use 0.4Gb. - - This object ID (called also "the original ID of the object") is - given to Bbl_ManCreateObject(), which construct the BBLIF objects - and to the procedure Bbl_ManAddFanin(), which creates fanin/fanout - relations between two objects. The exact number of fanins of an - object should be declared when calling Bbl_ManCreateObject(). - Later on, each node should be assigned as many fanins using - Bbl_ManAddFanin(). The order/number of fanins corresponds to the - order/number of variables in the SOP of the logic function of the - node. The declared and actual number of fanins should be the same. - otherwise the interface will not function correctly. This is checked - by the procedure Bbl_ManCheck(), which should be called when - constructing all objects and their fanins is finished. - - The SOP representation of the logic function should be given to - every internal node. It is given as a C-string, showing the SOP - as it would appear in a BLIF or PLA file. Each cube is composed - of characters '0', '1', and '-', and ended by a seqence of three - characters: space ' ', followed by '0' or '1' (depending on whether - on- or off-set is used), followed by the new line character '\n'. - For example, a two-input OR has the following SOP representation: - "1- 1\n-1 1\n", or equivalently, "00 0\n". The SOP for a constant - function with no fanins is represented as " 0\n" (constant 0) and - " 1\n" (constant 1). SOP for a constant node with some fanins - may also be represented. For example, constant 0 node with three - fanins will have SOP representation as follows: "--- 0\n". - - The objects can be added to the BBLIF manager in any order, but - by the time the fanin/fanout connections are created, corresponding - objects should be already created. - - The number of objects is limited by 2^31. The number of fanins - of one object is restricted to 2^28. The SOP representation can - have arbitrary many products (cubes), as long as memory is enough - to represent them in the C-string form, as described above. - - (2) To write the manager into a file, call procedure Bbl_ManDumpBinaryBlif(). - It is recommended to use files with extension ".bblif" because it - will allow ABC to call the approapriate reader in command "read". - - (3) To read the network from file, call procedure Bbl_ManReadBinaryBlif(). - - (4) It is assumed that ABC will return the network after mapping. - This network will arrive in a BBLIF file, from which the BBLIF - manager is created by the call to Bbl_ManReadBinaryBlif(). The - following APIs are useful to extract the mapped network from the manager: - - Iterator Bbl_ManForEachObj() iterates through the pointers to the - BBLIF objects, which are guaranteed to be in a topological order. - - For each object, the following APIs can be used: - Bbl_ObjIsInput() returns 1 if the object is a CI - Bbl_ObjIsOutput() returns 1 if the object is a CO - Bbl_ObjIsLut() returns 1 if the object is a logic node (lookup table) - Bbl_ObjFaninNumber() returns the number of fanins of the node - Bbl_ObjSop() returns the SOP representation of the node, as described above. - - A special attention should be given to the representation of object IDs - after mapping. Recall that when the outgoing BBLIF network is constructed, - the IDs of objects are assigned by the calling application and given to - the BBLIF manager when procedure Bbl_ManCreateObject() is called. - We refer to these object IDs as "original IDs of the objects". - - When the network has been given to ABC, mapped, and returned to the - calling application in the incoming BBLIF file, only CIs and COs are - guaranteed to preserve their "original IDs". Other objects may be created - during synthesis/mapping. The original IDs of these objects are set to -1. - - The following two APIs are used to return the IDs of objects after mapping: - Bbl_ObjId() returns the new ID (useful to construct network after mapping) - Bbl_ObjIdOriginal() returns the original ID (or -1 if this is a new object). - - !!!***!!! - Note: The original ID currently cannot be returned by Bbl_ObjIdOriginal(). - It is recommended to use the work-around described below. - !!!***!!! - - The original ID is useful to map CIs/COs after mapping into CIs/COs before - mapping. However, the order of CIs/COs after mapping in the incoming network - is the same as the order of their creation by the calling application - in the outgoing network. This allows for a workaround that does not have - the need for the original IDs. We can simply iterate through the objects - after mapping, and create CIs and COs in the order of their appearance, - and this order is guaranteed to be the same as the order of their - construction by the calling application. - - It is also worth noting that currently the internal node names are not - preserved by ABC during synthesis. This may change in the future. and then - some of the internal nodes will preserve their IDs, which may allow the - calling application to reconstruct the names of some of the nodes after - synthesis/mapping in ABC using their original IDs whenever available. - - Finally, iterator Bbl_ObjForEachFanin() can be used to iterate through - the fanins of each mapped object. For CIs, there will be no fanins. - For COs, there will be exactly one fanin. For the internal nodes (LUTs) - the number of fanins is the number of inputs of these nodes. - - A demo of using this interface is included at the bottom of file "bblif.c" in - procedure Bbl_ManSimpleDemo(). Additional examples can be found in the files - "abc\src\base\io\ioReadBblif.c" and "abc\src\base\io\ioWriteBblif.c". These - files illustrate how an ABC network is created from the BBLIF data manager - and how the data manager is created from the ABC network. - - Note that only the files "bblif.h" and "bblif.c" are needed for interfacing - the user's application with ABC, while other files should not be compiled - as part of the application code. - - Finally, a warning regarding endianness. The interface may not work - if the BBLIF file is produced on a machine whose engianness is different - from the machine, which is reading this file. -*/ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -#ifdef _WIN32 -#define inline __inline -#endif - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -// object types -typedef enum { - BBL_OBJ_NONE, // 0: non-existent object - BBL_OBJ_CI, // 1: primary input - BBL_OBJ_CO, // 2: primary output - BBL_OBJ_NODE, // 3: buffer node - BBL_OBJ_VOID // 4: unused object -} Bbl_Type_t; - -// data manager -typedef struct Bbl_Man_t_ Bbl_Man_t; - -// data object -typedef struct Bbl_Obj_t_ Bbl_Obj_t; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// (1) creating the data manager in the application code -extern Bbl_Man_t * Bbl_ManStart( char * pName ); -extern void Bbl_ManCreateObject( Bbl_Man_t * p, Bbl_Type_t Type, int ObjId, int nFanins, char * pSop ); -extern void Bbl_ManAddFanin( Bbl_Man_t * p, int ObjId, int FaninId ); -extern int Bbl_ManCheck( Bbl_Man_t * p ); -extern void Bbl_ManPrintStats( Bbl_Man_t * p ); -extern void Bbl_ManStop( Bbl_Man_t * p ); - -// (2) writing the data manager into file -extern void Bbl_ManDumpBinaryBlif( Bbl_Man_t * p, char * pFileName ); - -// (3) reading the data manager from file -extern Bbl_Man_t * Bbl_ManReadBinaryBlif( char * pFileName ); - -// (4) returning the mapped network after reading the data manaager from file -extern char * Bbl_ManName( Bbl_Man_t * p ); -extern int Bbl_ObjIsInput( Bbl_Obj_t * p ); -extern int Bbl_ObjIsOutput( Bbl_Obj_t * p ); -extern int Bbl_ObjIsLut( Bbl_Obj_t * p ); -extern int Bbl_ObjId( Bbl_Obj_t * p ); -extern int Bbl_ObjIdOriginal( Bbl_Man_t * pMan, Bbl_Obj_t * p ); -extern int Bbl_ObjFaninNumber( Bbl_Obj_t * p ); -extern char * Bbl_ObjSop( Bbl_Man_t * pMan, Bbl_Obj_t * p ); - -// for the use in iterators only -extern Bbl_Obj_t * Bbl_ManObjFirst( Bbl_Man_t * p ); -extern Bbl_Obj_t * Bbl_ManObjNext( Bbl_Man_t * p, Bbl_Obj_t * pObj ); -extern Bbl_Obj_t * Bbl_ObjFaninFirst( Bbl_Obj_t * p ); -extern Bbl_Obj_t * Bbl_ObjFaninNext( Bbl_Obj_t * p, Bbl_Obj_t * pPrev ); - -// iterator through the objects -#define Bbl_ManForEachObj( p, pObj ) \ - for ( pObj = Bbl_ManObjFirst(p); pObj; pObj = Bbl_ManObjNext(p, pObj) ) -// iterator through the fanins fo the an object -#define Bbl_ObjForEachFanin( pObj, pFanin ) \ - for ( pFanin = Bbl_ObjFaninFirst(pObj); pFanin; pFanin = Bbl_ObjFaninNext(pObj, pFanin) ) - -// these additional procedures are provided to transform truth tables into SOPs, and vice versa -extern char * Bbl_ManTruthToSop( unsigned * pTruth, int nVars ); -extern unsigned * Bbl_ManSopToTruth( char * pSop, int nVars ); - -// write text BLIF file for debugging -extern void Bbl_ManDumpBlif( Bbl_Man_t * p, char * pFileName ); - -// a simple demo procedure -extern void Bbl_ManSimpleDemo(); - - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/bbl/module.make b/src/aig/bbl/module.make deleted file mode 100644 index 89ed2fa3..00000000 --- a/src/aig/bbl/module.make +++ /dev/null @@ -1 +0,0 @@ -SRC += src/aig/bbl/bblif.c diff --git a/src/aig/bbr/bbr.h b/src/aig/bbr/bbr.h deleted file mode 100644 index bb83ac95..00000000 --- a/src/aig/bbr/bbr.h +++ /dev/null @@ -1,93 +0,0 @@ -/**CFile**************************************************************** - - FileName [bbr.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD-based reachability analysis.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: bbr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __BBR_H__ -#define __BBR_H__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include "aig.h" -#include "saig.h" -#include "cuddInt.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline DdNode * Aig_ObjGlobalBdd( Aig_Obj_t * pObj ) { return (DdNode *)pObj->pData; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== bbrImage.c ==========================================================*/ -typedef struct Bbr_ImageTree_t_ Bbr_ImageTree_t; -extern Bbr_ImageTree_t * Bbr_bddImageStart( - DdManager * dd, DdNode * bCare, - int nParts, DdNode ** pbParts, - int nVars, DdNode ** pbVars, int nBddMax, int fVerbose ); -extern DdNode * Bbr_bddImageCompute( Bbr_ImageTree_t * pTree, DdNode * bCare ); -extern void Bbr_bddImageTreeDelete( Bbr_ImageTree_t * pTree ); -extern DdNode * Bbr_bddImageRead( Bbr_ImageTree_t * pTree ); -typedef struct Bbr_ImageTree2_t_ Bbr_ImageTree2_t; -extern Bbr_ImageTree2_t * Bbr_bddImageStart2( - DdManager * dd, DdNode * bCare, - int nParts, DdNode ** pbParts, - int nVars, DdNode ** pbVars, int fVerbose ); -extern DdNode * Bbr_bddImageCompute2( Bbr_ImageTree2_t * pTree, DdNode * bCare ); -extern void Bbr_bddImageTreeDelete2( Bbr_ImageTree2_t * pTree ); -extern DdNode * Bbr_bddImageRead2( Bbr_ImageTree2_t * pTree ); -/*=== bbrNtbdd.c ==========================================================*/ -extern void Aig_ManFreeGlobalBdds( Aig_Man_t * p, DdManager * dd ); -extern int Aig_ManSizeOfGlobalBdds( Aig_Man_t * p ); -extern DdManager * Aig_ManComputeGlobalBdds( Aig_Man_t * p, int nBddSizeMax, int fDropInternal, int fReorder, int fVerbose ); -/*=== bbrReach.c ==========================================================*/ -extern int Aig_ManVerifyUsingBdds( Aig_Man_t * p, Saig_ParBbr_t * pPars ); -extern void Bbr_ManSetDefaultParams( Saig_ParBbr_t * p ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/bbr/bbrCex.c b/src/aig/bbr/bbrCex.c deleted file mode 100644 index 4a1a1d67..00000000 --- a/src/aig/bbr/bbrCex.c +++ /dev/null @@ -1,172 +0,0 @@ -/**CFile**************************************************************** - - FileName [bbrCex.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD-based reachability analysis.] - - Synopsis [Procedures to derive a satisfiable counter-example.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: bbrCex.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "bbr.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -extern DdNode * Bbr_bddComputeRangeCube( DdManager * dd, int iStart, int iStop ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Derives the counter-example using the set of reached states.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Cex_t * Aig_ManVerifyUsingBddsCountExample( Aig_Man_t * p, DdManager * dd, - DdNode ** pbParts, Vec_Ptr_t * vOnionRings, DdNode * bCubeFirst, - int iOutput, int fVerbose, int fSilent ) -{ - Abc_Cex_t * pCex; - Aig_Obj_t * pObj; - Bbr_ImageTree_t * pTree; - DdNode * bCubeNs, * bState, * bImage; - DdNode * bTemp, * bVar, * bRing; - int i, v, RetValue, nPiOffset; - char * pValues; - int clk = clock(); -//printf( "\nDeriving counter-example.\n" ); - - // allocate room for the counter-example - pCex = Abc_CexAlloc( Saig_ManRegNum(p), Saig_ManPiNum(p), Vec_PtrSize(vOnionRings)+1 ); - pCex->iFrame = Vec_PtrSize(vOnionRings); - pCex->iPo = iOutput; - nPiOffset = Saig_ManRegNum(p) + Saig_ManPiNum(p) * Vec_PtrSize(vOnionRings); - - // create the cube of NS variables - bCubeNs = Bbr_bddComputeRangeCube( dd, Saig_ManCiNum(p), Saig_ManCiNum(p)+Saig_ManRegNum(p) ); Cudd_Ref( bCubeNs ); - pTree = Bbr_bddImageStart( dd, bCubeNs, Saig_ManRegNum(p), pbParts, Saig_ManCiNum(p), dd->vars, 100000000, fVerbose ); - Cudd_RecursiveDeref( dd, bCubeNs ); - if ( pTree == NULL ) - { - if ( !fSilent ) - printf( "BDDs blew up during qualitification scheduling. " ); - return NULL; - } - - // allocate room for the cube - pValues = ABC_ALLOC( char, dd->size ); - - // get the last cube - RetValue = Cudd_bddPickOneCube( dd, bCubeFirst, pValues ); - assert( RetValue ); - - // write PIs of counter-example - Saig_ManForEachPi( p, pObj, i ) - if ( pValues[i] == 1 ) - Aig_InfoSetBit( pCex->pData, nPiOffset + i ); - nPiOffset -= Saig_ManPiNum(p); - - // write state in terms of NS variables - bState = (dd)->one; Cudd_Ref( bState ); - Saig_ManForEachLo( p, pObj, i ) - { - bVar = Cudd_NotCond( dd->vars[Saig_ManCiNum(p)+i], pValues[Saig_ManPiNum(p)+i] != 1 ); - bState = Cudd_bddAnd( dd, bTemp = bState, bVar ); Cudd_Ref( bState ); - Cudd_RecursiveDeref( dd, bTemp ); - } - - // perform backward analysis - Vec_PtrForEachEntryReverse( DdNode *, vOnionRings, bRing, v ) - { - // compute the next states - bImage = Bbr_bddImageCompute( pTree, bState ); - if ( bImage == NULL ) - { - Cudd_RecursiveDeref( dd, bState ); - if ( !fSilent ) - printf( "BDDs blew up during image computation. " ); - Bbr_bddImageTreeDelete( pTree ); - ABC_FREE( pValues ); - return NULL; - } - Cudd_Ref( bImage ); - Cudd_RecursiveDeref( dd, bState ); - - // intersect with the previous set - bImage = Cudd_bddAnd( dd, bTemp = bImage, bRing ); Cudd_Ref( bImage ); - Cudd_RecursiveDeref( dd, bTemp ); - - // find any assignment of the BDD - RetValue = Cudd_bddPickOneCube( dd, bImage, pValues ); - assert( RetValue ); - Cudd_RecursiveDeref( dd, bImage ); - - // write PIs of counter-example - Saig_ManForEachPi( p, pObj, i ) - if ( pValues[i] == 1 ) - Aig_InfoSetBit( pCex->pData, nPiOffset + i ); - nPiOffset -= Saig_ManPiNum(p); - - // check that we get the init state - if ( v == 0 ) - { - Saig_ManForEachLo( p, pObj, i ) - assert( pValues[Saig_ManPiNum(p)+i] == 0 ); - break; - } - - // write state in terms of NS variables - bState = (dd)->one; Cudd_Ref( bState ); - Saig_ManForEachLo( p, pObj, i ) - { - bVar = Cudd_NotCond( dd->vars[Saig_ManCiNum(p)+i], pValues[Saig_ManPiNum(p)+i] != 1 ); - bState = Cudd_bddAnd( dd, bTemp = bState, bVar ); Cudd_Ref( bState ); - Cudd_RecursiveDeref( dd, bTemp ); - } - } - // cleanup - Bbr_bddImageTreeDelete( pTree ); - ABC_FREE( pValues ); - // verify the counter example - if ( Vec_PtrSize(vOnionRings) < 1000 ) - { - RetValue = Saig_ManVerifyCex( p, pCex ); - if ( RetValue == 0 && !fSilent ) - printf( "Aig_ManVerifyUsingBdds(): Counter-example verification has FAILED.\n" ); - } - if ( fVerbose && !fSilent ) - { - ABC_PRT( "Counter-example generation time", clock() - clk ); - } - return pCex; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/bbr/bbrImage.c b/src/aig/bbr/bbrImage.c deleted file mode 100644 index 8b18d84d..00000000 --- a/src/aig/bbr/bbrImage.c +++ /dev/null @@ -1,1327 +0,0 @@ -/**CFile**************************************************************** - - FileName [bbrImage.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD-based reachability analysis.] - - Synopsis [Performs image computation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: bbrImage.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "bbr.h" -#include "mtr.h" - -ABC_NAMESPACE_IMPL_START - - -/* - The ideas implemented in this file are inspired by the paper: - Pankaj Chauhan, Edmund Clarke, Somesh Jha, Jim Kukula, Tom Shiple, - Helmut Veith, Dong Wang. Non-linear Quantification Scheduling in - Image Computation. ICCAD, 2001. -*/ - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -typedef struct Bbr_ImageNode_t_ Bbr_ImageNode_t; -typedef struct Bbr_ImagePart_t_ Bbr_ImagePart_t; -typedef struct Bbr_ImageVar_t_ Bbr_ImageVar_t; - -struct Bbr_ImageTree_t_ -{ - Bbr_ImageNode_t * pRoot; // the root of quantification tree - Bbr_ImageNode_t * pCare; // the leaf node with the care set - DdNode * bCareSupp; // the cube to quantify from the care - int fVerbose; // the verbosity flag - int nNodesMax; // the max number of nodes in one iter - int nNodesMaxT; // the overall max number of nodes - int nIter; // the number of iterations with this tree - int nBddMax; // the number of node to stop -}; - -struct Bbr_ImageNode_t_ -{ - DdManager * dd; // the manager - DdNode * bCube; // the cube to quantify - DdNode * bImage; // the partial image - Bbr_ImageNode_t * pNode1; // the first branch - Bbr_ImageNode_t * pNode2; // the second branch - Bbr_ImagePart_t * pPart; // the partition (temporary) -}; - -struct Bbr_ImagePart_t_ -{ - DdNode * bFunc; // the partition - DdNode * bSupp; // the support of this partition - int nNodes; // the number of BDD nodes - short nSupp; // the number of support variables - short iPart; // the number of this partition -}; - -struct Bbr_ImageVar_t_ -{ - int iNum; // the BDD index of this variable - DdNode * bParts; // the partition numbers - int nParts; // the number of partitions -}; - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -#define b0 Cudd_Not((dd)->one) -#define b1 (dd)->one - -#ifndef ABC_PRB -#define ABC_PRB(dd,f) printf("%s = ", #f); Bbr_bddPrint(dd,f); printf("\n") -#endif - -/**AutomaticStart*************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static Bbr_ImagePart_t ** Bbr_CreateParts( DdManager * dd, - int nParts, DdNode ** pbParts, DdNode * bCare ); -static Bbr_ImageVar_t ** Bbr_CreateVars( DdManager * dd, - int nParts, Bbr_ImagePart_t ** pParts, - int nVars, DdNode ** pbVarsNs ); -static Bbr_ImageNode_t ** Bbr_CreateNodes( DdManager * dd, - int nParts, Bbr_ImagePart_t ** pParts, - int nVars, Bbr_ImageVar_t ** pVars ); -static void Bbr_DeleteParts_rec( Bbr_ImageNode_t * pNode ); -static int Bbr_BuildTreeNode( DdManager * dd, - int nNodes, Bbr_ImageNode_t ** pNodes, - int nVars, Bbr_ImageVar_t ** pVars, int * pfStop, int nBddMax ); -static Bbr_ImageNode_t * Bbr_MergeTopNodes( DdManager * dd, - int nNodes, Bbr_ImageNode_t ** pNodes ); -static void Bbr_bddImageTreeDelete_rec( Bbr_ImageNode_t * pNode ); -static int Bbr_bddImageCompute_rec( Bbr_ImageTree_t * pTree, Bbr_ImageNode_t * pNode ); -static int Bbr_FindBestVariable( DdManager * dd, - int nNodes, Bbr_ImageNode_t ** pNodes, - int nVars, Bbr_ImageVar_t ** pVars ); -static void Bbr_FindBestPartitions( DdManager * dd, DdNode * bParts, - int nNodes, Bbr_ImageNode_t ** pNodes, - int * piNode1, int * piNode2 ); -static Bbr_ImageNode_t * Bbr_CombineTwoNodes( DdManager * dd, DdNode * bCube, - Bbr_ImageNode_t * pNode1, Bbr_ImageNode_t * pNode2 ); - -static void Bbr_bddImagePrintLatchDependency( DdManager * dd, DdNode * bCare, - int nParts, DdNode ** pbParts, - int nVars, DdNode ** pbVars ); -static void Bbr_bddImagePrintLatchDependencyOne( DdManager * dd, DdNode * bFunc, - DdNode * bVarsCs, DdNode * bVarsNs, int iPart ); - -static void Bbr_bddImagePrintTree( Bbr_ImageTree_t * pTree ); -static void Bbr_bddImagePrintTree_rec( Bbr_ImageNode_t * pNode, int nOffset ); - -static void Bbr_bddPrint( DdManager * dd, DdNode * F ); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function************************************************************* - - Synopsis [Starts the image computation using tree-based scheduling.] - - Description [This procedure starts the image computation. It uses - the given care set to test-run the image computation and creates the - quantification tree by scheduling variable quantifications. The tree can - be used to compute images for other care sets without rescheduling. - In this case, Bbr_bddImageCompute() should be called.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bbr_ImageTree_t * Bbr_bddImageStart( - DdManager * dd, DdNode * bCare, // the care set - int nParts, DdNode ** pbParts, // the partitions for image computation - int nVars, DdNode ** pbVars, int nBddMax, int fVerbose ) // the NS and parameter variables (not quantified!) -{ - Bbr_ImageTree_t * pTree; - Bbr_ImagePart_t ** pParts; - Bbr_ImageVar_t ** pVars; - Bbr_ImageNode_t ** pNodes, * pCare; - int fStop, v; - - if ( fVerbose && dd->size <= 80 ) - Bbr_bddImagePrintLatchDependency( dd, bCare, nParts, pbParts, nVars, pbVars ); - - // create variables, partitions and leaf nodes - pParts = Bbr_CreateParts( dd, nParts, pbParts, bCare ); - pVars = Bbr_CreateVars( dd, nParts + 1, pParts, nVars, pbVars ); - pNodes = Bbr_CreateNodes( dd, nParts + 1, pParts, dd->size, pVars ); - pCare = pNodes[nParts]; - - // process the nodes - while ( Bbr_BuildTreeNode( dd, nParts + 1, pNodes, dd->size, pVars, &fStop, nBddMax ) ); - - // consider the case of BDD node blowup - if ( fStop ) - { - for ( v = 0; v < dd->size; v++ ) - if ( pVars[v] ) - ABC_FREE( pVars[v] ); - ABC_FREE( pVars ); - for ( v = 0; v <= nParts; v++ ) - if ( pNodes[v] ) - { - Bbr_DeleteParts_rec( pNodes[v] ); - Bbr_bddImageTreeDelete_rec( pNodes[v] ); - } - ABC_FREE( pNodes ); - ABC_FREE( pParts ); - return NULL; - } - - // make sure the variables are gone - for ( v = 0; v < dd->size; v++ ) - assert( pVars[v] == NULL ); - ABC_FREE( pVars ); - - // create the tree - pTree = ABC_ALLOC( Bbr_ImageTree_t, 1 ); - memset( pTree, 0, sizeof(Bbr_ImageTree_t) ); - pTree->pCare = pCare; - pTree->nBddMax = nBddMax; - pTree->fVerbose = fVerbose; - - // merge the topmost nodes - while ( (pTree->pRoot = Bbr_MergeTopNodes( dd, nParts + 1, pNodes )) == NULL ); - - // make sure the nodes are gone - for ( v = 0; v < nParts + 1; v++ ) - assert( pNodes[v] == NULL ); - ABC_FREE( pNodes ); - -// if ( fVerbose ) -// Bbr_bddImagePrintTree( pTree ); - - // set the support of the care set - pTree->bCareSupp = Cudd_Support( dd, bCare ); Cudd_Ref( pTree->bCareSupp ); - - // clean the partitions - Bbr_DeleteParts_rec( pTree->pRoot ); - ABC_FREE( pParts ); - - return pTree; -} - -/**Function************************************************************* - - Synopsis [Compute the image.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Bbr_bddImageCompute( Bbr_ImageTree_t * pTree, DdNode * bCare ) -{ - DdManager * dd = pTree->pCare->dd; - DdNode * bSupp, * bRem; - - pTree->nIter++; - - // make sure the supports are okay - bSupp = Cudd_Support( dd, bCare ); Cudd_Ref( bSupp ); - if ( bSupp != pTree->bCareSupp ) - { - bRem = Cudd_bddExistAbstract( dd, bSupp, pTree->bCareSupp ); Cudd_Ref( bRem ); - if ( bRem != b1 ) - { -printf( "Original care set support: " ); -ABC_PRB( dd, pTree->bCareSupp ); -printf( "Current care set support: " ); -ABC_PRB( dd, bSupp ); - Cudd_RecursiveDeref( dd, bSupp ); - Cudd_RecursiveDeref( dd, bRem ); - printf( "The care set depends on some vars that were not in the care set during scheduling.\n" ); - return NULL; - } - Cudd_RecursiveDeref( dd, bRem ); - } - Cudd_RecursiveDeref( dd, bSupp ); - - // remove the previous image - Cudd_RecursiveDeref( dd, pTree->pCare->bImage ); - pTree->pCare->bImage = bCare; Cudd_Ref( bCare ); - - // compute the image - pTree->nNodesMax = 0; - if ( !Bbr_bddImageCompute_rec( pTree, pTree->pRoot ) ) - return NULL; - if ( pTree->nNodesMaxT < pTree->nNodesMax ) - pTree->nNodesMaxT = pTree->nNodesMax; - -// if ( pTree->fVerbose ) -// printf( "Iter %2d : Max nodes = %5d.\n", pTree->nIter, pTree->nNodesMax ); - return pTree->pRoot->bImage; -} - -/**Function************************************************************* - - Synopsis [Delete the tree.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbr_bddImageTreeDelete( Bbr_ImageTree_t * pTree ) -{ - if ( pTree->bCareSupp ) - Cudd_RecursiveDeref( pTree->pRoot->dd, pTree->bCareSupp ); - Bbr_bddImageTreeDelete_rec( pTree->pRoot ); - ABC_FREE( pTree ); -} - -/**Function************************************************************* - - Synopsis [Reads the image from the tree.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Bbr_bddImageRead( Bbr_ImageTree_t * pTree ) -{ - return pTree->pRoot->bImage; -} - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Outputs the BDD in a readable format.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void Bbr_bddPrint( DdManager * dd, DdNode * F ) -{ - DdGen * Gen; - int * Cube; - CUDD_VALUE_TYPE Value; - int nVars = dd->size; - int fFirstCube = 1; - int i; - - if ( F == NULL ) - { - printf("NULL"); - return; - } - if ( F == b0 ) - { - printf("Constant 0"); - return; - } - if ( F == b1 ) - { - printf("Constant 1"); - return; - } - - Cudd_ForeachCube( dd, F, Gen, Cube, Value ) - { - if ( fFirstCube ) - fFirstCube = 0; - else -// Output << " + "; - printf( " + " ); - - for ( i = 0; i < nVars; i++ ) - if ( Cube[i] == 0 ) - printf( "[%d]'", i ); -// printf( "%c'", (char)('a'+i) ); - else if ( Cube[i] == 1 ) - printf( "[%d]", i ); -// printf( "%c", (char)('a'+i) ); - } - -// printf("\n"); -} - -/*---------------------------------------------------------------------------*/ -/* Definition of static Functions */ -/*---------------------------------------------------------------------------*/ - -/**Function************************************************************* - - Synopsis [Creates partitions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bbr_ImagePart_t ** Bbr_CreateParts( DdManager * dd, - int nParts, DdNode ** pbParts, DdNode * bCare ) -{ - Bbr_ImagePart_t ** pParts; - int i; - - // start the partitions - pParts = ABC_ALLOC( Bbr_ImagePart_t *, nParts + 1 ); - // create structures for each variable - for ( i = 0; i < nParts; i++ ) - { - pParts[i] = ABC_ALLOC( Bbr_ImagePart_t, 1 ); - pParts[i]->bFunc = pbParts[i]; Cudd_Ref( pParts[i]->bFunc ); - pParts[i]->bSupp = Cudd_Support( dd, pParts[i]->bFunc ); Cudd_Ref( pParts[i]->bSupp ); - pParts[i]->nSupp = Cudd_SupportSize( dd, pParts[i]->bSupp ); - pParts[i]->nNodes = Cudd_DagSize( pParts[i]->bFunc ); - pParts[i]->iPart = i; - } - // add the care set as the last partition - pParts[nParts] = ABC_ALLOC( Bbr_ImagePart_t, 1 ); - pParts[nParts]->bFunc = bCare; Cudd_Ref( pParts[nParts]->bFunc ); - pParts[nParts]->bSupp = Cudd_Support( dd, pParts[nParts]->bFunc ); Cudd_Ref( pParts[nParts]->bSupp ); - pParts[nParts]->nSupp = Cudd_SupportSize( dd, pParts[nParts]->bSupp ); - pParts[nParts]->nNodes = Cudd_DagSize( pParts[nParts]->bFunc ); - pParts[nParts]->iPart = nParts; - return pParts; -} - -/**Function************************************************************* - - Synopsis [Creates variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bbr_ImageVar_t ** Bbr_CreateVars( DdManager * dd, - int nParts, Bbr_ImagePart_t ** pParts, - int nVars, DdNode ** pbVars ) -{ - Bbr_ImageVar_t ** pVars; - DdNode ** pbFuncs; - DdNode * bCubeNs, * bSupp, * bParts, * bTemp, * bSuppTemp; - int nVarsTotal, iVar, p, Counter; - - // put all the functions into one array - pbFuncs = ABC_ALLOC( DdNode *, nParts ); - for ( p = 0; p < nParts; p++ ) - pbFuncs[p] = pParts[p]->bSupp; - bSupp = Cudd_VectorSupport( dd, pbFuncs, nParts ); Cudd_Ref( bSupp ); - ABC_FREE( pbFuncs ); - - // remove the NS vars - bCubeNs = Cudd_bddComputeCube( dd, pbVars, NULL, nVars ); Cudd_Ref( bCubeNs ); - bSupp = Cudd_bddExistAbstract( dd, bTemp = bSupp, bCubeNs ); Cudd_Ref( bSupp ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bCubeNs ); - - // get the number of I and CS variables to be quantified - nVarsTotal = Cudd_SupportSize( dd, bSupp ); - - // start the variables - pVars = ABC_ALLOC( Bbr_ImageVar_t *, dd->size ); - memset( pVars, 0, sizeof(Bbr_ImageVar_t *) * dd->size ); - // create structures for each variable - for ( bSuppTemp = bSupp; bSuppTemp != b1; bSuppTemp = cuddT(bSuppTemp) ) - { - iVar = bSuppTemp->index; - pVars[iVar] = ABC_ALLOC( Bbr_ImageVar_t, 1 ); - pVars[iVar]->iNum = iVar; - // collect all the parts this var belongs to - Counter = 0; - bParts = b1; Cudd_Ref( bParts ); - for ( p = 0; p < nParts; p++ ) - if ( Cudd_bddLeq( dd, pParts[p]->bSupp, dd->vars[bSuppTemp->index] ) ) - { - bParts = Cudd_bddAnd( dd, bTemp = bParts, dd->vars[p] ); Cudd_Ref( bParts ); - Cudd_RecursiveDeref( dd, bTemp ); - Counter++; - } - pVars[iVar]->bParts = bParts; // takes ref - pVars[iVar]->nParts = Counter; - } - Cudd_RecursiveDeref( dd, bSupp ); - return pVars; -} - -/**Function************************************************************* - - Synopsis [Creates variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bbr_ImageNode_t ** Bbr_CreateNodes( DdManager * dd, - int nParts, Bbr_ImagePart_t ** pParts, - int nVars, Bbr_ImageVar_t ** pVars ) -{ - Bbr_ImageNode_t ** pNodes; - Bbr_ImageNode_t * pNode; - DdNode * bTemp; - int i, v, iPart; -/* - DdManager * dd; // the manager - DdNode * bCube; // the cube to quantify - DdNode * bImage; // the partial image - Bbr_ImageNode_t * pNode1; // the first branch - Bbr_ImageNode_t * pNode2; // the second branch - Bbr_ImagePart_t * pPart; // the partition (temporary) -*/ - // start the partitions - pNodes = ABC_ALLOC( Bbr_ImageNode_t *, nParts ); - // create structures for each leaf nodes - for ( i = 0; i < nParts; i++ ) - { - pNodes[i] = ABC_ALLOC( Bbr_ImageNode_t, 1 ); - memset( pNodes[i], 0, sizeof(Bbr_ImageNode_t) ); - pNodes[i]->dd = dd; - pNodes[i]->pPart = pParts[i]; - } - // find the quantification cubes for each leaf node - for ( v = 0; v < nVars; v++ ) - { - if ( pVars[v] == NULL ) - continue; - assert( pVars[v]->nParts > 0 ); - if ( pVars[v]->nParts > 1 ) - continue; - iPart = pVars[v]->bParts->index; - if ( pNodes[iPart]->bCube == NULL ) - { - pNodes[iPart]->bCube = dd->vars[v]; - Cudd_Ref( dd->vars[v] ); - } - else - { - pNodes[iPart]->bCube = Cudd_bddAnd( dd, bTemp = pNodes[iPart]->bCube, dd->vars[v] ); - Cudd_Ref( pNodes[iPart]->bCube ); - Cudd_RecursiveDeref( dd, bTemp ); - } - // remove these variables - Cudd_RecursiveDeref( dd, pVars[v]->bParts ); - ABC_FREE( pVars[v] ); - } - - // assign the leaf node images - for ( i = 0; i < nParts; i++ ) - { - pNode = pNodes[i]; - if ( pNode->bCube ) - { - // update the partition - pParts[i]->bFunc = Cudd_bddExistAbstract( dd, bTemp = pParts[i]->bFunc, pNode->bCube ); - Cudd_Ref( pParts[i]->bFunc ); - Cudd_RecursiveDeref( dd, bTemp ); - // update the support the partition - pParts[i]->bSupp = Cudd_bddExistAbstract( dd, bTemp = pParts[i]->bSupp, pNode->bCube ); - Cudd_Ref( pParts[i]->bSupp ); - Cudd_RecursiveDeref( dd, bTemp ); - // update the numbers - pParts[i]->nSupp = Cudd_SupportSize( dd, pParts[i]->bSupp ); - pParts[i]->nNodes = Cudd_DagSize( pParts[i]->bFunc ); - // get rid of the cube - // save the last (care set) quantification cube - if ( i < nParts - 1 ) - { - Cudd_RecursiveDeref( dd, pNode->bCube ); - pNode->bCube = NULL; - } - } - // copy the function - pNode->bImage = pParts[i]->bFunc; Cudd_Ref( pNode->bImage ); - } -/* - for ( i = 0; i < nParts; i++ ) - { - pNode = pNodes[i]; -ABC_PRB( dd, pNode->bCube ); -ABC_PRB( dd, pNode->pPart->bFunc ); -ABC_PRB( dd, pNode->pPart->bSupp ); -printf( "\n" ); - } -*/ - return pNodes; -} - - -/**Function************************************************************* - - Synopsis [Delete the partitions from the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbr_DeleteParts_rec( Bbr_ImageNode_t * pNode ) -{ - Bbr_ImagePart_t * pPart; - if ( pNode->pNode1 ) - Bbr_DeleteParts_rec( pNode->pNode1 ); - if ( pNode->pNode2 ) - Bbr_DeleteParts_rec( pNode->pNode2 ); - pPart = pNode->pPart; - Cudd_RecursiveDeref( pNode->dd, pPart->bFunc ); - Cudd_RecursiveDeref( pNode->dd, pPart->bSupp ); - ABC_FREE( pNode->pPart ); -} - -/**Function************************************************************* - - Synopsis [Delete the partitions from the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbr_bddImageTreeDelete_rec( Bbr_ImageNode_t * pNode ) -{ - if ( pNode->pNode1 ) - Bbr_bddImageTreeDelete_rec( pNode->pNode1 ); - if ( pNode->pNode2 ) - Bbr_bddImageTreeDelete_rec( pNode->pNode2 ); - if ( pNode->bCube ) - Cudd_RecursiveDeref( pNode->dd, pNode->bCube ); - if ( pNode->bImage ) - Cudd_RecursiveDeref( pNode->dd, pNode->bImage ); - assert( pNode->pPart == NULL ); - ABC_FREE( pNode ); -} - -/**Function************************************************************* - - Synopsis [Recompute the image.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Bbr_bddImageCompute_rec( Bbr_ImageTree_t * pTree, Bbr_ImageNode_t * pNode ) -{ - DdManager * dd = pNode->dd; - DdNode * bTemp; - int nNodes; - - // trivial case - if ( pNode->pNode1 == NULL ) - { - if ( pNode->bCube ) - { - pNode->bImage = Cudd_bddExistAbstract( dd, bTemp = pNode->bImage, pNode->bCube ); - Cudd_Ref( pNode->bImage ); - Cudd_RecursiveDeref( dd, bTemp ); - } - return 1; - } - - // compute the children - if ( pNode->pNode1 ) - if ( !Bbr_bddImageCompute_rec( pTree, pNode->pNode1 ) ) - return 0; - if ( pNode->pNode2 ) - if ( !Bbr_bddImageCompute_rec( pTree, pNode->pNode2 ) ) - return 0; - - // clean the old image - if ( pNode->bImage ) - Cudd_RecursiveDeref( dd, pNode->bImage ); - pNode->bImage = NULL; - - // compute the new image - if ( pNode->bCube ) - pNode->bImage = Cudd_bddAndAbstract( dd, - pNode->pNode1->bImage, pNode->pNode2->bImage, pNode->bCube ); - else - pNode->bImage = Cudd_bddAnd( dd, pNode->pNode1->bImage, pNode->pNode2->bImage ); - Cudd_Ref( pNode->bImage ); - - if ( pTree->fVerbose ) - { - nNodes = Cudd_DagSize( pNode->bImage ); - if ( pTree->nNodesMax < nNodes ) - pTree->nNodesMax = nNodes; - } - if ( dd->keys-dd->dead > (unsigned)pTree->nBddMax ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Builds the tree.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Bbr_BuildTreeNode( DdManager * dd, - int nNodes, Bbr_ImageNode_t ** pNodes, - int nVars, Bbr_ImageVar_t ** pVars, int * pfStop, int nBddMax ) -{ - Bbr_ImageNode_t * pNode1, * pNode2; - Bbr_ImageVar_t * pVar; - Bbr_ImageNode_t * pNode; - DdNode * bCube, * bTemp, * bSuppTemp;//, * bParts; - int iNode1, iNode2; - int iVarBest, nSupp, v; - - // find the best variable - iVarBest = Bbr_FindBestVariable( dd, nNodes, pNodes, nVars, pVars ); - if ( iVarBest == -1 ) - return 0; -/* -for ( v = 0; v < nVars; v++ ) -{ - DdNode * bSupp; - if ( pVars[v] == NULL ) - continue; - printf( "%3d :", v ); - printf( "%3d ", pVars[v]->nParts ); - bSupp = Cudd_Support( dd, pVars[v]->bParts ); Cudd_Ref( bSupp ); - Bbr_bddPrint( dd, bSupp ); printf( "\n" ); - Cudd_RecursiveDeref( dd, bSupp ); -} -*/ - pVar = pVars[iVarBest]; - - // this var cannot appear in one partition only - nSupp = Cudd_SupportSize( dd, pVar->bParts ); - assert( nSupp == pVar->nParts ); - assert( nSupp != 1 ); -//printf( "var = %d supp = %d\n\n", iVarBest, nSupp ); - - // if it appears in only two partitions, quantify it - if ( pVar->nParts == 2 ) - { - // get the nodes - iNode1 = pVar->bParts->index; - iNode2 = cuddT(pVar->bParts)->index; - pNode1 = pNodes[iNode1]; - pNode2 = pNodes[iNode2]; - - // get the quantification cube - bCube = dd->vars[pVar->iNum]; Cudd_Ref( bCube ); - // add the variables that appear only in these partitions - for ( v = 0; v < nVars; v++ ) - if ( pVars[v] && v != iVarBest && pVars[v]->bParts == pVars[iVarBest]->bParts ) - { - // add this var - bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[pVars[v]->iNum] ); Cudd_Ref( bCube ); - Cudd_RecursiveDeref( dd, bTemp ); - // clean this var - Cudd_RecursiveDeref( dd, pVars[v]->bParts ); - ABC_FREE( pVars[v] ); - } - // clean the best var - Cudd_RecursiveDeref( dd, pVars[iVarBest]->bParts ); - ABC_FREE( pVars[iVarBest] ); - - // combines two nodes - pNode = Bbr_CombineTwoNodes( dd, bCube, pNode1, pNode2 ); - Cudd_RecursiveDeref( dd, bCube ); - } - else // if ( pVar->nParts > 2 ) - { - // find two smallest BDDs that have this var - Bbr_FindBestPartitions( dd, pVar->bParts, nNodes, pNodes, &iNode1, &iNode2 ); - pNode1 = pNodes[iNode1]; - pNode2 = pNodes[iNode2]; -//printf( "smallest bdds with this var: %d %d\n", iNode1, iNode2 ); -/* - // it is not possible that a var appears only in these two - // otherwise, it would have a different cost - bParts = Cudd_bddAnd( dd, dd->vars[iNode1], dd->vars[iNode2] ); Cudd_Ref( bParts ); - for ( v = 0; v < nVars; v++ ) - if ( pVars[v] && pVars[v]->bParts == bParts ) - assert( 0 ); - Cudd_RecursiveDeref( dd, bParts ); -*/ - // combines two nodes - pNode = Bbr_CombineTwoNodes( dd, b1, pNode1, pNode2 ); - } - - // clean the old nodes - pNodes[iNode1] = pNode; - pNodes[iNode2] = NULL; -//printf( "Removing node %d (leaving node %d)\n", iNode2, iNode1 ); - - // update the variables that appear in pNode[iNode2] - for ( bSuppTemp = pNode2->pPart->bSupp; bSuppTemp != b1; bSuppTemp = cuddT(bSuppTemp) ) - { - pVar = pVars[bSuppTemp->index]; - if ( pVar == NULL ) // this variable is not be quantified - continue; - // quantify this var - assert( Cudd_bddLeq( dd, pVar->bParts, dd->vars[iNode2] ) ); - pVar->bParts = Cudd_bddExistAbstract( dd, bTemp = pVar->bParts, dd->vars[iNode2] ); Cudd_Ref( pVar->bParts ); - Cudd_RecursiveDeref( dd, bTemp ); - // add the new var - pVar->bParts = Cudd_bddAnd( dd, bTemp = pVar->bParts, dd->vars[iNode1] ); Cudd_Ref( pVar->bParts ); - Cudd_RecursiveDeref( dd, bTemp ); - // update the score - pVar->nParts = Cudd_SupportSize( dd, pVar->bParts ); - } - - *pfStop = 0; - if ( dd->keys-dd->dead > (unsigned)nBddMax ) - { - *pfStop = 1; - return 0; - } - return 1; -} - - -/**Function************************************************************* - - Synopsis [Merges the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bbr_ImageNode_t * Bbr_MergeTopNodes( - DdManager * dd, int nNodes, Bbr_ImageNode_t ** pNodes ) -{ - Bbr_ImageNode_t * pNode; - int n1 = -1, n2 = -1, n; - - // find the first and the second non-empty spots - for ( n = 0; n < nNodes; n++ ) - if ( pNodes[n] ) - { - if ( n1 == -1 ) - n1 = n; - else if ( n2 == -1 ) - { - n2 = n; - break; - } - } - assert( n1 != -1 ); - // check the situation when only one such node is detected - if ( n2 == -1 ) - { - // save the node - pNode = pNodes[n1]; - // clean the node - pNodes[n1] = NULL; - return pNode; - } - - // combines two nodes - pNode = Bbr_CombineTwoNodes( dd, b1, pNodes[n1], pNodes[n2] ); - - // clean the old nodes - pNodes[n1] = pNode; - pNodes[n2] = NULL; - return NULL; -} - -/**Function************************************************************* - - Synopsis [Merges two nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bbr_ImageNode_t * Bbr_CombineTwoNodes( DdManager * dd, DdNode * bCube, - Bbr_ImageNode_t * pNode1, Bbr_ImageNode_t * pNode2 ) -{ - Bbr_ImageNode_t * pNode; - Bbr_ImagePart_t * pPart; - - // create a new partition - pPart = ABC_ALLOC( Bbr_ImagePart_t, 1 ); - memset( pPart, 0, sizeof(Bbr_ImagePart_t) ); - // create the function - pPart->bFunc = Cudd_bddAndAbstract( dd, pNode1->pPart->bFunc, pNode2->pPart->bFunc, bCube ); - Cudd_Ref( pPart->bFunc ); - // update the support the partition - pPart->bSupp = Cudd_bddAndAbstract( dd, pNode1->pPart->bSupp, pNode2->pPart->bSupp, bCube ); - Cudd_Ref( pPart->bSupp ); - // update the numbers - pPart->nSupp = Cudd_SupportSize( dd, pPart->bSupp ); - pPart->nNodes = Cudd_DagSize( pPart->bFunc ); - pPart->iPart = -1; -/* -ABC_PRB( dd, pNode1->pPart->bSupp ); -ABC_PRB( dd, pNode2->pPart->bSupp ); -ABC_PRB( dd, pPart->bSupp ); -*/ - // create a new node - pNode = ABC_ALLOC( Bbr_ImageNode_t, 1 ); - memset( pNode, 0, sizeof(Bbr_ImageNode_t) ); - pNode->dd = dd; - pNode->pPart = pPart; - pNode->pNode1 = pNode1; - pNode->pNode2 = pNode2; - // compute the image - pNode->bImage = Cudd_bddAndAbstract( dd, pNode1->bImage, pNode2->bImage, bCube ); - Cudd_Ref( pNode->bImage ); - // save the cube - if ( bCube != b1 ) - { - pNode->bCube = bCube; Cudd_Ref( bCube ); - } - return pNode; -} - -/**Function************************************************************* - - Synopsis [Computes the best variable.] - - Description [The variables is the best if the sum of squares of the - BDD sizes of the partitions, in which it participates, is the minimum.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Bbr_FindBestVariable( DdManager * dd, - int nNodes, Bbr_ImageNode_t ** pNodes, - int nVars, Bbr_ImageVar_t ** pVars ) -{ - DdNode * bTemp; - int iVarBest, v; - double CostBest, CostCur; - - CostBest = 100000000000000.0; - iVarBest = -1; - - // check if there are two-variable partitions - for ( v = 0; v < nVars; v++ ) - if ( pVars[v] && pVars[v]->nParts == 2 ) - { - CostCur = 0; - for ( bTemp = pVars[v]->bParts; bTemp != b1; bTemp = cuddT(bTemp) ) - CostCur += pNodes[bTemp->index]->pPart->nNodes * - pNodes[bTemp->index]->pPart->nNodes; - if ( CostBest > CostCur ) - { - CostBest = CostCur; - iVarBest = v; - } - } - if ( iVarBest >= 0 ) - return iVarBest; - - // find other partition - for ( v = 0; v < nVars; v++ ) - if ( pVars[v] ) - { - assert( pVars[v]->nParts > 1 ); - CostCur = 0; - for ( bTemp = pVars[v]->bParts; bTemp != b1; bTemp = cuddT(bTemp) ) - CostCur += pNodes[bTemp->index]->pPart->nNodes * - pNodes[bTemp->index]->pPart->nNodes; - if ( CostBest > CostCur ) - { - CostBest = CostCur; - iVarBest = v; - } - } - return iVarBest; -} - -/**Function************************************************************* - - Synopsis [Computes two smallest partions that have this var.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbr_FindBestPartitions( DdManager * dd, DdNode * bParts, - int nNodes, Bbr_ImageNode_t ** pNodes, - int * piNode1, int * piNode2 ) -{ - DdNode * bTemp; - int iPart1, iPart2; - int CostMin1, CostMin2, Cost; - - // go through the partitions - iPart1 = iPart2 = -1; - CostMin1 = CostMin2 = 1000000; - for ( bTemp = bParts; bTemp != b1; bTemp = cuddT(bTemp) ) - { - Cost = pNodes[bTemp->index]->pPart->nNodes; - if ( CostMin1 > Cost ) - { - CostMin2 = CostMin1; iPart2 = iPart1; - CostMin1 = Cost; iPart1 = bTemp->index; - } - else if ( CostMin2 > Cost ) - { - CostMin2 = Cost; iPart2 = bTemp->index; - } - } - - *piNode1 = iPart1; - *piNode2 = iPart2; -} - -/**Function************************************************************* - - Synopsis [Prints the latch dependency matrix.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbr_bddImagePrintLatchDependency( - DdManager * dd, DdNode * bCare, // the care set - int nParts, DdNode ** pbParts, // the partitions for image computation - int nVars, DdNode ** pbVars ) // the NS and parameter variables (not quantified!) -{ - int i; - DdNode * bVarsCs, * bVarsNs; - - bVarsCs = Cudd_Support( dd, bCare ); Cudd_Ref( bVarsCs ); - bVarsNs = Cudd_bddComputeCube( dd, pbVars, NULL, nVars ); Cudd_Ref( bVarsNs ); - - printf( "The latch dependency matrix:\n" ); - printf( "Partitions = %d Variables: total = %d non-quantifiable = %d\n", - nParts, dd->size, nVars ); - printf( " : " ); - for ( i = 0; i < dd->size; i++ ) - printf( "%d", i % 10 ); - printf( "\n" ); - - for ( i = 0; i < nParts; i++ ) - Bbr_bddImagePrintLatchDependencyOne( dd, pbParts[i], bVarsCs, bVarsNs, i ); - Bbr_bddImagePrintLatchDependencyOne( dd, bCare, bVarsCs, bVarsNs, nParts ); - - Cudd_RecursiveDeref( dd, bVarsCs ); - Cudd_RecursiveDeref( dd, bVarsNs ); -} - -/**Function************************************************************* - - Synopsis [Prints one row of the latch dependency matrix.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbr_bddImagePrintLatchDependencyOne( - DdManager * dd, DdNode * bFunc, // the function - DdNode * bVarsCs, DdNode * bVarsNs, // the current/next state vars - int iPart ) -{ - DdNode * bSupport; - int v; - bSupport = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupport ); - printf( " %3d : ", iPart ); - for ( v = 0; v < dd->size; v++ ) - { - if ( Cudd_bddLeq( dd, bSupport, dd->vars[v] ) ) - { - if ( Cudd_bddLeq( dd, bVarsCs, dd->vars[v] ) ) - printf( "c" ); - else if ( Cudd_bddLeq( dd, bVarsNs, dd->vars[v] ) ) - printf( "n" ); - else - printf( "i" ); - } - else - printf( "." ); - } - printf( "\n" ); - Cudd_RecursiveDeref( dd, bSupport ); -} - - -/**Function************************************************************* - - Synopsis [Prints the tree for quenstification scheduling.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbr_bddImagePrintTree( Bbr_ImageTree_t * pTree ) -{ - printf( "The quantification scheduling tree:\n" ); - Bbr_bddImagePrintTree_rec( pTree->pRoot, 1 ); -} - -/**Function************************************************************* - - Synopsis [Prints the tree for quenstification scheduling.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbr_bddImagePrintTree_rec( Bbr_ImageNode_t * pNode, int Offset ) -{ - DdNode * Cube; - int i; - - Cube = pNode->bCube; - - if ( pNode->pNode1 == NULL ) - { - printf( "<%d> ", pNode->pPart->iPart ); - if ( Cube != NULL ) - { - ABC_PRB( pNode->dd, Cube ); - } - else - printf( "\n" ); - return; - } - - printf( "<*> " ); - if ( Cube != NULL ) - { - ABC_PRB( pNode->dd, Cube ); - } - else - printf( "\n" ); - - for ( i = 0; i < Offset; i++ ) - printf( " " ); - Bbr_bddImagePrintTree_rec( pNode->pNode1, Offset + 1 ); - - for ( i = 0; i < Offset; i++ ) - printf( " " ); - Bbr_bddImagePrintTree_rec( pNode->pNode2, Offset + 1 ); -} - -/**Function******************************************************************** - - Synopsis [Computes the positive polarty cube composed of the first vars in the array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Bbr_bddComputeCube( DdManager * dd, DdNode ** bXVars, int nVars ) -{ - DdNode * bRes; - DdNode * bTemp; - int i; - - bRes = b1; Cudd_Ref( bRes ); - for ( i = 0; i < nVars; i++ ) - { - bRes = Cudd_bddAnd( dd, bTemp = bRes, bXVars[i] ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); - } - - Cudd_Deref( bRes ); - return bRes; -} - - - - - -struct Bbr_ImageTree2_t_ -{ - DdManager * dd; - DdNode * bRel; - DdNode * bCube; - DdNode * bImage; -}; - -/**Function************************************************************* - - Synopsis [Starts the monolithic image computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bbr_ImageTree2_t * Bbr_bddImageStart2( - DdManager * dd, DdNode * bCare, - int nParts, DdNode ** pbParts, - int nVars, DdNode ** pbVars, int fVerbose ) -{ - Bbr_ImageTree2_t * pTree; - DdNode * bCubeAll, * bCubeNot, * bTemp; - int i; - - pTree = ABC_ALLOC( Bbr_ImageTree2_t, 1 ); - pTree->dd = dd; - pTree->bImage = NULL; - - bCubeAll = Bbr_bddComputeCube( dd, dd->vars, dd->size ); Cudd_Ref( bCubeAll ); - bCubeNot = Bbr_bddComputeCube( dd, pbVars, nVars ); Cudd_Ref( bCubeNot ); - pTree->bCube = Cudd_bddExistAbstract( dd, bCubeAll, bCubeNot ); Cudd_Ref( pTree->bCube ); - Cudd_RecursiveDeref( dd, bCubeAll ); - Cudd_RecursiveDeref( dd, bCubeNot ); - - // derive the monolithic relation - pTree->bRel = b1; Cudd_Ref( pTree->bRel ); - for ( i = 0; i < nParts; i++ ) - { - pTree->bRel = Cudd_bddAnd( dd, bTemp = pTree->bRel, pbParts[i] ); Cudd_Ref( pTree->bRel ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Bbr_bddImageCompute2( pTree, bCare ); - return pTree; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Bbr_bddImageCompute2( Bbr_ImageTree2_t * pTree, DdNode * bCare ) -{ - if ( pTree->bImage ) - Cudd_RecursiveDeref( pTree->dd, pTree->bImage ); - pTree->bImage = Cudd_bddAndAbstract( pTree->dd, pTree->bRel, bCare, pTree->bCube ); - Cudd_Ref( pTree->bImage ); - return pTree->bImage; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbr_bddImageTreeDelete2( Bbr_ImageTree2_t * pTree ) -{ - if ( pTree->bRel ) - Cudd_RecursiveDeref( pTree->dd, pTree->bRel ); - if ( pTree->bCube ) - Cudd_RecursiveDeref( pTree->dd, pTree->bCube ); - if ( pTree->bImage ) - Cudd_RecursiveDeref( pTree->dd, pTree->bImage ); - ABC_FREE( pTree ); -} - -/**Function************************************************************* - - Synopsis [Returns the previously computed image.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Bbr_bddImageRead2( Bbr_ImageTree2_t * pTree ) -{ - return pTree->bImage; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/bbr/bbrNtbdd.c b/src/aig/bbr/bbrNtbdd.c deleted file mode 100644 index 09456df0..00000000 --- a/src/aig/bbr/bbrNtbdd.c +++ /dev/null @@ -1,218 +0,0 @@ -/**CFile**************************************************************** - - FileName [bbrNtbdd.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD-based reachability analysis.] - - Synopsis [Procedures to construct global BDDs for the network.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: bbrNtbdd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "bbr.h" -//#include "bar.h" - -ABC_NAMESPACE_IMPL_START - - -typedef char ProgressBar; - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline void Aig_ObjSetGlobalBdd( Aig_Obj_t * pObj, DdNode * bFunc ) { pObj->pData = bFunc; } -static inline void Aig_ObjCleanGlobalBdd( DdManager * dd, Aig_Obj_t * pObj ) { Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); pObj->pData = NULL; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Derives the global BDD for one AIG node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Bbr_NodeGlobalBdds_rec( DdManager * dd, Aig_Obj_t * pNode, int nBddSizeMax, int fDropInternal, ProgressBar * pProgress, int * pCounter, int fVerbose ) -{ - DdNode * bFunc, * bFunc0, * bFunc1; - assert( !Aig_IsComplement(pNode) ); - if ( Cudd_ReadKeys(dd)-Cudd_ReadDead(dd) > (unsigned)nBddSizeMax ) - { -// Extra_ProgressBarStop( pProgress ); - if ( fVerbose ) - printf( "The number of live nodes reached %d.\n", nBddSizeMax ); - fflush( stdout ); - return NULL; - } - // if the result is available return - if ( Aig_ObjGlobalBdd(pNode) == NULL ) - { - // compute the result for both branches - bFunc0 = Bbr_NodeGlobalBdds_rec( dd, Aig_ObjFanin0(pNode), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); - if ( bFunc0 == NULL ) - return NULL; - Cudd_Ref( bFunc0 ); - bFunc1 = Bbr_NodeGlobalBdds_rec( dd, Aig_ObjFanin1(pNode), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); - if ( bFunc1 == NULL ) - return NULL; - Cudd_Ref( bFunc1 ); - bFunc0 = Cudd_NotCond( bFunc0, Aig_ObjFaninC0(pNode) ); - bFunc1 = Cudd_NotCond( bFunc1, Aig_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( Aig_ObjGlobalBdd(pNode) == NULL ); - Aig_ObjSetGlobalBdd( pNode, bFunc ); - // increment the progress bar -// if ( pProgress ) -// Extra_ProgressBarUpdate( pProgress, *pCounter, NULL ); - } - // prepare the return value - bFunc = Aig_ObjGlobalBdd(pNode); - // dereference BDD at the node - if ( --pNode->nRefs == 0 && fDropInternal ) - { - Cudd_Deref( bFunc ); - Aig_ObjSetGlobalBdd( pNode, NULL ); - } - return bFunc; -} - -/**Function************************************************************* - - Synopsis [Frees the global BDDs of the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManFreeGlobalBdds( Aig_Man_t * p, DdManager * dd ) -{ - Aig_Obj_t * pObj; - int i; - Aig_ManForEachObj( p, pObj, i ) - if ( Aig_ObjGlobalBdd(pObj) ) - Aig_ObjCleanGlobalBdd( dd, pObj ); -} - -/**Function************************************************************* - - Synopsis [Returns the shared size of global BDDs of the COs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManSizeOfGlobalBdds( Aig_Man_t * p ) -{ - Vec_Ptr_t * vFuncsGlob; - Aig_Obj_t * pObj; - int RetValue, i; - // complement the global functions - vFuncsGlob = Vec_PtrAlloc( Aig_ManPoNum(p) ); - Aig_ManForEachPo( p, pObj, i ) - Vec_PtrPush( vFuncsGlob, Aig_ObjGlobalBdd(pObj) ); - RetValue = Cudd_SharingSize( (DdNode **)Vec_PtrArray(vFuncsGlob), Vec_PtrSize(vFuncsGlob) ); - Vec_PtrFree( vFuncsGlob ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Recursively computes global BDDs for the AIG in the manager.] - - Description [On exit, BDDs are stored in the pNode->pData fields.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdManager * Aig_ManComputeGlobalBdds( Aig_Man_t * p, int nBddSizeMax, int fDropInternal, int fReorder, int fVerbose ) -{ - ProgressBar * pProgress = NULL; - Aig_Obj_t * pObj; - DdManager * dd; - DdNode * bFunc; - int i, Counter; - // start the manager - dd = Cudd_Init( Aig_ManPiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - // set reordering - if ( fReorder ) - Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - // prepare to construct global BDDs - Aig_ManCleanData( p ); - // assign the constant node BDD - Aig_ObjSetGlobalBdd( Aig_ManConst1(p), dd->one ); Cudd_Ref( dd->one ); - // set the elementary variables - Aig_ManForEachPi( p, pObj, i ) - { - Aig_ObjSetGlobalBdd( pObj, dd->vars[i] ); Cudd_Ref( dd->vars[i] ); - } - - // collect the global functions of the COs - Counter = 0; - // construct the BDDs -// pProgress = Extra_ProgressBarStart( stdout, Aig_ManNodeNum(p) ); - Aig_ManForEachPo( p, pObj, i ) - { - bFunc = Bbr_NodeGlobalBdds_rec( dd, Aig_ObjFanin0(pObj), nBddSizeMax, fDropInternal, pProgress, &Counter, fVerbose ); - if ( bFunc == NULL ) - { - if ( fVerbose ) - printf( "Constructing global BDDs is aborted.\n" ); - Aig_ManFreeGlobalBdds( p, dd ); - Cudd_Quit( dd ); - // reset references - Aig_ManResetRefs( p ); - return NULL; - } - bFunc = Cudd_NotCond( bFunc, Aig_ObjFaninC0(pObj) ); Cudd_Ref( bFunc ); - Aig_ObjSetGlobalBdd( pObj, bFunc ); - } -// Extra_ProgressBarStop( pProgress ); - // reset references - Aig_ManResetRefs( p ); - // reorder one more time - if ( fReorder ) - { - Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 ); - Cudd_AutodynDisable( dd ); - } -// Cudd_PrintInfo( dd, stdout ); - return dd; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/bbr/bbrReach.c b/src/aig/bbr/bbrReach.c deleted file mode 100644 index 9c6dced3..00000000 --- a/src/aig/bbr/bbrReach.c +++ /dev/null @@ -1,606 +0,0 @@ -/**CFile**************************************************************** - - FileName [bbrReach.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD-based reachability analysis.] - - Synopsis [Procedures to perform reachability analysis.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: bbrReach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "bbr.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -extern Abc_Cex_t * Aig_ManVerifyUsingBddsCountExample( Aig_Man_t * p, DdManager * dd, - DdNode ** pbParts, Vec_Ptr_t * vOnionRings, DdNode * bCubeFirst, - int iOutput, int fVerbose, int fSilent ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [This procedure sets default resynthesis parameters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbr_ManSetDefaultParams( Saig_ParBbr_t * p ) -{ - memset( p, 0, sizeof(Saig_ParBbr_t) ); - p->TimeLimit = 0; - p->nBddMax = 50000; - p->nIterMax = 1000; - p->fPartition = 1; - p->fReorder = 1; - p->fReorderImage = 1; - p->fVerbose = 0; - p->fSilent = 0; - p->iFrame = -1; -} - -/**Function******************************************************************** - - Synopsis [Performs the reordering-sensitive step of Extra_bddMove().] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Bbr_bddComputeRangeCube( DdManager * dd, int iStart, int iStop ) -{ - DdNode * bTemp, * bProd; - int i; - assert( iStart <= iStop ); - assert( iStart >= 0 && iStart <= dd->size ); - assert( iStop >= 0 && iStop <= dd->size ); - bProd = (dd)->one; Cudd_Ref( bProd ); - for ( i = iStart; i < iStop; i++ ) - { - bProd = Cudd_bddAnd( dd, bTemp = bProd, dd->vars[i] ); Cudd_Ref( bProd ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bProd ); - return bProd; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbr_StopManager( DdManager * dd ) -{ - int RetValue; - // check for remaining references in the package - RetValue = Cudd_CheckZeroRef( dd ); - if ( RetValue > 0 ) - printf( "\nThe number of referenced nodes = %d\n\n", RetValue ); -// Cudd_PrintInfo( dd, stdout ); - Cudd_Quit( dd ); -} - -/**Function************************************************************* - - Synopsis [Computes the initial state and sets up the variable map.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Aig_ManInitStateVarMap( DdManager * dd, Aig_Man_t * p, int fVerbose ) -{ - DdNode ** pbVarsX, ** pbVarsY; - DdNode * bTemp, * bProd; - Aig_Obj_t * pLatch; - int i; - - // set the variable mapping for Cudd_bddVarMap() - pbVarsX = ABC_ALLOC( DdNode *, dd->size ); - pbVarsY = ABC_ALLOC( DdNode *, dd->size ); - bProd = (dd)->one; Cudd_Ref( bProd ); - Saig_ManForEachLo( p, pLatch, i ) - { - pbVarsX[i] = dd->vars[ Saig_ManPiNum(p) + i ]; - pbVarsY[i] = dd->vars[ Saig_ManCiNum(p) + i ]; - // get the initial value of the latch - bProd = Cudd_bddAnd( dd, bTemp = bProd, Cudd_Not(pbVarsX[i]) ); Cudd_Ref( bProd ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_SetVarMap( dd, pbVarsX, pbVarsY, Saig_ManRegNum(p) ); - ABC_FREE( pbVarsX ); - ABC_FREE( pbVarsY ); - - Cudd_Deref( bProd ); - return bProd; -} - -/**Function************************************************************* - - Synopsis [Collects the array of output BDDs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode ** Aig_ManCreateOutputs( DdManager * dd, Aig_Man_t * p ) -{ - DdNode ** pbOutputs; - Aig_Obj_t * pNode; - int i; - // compute the transition relation - pbOutputs = ABC_ALLOC( DdNode *, Saig_ManPoNum(p) ); - Saig_ManForEachPo( p, pNode, i ) - { - pbOutputs[i] = Aig_ObjGlobalBdd(pNode); Cudd_Ref( pbOutputs[i] ); - } - return pbOutputs; -} - -/**Function************************************************************* - - Synopsis [Collects the array of partition BDDs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode ** Aig_ManCreatePartitions( DdManager * dd, Aig_Man_t * p, int fReorder, int fVerbose ) -{ - DdNode ** pbParts; - DdNode * bVar; - Aig_Obj_t * pNode; - int i; - - // extand the BDD manager to represent NS variables - assert( dd->size == Saig_ManCiNum(p) ); - Cudd_bddIthVar( dd, Saig_ManCiNum(p) + Saig_ManRegNum(p) - 1 ); - - // enable reordering - if ( fReorder ) - Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - else - Cudd_AutodynDisable( dd ); - - // compute the transition relation - pbParts = ABC_ALLOC( DdNode *, Saig_ManRegNum(p) ); - Saig_ManForEachLi( p, pNode, i ) - { - bVar = Cudd_bddIthVar( dd, Saig_ManCiNum(p) + i ); - pbParts[i] = Cudd_bddXnor( dd, bVar, Aig_ObjGlobalBdd(pNode) ); Cudd_Ref( pbParts[i] ); - } - // free global BDDs - Aig_ManFreeGlobalBdds( p, dd ); - - // reorder and disable reordering - if ( fReorder ) - { - if ( fVerbose ) - fprintf( stdout, "BDD nodes in the partitions before reordering %d.\n", Cudd_SharingSize(pbParts,Saig_ManRegNum(p)) ); - Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); - Cudd_AutodynDisable( dd ); - if ( fVerbose ) - fprintf( stdout, "BDD nodes in the partitions after reordering %d.\n", Cudd_SharingSize(pbParts,Saig_ManRegNum(p)) ); - } - return pbParts; -} - -/**Function************************************************************* - - Synopsis [Computes the set of unreachable states.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManComputeReachable( DdManager * dd, Aig_Man_t * p, DdNode ** pbParts, DdNode * bInitial, DdNode ** pbOutputs, Saig_ParBbr_t * pPars, int fCheckOutputs ) -{ - int fInternalReorder = 0; - Bbr_ImageTree_t * pTree = NULL; // Suppress "might be used uninitialized" - Bbr_ImageTree2_t * pTree2 = NULL; // Supprses "might be used uninitialized" - DdNode * bReached, * bCubeCs; - DdNode * bCurrent; - DdNode * bNext = NULL; // Suppress "might be used uninitialized" - DdNode * bTemp; - Cudd_ReorderingType method; - int i, nIters, nBddSize = 0, status; - int nThreshold = 10000, clk = clock(); - Vec_Ptr_t * vOnionRings; - - status = Cudd_ReorderingStatus( dd, &method ); - if ( status ) - Cudd_AutodynDisable( dd ); - - // start the image computation - bCubeCs = Bbr_bddComputeRangeCube( dd, Saig_ManPiNum(p), Saig_ManCiNum(p) ); Cudd_Ref( bCubeCs ); - if ( pPars->fPartition ) - pTree = Bbr_bddImageStart( dd, bCubeCs, Saig_ManRegNum(p), pbParts, Saig_ManRegNum(p), dd->vars+Saig_ManCiNum(p), pPars->nBddMax, pPars->fVerbose ); - else - pTree2 = Bbr_bddImageStart2( dd, bCubeCs, Saig_ManRegNum(p), pbParts, Saig_ManRegNum(p), dd->vars+Saig_ManCiNum(p), pPars->fVerbose ); - Cudd_RecursiveDeref( dd, bCubeCs ); - if ( pTree == NULL ) - { - if ( !pPars->fSilent ) - printf( "BDDs blew up during qualitification scheduling. " ); - return -1; - } - - if ( status ) - Cudd_AutodynEnable( dd, method ); - - // start the onion rings - vOnionRings = Vec_PtrAlloc( 1000 ); - - // perform reachability analysis - bCurrent = bInitial; Cudd_Ref( bCurrent ); - bReached = bInitial; Cudd_Ref( bReached ); - Vec_PtrPush( vOnionRings, bCurrent ); Cudd_Ref( bCurrent ); - for ( nIters = 0; nIters < pPars->nIterMax; nIters++ ) - { - // check the runtime limit - if ( pPars->TimeLimit && ((float)pPars->TimeLimit <= (float)(clock()-clk)/(float)(CLOCKS_PER_SEC)) ) - { - printf( "Reached timeout after image computation (%d seconds).\n", pPars->TimeLimit ); - Vec_PtrFree( vOnionRings ); - // undo the image tree - if ( pPars->fPartition ) - Bbr_bddImageTreeDelete( pTree ); - else - Bbr_bddImageTreeDelete2( pTree2 ); - pPars->iFrame = nIters - 1; - return -1; - } - - // compute the next states - if ( pPars->fPartition ) - bNext = Bbr_bddImageCompute( pTree, bCurrent ); - else - bNext = Bbr_bddImageCompute2( pTree2, bCurrent ); - if ( bNext == NULL ) - { - if ( !pPars->fSilent ) - printf( "BDDs blew up during image computation. " ); - if ( pPars->fPartition ) - Bbr_bddImageTreeDelete( pTree ); - else - Bbr_bddImageTreeDelete2( pTree2 ); - Vec_PtrFree( vOnionRings ); - pPars->iFrame = nIters - 1; - return -1; - } - Cudd_Ref( bNext ); - Cudd_RecursiveDeref( dd, bCurrent ); - - // remap these states into the current state vars - bNext = Cudd_bddVarMap( dd, bTemp = bNext ); Cudd_Ref( bNext ); - Cudd_RecursiveDeref( dd, bTemp ); - // check if there are any new states - if ( Cudd_bddLeq( dd, bNext, bReached ) ) - break; - // check the BDD size - nBddSize = Cudd_DagSize(bNext); - if ( nBddSize > pPars->nBddMax ) - break; - // check the result - for ( i = 0; i < Saig_ManPoNum(p); i++ ) - { - if ( fCheckOutputs && !Cudd_bddLeq( dd, bNext, Cudd_Not(pbOutputs[i]) ) ) - { - DdNode * bIntersect; - bIntersect = Cudd_bddIntersect( dd, bNext, pbOutputs[i] ); Cudd_Ref( bIntersect ); - assert( p->pSeqModel == NULL ); - p->pSeqModel = Aig_ManVerifyUsingBddsCountExample( p, dd, pbParts, - vOnionRings, bIntersect, i, pPars->fVerbose, pPars->fSilent ); - Cudd_RecursiveDeref( dd, bIntersect ); - if ( !pPars->fSilent ) - printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump a witness). ", i, Vec_PtrSize(vOnionRings) ); - Cudd_RecursiveDeref( dd, bReached ); - bReached = NULL; - pPars->iFrame = nIters; - break; - } - } - if ( i < Saig_ManPoNum(p) ) - break; - // get the new states - bCurrent = Cudd_bddAnd( dd, bNext, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); - Vec_PtrPush( vOnionRings, bCurrent ); Cudd_Ref( bCurrent ); - // minimize the new states with the reached states -// bCurrent = Cudd_bddConstrain( dd, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); -// Cudd_RecursiveDeref( dd, bTemp ); - // add to the reached states - bReached = Cudd_bddOr( dd, bTemp = bReached, bNext ); Cudd_Ref( bReached ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bNext ); - if ( pPars->fVerbose ) - fprintf( stdout, "Frame = %3d. BDD = %5d. ", nIters, nBddSize ); - if ( fInternalReorder && pPars->fReorder && nBddSize > nThreshold ) - { - if ( pPars->fVerbose ) - fprintf( stdout, "Reordering... Before = %5d. ", Cudd_DagSize(bReached) ); - Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); - Cudd_AutodynDisable( dd ); - if ( pPars->fVerbose ) - fprintf( stdout, "After = %5d.\r", Cudd_DagSize(bReached) ); - nThreshold *= 2; - } - if ( pPars->fVerbose ) -// fprintf( stdout, "\r" ); - fprintf( stdout, "\n" ); - - if ( pPars->fVerbose ) - { - double nMints = Cudd_CountMinterm(dd, bReached, Saig_ManRegNum(p) ); -// Extra_bddPrint( dd, bReached );printf( "\n" ); - fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p)) ); - fflush( stdout ); - } - - } - Cudd_RecursiveDeref( dd, bNext ); - // free the onion rings - Vec_PtrForEachEntry( DdNode *, vOnionRings, bTemp, i ) - Cudd_RecursiveDeref( dd, bTemp ); - Vec_PtrFree( vOnionRings ); - // undo the image tree - if ( pPars->fPartition ) - Bbr_bddImageTreeDelete( pTree ); - else - Bbr_bddImageTreeDelete2( pTree2 ); - if ( bReached == NULL ) - return 0; // proved reachable - // report the stats - if ( pPars->fVerbose ) - { - double nMints = Cudd_CountMinterm(dd, bReached, Saig_ManRegNum(p) ); - if ( nIters > pPars->nIterMax || nBddSize > pPars->nBddMax ) - fprintf( stdout, "Reachability analysis is stopped after %d frames.\n", nIters ); - else - fprintf( stdout, "Reachability analysis completed after %d frames.\n", nIters ); - fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p)) ); - fflush( stdout ); - } -//ABC_PRB( dd, bReached ); - Cudd_RecursiveDeref( dd, bReached ); - if ( nIters > pPars->nIterMax || nBddSize > pPars->nBddMax ) - { - if ( !pPars->fSilent ) - printf( "Verified only for states reachable in %d frames. ", nIters ); - return -1; // undecided - } - if ( !pPars->fSilent ) - printf( "The miter is proved unreachable after %d iterations. ", nIters ); - pPars->iFrame = nIters - 1; - return 1; // unreachable -} - -/**Function************************************************************* - - Synopsis [Performs reachability to see if any PO can be asserted.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManVerifyUsingBdds_int( Aig_Man_t * p, Saig_ParBbr_t * pPars ) -{ - int fCheckOutputs = !pPars->fSkipOutCheck; - DdManager * dd; - DdNode ** pbParts, ** pbOutputs; - DdNode * bInitial, * bTemp; - int RetValue, i, clk = clock(); - Vec_Ptr_t * vOnionRings; - - assert( Saig_ManRegNum(p) > 0 ); - - // compute the global BDDs of the latches - dd = Aig_ManComputeGlobalBdds( p, pPars->nBddMax, 1, pPars->fReorder, pPars->fVerbose ); - if ( dd == NULL ) - { - if ( !pPars->fSilent ) - printf( "The number of intermediate BDD nodes exceeded the limit (%d).\n", pPars->nBddMax ); - return -1; - } - if ( pPars->fVerbose ) - printf( "Shared BDD size is %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); - - // check the runtime limit - if ( pPars->TimeLimit && ((float)pPars->TimeLimit <= (float)(clock()-clk)/(float)(CLOCKS_PER_SEC)) ) - { - printf( "Reached timeout after constructing global BDDs (%d seconds).\n", pPars->TimeLimit ); - Cudd_Quit( dd ); - return -1; - } - - // start the onion rings - vOnionRings = Vec_PtrAlloc( 1000 ); - - // save outputs - pbOutputs = Aig_ManCreateOutputs( dd, p ); - - // create partitions - pbParts = Aig_ManCreatePartitions( dd, p, pPars->fReorder, pPars->fVerbose ); - - // create the initial state and the variable map - bInitial = Aig_ManInitStateVarMap( dd, p, pPars->fVerbose ); Cudd_Ref( bInitial ); - - // set reordering - if ( pPars->fReorderImage ) - Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - - // check the result - RetValue = -1; - for ( i = 0; i < Saig_ManPoNum(p); i++ ) - { - if ( fCheckOutputs && !Cudd_bddLeq( dd, bInitial, Cudd_Not(pbOutputs[i]) ) ) - { - DdNode * bIntersect; - bIntersect = Cudd_bddIntersect( dd, bInitial, pbOutputs[i] ); Cudd_Ref( bIntersect ); - assert( p->pSeqModel == NULL ); - p->pSeqModel = Aig_ManVerifyUsingBddsCountExample( p, dd, pbParts, - vOnionRings, bIntersect, i, pPars->fVerbose, pPars->fSilent ); - Cudd_RecursiveDeref( dd, bIntersect ); - if ( !pPars->fSilent ) - printf( "The miter output %d is proved REACHABLE in the initial state (use \"write_counter\" to dump a witness). ", i ); - RetValue = 0; - break; - } - } - // free the onion rings - Vec_PtrForEachEntry( DdNode *, vOnionRings, bTemp, i ) - Cudd_RecursiveDeref( dd, bTemp ); - Vec_PtrFree( vOnionRings ); - // explore reachable states - if ( RetValue == -1 ) - RetValue = Aig_ManComputeReachable( dd, p, pbParts, bInitial, pbOutputs, pPars, fCheckOutputs ); - - // cleanup - Cudd_RecursiveDeref( dd, bInitial ); - for ( i = 0; i < Saig_ManRegNum(p); i++ ) - Cudd_RecursiveDeref( dd, pbParts[i] ); - ABC_FREE( pbParts ); - for ( i = 0; i < Saig_ManPoNum(p); i++ ) - Cudd_RecursiveDeref( dd, pbOutputs[i] ); - ABC_FREE( pbOutputs ); -// if ( RetValue == -1 ) - Cudd_Quit( dd ); -// else -// Bbr_StopManager( dd ); - - // report the runtime - if ( !pPars->fSilent ) - { - ABC_PRT( "Time", clock() - clk ); - fflush( stdout ); - } - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Performs reachability to see if any PO can be asserted.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManVerifyUsingBdds( Aig_Man_t * pInit, Saig_ParBbr_t * pPars ) -{ - Abc_Cex_t * pCexOld, * pCexNew; - Aig_Man_t * p; - Aig_Obj_t * pObj; - Vec_Int_t * vInputMap; - int i, k, Entry, iBitOld, iBitNew, RetValue; -// pPars->fVerbose = 1; - // check if there are PIs without fanout - Saig_ManForEachPi( pInit, pObj, i ) - if ( Aig_ObjRefs(pObj) == 0 ) - break; - if ( i == Saig_ManPiNum(pInit) ) - return Aig_ManVerifyUsingBdds_int( pInit, pPars ); - // create new AIG - p = Aig_ManDupTrim( pInit ); - assert( Aig_ManPiNum(p) < Aig_ManPiNum(pInit) ); - assert( Aig_ManRegNum(p) == Aig_ManRegNum(pInit) ); - RetValue = Aig_ManVerifyUsingBdds_int( p, pPars ); - if ( RetValue != 0 ) - { - Aig_ManStop( p ); - return RetValue; - } - // the problem is satisfiable - remap the pattern - pCexOld = p->pSeqModel; - assert( pCexOld != NULL ); - // create input map - vInputMap = Vec_IntAlloc( Saig_ManPiNum(pInit) ); - Saig_ManForEachPi( pInit, pObj, i ) - if ( pObj->pData != NULL ) - Vec_IntPush( vInputMap, Aig_ObjPioNum((Aig_Obj_t *)pObj->pData) ); - else - Vec_IntPush( vInputMap, -1 ); - // create new pattern - pCexNew = Abc_CexAlloc( Saig_ManRegNum(pInit), Saig_ManPiNum(pInit), pCexOld->iFrame+1 ); - pCexNew->iFrame = pCexOld->iFrame; - pCexNew->iPo = pCexOld->iPo; - // copy the bit-data - for ( iBitOld = 0; iBitOld < pCexOld->nRegs; iBitOld++ ) - if ( Aig_InfoHasBit( pCexOld->pData, iBitOld ) ) - Aig_InfoSetBit( pCexNew->pData, iBitOld ); - // copy the primary input data - iBitNew = iBitOld; - for ( i = 0; i <= pCexNew->iFrame; i++ ) - { - Vec_IntForEachEntry( vInputMap, Entry, k ) - { - if ( Entry == -1 ) - continue; - if ( Aig_InfoHasBit( pCexOld->pData, iBitOld + Entry ) ) - Aig_InfoSetBit( pCexNew->pData, iBitNew + k ); - } - iBitOld += Saig_ManPiNum(p); - iBitNew += Saig_ManPiNum(pInit); - } - assert( iBitOld < iBitNew ); - assert( iBitOld == pCexOld->nBits ); - assert( iBitNew == pCexNew->nBits ); - Vec_IntFree( vInputMap ); - pInit->pSeqModel = pCexNew; - Aig_ManStop( p ); - return 0; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/bbr/bbr_.c b/src/aig/bbr/bbr_.c deleted file mode 100644 index df934f7d..00000000 --- a/src/aig/bbr/bbr_.c +++ /dev/null @@ -1,52 +0,0 @@ -/**CFile**************************************************************** - - FileName [.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: .c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "__Int.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/bbr/module.make b/src/aig/bbr/module.make deleted file mode 100644 index dce30a21..00000000 --- a/src/aig/bbr/module.make +++ /dev/null @@ -1,4 +0,0 @@ -SRC += src/aig/bbr/bbrCex.c \ - src/aig/bbr/bbrImage.c \ - src/aig/bbr/bbrNtbdd.c \ - src/aig/bbr/bbrReach.c diff --git a/src/aig/bdc/bdc.h b/src/aig/bdc/bdc.h deleted file mode 100644 index 8a240b0c..00000000 --- a/src/aig/bdc/bdc.h +++ /dev/null @@ -1,92 +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__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Bdc_Fun_t_ Bdc_Fun_t; -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 -}; - -// working with complemented attributes of objects -static inline int Bdc_IsComplement( Bdc_Fun_t * p ) { return (int)((ABC_PTRUINT_T)p & (ABC_PTRUINT_T)01); } -static inline Bdc_Fun_t * Bdc_Regular( Bdc_Fun_t * p ) { return (Bdc_Fun_t *)((ABC_PTRUINT_T)p & ~(ABC_PTRUINT_T)01); } -static inline Bdc_Fun_t * Bdc_Not( Bdc_Fun_t * p ) { return (Bdc_Fun_t *)((ABC_PTRUINT_T)p ^ (ABC_PTRUINT_T)01); } -static inline Bdc_Fun_t * Bdc_NotCond( Bdc_Fun_t * p, int c ) { return (Bdc_Fun_t *)((ABC_PTRUINT_T)p ^ (ABC_PTRUINT_T)(c!=0)); } - -//////////////////////////////////////////////////////////////////////// -/// 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 nNodesMax ); -extern Bdc_Fun_t * Bdc_ManFunc( Bdc_Man_t * p, int i ); -extern Bdc_Fun_t * Bdc_ManRoot( Bdc_Man_t * p ); -extern int Bdc_ManNodeNum( Bdc_Man_t * p ); -extern Bdc_Fun_t * Bdc_FuncFanin0( Bdc_Fun_t * p ); -extern Bdc_Fun_t * Bdc_FuncFanin1( Bdc_Fun_t * p ); -extern void * Bdc_FuncCopy( Bdc_Fun_t * p ); -extern int Bdc_FuncCopyInt( Bdc_Fun_t * p ); -extern void Bdc_FuncSetCopy( Bdc_Fun_t * p, void * pCopy ); -extern void Bdc_FuncSetCopyInt( Bdc_Fun_t * p, int iCopy ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/bdc/bdcCore.c b/src/aig/bdc/bdcCore.c deleted file mode 100644 index 58324f81..00000000 --- a/src/aig/bdc/bdcCore.c +++ /dev/null @@ -1,314 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Accessing contents of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bdc_Fun_t * Bdc_ManFunc( Bdc_Man_t * p, int i ) { return Bdc_FunWithId(p, i); } -Bdc_Fun_t * Bdc_ManRoot( Bdc_Man_t * p ) { return p->pRoot; } -int Bdc_ManNodeNum( Bdc_Man_t * p ) { return p->nNodes; } -Bdc_Fun_t * Bdc_FuncFanin0( Bdc_Fun_t * p ) { return p->pFan0; } -Bdc_Fun_t * Bdc_FuncFanin1( Bdc_Fun_t * p ) { return p->pFan1; } -void * Bdc_FuncCopy( Bdc_Fun_t * p ) { return p->pCopy; } -int Bdc_FuncCopyInt( Bdc_Fun_t * p ) { return p->iCopy; } -void Bdc_FuncSetCopy( Bdc_Fun_t * p, void * pCopy ) { p->pCopy = pCopy; } -void Bdc_FuncSetCopyInt( Bdc_Fun_t * p, int iCopy ) { p->iCopy = iCopy; } - -/**Function************************************************************* - - Synopsis [Allocate resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bdc_Man_t * Bdc_ManAlloc( Bdc_Par_t * pPars ) -{ - Bdc_Man_t * p; - p = ABC_ALLOC( Bdc_Man_t, 1 ); - memset( p, 0, sizeof(Bdc_Man_t) ); - assert( pPars->nVarsMax > 1 && pPars->nVarsMax < 16 ); - p->pPars = pPars; - p->nWords = Kit_TruthWordNum( pPars->nVarsMax ); - p->nDivsLimit = 200; - // internal nodes - p->nNodesAlloc = 512; - p->pNodes = ABC_ALLOC( Bdc_Fun_t, p->nNodesAlloc ); - // memory - p->vMemory = Vec_IntStart( 8 * p->nWords * p->nNodesAlloc ); - Vec_IntClear(p->vMemory); - // set up hash table - p->nTableSize = (1 << p->pPars->nVarsMax); - p->pTable = ABC_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_PtrAllocTruthTables( p->pPars->nVarsMax ); - p->puTemp1 = ABC_ALLOC( unsigned, 4 * p->nWords ); - p->puTemp2 = p->puTemp1 + p->nWords; - p->puTemp3 = p->puTemp2 + p->nWords; - p->puTemp4 = p->puTemp3 + p->nWords; - // 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 ) -{ - if ( p->pPars->fVerbose ) - { - printf( "Bi-decomposition stats: Calls = %d. Nodes = %d. Reuse = %d.\n", - p->numCalls, p->numNodes, p->numReuse ); - printf( "ANDs = %d. ORs = %d. Weak = %d. Muxes = %d. Memory = %.2f K\n", - p->numAnds, p->numOrs, p->numWeaks, p->numMuxes, 4.0 * Vec_IntSize(p->vMemory) / (1<<10) ); - ABC_PRT( "Cache", p->timeCache ); - ABC_PRT( "Check", p->timeCheck ); - ABC_PRT( "Muxes", p->timeMuxes ); - ABC_PRT( "Supps", p->timeSupps ); - ABC_PRT( "TOTAL", p->timeTotal ); - } - Vec_IntFree( p->vMemory ); - Vec_IntFree( p->vSpots ); - Vec_PtrFree( p->vTruths ); - ABC_FREE( p->puTemp1 ); - ABC_FREE( p->pNodes ); - ABC_FREE( p->pTable ); - ABC_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 = 0; - p->nNodesNew = - 1 - p->nVars - (vDivs? Vec_PtrSize(vDivs) : 0); - // add constant 1 - pNode = Bdc_FunNew( p ); - pNode->Type = BDC_TYPE_CONST1; - pNode->puFunc = (unsigned *)Vec_IntFetch(p->vMemory, p->nWords); - Kit_TruthFill( pNode->puFunc, p->nVars ); - pNode->uSupp = 0; - Bdc_TableAdd( p, pNode ); - // add variables - for ( i = 0; i < p->nVars; i++ ) - { - pNode = Bdc_FunNew( p ); - pNode->Type = BDC_TYPE_PI; - pNode->puFunc = (unsigned *)Vec_PtrEntry( p->vTruths, i ); - pNode->uSupp = (1 << i); - Bdc_TableAdd( p, pNode ); - } - // add the divisors - if ( vDivs ) - Vec_PtrForEachEntry( unsigned *, 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; - } - assert( p->nNodesNew == 0 ); -} - -/**Function************************************************************* - - Synopsis [Clears the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bdc_ManDecPrint( Bdc_Man_t * p ) -{ - Bdc_Fun_t * pNode; - int i; - printf( " 0 : Const 1\n" ); - for ( i = 1; i < p->nNodes; i++ ) - { - printf( " %d : ", i ); - pNode = p->pNodes + i; - if ( pNode->Type == BDC_TYPE_PI ) - printf( "PI " ); - else - { - printf( "%s%d &", Bdc_IsComplement(pNode->pFan0)? "-":"", Bdc_FunId(p,Bdc_Regular(pNode->pFan0)) ); - printf( " %s%d ", Bdc_IsComplement(pNode->pFan1)? "-":"", Bdc_FunId(p,Bdc_Regular(pNode->pFan1)) ); - } - Extra_PrintBinary( stdout, pNode->puFunc, (1<nVars) ); - printf( "\n" ); - } - printf( "Root = %s%d.\n", Bdc_IsComplement(p->pRoot)? "-":"", Bdc_FunId(p,Bdc_Regular(p->pRoot)) ); -} - -/**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; - int clk = clock(); - assert( nVars <= p->pPars->nVarsMax ); - // set current manager parameters - p->nVars = nVars; - p->nWords = Kit_TruthWordNum( nVars ); - p->nNodesMax = nNodesMax; - Bdc_ManPrepare( p, vDivs ); - if ( puCare && Kit_TruthIsConst0( puCare, nVars ) ) - { - p->pRoot = Bdc_Not(p->pNodes); - return 0; - } - // copy the function - Bdc_IsfStart( p, pIsf ); - if ( puCare ) - { - Kit_TruthAnd( pIsf->puOn, puCare, puFunc, p->nVars ); - Kit_TruthSharp( pIsf->puOff, puCare, puFunc, p->nVars ); - } - else - { - Kit_TruthCopy( pIsf->puOn, puFunc, p->nVars ); - Kit_TruthNot( pIsf->puOff, puFunc, p->nVars ); - } - Bdc_SuppMinimize( p, pIsf ); - // call decomposition - p->pRoot = Bdc_ManDecompose_rec( p, pIsf ); - p->timeTotal += clock() - clk; - p->numCalls++; - p->numNodes += p->nNodesNew; - if ( p->pRoot == NULL ) - return -1; - if ( !Bdc_ManNodeVerify( p, pIsf, p->pRoot ) ) - printf( "Bdc_ManDecompose(): Internal verification failed.\n" ); -// assert( Bdc_ManNodeVerify( p, pIsf, p->pRoot ) ); - return p->nNodesNew; -} - -/**Function************************************************************* - - Synopsis [Performs decomposition of one function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bdc_ManDecomposeTest( unsigned uTruth, int nVars ) -{ - static int Counter = 0; - static int Total = 0; - Bdc_Par_t Pars = {0}, * pPars = &Pars; - Bdc_Man_t * p; - int RetValue; -// unsigned uCare = ~0x888f888f; - unsigned uCare = ~0; -// unsigned uFunc = 0x88888888; -// unsigned uFunc = 0xf888f888; -// unsigned uFunc = 0x117e117e; -// unsigned uFunc = 0x018b018b; - unsigned uFunc = uTruth; - - pPars->nVarsMax = 8; - p = Bdc_ManAlloc( pPars ); - RetValue = Bdc_ManDecompose( p, &uFunc, &uCare, nVars, NULL, 1000 ); - Total += RetValue; - printf( "%5d : Nodes = %5d. Total = %8d.\n", ++Counter, RetValue, Total ); -// Bdc_ManDecPrint( p ); - Bdc_ManFree( p ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/bdc/bdcDec.c b/src/aig/bdc/bdcDec.c deleted file mode 100644 index 61f46f17..00000000 --- a/src/aig/bdc/bdcDec.c +++ /dev/null @@ -1,751 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Minimizes the support of the ISF.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bdc_SuppMinimize2( Bdc_Man_t * p, Bdc_Isf_t * pIsf ) -{ - int v; - int clk = 0; // Suppress "might be used uninitialized" - if ( p->pPars->fVerbose ) - clk = clock(); - // compute support - pIsf->uSupp = Kit_TruthSupport( pIsf->puOn, p->nVars ) | - Kit_TruthSupport( pIsf->puOff, p->nVars ); - // 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; -// if ( !Kit_TruthVarIsVacuous( pIsf->puOn, pIsf->puOff, p->nVars, v ) ) -// continue; - // remove the variable - Kit_TruthCopy( pIsf->puOn, p->puTemp1, p->nVars ); - Kit_TruthCopy( pIsf->puOff, p->puTemp2, p->nVars ); -// Kit_TruthExist( pIsf->puOn, p->nVars, v ); -// Kit_TruthExist( pIsf->puOff, p->nVars, v ); - pIsf->uSupp &= ~(1 << v); - } - if ( p->pPars->fVerbose ) - p->timeSupps += clock() - clk; -} - -/**Function************************************************************* - - Synopsis [Minimizes the support of the ISF.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bdc_SuppMinimize( Bdc_Man_t * p, Bdc_Isf_t * pIsf ) -{ - int v; - int clk = 0; // Suppress "might be used uninitialized" - if ( p->pPars->fVerbose ) - clk = clock(); - // go through the support variables - pIsf->uSupp = 0; - for ( v = 0; v < p->nVars; v++ ) - { - if ( !Kit_TruthVarInSupport( pIsf->puOn, p->nVars, v ) && - !Kit_TruthVarInSupport( pIsf->puOff, p->nVars, v ) ) - continue; - if ( Kit_TruthVarIsVacuous( pIsf->puOn, pIsf->puOff, p->nVars, v ) ) - { - Kit_TruthExist( pIsf->puOn, p->nVars, v ); - Kit_TruthExist( pIsf->puOff, p->nVars, v ); - continue; - } - pIsf->uSupp |= (1 << v); - } - if ( p->pPars->fVerbose ) - p->timeSupps += clock() - clk; -} - -/**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, Bdc_Fun_t * pFunc0, Bdc_Type_t Type ) -{ - unsigned * puTruth = p->puTemp1; - // get the truth table of the left branch - if ( Bdc_IsComplement(pFunc0) ) - Kit_TruthNot( puTruth, Bdc_Regular(pFunc0)->puFunc, p->nVars ); - else - Kit_TruthCopy( puTruth, pFunc0->puFunc, p->nVars ); - // split into parts - 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->uUniq ); - Kit_TruthExistSet( pIsfR->puOff, pIsf->puOff, p->nVars, pIsfL->uUniq ); -// assert( Kit_TruthIsDisjoint(pIsfR->puOn, pIsfR->puOff, p->nVars) ); - 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_TruthAnd( pIsfR->puOff, pIsf->puOff, puTruth, p->nVars ); - Kit_TruthExistSet( pIsfR->puOff, pIsfR->puOff, p->nVars, pIsfL->uUniq ); - Kit_TruthExistSet( pIsfR->puOn, pIsf->puOn, p->nVars, pIsfL->uUniq ); -// assert( Kit_TruthIsDisjoint(pIsfR->puOn, pIsfR->puOff, p->nVars) ); - assert( !Kit_TruthIsConst0(pIsfR->puOn, p->nVars) ); - return Kit_TruthIsConst0(pIsfR->puOff, 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->uUniq = (1 << pVars[Beg]); - pIsfR->uUniq = (1 << pVars[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; - int VarBest = -1; // Suppress "might be used uninitialized" - int Cost, VarCostBest = 0; - - for ( v = 0; v < p->nVars; v++ ) - { - if ( (pIsf->uSupp & (1 << v)) == 0 ) - continue; -// 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 ) - - Kit_TruthExistNew( p->puTemp1, pIsf->puOff, p->nVars, v ); - 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->uUniq = (1 << VarBest); - pIsfR->uUniq = 0; - -// assert( pL->Q != b0 ); -// assert( pL->R != b0 ); -// assert( Cudd_bddIteConstant( dd, pL->Q, pL->R, b0 ) == b0 ); -// assert( Kit_TruthIsDisjoint(pIsfL->puOn, pIsfL->puOff, p->nVars) ); - - // 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 uSupportRem; - int v, nLeftVars = 1, nRightVars = 1; - // clean the var sets - Bdc_IsfStart( p, pIsfL ); - Bdc_IsfStart( p, pIsfR ); - // check that the support is correct - assert( Kit_TruthSupport(pIsf->puOn, p->nVars) == Kit_TruthSupport(pIsf->puOff, p->nVars) ); - assert( pIsf->uSupp == Kit_TruthSupport(pIsf->puOn, p->nVars) ); - // 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_TruthExistSet( p->puTemp1, pIsf->puOff, p->nVars, pIsfL->uUniq ); - Kit_TruthExistSet( p->puTemp2, pIsf->puOff, p->nVars, pIsfR->uUniq ); - // go through the remaining variables - uSupportRem = pIsf->uSupp & ~pIsfL->uUniq & ~pIsfR->uUniq; - for ( v = 0; v < p->nVars; v++ ) - { - if ( (uSupportRem & (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->uUniq |= (1 << v); - nLeftVars++; - Kit_TruthCopy( p->puTemp1, p->puTemp3, p->nVars ); - } -// 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->uUniq |= (1 << v); - nRightVars++; - Kit_TruthCopy( p->puTemp2, p->puTemp4, p->nVars ); - } - } - 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->uUniq |= (1 << v); - nRightVars++; - Kit_TruthCopy( p->puTemp2, p->puTemp4, p->nVars ); - } -// 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->uUniq |= (1 << v); - nLeftVars++; - Kit_TruthCopy( p->puTemp1, p->puTemp3, p->nVars ); - } - } - } - - // 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->uUniq ); - Kit_TruthCopy( pIsfL->puOff, p->puTemp2, 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) ); - - // 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->uUniq ); - Kit_TruthCopy( pIsfR->puOff, p->puTemp1, p->nVars ); - - assert( !Kit_TruthIsConst0(pIsfR->puOn, p->nVars) ); - assert( !Kit_TruthIsConst0(pIsfR->puOff, p->nVars) ); -// assert( Kit_TruthIsDisjoint(pIsfR->puOn, pIsfR->puOff, p->nVars) ); - - assert( pIsfL->uUniq ); - assert( pIsfR->uUniq ); - 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 WeightOr, WeightAnd, WeightOrL, WeightOrR, WeightAndL, WeightAndR; - - Bdc_IsfClean( p->pIsfOL ); - Bdc_IsfClean( p->pIsfOR ); - Bdc_IsfClean( p->pIsfAL ); - Bdc_IsfClean( p->pIsfAR ); - - // perform OR decomposition - WeightOr = Bdc_DecomposeOr( p, pIsf, p->pIsfOL, p->pIsfOR ); - - // perform AND decomposition - Bdc_IsfNot( pIsf ); - WeightAnd = Bdc_DecomposeOr( p, pIsf, p->pIsfAL, p->pIsfAR ); - Bdc_IsfNot( pIsf ); - Bdc_IsfNot( p->pIsfAL ); - Bdc_IsfNot( p->pIsfAR ); - - // check the case when decomposition does not exist - if ( WeightOr == 0 && WeightAnd == 0 ) - { - Bdc_IsfCopy( pIsfL, p->pIsfOL ); - Bdc_IsfCopy( pIsfR, p->pIsfOR ); - return BDC_TYPE_MUX; - } - // check the hash table - assert( WeightOr || WeightAnd ); - WeightOrL = WeightOrR = 0; - if ( WeightOr ) - { - if ( p->pIsfOL->uUniq ) - { - Bdc_SuppMinimize( p, p->pIsfOL ); - WeightOrL = (Bdc_TableLookup(p, p->pIsfOL) != NULL); - } - if ( p->pIsfOR->uUniq ) - { - Bdc_SuppMinimize( p, p->pIsfOR ); - WeightOrR = (Bdc_TableLookup(p, p->pIsfOR) != NULL); - } - } - WeightAndL = WeightAndR = 0; - if ( WeightAnd ) - { - if ( p->pIsfAL->uUniq ) - { - Bdc_SuppMinimize( p, p->pIsfAL ); - WeightAndL = (Bdc_TableLookup(p, p->pIsfAL) != NULL); - } - if ( p->pIsfAR->uUniq ) - { - Bdc_SuppMinimize( p, p->pIsfAR ); - WeightAndR = (Bdc_TableLookup(p, p->pIsfAR) != NULL); - } - } - - // check if there is any reuse for the components - if ( WeightOrL + WeightOrR > WeightAndL + WeightAndR ) - { - p->numReuse++; - p->numOrs++; - Bdc_IsfCopy( pIsfL, p->pIsfOL ); - Bdc_IsfCopy( pIsfR, p->pIsfOR ); - return BDC_TYPE_OR; - } - if ( WeightOrL + WeightOrR < WeightAndL + WeightAndR ) - { - p->numReuse++; - p->numAnds++; - Bdc_IsfCopy( pIsfL, p->pIsfAL ); - Bdc_IsfCopy( pIsfR, p->pIsfAR ); - return BDC_TYPE_AND; - } - - // compare the two-component costs - if ( WeightOr > WeightAnd ) - { - if ( WeightOr < BDC_SCALE ) - p->numWeaks++; - p->numOrs++; - Bdc_IsfCopy( pIsfL, p->pIsfOL ); - Bdc_IsfCopy( pIsfR, p->pIsfOR ); - return BDC_TYPE_OR; - } - if ( WeightAnd < BDC_SCALE ) - p->numWeaks++; - p->numAnds++; - Bdc_IsfCopy( pIsfL, p->pIsfAL ); - Bdc_IsfCopy( pIsfR, p->pIsfAR ); - return BDC_TYPE_AND; -} - -/**Function************************************************************* - - Synopsis [Find variable that leads to minimum sum of support sizes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Bdc_DecomposeStepMux( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR ) -{ - int Var, VarMin, nSuppMin, nSuppCur; - unsigned uSupp0, uSupp1; - int clk = 0; // Suppress "might be used uninitialized" - if ( p->pPars->fVerbose ) - clk = clock(); - VarMin = -1; - nSuppMin = 1000; - for ( Var = 0; Var < p->nVars; Var++ ) - { - if ( (pIsf->uSupp & (1 << Var)) == 0 ) - continue; - Kit_TruthCofactor0New( pIsfL->puOn, pIsf->puOn, p->nVars, Var ); - Kit_TruthCofactor0New( pIsfL->puOff, pIsf->puOff, p->nVars, Var ); - Kit_TruthCofactor1New( pIsfR->puOn, pIsf->puOn, p->nVars, Var ); - Kit_TruthCofactor1New( pIsfR->puOff, pIsf->puOff, p->nVars, Var ); - uSupp0 = Kit_TruthSupport( pIsfL->puOn, p->nVars ) & Kit_TruthSupport( pIsfL->puOff, p->nVars ); - uSupp1 = Kit_TruthSupport( pIsfR->puOn, p->nVars ) & Kit_TruthSupport( pIsfR->puOff, p->nVars ); - nSuppCur = Kit_WordCountOnes(uSupp0) + Kit_WordCountOnes(uSupp1); - if ( nSuppMin > nSuppCur ) - { - nSuppMin = nSuppCur; - VarMin = Var; - break; - } - } - if ( VarMin >= 0 ) - { - Kit_TruthCofactor0New( pIsfL->puOn, pIsf->puOn, p->nVars, VarMin ); - Kit_TruthCofactor0New( pIsfL->puOff, pIsf->puOff, p->nVars, VarMin ); - Kit_TruthCofactor1New( pIsfR->puOn, pIsf->puOn, p->nVars, VarMin ); - Kit_TruthCofactor1New( pIsfR->puOff, pIsf->puOff, p->nVars, VarMin ); - Bdc_SuppMinimize( p, pIsfL ); - Bdc_SuppMinimize( p, pIsfR ); - } - if ( p->pPars->fVerbose ) - p->timeMuxes += clock() - clk; - return VarMin; -} - -/**Function************************************************************* - - Synopsis [Creates gates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Bdc_ManNodeVerify( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Fun_t * pFunc ) -{ - unsigned * puTruth = p->puTemp1; - if ( Bdc_IsComplement(pFunc) ) - Kit_TruthNot( puTruth, Bdc_Regular(pFunc)->puFunc, p->nVars ); - else - Kit_TruthCopy( puTruth, pFunc->puFunc, p->nVars ); - return Bdc_TableCheckContainment( p, pIsf, puTruth ); -} - -/**Function************************************************************* - - Synopsis [Creates gates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bdc_Fun_t * Bdc_ManCreateGate( Bdc_Man_t * p, Bdc_Fun_t * pFunc0, Bdc_Fun_t * pFunc1, Bdc_Type_t Type ) -{ - Bdc_Fun_t * pFunc; - pFunc = Bdc_FunNew( p ); - if ( pFunc == NULL ) - return NULL; - pFunc->Type = Type; - pFunc->pFan0 = pFunc0; - pFunc->pFan1 = pFunc1; - pFunc->puFunc = (unsigned *)Vec_IntFetch(p->vMemory, p->nWords); - // get the truth table of the left branch - if ( Bdc_IsComplement(pFunc0) ) - Kit_TruthNot( p->puTemp1, Bdc_Regular(pFunc0)->puFunc, p->nVars ); - else - Kit_TruthCopy( p->puTemp1, pFunc0->puFunc, p->nVars ); - // get the truth table of the right branch - if ( Bdc_IsComplement(pFunc1) ) - Kit_TruthNot( p->puTemp2, Bdc_Regular(pFunc1)->puFunc, p->nVars ); - else - Kit_TruthCopy( p->puTemp2, pFunc1->puFunc, p->nVars ); - // compute the function of node - if ( pFunc->Type == BDC_TYPE_AND ) - { - Kit_TruthAnd( pFunc->puFunc, p->puTemp1, p->puTemp2, p->nVars ); - } - else if ( pFunc->Type == BDC_TYPE_OR ) - { - Kit_TruthOr( pFunc->puFunc, p->puTemp1, p->puTemp2, p->nVars ); - // transform to AND gate - 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); - } - else - assert( 0 ); - // add to table - Bdc_Regular(pFunc)->uSupp = Kit_TruthSupport( Bdc_Regular(pFunc)->puFunc, p->nVars ); - Bdc_TableAdd( p, Bdc_Regular(pFunc) ); - return pFunc; -} - -/**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 ) -{ -// int static Counter = 0; -// int LocalCounter = Counter++; - Bdc_Type_t Type; - Bdc_Fun_t * pFunc, * pFunc0, * pFunc1; - Bdc_Isf_t IsfL, * pIsfL = &IsfL; - Bdc_Isf_t IsfB, * pIsfR = &IsfB; - int iVar; - int clk = 0; // Suppress "might be used uninitialized" -/* -printf( "Init function (%d):\n", LocalCounter ); -Extra_PrintBinary( stdout, pIsf->puOn, 1<<4 );printf("\n"); -Extra_PrintBinary( stdout, pIsf->puOff, 1<<4 );printf("\n"); -*/ - // check computed results - assert( Kit_TruthIsDisjoint(pIsf->puOn, pIsf->puOff, p->nVars) ); - if ( p->pPars->fVerbose ) - clk = clock(); - pFunc = Bdc_TableLookup( p, pIsf ); - if ( p->pPars->fVerbose ) - p->timeCache += clock() - clk; - if ( pFunc ) - return pFunc; - // decide on the decomposition type - if ( p->pPars->fVerbose ) - clk = clock(); - Type = Bdc_DecomposeStep( p, pIsf, pIsfL, pIsfR ); - if ( p->pPars->fVerbose ) - p->timeCheck += clock() - clk; - if ( Type == BDC_TYPE_MUX ) - { - if ( p->pPars->fVerbose ) - clk = clock(); - iVar = Bdc_DecomposeStepMux( p, pIsf, pIsfL, pIsfR ); - if ( p->pPars->fVerbose ) - p->timeMuxes += clock() - clk; - p->numMuxes++; - pFunc0 = Bdc_ManDecompose_rec( p, pIsfL ); - pFunc1 = Bdc_ManDecompose_rec( p, pIsfR ); - if ( pFunc0 == NULL || pFunc1 == NULL ) - return NULL; - pFunc = Bdc_FunWithId( p, iVar + 1 ); - pFunc0 = Bdc_ManCreateGate( p, Bdc_Not(pFunc), pFunc0, BDC_TYPE_AND ); - pFunc1 = Bdc_ManCreateGate( p, pFunc, pFunc1, BDC_TYPE_AND ); - if ( pFunc0 == NULL || pFunc1 == NULL ) - return NULL; - pFunc = Bdc_ManCreateGate( p, pFunc0, pFunc1, BDC_TYPE_OR ); - } - else - { - pFunc0 = Bdc_ManDecompose_rec( p, pIsfL ); - if ( pFunc0 == NULL ) - return NULL; - // decompose the right branch - if ( Bdc_DecomposeUpdateRight( p, pIsf, pIsfL, pIsfR, pFunc0, Type ) ) - { - p->nNodesNew--; - return pFunc0; - } - Bdc_SuppMinimize( p, pIsfR ); - pFunc1 = Bdc_ManDecompose_rec( p, pIsfR ); - if ( pFunc1 == NULL ) - return NULL; - // create new gate - pFunc = Bdc_ManCreateGate( p, pFunc0, pFunc1, Type ); - } - return pFunc; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/bdc/bdcInt.h b/src/aig/bdc/bdcInt.h deleted file mode 100644 index 74630664..00000000 --- a/src/aig/bdc/bdcInt.h +++ /dev/null @@ -1,165 +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__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "kit.h" -#include "bdc.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -#define BDC_SCALE 1000 // 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, // 3: AND-gate - BDC_TYPE_OR, // 4: OR-gate (temporary) - BDC_TYPE_XOR, // 5: XOR-gate - BDC_TYPE_MUX, // 6: MUX-gate - BDC_TYPE_OTHER // 7: unused -} Bdc_Type_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 - unsigned uSupp; // bit mask of current support - unsigned * puFunc; // the function of the node - Bdc_Fun_t * pNext; // next function with same support - union { int iCopy; // the literal of the node (AIG) - void * pCopy; }; // the function of the node (BDD or AIG) - -}; - -typedef struct Bdc_Isf_t_ Bdc_Isf_t; -struct Bdc_Isf_t_ -{ - unsigned uSupp; // the complete support of this component - unsigned uUniq; // the unique variables of this component - 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 nNodesMax; // 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 nNodesAlloc; // the number of nodes allocated - int nNodes; // the number of all nodes created so far - int nNodesNew; // the number of new AND nodes created so far - 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 - // statistics - int numCalls; - int numNodes; - int numMuxes; - int numAnds; - int numOrs; - int numWeaks; - int numReuse; - // runtime - int timeCache; - int timeCheck; - int timeMuxes; - int timeSupps; - int timeTotal; -}; - -static inline Bdc_Fun_t * Bdc_FunNew( Bdc_Man_t * p ) { Bdc_Fun_t * pRes; if ( p->nNodes >= p->nNodesAlloc || p->nNodesNew >= p->nNodesMax ) return NULL; pRes = p->pNodes + p->nNodes++; p->nNodesNew++; memset( pRes, 0, sizeof(Bdc_Fun_t) ); return pRes; } -static inline Bdc_Fun_t * Bdc_FunWithId( Bdc_Man_t * p, int Id ) { assert( Id < p->nNodes ); return p->pNodes + Id; } -static inline int Bdc_FunId( Bdc_Man_t * p, Bdc_Fun_t * pFun ) { return pFun - p->pNodes; } -static inline void Bdc_IsfStart( Bdc_Man_t * p, Bdc_Isf_t * pF ) { pF->uSupp = 0; pF->uUniq = 0; pF->puOn = Vec_IntFetch( p->vMemory, p->nWords ); pF->puOff = Vec_IntFetch( p->vMemory, p->nWords ); assert( pF->puOff && pF->puOn ); } -static inline void Bdc_IsfClean( Bdc_Isf_t * p ) { p->uSupp = 0; p->uUniq = 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 ); -extern void Bdc_SuppMinimize( Bdc_Man_t * p, Bdc_Isf_t * pIsf ); -extern int Bdc_ManNodeVerify( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Fun_t * pFunc ); -/*=== 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 int Bdc_TableCheckContainment( Bdc_Man_t * p, Bdc_Isf_t * pIsf, unsigned * puTruth ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/bdc/bdcSpfd.c b/src/aig/bdc/bdcSpfd.c deleted file mode 100644 index 2f05419d..00000000 --- a/src/aig/bdc/bdcSpfd.c +++ /dev/null @@ -1,1176 +0,0 @@ -/**CFile**************************************************************** - - FileName [bdcSpfd.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: bdcSpfd.c,v 1.00 2007/01/30 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "bdcInt.h" -#include "aig.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Bdc_Nod_t_ Bdc_Nod_t; -struct Bdc_Nod_t_ -{ - unsigned iFan0g : 8; - unsigned iFan0n : 12; - unsigned Type : 12; // 0-3 = AND; 4 = XOR - - unsigned iFan1g : 8; - unsigned iFan1n : 12; - unsigned Weight : 12; - - word Truth; -}; - -static word Truths[6] = { - 0xAAAAAAAAAAAAAAAA, - 0xCCCCCCCCCCCCCCCC, - 0xF0F0F0F0F0F0F0F0, - 0xFF00FF00FF00FF00, - 0xFFFF0000FFFF0000, - 0xFFFFFFFF00000000 -}; - -static inline int Bdc_CountOnes( word t ) -{ - t = (t & 0x5555555555555555) + ((t>> 1) & 0x5555555555555555); - t = (t & 0x3333333333333333) + ((t>> 2) & 0x3333333333333333); - t = (t & 0x0F0F0F0F0F0F0F0F) + ((t>> 4) & 0x0F0F0F0F0F0F0F0F); - t = (t & 0x00FF00FF00FF00FF) + ((t>> 8) & 0x00FF00FF00FF00FF); - t = (t & 0x0000FFFF0000FFFF) + ((t>>16) & 0x0000FFFF0000FFFF); - return (t & 0x00000000FFFFFFFF) + (t>>32); -} - -static inline int Bdc_CountSpfd( word t, word f ) -{ - int n00 = Bdc_CountOnes( ~t & ~f ); - int n01 = Bdc_CountOnes( t & ~f ); - int n10 = Bdc_CountOnes( ~t & f ); - int n11 = Bdc_CountOnes( t & f ); - return n00 * n11 + n10 * n01; -} - -static inline word Bdc_Cof6( word t, int iVar, int fCof1 ) -{ - assert( iVar >= 0 && iVar < 6 ); - if ( fCof1 ) - return (t & Truths[iVar]) | ((t & Truths[iVar]) >> (1< 0 ); - printf( "(" ); - - if ( pNode->Type & 1 ) - printf( "!" ); - if ( pNode->iFan0g == 0 ) - printf( "%c", 'a' + pNode->iFan0n ); - else - { - Bdc_Nod_t * pNode0 = (Bdc_Nod_t *)Vec_PtrEntry(vLevels, pNode->iFan0g); - Bdc_SpfdPrint_rec( pNode0 + pNode->iFan0n, pNode->iFan0g, vLevels ); - } - - if ( pNode->Type & 4 ) - printf( "+" ); - else - printf( "*" ); - - if ( pNode->Type & 2 ) - printf( "!" ); - if ( pNode->iFan1g == 0 ) - printf( "%c", 'a' + pNode->iFan1n ); - else - { - Bdc_Nod_t * pNode1 = (Bdc_Nod_t *)Vec_PtrEntry(vLevels, pNode->iFan1g); - Bdc_SpfdPrint_rec( pNode1 + pNode->iFan1n, pNode->iFan1g, vLevels ); - } - - printf( ")" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bdc_SpfdPrint( Bdc_Nod_t * pNode, int Level, Vec_Ptr_t * vLevels, word Truth ) -{ - word Diff = Truth ^ pNode->Truth; - Extra_PrintHex( stdout, (unsigned *)&pNode->Truth, 6 ); printf( " " ); - Extra_PrintHex( stdout, (unsigned *)&Diff, 6 ); printf( " " ); - Bdc_SpfdPrint_rec( pNode, Level, vLevels ); - printf( " %d\n", pNode->Weight ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bdc_SpfdDecompose( word Truth, int nVars, int nCands, int nGatesMax ) -{ - int nSize = nCands * nCands * (nGatesMax + 1) * 5; - Vec_Ptr_t * vLevels; - Vec_Int_t * vBegs, * vWeight; - Bdc_Nod_t * pNode, * pNode0, * pNode1, * pNode2; - int Count0, Count1, * pPerm; - int i, j, k, c, n, clk; - assert( nGatesMax < (1<<8) ); - assert( nCands < (1<<12) ); - assert( (1<<(nVars-1))*(1<<(nVars-1)) < (1<<12) ); // max SPFD - - printf( "Storage size = %d (%d * %d * %d * %d).\n", nSize, nCands, nCands, nGatesMax + 1, 5 ); - - printf( "SPFD = %d.\n", Bdc_CountOnes(Truth) * Bdc_CountOnes(~Truth) ); - - // consider elementary functions - if ( Truth == 0 || Truth == ~0 ) - { - printf( "Function is a constant.\n" ); - return; - } - for ( i = 0; i < nVars; i++ ) - if ( Truth == Truths[i] || Truth == ~Truths[i] ) - { - printf( "Function is an elementary variable.\n" ); - return; - } - - // allocate - vLevels = Vec_PtrAlloc( 100 ); - vBegs = Vec_IntAlloc( 100 ); - vWeight = Vec_IntAlloc( 100 ); - - // initialize elementary variables - pNode = ABC_CALLOC( Bdc_Nod_t, nVars ); - for ( i = 0; i < nVars; i++ ) - pNode[i].Truth = Truths[i]; - for ( i = 0; i < nVars; i++ ) - pNode[i].Weight = Bdc_CountSpfd( pNode[i].Truth, Truth ); - Vec_PtrPush( vLevels, pNode ); - Vec_IntPush( vBegs, nVars ); - - // the next level -clk = clock(); - pNode0 = pNode; - pNode = ABC_CALLOC( Bdc_Nod_t, 5 * nVars * (nVars - 1) / 2 ); - for ( c = i = 0; i < nVars; i++ ) - for ( j = i+1; j < nVars; j++ ) - { - pNode[c].Truth = pNode0[i].Truth & pNode0[j].Truth; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 0; - pNode[c].Truth = ~pNode0[i].Truth & pNode0[j].Truth; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 1; - pNode[c].Truth = pNode0[i].Truth & ~pNode0[j].Truth; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 2; - pNode[c].Truth = ~pNode0[i].Truth & ~pNode0[j].Truth; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 3; - pNode[c].Truth = pNode0[i].Truth ^ pNode0[j].Truth; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 4; - } - assert( c == 5 * nVars * (nVars - 1) / 2 ); - Vec_PtrPush( vLevels, pNode ); - Vec_IntPush( vBegs, c ); - for ( i = 0; i < c; i++ ) - { - pNode[i].Weight = Bdc_CountSpfd( pNode[i].Truth, Truth ); -//Bdc_SpfdPrint( pNode + i, 1, vLevels ); - if ( Truth == pNode[i].Truth || Truth == ~pNode[i].Truth ) - { - printf( "Function can be implemented using 1 gate.\n" ); - pNode = NULL; - goto cleanup; - } - } -printf( "Selected %6d gates on level %2d. ", c, 1 ); -Abc_PrintTime( 1, "Time", clock() - clk ); - - - // iterate through levels - pNode = ABC_CALLOC( Bdc_Nod_t, nSize ); - for ( n = 2; n <= nGatesMax; n++ ) - { -clk = clock(); - c = 0; - pNode1 = (Bdc_Nod_t *)Vec_PtrEntry( vLevels, n-1 ); - Count1 = Vec_IntEntry( vBegs, n-1 ); - // go through previous levels - for ( k = 0; k < n-1; k++ ) - { - pNode0 = (Bdc_Nod_t *)Vec_PtrEntry( vLevels, k ); - Count0 = Vec_IntEntry( vBegs, k ); - for ( i = 0; i < Count0; i++ ) - for ( j = 0; j < Count1; j++ ) - { - pNode[c].Truth = pNode0[i].Truth & pNode1[j].Truth; pNode[c].iFan0g = k; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 0; - pNode[c].Truth = ~pNode0[i].Truth & pNode1[j].Truth; pNode[c].iFan0g = k; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 1; - pNode[c].Truth = pNode0[i].Truth & ~pNode1[j].Truth; pNode[c].iFan0g = k; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 2; - pNode[c].Truth = ~pNode0[i].Truth & ~pNode1[j].Truth; pNode[c].iFan0g = k; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 3; - pNode[c].Truth = pNode0[i].Truth ^ pNode1[j].Truth; pNode[c].iFan0g = k; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 4; - } - assert( c < nSize ); - } - // go through current level - for ( i = 0; i < Count1; i++ ) - for ( j = i+1; j < Count1; j++ ) - { - pNode[c].Truth = pNode1[i].Truth & pNode1[j].Truth; pNode[c].iFan0g = n-1; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 0; - pNode[c].Truth = ~pNode1[i].Truth & pNode1[j].Truth; pNode[c].iFan0g = n-1; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 1; - pNode[c].Truth = pNode1[i].Truth & ~pNode1[j].Truth; pNode[c].iFan0g = n-1; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 2; - pNode[c].Truth = ~pNode1[i].Truth & ~pNode1[j].Truth; pNode[c].iFan0g = n-1; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 3; - pNode[c].Truth = pNode1[i].Truth ^ pNode1[j].Truth; pNode[c].iFan0g = n-1; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 4; - } - assert( c < nSize ); - // sort - Vec_IntClear( vWeight ); - for ( i = 0; i < c; i++ ) - { - pNode[i].Weight = Bdc_CountSpfd( pNode[i].Truth, Truth ); -if ( pNode[i].Weight > 300 ) -Bdc_SpfdPrint( pNode + i, 1, vLevels, Truth ); - Vec_IntPush( vWeight, pNode[i].Weight ); - - if ( Truth == pNode[i].Truth || Truth == ~pNode[i].Truth ) - { - printf( "Function can be implemented using %d gates.\n", n ); - Bdc_SpfdPrint( pNode + i, n, vLevels, Truth ); - goto cleanup; - } - } - pPerm = Abc_SortCost( Vec_IntArray(vWeight), c ); - assert( Vec_IntEntry(vWeight, pPerm[0]) <= Vec_IntEntry(vWeight, pPerm[c-1]) ); - - printf( "Best SPFD = %d.\n", Vec_IntEntry(vWeight, pPerm[c-1]) ); -// for ( i = 0; i < c; i++ ) -//printf( "%d ", Vec_IntEntry(vWeight, pPerm[i]) ); - - // choose the best ones - pNode2 = ABC_CALLOC( Bdc_Nod_t, nCands ); - for ( j = 0, i = c-1; i >= 0; i-- ) - { - pNode2[j++] = pNode[pPerm[i]]; - if ( j == nCands ) - break; - } - ABC_FREE( pPerm ); - Vec_PtrPush( vLevels, pNode2 ); - Vec_IntPush( vBegs, j ); - -printf( "Selected %6d gates (out of %6d) on level %2d. ", j, c, n ); -Abc_PrintTime( 1, "Time", clock() - clk ); - - for ( i = 0; i < 10; i++ ) - Bdc_SpfdPrint( pNode2 + i, n, vLevels, Truth ); - } - -cleanup: - ABC_FREE( pNode ); - Vec_PtrForEachEntry( Bdc_Nod_t *, vLevels, pNode, i ) - ABC_FREE( pNode ); - Vec_PtrFree( vLevels ); - Vec_IntFree( vBegs ); - Vec_IntFree( vWeight ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bdc_SpfdDecomposeTest_() -{ - int fTry = 0; -// word T[17]; -// int i; - -// word Truth = Truths[0] & ~Truths[3]; -// word Truth = (Truths[0] & Truths[1]) | (Truths[2] & Truths[3]) | (Truths[4] & Truths[5]); -// word Truth = (Truths[0] & Truths[1]) | ((Truths[2] & ~Truths[3]) ^ (Truths[4] & ~Truths[5])); -// word Truth = (Truths[0] & Truths[1]) | (Truths[2] & Truths[3]); -// word Truth = 0x9ef7a8d9c7193a0f; // AAFFAAFF0A0F0A0F -// word Truth = 0x34080226CD163000; - word Truth = 0x5052585a0002080a; - int nVars = 6; - int nCands = 200;// 75; - int nGatesMax = 20; - - if ( fTry ) - Bdc_SpfdDecompose( Truth, nVars, nCands, nGatesMax ); -/* - for ( i = 0; i < 6; i++ ) - T[i] = Truths[i]; - T[7] = 0; - T[8] = ~T[1] & T[3]; - T[9] = ~T[8] & T[0]; - T[10] = T[1] & T[4]; - T[11] = T[10] & T[2]; - T[12] = T[11] & T[9]; - T[13] = ~T[0] & T[5]; - T[14] = T[2] & T[13]; - T[15] = ~T[12] & ~T[14]; - T[16] = ~T[15]; -// if ( T[16] != Truth ) -// printf( "Failed\n" ); - - for ( i = 0; i < 17; i++ ) - { -// printf( "%2d = %3d ", i, Bdc_CountSpfd(T[i], Truth) ); - printf( "%2d = %3d ", i, Bdc_CountSpfd(T[i], T[16]) ); - Extra_PrintBinary( stdout, (unsigned *)&T[i], 64 ); printf( "\n" ); - } -// Extra_PrintBinary( stdout, (unsigned *)&Truth, 64 ); printf( "\n" ); -*/ -} - - - - -typedef struct Bdc_Ent_t_ Bdc_Ent_t; // 24 bytes -struct Bdc_Ent_t_ -{ - unsigned iFan0 : 29; - unsigned fCompl0 : 1; - unsigned fCompl : 1; - unsigned fMark0 : 1; - unsigned iFan1 : 29; - unsigned fCompl1 : 1; - unsigned fExor : 1; - unsigned fMark1 : 1; - int iNext; - int iList; - word Truth; -}; - -#define BDC_TERM 0x1FFFFFFF - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Bdc_SpfdMark0( Bdc_Ent_t * p, Bdc_Ent_t * pEnt ) -{ - if ( pEnt->iFan0 == BDC_TERM ) - return 0; - if ( pEnt->fMark0 ) - return 0; - pEnt->fMark0 = 1; - return pEnt->fMark1 + - Bdc_SpfdMark0(p, p + pEnt->iFan0) + - Bdc_SpfdMark0(p, p + pEnt->iFan1); -} -int Bdc_SpfdMark1( Bdc_Ent_t * p, Bdc_Ent_t * pEnt ) -{ - if ( pEnt->iFan0 == BDC_TERM ) - return 0; - if ( pEnt->fMark1 ) - return 0; - pEnt->fMark1 = 1; - return pEnt->fMark0 + - Bdc_SpfdMark1(p, p + pEnt->iFan0) + - Bdc_SpfdMark1(p, p + pEnt->iFan1); -} -void Bdc_SpfdUnmark0( Bdc_Ent_t * p, Bdc_Ent_t * pEnt ) -{ - if ( pEnt->iFan0 == BDC_TERM ) - return; - pEnt->fMark0 = 0; - Bdc_SpfdUnmark0( p, p + pEnt->iFan0 ); - Bdc_SpfdUnmark0( p, p + pEnt->iFan1 ); -} -void Bdc_SpfdUnmark1( Bdc_Ent_t * p, Bdc_Ent_t * pEnt ) -{ - if ( pEnt->iFan0 == BDC_TERM ) - return; - pEnt->fMark1 = 0; - Bdc_SpfdUnmark1( p, p + pEnt->iFan0 ); - Bdc_SpfdUnmark1( p, p + pEnt->iFan1 ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Bdc_SpfdCheckOverlap( Bdc_Ent_t * p, Bdc_Ent_t * pEnt0, Bdc_Ent_t * pEnt1 ) -{ - int RetValue; - RetValue = Bdc_SpfdMark0( p, pEnt0 ); - assert( RetValue == 0 ); - RetValue = Bdc_SpfdMark1( p, pEnt1 ); - Bdc_SpfdUnmark0( p, pEnt0 ); - Bdc_SpfdUnmark1( p, pEnt1 ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Bdc_SpfdHashValue( word t, int Size ) -{ - // http://planetmath.org/encyclopedia/GoodHashTablePrimes.html - // 53, - // 97, - // 193, - // 389, - // 769, - // 1543, - // 3079, - // 6151, - // 12289, - // 24593, - // 49157, - // 98317, - // 196613, - // 393241, - // 786433, - // 1572869, - // 3145739, - // 6291469, - // 12582917, - // 25165843, - // 50331653, - // 100663319, - // 201326611, - // 402653189, - // 805306457, - // 1610612741, - static unsigned BigPrimes[8] = {12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741}; - unsigned char * s = (unsigned char *)&t; - unsigned i, Value = 0; - for ( i = 0; i < 8; i++ ) - Value ^= BigPrimes[i] * s[i]; - return Value % Size; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int * Bdc_SpfdHashLookup( Bdc_Ent_t * p, int Size, word t ) -{ - Bdc_Ent_t * pBin = p + Bdc_SpfdHashValue( t, Size ); - if ( pBin->iList == 0 ) - return &pBin->iList; - for ( pBin = p + pBin->iList; ; pBin = p + pBin->iNext ) - { - if ( pBin->Truth == t ) - return NULL; - if ( pBin->iNext == 0 ) - return &pBin->iNext; - } - assert( 0 ); - return NULL; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Wrd_t * Bdc_SpfdDecomposeTest__( Vec_Int_t ** pvWeights ) -{ -// int nFuncs = 8000000; // the number of functions to compute -// int nSize = 2777111; // the hash table size to use -// int Limit = 6; - -// int nFuncs = 51000000; // the number of functions to compute -// int nSize = 50331653; // the hash table size to use -// int Limit = 6; - - int nFuncs = 250000000; // the number of functions to compute - int nSize = 201326611; // the hash table size to use - int Limit = 6; - - int * pPlace, i, n, m, k, s, fCompl, clk = clock(), clk2; - Vec_Int_t * vStops; - Vec_Wrd_t * vTruths; - Vec_Int_t * vWeights; - Bdc_Ent_t * p, * q, * pBeg0, * pEnd0, * pBeg1, * pEnd1, * pThis0, * pThis1; - word t0, t1, t; - assert( nSize <= nFuncs ); - - printf( "Allocating %.2f Mb of internal memory.\n", 1.0*sizeof(Bdc_Ent_t)*nFuncs/(1<<20) ); - - p = (Bdc_Ent_t *)calloc( nFuncs, sizeof(Bdc_Ent_t) ); - memset( p, 255, sizeof(Bdc_Ent_t) ); - p->iList = 0; - for ( q = p; q < p+nFuncs; q++ ) - q->iList = 0; - q = p + 1; - printf( "Added %d + %d + 0 = %d. Total = %8d.\n", 0, 0, 0, q-p ); - - vTruths = Vec_WrdStart( nFuncs ); - vWeights = Vec_IntStart( nFuncs ); - Vec_WrdClear( vTruths ); - Vec_IntClear( vWeights ); - - // create elementary vars - vStops = Vec_IntAlloc( 10 ); - Vec_IntPush( vStops, 1 ); - for ( i = 0; i < 6; i++ ) - { - q->iFan0 = BDC_TERM; - q->iFan1 = i; - q->Truth = Truths[i]; - pPlace = Bdc_SpfdHashLookup( p, nSize, q->Truth ); - *pPlace = q-p; - q++; - Vec_WrdPush( vTruths, Truths[i] ); - Vec_IntPush( vWeights, 0 ); - } - Vec_IntPush( vStops, 7 ); - printf( "Added %d + %d + 0 = %d. Total = %8d.\n", 0, 0, 0, q-p ); - - // create gates - for ( n = 0; n < Limit; n++ ) - { - // try previous - for ( k = 0; k < Limit; k++ ) - for ( m = 0; m < Limit; m++ ) - { - if ( k + m != n || k > m ) - continue; - // set the start and stop - pBeg0 = p + Vec_IntEntry( vStops, k ); - pEnd0 = p + Vec_IntEntry( vStops, k+1 ); - // set the start and stop - pBeg1 = p + Vec_IntEntry( vStops, m ); - pEnd1 = p + Vec_IntEntry( vStops, m+1 ); - - clk2 = clock(); - printf( "Trying %7d x %7d. ", pEnd0-pBeg0, pEnd1-pBeg1 ); - for ( pThis0 = pBeg0; pThis0 < pEnd0; pThis0++ ) - for ( pThis1 = pBeg1; pThis1 < pEnd1; pThis1++ ) - if ( k < m || pThis1 > pThis0 ) -// if ( n < 5 || Bdc_SpfdCheckOverlap(p, pThis0, pThis1) ) - for ( s = 0; s < 5; s++ ) - { - t0 = (s&1) ? ~pThis0->Truth : pThis0->Truth; - t1 = ((s>>1)&1) ? ~pThis1->Truth : pThis1->Truth; - t = ((s>>2)&1) ? t0 ^ t1 : t0 & t1; - fCompl = t & 1; - if ( fCompl ) - t = ~t; - if ( t == 0 ) - continue; - pPlace = Bdc_SpfdHashLookup( p, nSize, t ); - if ( pPlace == NULL ) - continue; - q->iFan0 = pThis0-p; - q->fCompl0 = s&1; - q->iFan1 = pThis1-p; - q->fCompl1 = (s>>1)&1; - q->fExor = (s>>2)&1; - q->Truth = t; - q->fCompl = fCompl; - *pPlace = q-p; - q++; - Vec_WrdPush( vTruths, t ); -// Vec_IntPush( vWeights, n == 5 ? n : n+1 ); - Vec_IntPush( vWeights, n+1 ); - if ( q-p == nFuncs ) - { - printf( "Reached limit of %d functions.\n", nFuncs ); - goto finish; - } - } - printf( "Added %d + %d + 1 = %d. Total = %8d. ", k, m, n+1, q-p ); - Abc_PrintTime( 1, "Time", clock() - clk2 ); - } - Vec_IntPush( vStops, q-p ); - } - Abc_PrintTime( 1, "Time", clock() - clk ); - - - { - FILE * pFile = fopen( "func6v6n_bin.txt", "wb" ); - fwrite( Vec_WrdArray(vTruths), sizeof(word), Vec_WrdSize(vTruths), pFile ); - fclose( pFile ); - } - { - FILE * pFile = fopen( "func6v6nW_bin.txt", "wb" ); - fwrite( Vec_IntArray(vWeights), sizeof(int), Vec_IntSize(vWeights), pFile ); - fclose( pFile ); - } - - -finish: - Vec_IntFree( vStops ); - free( p ); - - *pvWeights = vWeights; -// Vec_WrdFree( vTruths ); - return vTruths; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Wrd_t * Bdc_SpfdReadFiles5( Vec_Int_t ** pvWeights ) -{ - Vec_Int_t * vWeights; - Vec_Wrd_t * vDivs; - FILE * pFile; - - vDivs = Vec_WrdStart( 3863759 ); - pFile = fopen( "func6v5n_bin.txt", "rb" ); - fread( Vec_WrdArray(vDivs), sizeof(word), Vec_WrdSize(vDivs), pFile ); - fclose( pFile ); - - vWeights = Vec_IntStart( 3863759 ); - pFile = fopen( "func6v5nW_bin.txt", "rb" ); - fread( Vec_IntArray(vWeights), sizeof(int), Vec_IntSize(vWeights), pFile ); - fclose( pFile ); - - *pvWeights = vWeights; - return vDivs; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Wrd_t * Bdc_SpfdReadFiles6( Vec_Int_t ** pvWeights ) -{ - Vec_Int_t * vWeights; - Vec_Wrd_t * vDivs = Vec_WrdStart( 12776759 ); - FILE * pFile = fopen( "func6v6n_bin.txt", "rb" ); - fread( Vec_WrdArray(vDivs), sizeof(word), Vec_WrdSize(vDivs), pFile ); - fclose( pFile ); - - vWeights = Vec_IntStart( 12776759 ); - pFile = fopen( "func6v6nW_bin.txt", "rb" ); - fread( Vec_IntArray(vWeights), sizeof(int), Vec_IntSize(vWeights), pFile ); - fclose( pFile ); - - *pvWeights = vWeights; - return vDivs; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Bdc_SpfdComputeCost( word f, int i, Vec_Int_t * vWeights ) -{ - int Ones = Bdc_CountOnes(f); - if ( Ones == 0 ) - return -1; - return 7*Ones + 10*(8 - Vec_IntEntry(vWeights, i)); -// return Bdc_CountOnes(f); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -word Bdc_SpfdFindBest( Vec_Wrd_t * vDivs, Vec_Int_t * vWeights, word F0, word F1, int * pCost ) -{ - word Func, FuncBest; - int i, Cost, CostBest = -1, NumBest; - Vec_WrdForEachEntry( vDivs, Func, i ) - { - if ( (Func & F0) == 0 ) - { - Cost = Bdc_SpfdComputeCost(Func & F1, i, vWeights); - if ( CostBest < Cost ) - { - CostBest = Cost; - FuncBest = Func; - NumBest = i; - } - } - if ( (Func & F1) == 0 ) - { - Cost = Bdc_SpfdComputeCost(Func & F0, i, vWeights); - if ( CostBest < Cost ) - { - CostBest = Cost; - FuncBest = Func; - NumBest = i; - } - } - if ( (~Func & F0) == 0 ) - { - Cost = Bdc_SpfdComputeCost(~Func & F1, i, vWeights); - if ( CostBest < Cost ) - { - CostBest = Cost; - FuncBest = ~Func; - NumBest = i; - } - } - if ( (~Func & F1) == 0 ) - { - Cost = Bdc_SpfdComputeCost(~Func & F0, i, vWeights); - if ( CostBest < Cost ) - { - CostBest = Cost; - FuncBest = ~Func; - NumBest = i; - } - } - } - (*pCost) += Vec_IntEntry(vWeights, NumBest); - assert( CostBest > 0 ); - printf( "Selected %8d with cost %2d and weight %d: ", NumBest, 0, Vec_IntEntry(vWeights, NumBest) ); - Extra_PrintHex( stdout, (unsigned *)&FuncBest, 6 ); printf( "\n" ); - return FuncBest; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Bdc_SpfdDecomposeTestOne( word t, Vec_Wrd_t * vDivs, Vec_Int_t * vWeights ) -{ - word F1 = t; - word F0 = ~F1; - word Func; - int i, Cost = 0; - printf( "Trying: " ); - Extra_PrintHex( stdout, (unsigned *)&t, 6 ); printf( "\n" ); -// Abc_Show6VarFunc( F0, F1 ); - for ( i = 0; F0 && F1; i++ ) - { - printf( "*** ITER %2d ", i ); - Func = Bdc_SpfdFindBest( vDivs, vWeights, F0, F1, &Cost ); - F0 &= ~Func; - F1 &= ~Func; -// Abc_Show6VarFunc( F0, F1 ); - } - Cost += (i-1); - printf( "Produce solution with cost %2d (with adj cost %4d).\n", Cost, Bdc_SpfdAdjCost(t) ); - return Cost; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bdc_SpfdDecomposeTest44() -{ -// word t = 0x5052585a0002080a; - - word t = 0x9ef7a8d9c7193a0f; -// word t = 0x6BFDA276C7193A0F; -// word t = 0xA3756AFE0B1DF60B; - -// word t = 0xFEF7AEBFCE80AA0F; -// word t = 0x9EF7FDBFC77F6F0F; -// word t = 0xDEF7FDFF377F6FFF; - -// word t = 0x345D02736DB390A5; // xor with var 0 - -// word t = 0x3EFDA2736D139A0F; // best solution after changes - - Vec_Int_t * vWeights; - Vec_Wrd_t * vDivs; - word c0, c1, s, tt, tbest; - int i, j, Cost, CostBest = 100000; - int clk = clock(); - - return; - -// printf( "%d\n", RAND_MAX ); - - vDivs = Bdc_SpfdDecomposeTest__( &vWeights ); -// vDivs = Bdc_SpfdReadFiles5( &vWeights ); - -// Abc_Show6VarFunc( ~t, t ); - - // try function - tt = t; - Cost = Bdc_SpfdDecomposeTestOne( tt, vDivs, vWeights ); - if ( CostBest > Cost ) - { - CostBest = Cost; - tbest = tt; - } - printf( "\n" ); - - // try complemented output - for ( i = 0; i < 6; i++ ) - { - tt = t ^ Truths[i]; - Cost = Bdc_SpfdDecomposeTestOne( tt, vDivs, vWeights ); - if ( CostBest > Cost ) - { - CostBest = Cost; - tbest = tt; - } - } - printf( "\n" ); - - // try complemented input - for ( i = 0; i < 6; i++ ) - for ( j = 0; j < 6; j++ ) - { - if ( i == j ) - continue; - c0 = Bdc_Cof6( t, i, 0 ); - c1 = Bdc_Cof6( t, i, 1 ); - s = Truths[i] ^ Truths[j]; - tt = (~s & c0) | (s & c1); - - Cost = Bdc_SpfdDecomposeTestOne( tt, vDivs, vWeights ); - if ( CostBest > Cost ) - { - CostBest = Cost; - tbest = tt; - } - } - -/* - for ( i = 0; i < 6; i++ ) - for ( j = 0; j < 6; j++ ) - { - if ( i == j ) - continue; - c0 = Bdc_Cof6( t, i, 0 ); - c1 = Bdc_Cof6( t, i, 1 ); - s = Truths[i] ^ Truths[j]; - tt = (~s & c0) | (s & c1); - - for ( k = 0; k < 6; k++ ) - for ( n = 0; n < 6; n++ ) - { - if ( k == n ) - continue; - c0 = Bdc_Cof6( tt, k, 0 ); - c1 = Bdc_Cof6( tt, k, 1 ); - s = Truths[k] ^ Truths[n]; - ttt= (~s & c0) | (s & c1); - - Cost = Bdc_SpfdDecomposeTestOne( ttt, vDivs, vWeights ); - if ( CostBest > Cost ) - { - CostBest = Cost; - tbest = ttt; - } - } - } -*/ - - printf( "Best solution found with cost %d. ", CostBest ); - Extra_PrintHex( stdout, (unsigned *)&tbest, 6 ); //printf( "\n" ); - Abc_PrintTime( 1, " Time", clock() - clk ); - - Vec_WrdFree( vDivs ); - Vec_IntFree( vWeights ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bdc_SpfdDecomposeTest3() -{ - int nSizeM = (1 << 26); - int nSizeK = (1 << 3); - Vec_Wrd_t * v1M; - Vec_Wrd_t * v1K; - int i, k, Counter, clk; -// int EntryM, EntryK; - Aig_ManRandom64( 1 ); - - v1M = Vec_WrdAlloc( nSizeM ); - for ( i = 0; i < nSizeM; i++ ) - Vec_WrdPush( v1M, Aig_ManRandom64(0) ); - - v1K = Vec_WrdAlloc( nSizeK ); - for ( i = 0; i < nSizeK; i++ ) - Vec_WrdPush( v1K, Aig_ManRandom64(0) ); - - clk = clock(); - Counter = 0; - for ( i = 0; i < nSizeM; i++ ) - for ( k = 0; k < nSizeK; k++ ) - Counter += ((v1M->pArray[i] & v1K->pArray[k]) == v1K->pArray[k]); -// Vec_WrdForEachEntry( v1M, EntryM, i ) -// Vec_WrdForEachEntry( v1K, EntryK, k ) -// Counter += ((EntryM & EntryK) == EntryK); - - printf( "Total = %8d. ", Counter ); - Abc_PrintTime( 1, "Time", clock() - clk ); - - clk = clock(); - Counter = 0; - for ( k = 0; k < nSizeK; k++ ) - for ( i = 0; i < nSizeM; i++ ) - Counter += ((v1M->pArray[i] & v1K->pArray[k]) == v1K->pArray[k]); - printf( "Total = %8d. ", Counter ); - Abc_PrintTime( 1, "Time", clock() - clk ); - -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bdc_SpfdDecomposeTest8() -{ -// word t = 0x9ef7a8d9c7193a0f; -// word t = 0x9EF7FDBFC77F6F0F; - word t = 0x513B57150819050F; - - Vec_Int_t * vWeights; - Vec_Wrd_t * vDivs; - word Func, FuncBest; - int Cost, CostBest = ABC_INFINITY; - int i, clk = clock(); - -// return; - - vDivs = Bdc_SpfdReadFiles5( &vWeights ); - - printf( "Best init = %4d. ", Bdc_SpfdAdjCost(t) ); - Extra_PrintHex( stdout, (unsigned *)&t, 6 ); //printf( "\n" ); - Abc_PrintTime( 1, " Time", clock() - clk ); - - Vec_WrdForEachEntry( vDivs, Func, i ) - { - Cost = Bdc_SpfdAdjCost( t ^ Func ); - if ( CostBest > Cost ) - { - CostBest = Cost; - FuncBest = Func; - } - } - - printf( "Best cost = %4d. ", CostBest ); - Extra_PrintHex( stdout, (unsigned *)&FuncBest, 6 ); //printf( "\n" ); - Abc_PrintTime( 1, " Time", clock() - clk ); - -Abc_Show6VarFunc( 0, t ); -Abc_Show6VarFunc( 0, FuncBest ); -Abc_Show6VarFunc( 0, (FuncBest ^ t) ); - - FuncBest ^= t; - Extra_PrintHex( stdout, (unsigned *)&FuncBest, 6 ); printf( "\n" ); - -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bdc_SpfdDecomposeTest() -{ - int nSizeM = (1 << 26); // big array size - int nSizeK = (1 << 3); // small array size - Vec_Wrd_t * v1M, * v1K; - int EntryM, EntryK; - int i, k, Counter, clk; - - Aig_ManRandom64( 1 ); - - v1M = Vec_WrdAlloc( nSizeM ); - for ( i = 0; i < nSizeM; i++ ) - Vec_WrdPush( v1M, Aig_ManRandom64(0) ); - - v1K = Vec_WrdAlloc( nSizeK ); - for ( i = 0; i < nSizeK; i++ ) - Vec_WrdPush( v1K, Aig_ManRandom64(0) ); - - clk = clock(); - Counter = 0; -// for ( i = 0; i < nSizeM; i++ ) -// for ( k = 0; k < nSizeK; k++ ) -// Counter += ((v1M->pArray[i] & v1K->pArray[k]) == v1K->pArray[k]); - Vec_WrdForEachEntry( v1M, EntryM, i ) - Vec_WrdForEachEntry( v1K, EntryK, k ) - Counter += ((EntryM & EntryK) == EntryK); - printf( "Total = %8d. ", Counter ); - Abc_PrintTime( 1, "Time", clock() - clk ); - - clk = clock(); - Counter = 0; -// for ( k = 0; k < nSizeK; k++ ) -// for ( i = 0; i < nSizeM; i++ ) -// Counter += ((v1M->pArray[i] & v1K->pArray[k]) == v1K->pArray[k]); - Vec_WrdForEachEntry( v1K, EntryK, k ) - Vec_WrdForEachEntry( v1M, EntryM, i ) - Counter += ((EntryM & EntryK) == EntryK); - printf( "Total = %8d. ", Counter ); - Abc_PrintTime( 1, "Time", clock() - clk ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/bdc/bdcTable.c b/src/aig/bdc/bdcTable.c deleted file mode 100644 index 69f35d88..00000000 --- a/src/aig/bdc/bdcTable.c +++ /dev/null @@ -1,134 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**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( puTruth, pIsf->puOff, 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 ) -{ - int fDisableCache = 0; - Bdc_Fun_t * pFunc; - if ( fDisableCache && Kit_WordCountOnes(pIsf->uSupp) > 1 ) - return NULL; - if ( pIsf->uSupp == 0 ) - { - assert( p->pTable[pIsf->uSupp] == p->pNodes ); - if ( Kit_TruthIsConst1( pIsf->puOn, p->nVars ) ) - return p->pNodes; - assert( Kit_TruthIsConst1( pIsf->puOff, p->nVars ) ); - return Bdc_Not(p->pNodes); - } - for ( pFunc = p->pTable[pIsf->uSupp]; pFunc; pFunc = pFunc->pNext ) - if ( Bdc_TableCheckContainment( p, pIsf, pFunc->puFunc ) ) - return pFunc; - Bdc_IsfNot( pIsf ); - for ( pFunc = p->pTable[pIsf->uSupp]; pFunc; pFunc = pFunc->pNext ) - if ( Bdc_TableCheckContainment( p, pIsf, pFunc->puFunc ) ) - { - Bdc_IsfNot( pIsf ); - return Bdc_Not(pFunc); - } - Bdc_IsfNot( pIsf ); - 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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/bdc/bdc_.c b/src/aig/bdc/bdc_.c deleted file mode 100644 index b29d4f5e..00000000 --- a/src/aig/bdc/bdc_.c +++ /dev/null @@ -1,54 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/bdc/module.make b/src/aig/bdc/module.make deleted file mode 100644 index 97f5b33b..00000000 --- a/src/aig/bdc/module.make +++ /dev/null @@ -1,5 +0,0 @@ -SRC += src/aig/bdc/bdcCore.c \ - src/aig/bdc/bdcDec.c \ - src/aig/bdc/bdcSpfd.c \ - src/aig/bdc/bdcTable.c - diff --git a/src/aig/cec/cec.c b/src/aig/cec/cec.c deleted file mode 100644 index 6968a599..00000000 --- a/src/aig/cec/cec.c +++ /dev/null @@ -1,53 +0,0 @@ -/**CFile**************************************************************** - - FileName [cec.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Combinational equivalence checking.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cecInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cec/cec.h b/src/aig/cec/cec.h deleted file mode 100644 index 9e2237d7..00000000 --- a/src/aig/cec/cec.h +++ /dev/null @@ -1,233 +0,0 @@ -/**CFile**************************************************************** - - FileName [cec.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Combinational equivalence checking.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __CEC_H__ -#define __CEC_H__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -// dynamic SAT parameters -typedef struct Cec_ParSat_t_ Cec_ParSat_t; -struct Cec_ParSat_t_ -{ - int nBTLimit; // conflict limit at a node - int nSatVarMax; // the max number of SAT variables - int nCallsRecycle; // calls to perform before recycling SAT solver - int fNonChrono; // use non-chronological backtracling (for circuit SAT only) - int fPolarFlip; // flops polarity of variables - int fCheckMiter; // the circuit is the miter -// int fFirstStop; // stop on the first sat output - int fLearnCls; // perform clause learning - int fVerbose; // verbose stats -}; - -// simulation parameters -typedef struct Cec_ParSim_t_ Cec_ParSim_t; -struct Cec_ParSim_t_ -{ - int nWords; // the number of simulation words - int nFrames; // the number of simulation frames - int nRounds; // the number of simulation rounds - int nNonRefines; // the max number of rounds without refinement - int TimeLimit; // the runtime limit in seconds - int fDualOut; // miter with separate outputs - int fCheckMiter; // the circuit is the miter -// int fFirstStop; // stop on the first sat output - int fSeqSimulate; // performs sequential simulation - int fLatchCorr; // consider only latch outputs - int fConstCorr; // consider only constants - int fVeryVerbose; // verbose stats - int fVerbose; // verbose stats -}; - -// semiformal parameters -typedef struct Cec_ParSmf_t_ Cec_ParSmf_t; -struct Cec_ParSmf_t_ -{ - int nWords; // the number of simulation words - int nRounds; // the number of simulation rounds - int nFrames; // the max number of time frames - int nNonRefines; // the max number of rounds without refinement - int nMinOutputs; // the min outputs to accumulate - int nBTLimit; // conflict limit at a node - int TimeLimit; // the runtime limit in seconds - int fDualOut; // miter with separate outputs - int fCheckMiter; // the circuit is the miter -// int fFirstStop; // stop on the first sat output - int fVerbose; // verbose stats -}; - -// combinational SAT sweeping parameters -typedef struct Cec_ParFra_t_ Cec_ParFra_t; -struct Cec_ParFra_t_ -{ - int nWords; // the number of simulation words - int nRounds; // the number of simulation rounds - int nItersMax; // the maximum number of iterations of SAT sweeping - int nBTLimit; // conflict limit at a node - int TimeLimit; // the runtime limit in seconds - int nLevelMax; // restriction on the level nodes to be swept - int nDepthMax; // the depth in terms of steps of speculative reduction - int fRewriting; // enables AIG rewriting - int fCheckMiter; // the circuit is the miter -// int fFirstStop; // stop on the first sat output - int fDualOut; // miter with separate outputs - int fColorDiff; // miter with separate outputs - int fSatSweeping; // enable SAT sweeping - int fVeryVerbose; // verbose stats - int fVerbose; // verbose stats - int iOutFail; // the failed output -}; - -// combinational equivalence checking parameters -typedef struct Cec_ParCec_t_ Cec_ParCec_t; -struct Cec_ParCec_t_ -{ - int nBTLimit; // conflict limit at a node - int TimeLimit; // the runtime limit in seconds -// int fFirstStop; // stop on the first sat output - int fUseSmartCnf; // use smart CNF computation - int fRewriting; // enables AIG rewriting - int fVeryVerbose; // verbose stats - int fVerbose; // verbose stats - int iOutFail; // the number of failed output -}; - -// sequential register correspodence parameters -typedef struct Cec_ParCor_t_ Cec_ParCor_t; -struct Cec_ParCor_t_ -{ - int nWords; // the number of simulation words - int nRounds; // the number of simulation rounds - int nFrames; // the number of time frames - int nPrefix; // the number of time frames in the prefix - int nBTLimit; // conflict limit at a node - int nLevelMax; // (scorr only) the max number of levels - int nStepsMax; // (scorr only) the max number of induction steps - int fLatchCorr; // consider only latch outputs - int fConstCorr; // consider only constants - int fUseRings; // use rings - int fMakeChoices; // use equilvaences as choices - int fUseCSat; // use circuit-based solver -// int fFirstStop; // stop on the first sat output - int fUseSmartCnf; // use smart CNF computation - int fVerboseFlops; // verbose stats - int fVeryVerbose; // verbose stats - int fVerbose; // verbose stats - // callback - void * pData; - void * pFunc; -}; - -// sequential register correspodence parameters -typedef struct Cec_ParChc_t_ Cec_ParChc_t; -struct Cec_ParChc_t_ -{ - int nWords; // the number of simulation words - int nRounds; // the number of simulation rounds - int nBTLimit; // conflict limit at a node - int fUseRings; // use rings - int fUseCSat; // use circuit-based solver - int fVeryVerbose; // verbose stats - int fVerbose; // verbose stats -}; - -// sequential synthesis parameters -typedef struct Cec_ParSeq_t_ Cec_ParSeq_t; -struct Cec_ParSeq_t_ -{ - int fUseLcorr; // enables latch correspondence - int fUseScorr; // enables signal correspondence - int nBTLimit; // (scorr/lcorr) conflict limit at a node - int nFrames; // (scorr/lcorr) the number of timeframes - int nLevelMax; // (scorr only) the max number of levels - int fConsts; // (scl only) merging constants - int fEquivs; // (scl only) merging equivalences - int fUseMiniSat; // enables MiniSat in lcorr/scorr - int nMinDomSize; // the size of minimum clock domain - int fVeryVerbose; // verbose stats - int fVerbose; // verbose stats -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== cecCec.c ==========================================================*/ -extern int Cec_ManVerify( Gia_Man_t * p, Cec_ParCec_t * pPars ); -extern int Cec_ManVerifyTwo( Gia_Man_t * p0, Gia_Man_t * p1, int fVerbose ); -/*=== cecChoice.c ==========================================================*/ -extern Gia_Man_t * Cec_ManChoiceComputation( Gia_Man_t * pAig, Cec_ParChc_t * pPars ); -/*=== cecCorr.c ==========================================================*/ -extern int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars ); -extern Gia_Man_t * Cec_ManLSCorrespondence( Gia_Man_t * pAig, Cec_ParCor_t * pPars ); -/*=== cecCore.c ==========================================================*/ -extern void Cec_ManSatSetDefaultParams( Cec_ParSat_t * p ); -extern void Cec_ManSimSetDefaultParams( Cec_ParSim_t * p ); -extern void Cec_ManSmfSetDefaultParams( Cec_ParSmf_t * p ); -extern void Cec_ManFraSetDefaultParams( Cec_ParFra_t * p ); -extern void Cec_ManCecSetDefaultParams( Cec_ParCec_t * p ); -extern void Cec_ManCorSetDefaultParams( Cec_ParCor_t * p ); -extern void Cec_ManChcSetDefaultParams( Cec_ParChc_t * p ); -extern Gia_Man_t * Cec_ManSatSweeping( Gia_Man_t * pAig, Cec_ParFra_t * pPars ); -extern Gia_Man_t * Cec_ManSatSolving( Gia_Man_t * pAig, Cec_ParSat_t * pPars ); -extern void Cec_ManSimulation( Gia_Man_t * pAig, Cec_ParSim_t * pPars ); -/*=== cecSeq.c ==========================================================*/ -extern int Cec_ManSeqResimulateCounter( Gia_Man_t * pAig, Cec_ParSim_t * pPars, Abc_Cex_t * pCex ); -extern int Cec_ManSeqSemiformal( Gia_Man_t * pAig, Cec_ParSmf_t * pPars ); -extern int Cec_ManCheckNonTrivialCands( Gia_Man_t * pAig ); -/*=== cecSynth.c ==========================================================*/ -extern int Cec_SeqReadMinDomSize( Cec_ParSeq_t * p ); -extern int Cec_SeqReadVerbose( Cec_ParSeq_t * p ); -extern void Cec_SeqSynthesisSetDefaultParams( Cec_ParSeq_t * pPars ); -extern int Cec_SequentialSynthesisPart( Gia_Man_t * p, Cec_ParSeq_t * pPars ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/cec/cecCec.c b/src/aig/cec/cecCec.c deleted file mode 100644 index 9fd8a03f..00000000 --- a/src/aig/cec/cecCec.c +++ /dev/null @@ -1,373 +0,0 @@ -/**CFile**************************************************************** - - FileName [cecCec.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Combinational equivalence checking.] - - Synopsis [Integrated combinatinal equivalence checker.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cecCec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cecInt.h" -#include "fra.h" -#include "giaAig.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Saves the input pattern with the given number.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManTransformPattern( Gia_Man_t * p, int iOut, int * pValues ) -{ - int i; - assert( p->pCexComb == NULL ); - p->pCexComb = (Abc_Cex_t *)ABC_CALLOC( char, - sizeof(Abc_Cex_t) + sizeof(unsigned) * Gia_BitWordNum(Gia_ManCiNum(p)) ); - p->pCexComb->iPo = iOut; - p->pCexComb->nPis = Gia_ManCiNum(p); - p->pCexComb->nBits = Gia_ManCiNum(p); - for ( i = 0; i < Gia_ManCiNum(p); i++ ) - if ( pValues[i] ) - Aig_InfoSetBit( p->pCexComb->pData, i ); -} - -/**Function************************************************************* - - Synopsis [Interface to the old CEC engine] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManVerifyOld( Gia_Man_t * pMiter, int fVerbose, int * piOutFail ) -{ -// extern int Fra_FraigCec( Aig_Man_t ** ppAig, int nConfLimit, int fVerbose ); - extern int Ssw_SecCexResimulate( Aig_Man_t * p, int * pModel, int * pnOutputs ); - Gia_Man_t * pTemp = Gia_ManTransformMiter( pMiter ); - Aig_Man_t * pMiterCec = Gia_ManToAig( pTemp, 0 ); - int RetValue, iOut, nOuts, clkTotal = clock(); - if ( piOutFail ) - *piOutFail = -1; - Gia_ManStop( pTemp ); - // run CEC on this miter - RetValue = Fra_FraigCec( &pMiterCec, 10000000, fVerbose ); - // report the miter - if ( RetValue == 1 ) - { - Abc_Print( 1, "Networks are equivalent. " ); -Abc_PrintTime( 1, "Time", clock() - clkTotal ); - } - else if ( RetValue == 0 ) - { - Abc_Print( 1, "Networks are NOT EQUIVALENT. " ); -Abc_PrintTime( 1, "Time", clock() - clkTotal ); - if ( pMiterCec->pData == NULL ) - Abc_Print( 1, "Counter-example is not available.\n" ); - else - { - iOut = Ssw_SecCexResimulate( pMiterCec, (int *)pMiterCec->pData, &nOuts ); - if ( iOut == -1 ) - Abc_Print( 1, "Counter-example verification has failed.\n" ); - else - { -// Aig_Obj_t * pObj = Aig_ManPo(pMiterCec, iOut); -// Aig_Obj_t * pFan = Aig_ObjFanin0(pObj); - Abc_Print( 1, "Primary output %d has failed", iOut ); - if ( nOuts-1 >= 0 ) - Abc_Print( 1, ", along with other %d incorrect outputs", nOuts-1 ); - Abc_Print( 1, ".\n" ); - if ( piOutFail ) - *piOutFail = iOut; - } - Cec_ManTransformPattern( pMiter, iOut, (int *)pMiterCec->pData ); - } - } - else - { - Abc_Print( 1, "Networks are UNDECIDED. " ); -Abc_PrintTime( 1, "Time", clock() - clkTotal ); - } - fflush( stdout ); - Aig_ManStop( pMiterCec ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [New CEC engine.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManVerify( Gia_Man_t * pInit, Cec_ParCec_t * pPars ) -{ - int fDumpUndecided = 0; - Cec_ParFra_t ParsFra, * pParsFra = &ParsFra; - Gia_Man_t * p, * pNew; - int RetValue, clk = clock(); - double clkTotal = clock(); - // preprocess - p = Gia_ManDup( pInit ); - Gia_ManEquivFixOutputPairs( p ); - p = Gia_ManCleanup( pNew = p ); - Gia_ManStop( pNew ); - // sweep for equivalences - Cec_ManFraSetDefaultParams( pParsFra ); - pParsFra->nItersMax = 1000; - pParsFra->nBTLimit = pPars->nBTLimit; - pParsFra->TimeLimit = pPars->TimeLimit; - pParsFra->fVerbose = pPars->fVerbose; - pParsFra->fCheckMiter = 1; - pParsFra->fDualOut = 1; - pNew = Cec_ManSatSweeping( p, pParsFra ); - pPars->iOutFail = pParsFra->iOutFail; - // update - pInit->pCexComb = p->pCexComb; p->pCexComb = NULL; - Gia_ManStop( p ); - p = pInit; - // continue - if ( pNew == NULL ) - { - if ( p->pCexComb != NULL ) - { - if ( p->pCexComb && !Gia_ManVerifyCex( p, p->pCexComb, 1 ) ) - Abc_Print( 1, "Counter-example simulation has failed.\n" ); - Abc_Print( 1, "Networks are NOT EQUIVALENT. " ); - Abc_PrintTime( 1, "Time", clock() - clk ); - return 0; - } - p = Gia_ManDup( pInit ); - Gia_ManEquivFixOutputPairs( p ); - p = Gia_ManCleanup( pNew = p ); - Gia_ManStop( pNew ); - pNew = p; - } - if ( Gia_ManAndNum(pNew) == 0 ) - { - Gia_Obj_t * pObj1, * pObj2; - int i; - Gia_ManForEachPo( pNew, pObj1, i ) - { - pObj2 = Gia_ManPo( pNew, ++i ); - if ( Gia_ObjChild0(pObj1) != Gia_ObjChild0(pObj2) ) - { - Abc_Print( 1, "Networks are NOT EQUIVALENT. Outputs %d trivially differ. ", i/2 ); - Abc_PrintTime( 1, "Time", clock() - clk ); - Gia_ManStop( pNew ); - pPars->iOutFail = i/2; - return 0; - } - } - Abc_Print( 1, "Networks are equivalent. " ); - Abc_PrintTime( 1, "Time", clock() - clk ); - Gia_ManStop( pNew ); - return 1; - } - if ( pPars->fVerbose ) - { - Abc_Print( 1, "Networks are UNDECIDED after the new CEC engine. " ); - Abc_PrintTime( 1, "Time", clock() - clk ); - } - if ( fDumpUndecided ) - { - ABC_FREE( pNew->pReprs ); - ABC_FREE( pNew->pNexts ); - Gia_WriteAiger( pNew, "gia_cec_undecided.aig", 0, 0 ); - Abc_Print( 1, "The result is written into file \"%s\".\n", "gia_cec_undecided.aig" ); - } - if ( pPars->TimeLimit && ((double)clock() - clkTotal)/CLOCKS_PER_SEC >= pPars->TimeLimit ) - { - Gia_ManStop( pNew ); - return -1; - } - // call other solver - if ( pPars->fVerbose ) - Abc_Print( 1, "Calling the old CEC engine.\n" ); - fflush( stdout ); - RetValue = Cec_ManVerifyOld( pNew, pPars->fVerbose, &pPars->iOutFail ); - p->pCexComb = pNew->pCexComb; pNew->pCexComb = NULL; - if ( p->pCexComb && !Gia_ManVerifyCex( p, p->pCexComb, 1 ) ) - Abc_Print( 1, "Counter-example simulation has failed.\n" ); - Gia_ManStop( pNew ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [New CEC engine applied to two circuits.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManVerifyTwo( Gia_Man_t * p0, Gia_Man_t * p1, int fVerbose ) -{ - Cec_ParCec_t ParsCec, * pPars = &ParsCec; - Gia_Man_t * pMiter; - int RetValue; - Cec_ManCecSetDefaultParams( pPars ); - pPars->fVerbose = fVerbose; - pMiter = Gia_ManMiter( p0, p1, 1, 0, pPars->fVerbose ); - if ( pMiter == NULL ) - return -1; - RetValue = Cec_ManVerify( pMiter, pPars ); - p0->pCexComb = pMiter->pCexComb; pMiter->pCexComb = NULL; - Gia_ManStop( pMiter ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [New CEC engine applied to two circuits.] - - Description [Returns 1 if equivalent, 0 if counter-example, -1 if undecided. - Counter-example is returned in the first manager as pAig0->pSeqModel. - The format is given in Abc_Cex_t (file "abc\src\aig\gia\gia.h").] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManVerifyTwoAigs( Aig_Man_t * pAig0, Aig_Man_t * pAig1, int fVerbose ) -{ - Gia_Man_t * p0, * p1, * pTemp; - int RetValue; - - p0 = Gia_ManFromAig( pAig0 ); - p0 = Gia_ManCleanup( pTemp = p0 ); - Gia_ManStop( pTemp ); - - p1 = Gia_ManFromAig( pAig1 ); - p1 = Gia_ManCleanup( pTemp = p1 ); - Gia_ManStop( pTemp ); - - RetValue = Cec_ManVerifyTwo( p0, p1, fVerbose ); - pAig0->pSeqModel = p0->pCexComb; p0->pCexComb = NULL; - Gia_ManStop( p0 ); - Gia_ManStop( p1 ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Implementation of new signal correspodence.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Cec_LatchCorrespondence( Aig_Man_t * pAig, int nConfs, int fUseCSat ) -{ - Gia_Man_t * pGia; - Cec_ParCor_t CorPars, * pCorPars = &CorPars; - Cec_ManCorSetDefaultParams( pCorPars ); - pCorPars->fLatchCorr = 1; - pCorPars->fUseCSat = fUseCSat; - pCorPars->nBTLimit = nConfs; - pGia = Gia_ManFromAigSimple( pAig ); - Cec_ManLSCorrespondenceClasses( pGia, pCorPars ); - Gia_ManReprToAigRepr( pAig, pGia ); - Gia_ManStop( pGia ); - return Aig_ManDupSimple( pAig ); -} - -/**Function************************************************************* - - Synopsis [Implementation of new signal correspodence.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Cec_SignalCorrespondence( Aig_Man_t * pAig, int nConfs, int fUseCSat ) -{ - Gia_Man_t * pGia; - Cec_ParCor_t CorPars, * pCorPars = &CorPars; - Cec_ManCorSetDefaultParams( pCorPars ); - pCorPars->fUseCSat = fUseCSat; - pCorPars->nBTLimit = nConfs; - pGia = Gia_ManFromAigSimple( pAig ); - Cec_ManLSCorrespondenceClasses( pGia, pCorPars ); - Gia_ManReprToAigRepr( pAig, pGia ); - Gia_ManStop( pGia ); - return Aig_ManDupSimple( pAig ); -} - -/**Function************************************************************* - - Synopsis [Implementation of fraiging.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Cec_FraigCombinational( Aig_Man_t * pAig, int nConfs, int fVerbose ) -{ - Gia_Man_t * pGia; - Cec_ParFra_t FraPars, * pFraPars = &FraPars; - Cec_ManFraSetDefaultParams( pFraPars ); - pFraPars->fSatSweeping = 1; - pFraPars->nBTLimit = nConfs; - pFraPars->nItersMax = 20; - pFraPars->fVerbose = fVerbose; - pGia = Gia_ManFromAigSimple( pAig ); - Cec_ManSatSweeping( pGia, pFraPars ); - Gia_ManReprToAigRepr( pAig, pGia ); - Gia_ManStop( pGia ); - return Aig_ManDupSimple( pAig ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cec/cecChoice.c b/src/aig/cec/cecChoice.c deleted file mode 100644 index 076b34a2..00000000 --- a/src/aig/cec/cecChoice.c +++ /dev/null @@ -1,409 +0,0 @@ -/**CFile**************************************************************** - - FileName [cecChoice.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Combinational equivalence checking.] - - Synopsis [Computation of structural choices.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cecChoice.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cecInt.h" -#include "giaAig.h" -#include "dch.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Cec_ManCombSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ); - -extern int Cec_ManResimulateCounterExamplesComb( Cec_ManSim_t * pSim, Vec_Int_t * vCexStore ); -extern int Gia_ManCheckRefinements( Gia_Man_t * p, Vec_Str_t * vStatus, Vec_Int_t * vOutputs, Cec_ManSim_t * pSim, int fRings ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes the real value of the literal w/o spec reduction.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Cec_ManCombSpecReal( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) -{ - assert( Gia_ObjIsAnd(pObj) ); - Cec_ManCombSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj) ); - Cec_ManCombSpecReduce_rec( pNew, p, Gia_ObjFanin1(pObj) ); - return Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Recursively performs speculative reduction for the object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManCombSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) -{ - Gia_Obj_t * pRepr; - if ( ~pObj->Value ) - return; - if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) - { - Cec_ManCombSpecReduce_rec( pNew, p, pRepr ); - pObj->Value = Gia_LitNotCond( pRepr->Value, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); - return; - } - pObj->Value = Cec_ManCombSpecReal( pNew, p, pObj ); -} - -/**Function************************************************************* - - Synopsis [Derives SRM for signal correspondence.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Gia_Man_t * Cec_ManCombSpecReduce( Gia_Man_t * p, Vec_Int_t ** pvOutputs, int fRings ) -{ - Gia_Man_t * pNew, * pTemp; - Gia_Obj_t * pObj, * pRepr; - Vec_Int_t * vXorLits; - int i, iPrev, iObj, iPrevNew, iObjNew; - assert( p->pReprs != NULL ); - Gia_ManSetPhase( p ); - Gia_ManFillValue( p ); - pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); - Gia_ManHashAlloc( pNew ); - Gia_ManConst0(p)->Value = 0; - Gia_ManForEachCi( p, pObj, i ) - pObj->Value = Gia_ManAppendCi(pNew); - *pvOutputs = Vec_IntAlloc( 1000 ); - vXorLits = Vec_IntAlloc( 1000 ); - if ( fRings ) - { - Gia_ManForEachObj1( p, pObj, i ) - { - if ( Gia_ObjIsConst( p, i ) ) - { - iObjNew = Cec_ManCombSpecReal( pNew, p, pObj ); - iObjNew = Gia_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ); - if ( iObjNew != 0 ) - { - Vec_IntPush( *pvOutputs, 0 ); - Vec_IntPush( *pvOutputs, i ); - Vec_IntPush( vXorLits, iObjNew ); - } - } - else if ( Gia_ObjIsHead( p, i ) ) - { - iPrev = i; - Gia_ClassForEachObj1( p, i, iObj ) - { - iPrevNew = Cec_ManCombSpecReal( pNew, p, Gia_ManObj(p, iPrev) ); - iObjNew = Cec_ManCombSpecReal( pNew, p, Gia_ManObj(p, iObj) ); - iPrevNew = Gia_LitNotCond( iPrevNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) ); - iObjNew = Gia_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) ); - if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 ) - { - Vec_IntPush( *pvOutputs, iPrev ); - Vec_IntPush( *pvOutputs, iObj ); - Vec_IntPush( vXorLits, Gia_ManHashAnd(pNew, iPrevNew, Gia_LitNot(iObjNew)) ); - } - iPrev = iObj; - } - iObj = i; - iPrevNew = Cec_ManCombSpecReal( pNew, p, Gia_ManObj(p, iPrev) ); - iObjNew = Cec_ManCombSpecReal( pNew, p, Gia_ManObj(p, iObj) ); - iPrevNew = Gia_LitNotCond( iPrevNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) ); - iObjNew = Gia_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) ); - if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 ) - { - Vec_IntPush( *pvOutputs, iPrev ); - Vec_IntPush( *pvOutputs, iObj ); - Vec_IntPush( vXorLits, Gia_ManHashAnd(pNew, iPrevNew, Gia_LitNot(iObjNew)) ); - } - } - } - } - else - { - Gia_ManForEachObj1( p, pObj, i ) - { - pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); - if ( pRepr == NULL ) - continue; - iPrevNew = Gia_ObjIsConst(p, i)? 0 : Cec_ManCombSpecReal( pNew, p, pRepr ); - iObjNew = Cec_ManCombSpecReal( pNew, p, pObj ); - iObjNew = Gia_LitNotCond( iObjNew, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); - if ( iPrevNew != iObjNew ) - { - Vec_IntPush( *pvOutputs, Gia_ObjId(p, pRepr) ); - Vec_IntPush( *pvOutputs, Gia_ObjId(p, pObj) ); - Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, iPrevNew, iObjNew) ); - } - } - } - Vec_IntForEachEntry( vXorLits, iObjNew, i ) - Gia_ManAppendCo( pNew, iObjNew ); - Vec_IntFree( vXorLits ); - Gia_ManHashStop( pNew ); -//Abc_Print( 1, "Before sweeping = %d\n", Gia_ManAndNum(pNew) ); - pNew = Gia_ManCleanup( pTemp = pNew ); -//Abc_Print( 1, "After sweeping = %d\n", Gia_ManAndNum(pNew) ); - Gia_ManStop( pTemp ); - return pNew; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManChoiceComputation_int( Gia_Man_t * pAig, Cec_ParChc_t * pPars ) -{ - int nItersMax = 1000; - Vec_Str_t * vStatus; - Vec_Int_t * vOutputs; - Vec_Int_t * vCexStore; - Cec_ParSim_t ParsSim, * pParsSim = &ParsSim; - Cec_ParSat_t ParsSat, * pParsSat = &ParsSat; - Cec_ManSim_t * pSim; - Gia_Man_t * pSrm; - int r, RetValue; - int clkSat = 0, clkSim = 0, clkSrm = 0, clkTotal = clock(); - int clk2, clk = clock(); - ABC_FREE( pAig->pReprs ); - ABC_FREE( pAig->pNexts ); - Gia_ManRandom( 1 ); - // prepare simulation manager - Cec_ManSimSetDefaultParams( pParsSim ); - pParsSim->nWords = pPars->nWords; - pParsSim->nFrames = pPars->nRounds; - pParsSim->fVerbose = pPars->fVerbose; - pParsSim->fLatchCorr = 0; - pParsSim->fSeqSimulate = 0; - // create equivalence classes of registers - pSim = Cec_ManSimStart( pAig, pParsSim ); - Cec_ManSimClassesPrepare( pSim, -1 ); - Cec_ManSimClassesRefine( pSim ); - // prepare SAT solving - Cec_ManSatSetDefaultParams( pParsSat ); - pParsSat->nBTLimit = pPars->nBTLimit; - pParsSat->fVerbose = pPars->fVerbose; - if ( pPars->fVerbose ) - { - Abc_Print( 1, "Obj = %7d. And = %7d. Conf = %5d. Ring = %d. CSat = %d.\n", - Gia_ManObjNum(pAig), Gia_ManAndNum(pAig), pPars->nBTLimit, pPars->fUseRings, pPars->fUseCSat ); - Cec_ManRefinedClassPrintStats( pAig, NULL, 0, clock() - clk ); - } - // perform refinement of equivalence classes - for ( r = 0; r < nItersMax; r++ ) - { - clk = clock(); - // perform speculative reduction - clk2 = clock(); - pSrm = Cec_ManCombSpecReduce( pAig, &vOutputs, pPars->fUseRings ); - assert( Gia_ManRegNum(pSrm) == 0 && Gia_ManCiNum(pSrm) == Gia_ManCiNum(pAig) ); - clkSrm += clock() - clk2; - if ( Gia_ManCoNum(pSrm) == 0 ) - { - if ( pPars->fVerbose ) - Cec_ManRefinedClassPrintStats( pAig, NULL, r+1, clock() - clk ); - Vec_IntFree( vOutputs ); - Gia_ManStop( pSrm ); - break; - } -//Gia_DumpAiger( pSrm, "choicesrm", r, 2 ); - // found counter-examples to speculation - clk2 = clock(); - if ( pPars->fUseCSat ) - vCexStore = Cbs_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0 ); - else - vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus ); - Gia_ManStop( pSrm ); - clkSat += clock() - clk2; - if ( Vec_IntSize(vCexStore) == 0 ) - { - if ( pPars->fVerbose ) - Cec_ManRefinedClassPrintStats( pAig, vStatus, r+1, clock() - clk ); - Vec_IntFree( vCexStore ); - Vec_StrFree( vStatus ); - Vec_IntFree( vOutputs ); - break; - } - // refine classes with these counter-examples - clk2 = clock(); - RetValue = Cec_ManResimulateCounterExamplesComb( pSim, vCexStore ); - Vec_IntFree( vCexStore ); - clkSim += clock() - clk2; - Gia_ManCheckRefinements( pAig, vStatus, vOutputs, pSim, pPars->fUseRings ); - if ( pPars->fVerbose ) - Cec_ManRefinedClassPrintStats( pAig, vStatus, r+1, clock() - clk ); - Vec_StrFree( vStatus ); - Vec_IntFree( vOutputs ); -//Gia_ManEquivPrintClasses( pAig, 1, 0 ); - } - // check the overflow - if ( r == nItersMax ) - Abc_Print( 1, "The refinement was not finished. The result may be incorrect.\n" ); - Cec_ManSimStop( pSim ); - clkTotal = clock() - clkTotal; - // report the results - if ( pPars->fVerbose ) - { - Abc_PrintTimeP( 1, "Srm ", clkSrm, clkTotal ); - Abc_PrintTimeP( 1, "Sat ", clkSat, clkTotal ); - Abc_PrintTimeP( 1, "Sim ", clkSim, clkTotal ); - Abc_PrintTimeP( 1, "Other", clkTotal-clkSat-clkSrm-clkSim, clkTotal ); - Abc_PrintTime( 1, "TOTAL", clkTotal ); - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Computes choices for the vector of AIGs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Gia_Man_t * Cec_ManChoiceComputationVec( Gia_Man_t * pGia, int nGias, Cec_ParChc_t * pPars ) -{ - Gia_Man_t * pNew; - int RetValue; - // compute equivalences of the miter -// pMiter = Gia_ManChoiceMiter( vGias ); -// Gia_ManSetRegNum( pMiter, 0 ); - RetValue = Cec_ManChoiceComputation_int( pGia, pPars ); - // derive AIG with choices - pNew = Gia_ManEquivToChoices( pGia, nGias ); - Gia_ManHasChoices( pNew ); -// Gia_ManStop( pMiter ); - // report the results - if ( pPars->fVerbose ) - { -// Abc_Print( 1, "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n", -// Gia_ManAndNum(pAig), Gia_ManAndNum(pNew), -// 100.0*(Gia_ManAndNum(pAig)-Gia_ManAndNum(pNew))/(Gia_ManAndNum(pAig)?Gia_ManAndNum(pAig):1), -// Gia_ManRegNum(pAig), Gia_ManRegNum(pNew), -// 100.0*(Gia_ManRegNum(pAig)-Gia_ManRegNum(pNew))/(Gia_ManRegNum(pAig)?Gia_ManRegNum(pAig):1) ); - } - return pNew; -} - -/**Function************************************************************* - - Synopsis [Computes choices for one AIGs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Gia_Man_t * Cec_ManChoiceComputation( Gia_Man_t * pAig, Cec_ParChc_t * pParsChc ) -{ -// extern Aig_Man_t * Dar_ManChoiceNew( Aig_Man_t * pAig, Dch_Pars_t * pPars ); - Dch_Pars_t Pars, * pPars = &Pars; - Aig_Man_t * pMan, * pManNew; - Gia_Man_t * pGia; - if ( 0 ) - { - pGia = Cec_ManChoiceComputationVec( pAig, 3, pParsChc ); - } - else - { - pMan = Gia_ManToAig( pAig, 0 ); - Dch_ManSetDefaultParams( pPars ); - pPars->fUseGia = 1; - pPars->nBTLimit = pParsChc->nBTLimit; - pPars->fUseCSat = pParsChc->fUseCSat; - pPars->fVerbose = pParsChc->fVerbose; - pManNew = Dar_ManChoiceNew( pMan, pPars ); - pGia = Gia_ManFromAig( pManNew ); - Aig_ManStop( pManNew ); -// Aig_ManStop( pMan ); - } - return pGia; -} - -/**Function************************************************************* - - Synopsis [Performs computation of AIGs with choices.] - - Description [Takes several AIGs and performs choicing.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Cec_ComputeChoices( Gia_Man_t * pGia, Dch_Pars_t * pPars ) -{ - Cec_ParChc_t ParsChc, * pParsChc = &ParsChc; - Aig_Man_t * pAig; - if ( pPars->fVerbose ) - Abc_PrintTime( 1, "Synthesis time", pPars->timeSynth ); - Cec_ManChcSetDefaultParams( pParsChc ); - pParsChc->nBTLimit = pPars->nBTLimit; - pParsChc->fUseCSat = pPars->fUseCSat; - if ( pParsChc->fUseCSat && pParsChc->nBTLimit > 100 ) - pParsChc->nBTLimit = 100; - pParsChc->fVerbose = pPars->fVerbose; - pGia = Cec_ManChoiceComputationVec( pGia, 3, pParsChc ); - Gia_ManSetRegNum( pGia, Gia_ManRegNum(pGia) ); - pAig = Gia_ManToAig( pGia, 1 ); - Gia_ManStop( pGia ); - return pAig; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cec/cecClass.c b/src/aig/cec/cecClass.c deleted file mode 100644 index b6118038..00000000 --- a/src/aig/cec/cecClass.c +++ /dev/null @@ -1,931 +0,0 @@ -/**CFile**************************************************************** - - FileName [cecClass.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Combinational equivalence checking.] - - Synopsis [Equivalence class refinement.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cecClass.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cecInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline unsigned * Cec_ObjSim( Cec_ManSim_t * p, int Id ) { return p->pMems + p->pSimInfo[Id] + 1; } -static inline void Cec_ObjSetSim( Cec_ManSim_t * p, int Id, int n ) { p->pSimInfo[Id] = n; } - -static inline float Cec_MemUsage( Cec_ManSim_t * p ) { return 1.0*p->nMemsMax*(p->pPars->nWords+1)/(1<<20); } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Compares simulation info of one node with constant 0.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManSimCompareConst( unsigned * p, int nWords ) -{ - int w; - if ( p[0] & 1 ) - { - for ( w = 0; w < nWords; w++ ) - if ( p[w] != ~0 ) - return 0; - return 1; - } - else - { - for ( w = 0; w < nWords; w++ ) - if ( p[w] != 0 ) - return 0; - return 1; - } -} - -/**Function************************************************************* - - Synopsis [Compares simulation info of two nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManSimCompareEqual( unsigned * p0, unsigned * p1, int nWords ) -{ - int w; - if ( (p0[0] & 1) == (p1[0] & 1) ) - { - for ( w = 0; w < nWords; w++ ) - if ( p0[w] != p1[w] ) - return 0; - return 1; - } - else - { - for ( w = 0; w < nWords; w++ ) - if ( p0[w] != ~p1[w] ) - return 0; - return 1; - } -} - -/**Function************************************************************* - - Synopsis [Returns the number of the first non-equal bit.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManSimCompareConstFirstBit( unsigned * p, int nWords ) -{ - int w; - if ( p[0] & 1 ) - { - for ( w = 0; w < nWords; w++ ) - if ( p[w] != ~0 ) - return 32*w + Gia_WordFindFirstBit( ~p[w] ); - return -1; - } - else - { - for ( w = 0; w < nWords; w++ ) - if ( p[w] != 0 ) - return 32*w + Gia_WordFindFirstBit( p[w] ); - return -1; - } -} - -/**Function************************************************************* - - Synopsis [Compares simulation info of two nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManSimCompareEqualFirstBit( unsigned * p0, unsigned * p1, int nWords ) -{ - int w; - if ( (p0[0] & 1) == (p1[0] & 1) ) - { - for ( w = 0; w < nWords; w++ ) - if ( p0[w] != p1[w] ) - return 32*w + Gia_WordFindFirstBit( p0[w] ^ p1[w] ); - return -1; - } - else - { - for ( w = 0; w < nWords; w++ ) - if ( p0[w] != ~p1[w] ) - return 32*w + Gia_WordFindFirstBit( p0[w] ^ ~p1[w] ); - return -1; - } -} - -/**Function************************************************************* - - Synopsis [Returns the number of the first non-equal bit.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManSimCompareConstScore( unsigned * p, int nWords, int * pScores ) -{ - int w, b; - if ( p[0] & 1 ) - { - for ( w = 0; w < nWords; w++ ) - if ( p[w] != ~0 ) - for ( b = 0; b < 32; b++ ) - if ( ((~p[w]) >> b ) & 1 ) - pScores[32*w + b]++; - } - else - { - for ( w = 0; w < nWords; w++ ) - if ( p[w] != 0 ) - for ( b = 0; b < 32; b++ ) - if ( ((p[w]) >> b ) & 1 ) - pScores[32*w + b]++; - } -} - -/**Function************************************************************* - - Synopsis [Compares simulation info of two nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManSimCompareEqualScore( unsigned * p0, unsigned * p1, int nWords, int * pScores ) -{ - int w, b; - if ( (p0[0] & 1) == (p1[0] & 1) ) - { - for ( w = 0; w < nWords; w++ ) - if ( p0[w] != p1[w] ) - for ( b = 0; b < 32; b++ ) - if ( ((p0[w] ^ p1[w]) >> b ) & 1 ) - pScores[32*w + b]++; - } - else - { - for ( w = 0; w < nWords; w++ ) - if ( p0[w] != ~p1[w] ) - for ( b = 0; b < 32; b++ ) - if ( ((p0[w] ^ ~p1[w]) >> b ) & 1 ) - pScores[32*w + b]++; - } -} - -/**Function************************************************************* - - Synopsis [Creates equivalence class.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManSimClassCreate( Gia_Man_t * p, Vec_Int_t * vClass ) -{ - int Repr = GIA_VOID, EntPrev = -1, Ent, i; - assert( Vec_IntSize(vClass) > 0 ); - Vec_IntForEachEntry( vClass, Ent, i ) - { - if ( i == 0 ) - { - Repr = Ent; - Gia_ObjSetRepr( p, Ent, GIA_VOID ); - EntPrev = Ent; - } - else - { - assert( Repr < Ent ); - Gia_ObjSetRepr( p, Ent, Repr ); - Gia_ObjSetNext( p, EntPrev, Ent ); - EntPrev = Ent; - } - } - Gia_ObjSetNext( p, EntPrev, 0 ); -} - -/**Function************************************************************* - - Synopsis [Refines one equivalence class.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManSimClassRefineOne( Cec_ManSim_t * p, int i ) -{ - unsigned * pSim0, * pSim1; - int Ent; - Vec_IntClear( p->vClassOld ); - Vec_IntClear( p->vClassNew ); - Vec_IntPush( p->vClassOld, i ); - pSim0 = Cec_ObjSim(p, i); - Gia_ClassForEachObj1( p->pAig, i, Ent ) - { - pSim1 = Cec_ObjSim(p, Ent); - if ( Cec_ManSimCompareEqual( pSim0, pSim1, p->nWords ) ) - Vec_IntPush( p->vClassOld, Ent ); - else - { - Vec_IntPush( p->vClassNew, Ent ); - if ( p->pBestState ) - Cec_ManSimCompareEqualScore( pSim0, pSim1, p->nWords, p->pScores ); - } - } - if ( Vec_IntSize( p->vClassNew ) == 0 ) - return 0; - Cec_ManSimClassCreate( p->pAig, p->vClassOld ); - Cec_ManSimClassCreate( p->pAig, p->vClassNew ); - if ( Vec_IntSize(p->vClassNew) > 1 ) - return 1 + Cec_ManSimClassRefineOne( p, Vec_IntEntry(p->vClassNew,0) ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Refines one equivalence class.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManSimClassRemoveOne( Cec_ManSim_t * p, int i ) -{ - int iRepr, Ent; - if ( Gia_ObjIsConst(p->pAig, i) ) - { - Gia_ObjSetRepr( p->pAig, i, GIA_VOID ); - return 1; - } - if ( !Gia_ObjIsClass(p->pAig, i) ) - return 0; - assert( Gia_ObjIsClass(p->pAig, i) ); - iRepr = Gia_ObjRepr( p->pAig, i ); - if ( iRepr == GIA_VOID ) - iRepr = i; - // collect nodes - Vec_IntClear( p->vClassOld ); - Vec_IntClear( p->vClassNew ); - Gia_ClassForEachObj( p->pAig, iRepr, Ent ) - { - if ( Ent == i ) - Vec_IntPush( p->vClassNew, Ent ); - else - Vec_IntPush( p->vClassOld, Ent ); - } - assert( Vec_IntSize( p->vClassNew ) == 1 ); - Cec_ManSimClassCreate( p->pAig, p->vClassOld ); - Cec_ManSimClassCreate( p->pAig, p->vClassNew ); - assert( !Gia_ObjIsClass(p->pAig, i) ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Computes hash key of the simuation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManSimHashKey( unsigned * pSim, int nWords, int nTableSize ) -{ - static int s_Primes[16] = { - 1291, 1699, 1999, 2357, 2953, 3313, 3907, 4177, - 4831, 5147, 5647, 6343, 6899, 7103, 7873, 8147 }; - unsigned uHash = 0; - int i; - if ( pSim[0] & 1 ) - for ( i = 0; i < nWords; i++ ) - uHash ^= ~pSim[i] * s_Primes[i & 0xf]; - else - for ( i = 0; i < nWords; i++ ) - uHash ^= pSim[i] * s_Primes[i & 0xf]; - return (int)(uHash % nTableSize); - -} - -/**Function************************************************************* - - Synopsis [Resets pointers to the simulation memory.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManSimMemRelink( Cec_ManSim_t * p ) -{ - unsigned * pPlace, Ent; - pPlace = (unsigned *)&p->MemFree; - for ( Ent = p->nMems * (p->nWords + 1); - Ent + p->nWords + 1 < (unsigned)p->nWordsAlloc; - Ent += p->nWords + 1 ) - { - *pPlace = Ent; - pPlace = p->pMems + Ent; - } - *pPlace = 0; - p->nWordsOld = p->nWords; -} - -/**Function************************************************************* - - Synopsis [References simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Cec_ManSimSimRef( Cec_ManSim_t * p, int i ) -{ - unsigned * pSim; - assert( p->pSimInfo[i] == 0 ); - if ( p->MemFree == 0 ) - { - if ( p->nWordsAlloc == 0 ) - { - assert( p->pMems == NULL ); - p->nWordsAlloc = (1<<17); // -> 1Mb - p->nMems = 1; - } - p->nWordsAlloc *= 2; - p->pMems = ABC_REALLOC( unsigned, p->pMems, p->nWordsAlloc ); - Cec_ManSimMemRelink( p ); - } - p->pSimInfo[i] = p->MemFree; - pSim = p->pMems + p->MemFree; - p->MemFree = pSim[0]; - pSim[0] = Gia_ObjValue( Gia_ManObj(p->pAig, i) ); - p->nMems++; - if ( p->nMemsMax < p->nMems ) - p->nMemsMax = p->nMems; - return pSim; -} - -/**Function************************************************************* - - Synopsis [Dereferences simulaton info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Cec_ManSimSimDeref( Cec_ManSim_t * p, int i ) -{ - unsigned * pSim; - assert( p->pSimInfo[i] > 0 ); - pSim = p->pMems + p->pSimInfo[i]; - if ( --pSim[0] == 0 ) - { - pSim[0] = p->MemFree; - p->MemFree = p->pSimInfo[i]; - p->pSimInfo[i] = 0; - p->nMems--; - } - return pSim; -} - -/**Function************************************************************* - - Synopsis [Refines nodes belonging to candidate constant class.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManSimProcessRefined( Cec_ManSim_t * p, Vec_Int_t * vRefined ) -{ - unsigned * pSim; - int * pTable, nTableSize, i, k, Key; - if ( Vec_IntSize(vRefined) == 0 ) - return; - nTableSize = Gia_PrimeCudd( 100 + Vec_IntSize(vRefined) / 3 ); - pTable = ABC_CALLOC( int, nTableSize ); - Vec_IntForEachEntry( vRefined, i, k ) - { - pSim = Cec_ObjSim( p, i ); - assert( !Cec_ManSimCompareConst( pSim, p->nWords ) ); - Key = Cec_ManSimHashKey( pSim, p->nWords, nTableSize ); - if ( pTable[Key] == 0 ) - { - assert( Gia_ObjRepr(p->pAig, i) == 0 ); - assert( Gia_ObjNext(p->pAig, i) == 0 ); - Gia_ObjSetRepr( p->pAig, i, GIA_VOID ); - } - else - { - Gia_ObjSetNext( p->pAig, pTable[Key], i ); - Gia_ObjSetRepr( p->pAig, i, Gia_ObjRepr(p->pAig, pTable[Key]) ); - if ( Gia_ObjRepr(p->pAig, i) == GIA_VOID ) - Gia_ObjSetRepr( p->pAig, i, pTable[Key] ); - assert( Gia_ObjRepr(p->pAig, i) > 0 ); - } - pTable[Key] = i; - } - Vec_IntForEachEntry( vRefined, i, k ) - { - if ( Gia_ObjIsHead( p->pAig, i ) ) - Cec_ManSimClassRefineOne( p, i ); - } - Vec_IntForEachEntry( vRefined, i, k ) - Cec_ManSimSimDeref( p, i ); - ABC_FREE( pTable ); -} - - -/**Function************************************************************* - - Synopsis [Saves the input pattern with the given number.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManSimSavePattern( Cec_ManSim_t * p, int iPat ) -{ - unsigned * pInfo; - int i; - assert( p->pCexComb == NULL ); - assert( iPat >= 0 && iPat < 32 * p->nWords ); - p->pCexComb = (Abc_Cex_t *)ABC_CALLOC( char, - sizeof(Abc_Cex_t) + sizeof(unsigned) * Gia_BitWordNum(Gia_ManCiNum(p->pAig)) ); - p->pCexComb->iPo = p->iOut; - p->pCexComb->nPis = Gia_ManCiNum(p->pAig); - p->pCexComb->nBits = Gia_ManCiNum(p->pAig); - for ( i = 0; i < Gia_ManCiNum(p->pAig); i++ ) - { - pInfo = (unsigned *)Vec_PtrEntry( p->vCiSimInfo, i ); - if ( Gia_InfoHasBit( pInfo, iPat ) ) - Gia_InfoSetBit( p->pCexComb->pData, i ); - } -} - -/**Function************************************************************* - - Synopsis [Find the best pattern using the scores.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManSimFindBestPattern( Cec_ManSim_t * p ) -{ - unsigned * pInfo; - int i, ScoreBest = 0, iPatBest = 1; // set the first pattern - // find the best pattern - for ( i = 0; i < 32 * p->nWords; i++ ) - if ( ScoreBest < p->pScores[i] ) - { - ScoreBest = p->pScores[i]; - iPatBest = i; - } - // compare this with the available patterns - and save - if ( p->pBestState->iPo <= ScoreBest ) - { - assert( p->pBestState->nRegs == Gia_ManRegNum(p->pAig) ); - for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) - { - pInfo = (unsigned *)Vec_PtrEntry( p->vCiSimInfo, Gia_ManPiNum(p->pAig) + i ); - if ( Gia_InfoHasBit(p->pBestState->pData, i) != Gia_InfoHasBit(pInfo, iPatBest) ) - Gia_InfoXorBit( p->pBestState->pData, i ); - } - p->pBestState->iPo = ScoreBest; - } -} - -/**Function************************************************************* - - Synopsis [Returns 1 if computation should stop.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManSimAnalyzeOutputs( Cec_ManSim_t * p ) -{ - unsigned * pInfo, * pInfo2; - int i; - if ( !p->pPars->fCheckMiter ) - return 0; - assert( p->vCoSimInfo != NULL ); - // compare outputs with 0 - if ( p->pPars->fDualOut ) - { - assert( (Gia_ManPoNum(p->pAig) & 1) == 0 ); - for ( i = 0; i < Gia_ManPoNum(p->pAig); i++ ) - { - pInfo = (unsigned *)Vec_PtrEntry( p->vCoSimInfo, i ); - pInfo2 = (unsigned *)Vec_PtrEntry( p->vCoSimInfo, ++i ); - if ( !Cec_ManSimCompareEqual( pInfo, pInfo2, p->nWords ) ) - { - if ( p->iOut == -1 ) - { - p->iOut = i/2; - Cec_ManSimSavePattern( p, Cec_ManSimCompareEqualFirstBit(pInfo, pInfo2, p->nWords) ); - } - if ( p->pCexes == NULL ) - p->pCexes = ABC_CALLOC( void *, Gia_ManPoNum(p->pAig)/2 ); - if ( p->pCexes[i/2] == NULL ) - { - p->nOuts++; - p->pCexes[i/2] = (void *)1; - } - } - } - } - else - { - for ( i = 0; i < Gia_ManPoNum(p->pAig); i++ ) - { - pInfo = (unsigned *)Vec_PtrEntry( p->vCoSimInfo, i ); - if ( !Cec_ManSimCompareConst( pInfo, p->nWords ) ) - { - if ( p->iOut == -1 ) - { - p->iOut = i; - Cec_ManSimSavePattern( p, Cec_ManSimCompareConstFirstBit(pInfo, p->nWords) ); - } - if ( p->pCexes == NULL ) - p->pCexes = ABC_CALLOC( void *, Gia_ManPoNum(p->pAig) ); - if ( p->pCexes[i] == NULL ) - { - p->nOuts++; - p->pCexes[i] = (void *)1; - } - } - } - } - return p->pCexes != NULL; -} - -/**Function************************************************************* - - Synopsis [Simulates one round.] - - Description [Returns the number of PO entry if failed; 0 otherwise.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManSimSimulateRound( Cec_ManSim_t * p, Vec_Ptr_t * vInfoCis, Vec_Ptr_t * vInfoCos ) -{ - Gia_Obj_t * pObj; - unsigned * pRes0, * pRes1, * pRes; - int i, k, w, Ent, iCiId = 0, iCoId = 0; - // prepare internal storage - if ( p->nWordsOld != p->nWords ) - Cec_ManSimMemRelink( p ); - p->nMemsMax = 0; - // allocate score counters - ABC_FREE( p->pScores ); - if ( p->pBestState ) - p->pScores = ABC_CALLOC( int, 32 * p->nWords ); - // simulate nodes - Vec_IntClear( p->vRefinedC ); - if ( Gia_ObjValue(Gia_ManConst0(p->pAig)) ) - { - pRes = Cec_ManSimSimRef( p, 0 ); - for ( w = 1; w <= p->nWords; w++ ) - pRes[w] = 0; - } - Gia_ManForEachObj1( p->pAig, pObj, i ) - { - if ( Gia_ObjIsCi(pObj) ) - { - if ( Gia_ObjValue(pObj) == 0 ) - { - iCiId++; - continue; - } - pRes = Cec_ManSimSimRef( p, i ); - if ( vInfoCis ) - { - pRes0 = (unsigned *)Vec_PtrEntry( vInfoCis, iCiId++ ); - for ( w = 1; w <= p->nWords; w++ ) - pRes[w] = pRes0[w-1]; - } - else - { - for ( w = 1; w <= p->nWords; w++ ) - pRes[w] = Gia_ManRandom( 0 ); - } - // make sure the first pattern is always zero - pRes[1] ^= (pRes[1] & 1); - goto references; - } - if ( Gia_ObjIsCo(pObj) ) // co always has non-zero 1st fanin and zero 2nd fanin - { - pRes0 = Cec_ManSimSimDeref( p, Gia_ObjFaninId0(pObj,i) ); - if ( vInfoCos ) - { - pRes = (unsigned *)Vec_PtrEntry( vInfoCos, iCoId++ ); - if ( Gia_ObjFaninC0(pObj) ) - for ( w = 1; w <= p->nWords; w++ ) - pRes[w-1] = ~pRes0[w]; - else - for ( w = 1; w <= p->nWords; w++ ) - pRes[w-1] = pRes0[w]; - } - continue; - } - assert( Gia_ObjValue(pObj) ); - pRes = Cec_ManSimSimRef( p, i ); - pRes0 = Cec_ManSimSimDeref( p, Gia_ObjFaninId0(pObj,i) ); - pRes1 = Cec_ManSimSimDeref( p, Gia_ObjFaninId1(pObj,i) ); - -// Abc_Print( 1, "%d,%d ", Gia_ObjValue( Gia_ObjFanin0(pObj) ), Gia_ObjValue( Gia_ObjFanin1(pObj) ) ); - - if ( Gia_ObjFaninC0(pObj) ) - { - if ( Gia_ObjFaninC1(pObj) ) - for ( w = 1; w <= p->nWords; w++ ) - pRes[w] = ~(pRes0[w] | pRes1[w]); - else - for ( w = 1; w <= p->nWords; w++ ) - pRes[w] = ~pRes0[w] & pRes1[w]; - } - else - { - if ( Gia_ObjFaninC1(pObj) ) - for ( w = 1; w <= p->nWords; w++ ) - pRes[w] = pRes0[w] & ~pRes1[w]; - else - for ( w = 1; w <= p->nWords; w++ ) - pRes[w] = pRes0[w] & pRes1[w]; - } - -references: - // if this node is candidate constant, collect it - if ( Gia_ObjIsConst(p->pAig, i) && !Cec_ManSimCompareConst(pRes + 1, p->nWords) ) - { - pRes[0]++; - Vec_IntPush( p->vRefinedC, i ); - if ( p->pBestState ) - Cec_ManSimCompareConstScore( pRes + 1, p->nWords, p->pScores ); - } - // if the node belongs to a class, save it - if ( Gia_ObjIsClass(p->pAig, i) ) - pRes[0]++; - // if this is the last node of the class, process it - if ( Gia_ObjIsTail(p->pAig, i) ) - { - Vec_IntClear( p->vClassTemp ); - Gia_ClassForEachObj( p->pAig, Gia_ObjRepr(p->pAig, i), Ent ) - Vec_IntPush( p->vClassTemp, Ent ); - Cec_ManSimClassRefineOne( p, Gia_ObjRepr(p->pAig, i) ); - Vec_IntForEachEntry( p->vClassTemp, Ent, k ) - Cec_ManSimSimDeref( p, Ent ); - } - } - - if ( p->pPars->fConstCorr ) - { - Vec_IntForEachEntry( p->vRefinedC, i, k ) - { - Gia_ObjSetRepr( p->pAig, i, GIA_VOID ); - Cec_ManSimSimDeref( p, i ); - } - Vec_IntClear( p->vRefinedC ); - } - - if ( Vec_IntSize(p->vRefinedC) > 0 ) - Cec_ManSimProcessRefined( p, p->vRefinedC ); - assert( vInfoCis == NULL || iCiId == Gia_ManCiNum(p->pAig) ); - assert( vInfoCos == NULL || iCoId == Gia_ManCoNum(p->pAig) ); - assert( p->nMems == 1 ); - if ( p->nMems != 1 ) - Abc_Print( 1, "Cec_ManSimSimulateRound(): Memory management error!\n" ); - if ( p->pPars->fVeryVerbose ) - Gia_ManEquivPrintClasses( p->pAig, 0, Cec_MemUsage(p) ); - if ( p->pBestState ) - Cec_ManSimFindBestPattern( p ); -/* - if ( p->nMems > 1 ) { - for ( i = 1; i < p->nObjs; i++ ) - if ( p->pSims[i] ) { - int x = 0; - } - } -*/ - return Cec_ManSimAnalyzeOutputs( p ); -} - - - -/**Function************************************************************* - - Synopsis [Creates simulation info for this round.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManSimCreateInfo( Cec_ManSim_t * p, Vec_Ptr_t * vInfoCis, Vec_Ptr_t * vInfoCos ) -{ - unsigned * pRes0, * pRes1; - int i, w; - if ( p->pPars->fSeqSimulate && Gia_ManRegNum(p->pAig) > 0 ) - { - assert( vInfoCis && vInfoCos ); - for ( i = 0; i < Gia_ManPiNum(p->pAig); i++ ) - { - pRes0 = (unsigned *)Vec_PtrEntry( vInfoCis, i ); - for ( w = 0; w < p->nWords; w++ ) - pRes0[w] = Gia_ManRandom( 0 ); - } - for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) - { - pRes0 = (unsigned *)Vec_PtrEntry( vInfoCis, Gia_ManPiNum(p->pAig) + i ); - pRes1 = (unsigned *)Vec_PtrEntry( vInfoCos, Gia_ManPoNum(p->pAig) + i ); - for ( w = 0; w < p->nWords; w++ ) - pRes0[w] = pRes1[w]; - } - } - else - { - for ( i = 0; i < Gia_ManCiNum(p->pAig); i++ ) - { - pRes0 = (unsigned *)Vec_PtrEntry( vInfoCis, i ); - for ( w = 0; w < p->nWords; w++ ) - pRes0[w] = Gia_ManRandom( 0 ); - } - } -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the bug is found.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManSimClassesPrepare( Cec_ManSim_t * p, int LevelMax ) -{ - Gia_Obj_t * pObj; - int i; - assert( p->pAig->pReprs == NULL ); - // allocate representation - p->pAig->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p->pAig) ); - p->pAig->pNexts = ABC_CALLOC( int, Gia_ManObjNum(p->pAig) ); - // create references - Gia_ManSetRefs( p->pAig ); - // set starting representative of internal nodes to be constant 0 - if ( p->pPars->fLatchCorr ) - Gia_ManForEachObj( p->pAig, pObj, i ) - Gia_ObjSetRepr( p->pAig, i, GIA_VOID ); - else if ( LevelMax == -1 ) - Gia_ManForEachObj( p->pAig, pObj, i ) - Gia_ObjSetRepr( p->pAig, i, Gia_ObjIsAnd(pObj) ? 0 : GIA_VOID ); - else - { - Gia_ManLevelNum( p->pAig ); - Gia_ManForEachObj( p->pAig, pObj, i ) - Gia_ObjSetRepr( p->pAig, i, (Gia_ObjIsAnd(pObj) && Gia_ObjLevel(p->pAig,pObj) <= LevelMax) ? 0 : GIA_VOID ); - Vec_IntFreeP( &p->pAig->vLevels ); - } - // if sequential simulation, set starting representative of ROs to be constant 0 - if ( p->pPars->fSeqSimulate ) - Gia_ManForEachRo( p->pAig, pObj, i ) - if ( pObj->Value ) - Gia_ObjSetRepr( p->pAig, Gia_ObjId(p->pAig, pObj), 0 ); - // perform simulation - p->nWords = 1; - do { - if ( p->pPars->fVerbose ) - Gia_ManEquivPrintClasses( p->pAig, 0, Cec_MemUsage(p) ); - for ( i = 0; i < 4; i++ ) - { - Cec_ManSimCreateInfo( p, p->vCiSimInfo, p->vCoSimInfo ); - if ( Cec_ManSimSimulateRound( p, p->vCiSimInfo, p->vCoSimInfo ) ) - return 1; - } - p->nWords = 2 * p->nWords + 1; - } - while ( p->nWords <= p->pPars->nWords ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the bug is found.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManSimClassesRefine( Cec_ManSim_t * p ) -{ - int i; - Gia_ManSetRefs( p->pAig ); - p->nWords = p->pPars->nWords; - for ( i = 0; i < p->pPars->nRounds; i++ ) - { - if ( (i % (p->pPars->nRounds / 5)) == 0 && p->pPars->fVerbose ) - Gia_ManEquivPrintClasses( p->pAig, 0, Cec_MemUsage(p) ); - Cec_ManSimCreateInfo( p, p->vCiSimInfo, p->vCoSimInfo ); - if ( Cec_ManSimSimulateRound( p, p->vCiSimInfo, p->vCoSimInfo ) ) - return 1; - } - if ( p->pPars->fVerbose ) - Gia_ManEquivPrintClasses( p->pAig, 0, Cec_MemUsage(p) ); - return 0; -} -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cec/cecCore.c b/src/aig/cec/cecCore.c deleted file mode 100644 index bf41304b..00000000 --- a/src/aig/cec/cecCore.c +++ /dev/null @@ -1,542 +0,0 @@ -/**CFile**************************************************************** - - FileName [cecCore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Combinational equivalence checking.] - - Synopsis [Core procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cecCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cecInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [This procedure sets default parameters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManSatSetDefaultParams( Cec_ParSat_t * p ) -{ - memset( p, 0, sizeof(Cec_ParSat_t) ); - p->nBTLimit = 100; // conflict limit at a node - p->nSatVarMax = 2000; // the max number of SAT variables - p->nCallsRecycle = 200; // calls to perform before recycling SAT solver - p->fNonChrono = 0; // use non-chronological backtracling (for circuit SAT only) - p->fPolarFlip = 1; // flops polarity of variables - p->fCheckMiter = 0; // the circuit is the miter -// p->fFirstStop = 0; // stop on the first sat output - p->fLearnCls = 0; // perform clause learning - p->fVerbose = 0; // verbose stats -} - -/**Function************ ************************************************* - - Synopsis [This procedure sets default parameters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManSimSetDefaultParams( Cec_ParSim_t * p ) -{ - memset( p, 0, sizeof(Cec_ParSim_t) ); - p->nWords = 31; // the number of simulation words - p->nFrames = 100; // the number of simulation frames - p->nRounds = 20; // the max number of simulation rounds - p->nNonRefines = 3; // the max number of rounds without refinement - p->TimeLimit = 0; // the runtime limit in seconds - p->fCheckMiter = 0; // the circuit is the miter -// p->fFirstStop = 0; // stop on the first sat output - p->fDualOut = 0; // miter with separate outputs - p->fConstCorr = 0; // consider only constants - p->fSeqSimulate = 0; // performs sequential simulation - p->fVeryVerbose = 0; // verbose stats - p->fVerbose = 0; // verbose stats -} - -/**Function************ ************************************************* - - Synopsis [This procedure sets default parameters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManSmfSetDefaultParams( Cec_ParSmf_t * p ) -{ - memset( p, 0, sizeof(Cec_ParSmf_t) ); - p->nWords = 31; // the number of simulation words - p->nRounds = 200; // the number of simulation rounds - p->nFrames = 200; // the max number of time frames - p->nNonRefines = 3; // the max number of rounds without refinement - p->nMinOutputs = 0; // the min outputs to accumulate - p->nBTLimit = 100; // conflict limit at a node - p->TimeLimit = 0; // the runtime limit in seconds - p->fDualOut = 0; // miter with separate outputs - p->fCheckMiter = 0; // the circuit is the miter -// p->fFirstStop = 0; // stop on the first sat output - p->fVerbose = 0; // verbose stats -} - -/**Function************ ************************************************* - - Synopsis [This procedure sets default parameters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManFraSetDefaultParams( Cec_ParFra_t * p ) -{ - memset( p, 0, sizeof(Cec_ParFra_t) ); - p->nWords = 15; // the number of simulation words - p->nRounds = 15; // the number of simulation rounds - p->TimeLimit = 0; // the runtime limit in seconds - p->nItersMax = 10; // the maximum number of iterations of SAT sweeping - p->nBTLimit = 100; // conflict limit at a node - p->nLevelMax = 0; // restriction on the level of nodes to be swept - p->nDepthMax = 1; // the depth in terms of steps of speculative reduction - p->fRewriting = 0; // enables AIG rewriting - p->fCheckMiter = 0; // the circuit is the miter -// p->fFirstStop = 0; // stop on the first sat output - p->fDualOut = 0; // miter with separate outputs - p->fColorDiff = 0; // miter with separate outputs - p->fSatSweeping = 0; // enable SAT sweeping - p->fVeryVerbose = 0; // verbose stats - p->fVerbose = 0; // verbose stats - p->iOutFail = -1; // the failed output -} - -/**Function************************************************************* - - Synopsis [This procedure sets default parameters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManCecSetDefaultParams( Cec_ParCec_t * p ) -{ - memset( p, 0, sizeof(Cec_ParCec_t) ); - p->nBTLimit = 1000; // conflict limit at a node - p->TimeLimit = 0; // the runtime limit in seconds -// p->fFirstStop = 0; // stop on the first sat output - p->fUseSmartCnf = 0; // use smart CNF computation - p->fRewriting = 0; // enables AIG rewriting - p->fVeryVerbose = 0; // verbose stats - p->fVerbose = 0; // verbose stats - p->iOutFail = -1; // the number of failed output -} - -/**Function************************************************************* - - Synopsis [This procedure sets default parameters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManCorSetDefaultParams( Cec_ParCor_t * p ) -{ - memset( p, 0, sizeof(Cec_ParCor_t) ); - p->nWords = 15; // the number of simulation words - p->nRounds = 15; // the number of simulation rounds - p->nFrames = 1; // the number of time frames - p->nBTLimit = 100; // conflict limit at a node - p->nLevelMax = -1; // (scorr only) the max number of levels - p->nStepsMax = -1; // (scorr only) the max number of induction steps - p->fLatchCorr = 0; // consider only latch outputs - p->fConstCorr = 0; // consider only constants - p->fUseRings = 1; // combine classes into rings - p->fUseCSat = 1; // use circuit-based solver -// p->fFirstStop = 0; // stop on the first sat output - p->fUseSmartCnf = 0; // use smart CNF computation - p->fVeryVerbose = 0; // verbose stats - p->fVerbose = 0; // verbose stats -} - -/**Function************************************************************* - - Synopsis [This procedure sets default parameters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManChcSetDefaultParams( Cec_ParChc_t * p ) -{ - memset( p, 0, sizeof(Cec_ParChc_t) ); - p->nWords = 15; // the number of simulation words - p->nRounds = 15; // the number of simulation rounds - p->nBTLimit = 1000; // conflict limit at a node - p->fUseRings = 1; // use rings - p->fUseCSat = 0; // use circuit-based solver - p->fVeryVerbose = 0; // verbose stats - p->fVerbose = 0; // verbose stats -} - -/**Function************************************************************* - - Synopsis [Core procedure for SAT sweeping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Gia_Man_t * Cec_ManSatSolving( Gia_Man_t * pAig, Cec_ParSat_t * pPars ) -{ - Gia_Man_t * pNew; - Cec_ManPat_t * pPat; - pPat = Cec_ManPatStart(); - Cec_ManSatSolve( pPat, pAig, pPars ); -// pNew = Gia_ManDupDfsSkip( pAig ); - pNew = Gia_ManDup( pAig ); - Cec_ManPatStop( pPat ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Core procedure for simulation.] - - Description [Returns 1 if refinement has happened.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManSimulationOne( Gia_Man_t * pAig, Cec_ParSim_t * pPars ) -{ - Cec_ManSim_t * pSim; - int RetValue = 0, clkTotal = clock(); - pSim = Cec_ManSimStart( pAig, pPars ); - if ( (pAig->pReprs == NULL && (RetValue = Cec_ManSimClassesPrepare( pSim, -1 ))) || - (RetValue == 0 && (RetValue = Cec_ManSimClassesRefine( pSim ))) ) - Abc_Print( 1, "The number of failed outputs of the miter = %6d. (Words = %4d. Frames = %4d.)\n", - pSim->nOuts, pPars->nWords, pPars->nFrames ); - if ( pPars->fVerbose ) - Abc_PrintTime( 1, "Time", clock() - clkTotal ); - Cec_ManSimStop( pSim ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Core procedure for simulation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManSimulation( Gia_Man_t * pAig, Cec_ParSim_t * pPars ) -{ - int r, nLitsOld, nLitsNew, nCountNoRef = 0, fStop = 0; - Gia_ManRandom( 1 ); - if ( pPars->fSeqSimulate ) - Abc_Print( 1, "Performing rounds of random simulation of %d frames with %d words.\n", - pPars->nRounds, pPars->nFrames, pPars->nWords ); - nLitsOld = Gia_ManEquivCountLits( pAig ); - for ( r = 0; r < pPars->nRounds; r++ ) - { - if ( Cec_ManSimulationOne( pAig, pPars ) ) - { - fStop = 1; - break; - } - // decide when to stop - nLitsNew = Gia_ManEquivCountLits( pAig ); - if ( nLitsOld == 0 || nLitsOld > nLitsNew ) - { - nLitsOld = nLitsNew; - nCountNoRef = 0; - } - else if ( ++nCountNoRef == pPars->nNonRefines ) - { - r++; - break; - } - assert( nLitsOld == nLitsNew ); - } -// if ( pPars->fVerbose ) - if ( r == pPars->nRounds || fStop ) - Abc_Print( 1, "Random simulation is stopped after %d rounds.\n", r ); - else - Abc_Print( 1, "Random simulation saturated after %d rounds.\n", r ); - if ( pPars->fCheckMiter ) - { - int nNonConsts = Cec_ManCountNonConstOutputs( pAig ); - if ( nNonConsts ) - Abc_Print( 1, "The number of POs that are not const-0 candidates = %d.\n", nNonConsts ); - } -} - -/**Function************************************************************* - - Synopsis [Core procedure for SAT sweeping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Gia_Man_t * Cec_ManSatSweeping( Gia_Man_t * pAig, Cec_ParFra_t * pPars ) -{ - int fOutputResult = 0; - Cec_ParSat_t ParsSat, * pParsSat = &ParsSat; - Cec_ParSim_t ParsSim, * pParsSim = &ParsSim; - Gia_Man_t * pIni, * pSrm, * pTemp; - Cec_ManFra_t * p; - Cec_ManSim_t * pSim; - Cec_ManPat_t * pPat; - int i, fTimeOut = 0, nMatches = 0, clk, clk2; - double clkTotal = clock(); - - // duplicate AIG and transfer equivalence classes - Gia_ManRandom( 1 ); - pIni = Gia_ManDup(pAig); - pIni->pReprs = pAig->pReprs; pAig->pReprs = NULL; - pIni->pNexts = pAig->pNexts; pAig->pNexts = NULL; - - // prepare the managers - // SAT sweeping - p = Cec_ManFraStart( pIni, pPars ); - if ( pPars->fDualOut ) - pPars->fColorDiff = 1; - // simulation - Cec_ManSimSetDefaultParams( pParsSim ); - pParsSim->nWords = pPars->nWords; - pParsSim->nFrames = pPars->nRounds; - pParsSim->fCheckMiter = pPars->fCheckMiter; - pParsSim->fDualOut = pPars->fDualOut; - pParsSim->fVerbose = pPars->fVerbose; - pSim = Cec_ManSimStart( p->pAig, pParsSim ); - // SAT solving - Cec_ManSatSetDefaultParams( pParsSat ); - pParsSat->nBTLimit = pPars->nBTLimit; - pParsSat->fVerbose = pPars->fVeryVerbose; - // simulation patterns - pPat = Cec_ManPatStart(); - pPat->fVerbose = pPars->fVeryVerbose; - - // start equivalence classes -clk = clock(); - if ( p->pAig->pReprs == NULL ) - { - if ( Cec_ManSimClassesPrepare(pSim, -1) || Cec_ManSimClassesRefine(pSim) ) - { - Gia_ManStop( p->pAig ); - p->pAig = NULL; - goto finalize; - } - } -p->timeSim += clock() - clk; - // perform solving - for ( i = 1; i <= pPars->nItersMax; i++ ) - { - clk2 = clock(); - nMatches = 0; - if ( pPars->fDualOut ) - { - nMatches = Gia_ManEquivSetColors( p->pAig, pPars->fVeryVerbose ); -// p->pAig->pIso = Cec_ManDetectIsomorphism( p->pAig ); -// Gia_ManEquivTransform( p->pAig, 1 ); - } - pSrm = Cec_ManFraSpecReduction( p ); - -// Gia_WriteAiger( pSrm, "gia_srm.aig", 0, 0 ); - - if ( pPars->fVeryVerbose ) - Gia_ManPrintStats( pSrm, 0 ); - if ( Gia_ManCoNum(pSrm) == 0 ) - { - Gia_ManStop( pSrm ); - if ( p->pPars->fVerbose ) - Abc_Print( 1, "Considered all available candidate equivalences.\n" ); - if ( pPars->fDualOut && Gia_ManAndNum(p->pAig) > 0 ) - { - if ( pPars->fColorDiff ) - { - if ( p->pPars->fVerbose ) - Abc_Print( 1, "Switching into reduced mode.\n" ); - pPars->fColorDiff = 0; - } - else - { - if ( p->pPars->fVerbose ) - Abc_Print( 1, "Switching into normal mode.\n" ); - pPars->fDualOut = 0; - } - continue; - } - break; - } -clk = clock(); - Cec_ManSatSolve( pPat, pSrm, pParsSat ); -p->timeSat += clock() - clk; - if ( Cec_ManFraClassesUpdate( p, pSim, pPat, pSrm ) ) - { - Gia_ManStop( pSrm ); - Gia_ManStop( p->pAig ); - p->pAig = NULL; - goto finalize; - } - Gia_ManStop( pSrm ); - - // update the manager - pSim->pAig = p->pAig = Gia_ManEquivReduceAndRemap( pTemp = p->pAig, 0, pParsSim->fDualOut ); - if ( p->pAig == NULL ) - { - p->pAig = pTemp; - break; - } - Gia_ManStop( pTemp ); - if ( p->pPars->fVerbose ) - { - Abc_Print( 1, "%3d : P =%7d. D =%7d. F =%6d. M = %7d. And =%8d. ", - i, p->nAllProved, p->nAllDisproved, p->nAllFailed, nMatches, Gia_ManAndNum(p->pAig) ); - Abc_PrintTime( 1, "Time", clock() - clk2 ); - } - if ( Gia_ManAndNum(p->pAig) == 0 ) - { - if ( p->pPars->fVerbose ) - Abc_Print( 1, "Network after reduction is empty.\n" ); - break; - } - // check resource limits - if ( p->pPars->TimeLimit && ((double)clock() - clkTotal)/CLOCKS_PER_SEC >= p->pPars->TimeLimit ) - { - fTimeOut = 1; - break; - } -// if ( p->nAllFailed && !p->nAllProved && !p->nAllDisproved ) - if ( p->nAllFailed > p->nAllProved + p->nAllDisproved ) - { - if ( pParsSat->nBTLimit >= 10001 ) - break; - if ( pPars->fSatSweeping ) - { - if ( p->pPars->fVerbose ) - Abc_Print( 1, "Exceeded the limit on the number of conflicts (%d).\n", pParsSat->nBTLimit ); - break; - } - pParsSat->nBTLimit *= 10; - if ( p->pPars->fVerbose ) - { - if ( p->pPars->fVerbose ) - Abc_Print( 1, "Increasing conflict limit to %d.\n", pParsSat->nBTLimit ); - if ( fOutputResult ) - { - Gia_WriteAiger( p->pAig, "gia_cec_temp.aig", 0, 0 ); - Abc_Print( 1,"The result is written into file \"%s\".\n", "gia_cec_temp.aig" ); - } - } - } - if ( pPars->fDualOut && pPars->fColorDiff && (Gia_ManAndNum(p->pAig) < 100000 || p->nAllProved + p->nAllDisproved < 10) ) - { - if ( p->pPars->fVerbose ) - Abc_Print( 1, "Switching into reduced mode.\n" ); - pPars->fColorDiff = 0; - } -// if ( pPars->fDualOut && Gia_ManAndNum(p->pAig) < 20000 ) - else if ( pPars->fDualOut && (Gia_ManAndNum(p->pAig) < 20000 || p->nAllProved + p->nAllDisproved < 10) ) - { - if ( p->pPars->fVerbose ) - Abc_Print( 1, "Switching into normal mode.\n" ); - pPars->fColorDiff = 0; - pPars->fDualOut = 0; - } - } -finalize: - if ( p->pPars->fVerbose && p->pAig ) - { - Abc_Print( 1, "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n", - Gia_ManAndNum(pAig), Gia_ManAndNum(p->pAig), - 100.0*(Gia_ManAndNum(pAig)-Gia_ManAndNum(p->pAig))/(Gia_ManAndNum(pAig)?Gia_ManAndNum(pAig):1), - Gia_ManRegNum(pAig), Gia_ManRegNum(p->pAig), - 100.0*(Gia_ManRegNum(pAig)-Gia_ManRegNum(p->pAig))/(Gia_ManRegNum(pAig)?Gia_ManRegNum(pAig):1) ); - Abc_PrintTimeP( 1, "Sim ", p->timeSim, clock() - (int)clkTotal ); - Abc_PrintTimeP( 1, "Sat ", p->timeSat-pPat->timeTotalSave, clock() - (int)clkTotal ); - Abc_PrintTimeP( 1, "Pat ", p->timePat+pPat->timeTotalSave, clock() - (int)clkTotal ); - Abc_PrintTime( 1, "Time", (int)(clock() - clkTotal) ); - } - - pTemp = p->pAig; p->pAig = NULL; - if ( pTemp == NULL && pSim->iOut >= 0 ) - { - Abc_Print( 1, "Disproved at least one output of the miter (zero-based number %d).\n", pSim->iOut ); - pPars->iOutFail = pSim->iOut; - } - else if ( pSim->pCexes ) - Abc_Print( 1, "Disproved %d outputs of the miter.\n", pSim->nOuts ); - if ( fTimeOut ) - Abc_Print( 1, "Timed out after %d seconds.\n", (int)((double)clock() - clkTotal)/CLOCKS_PER_SEC ); - - pAig->pCexComb = pSim->pCexComb; pSim->pCexComb = NULL; - Cec_ManSimStop( pSim ); - Cec_ManPatStop( pPat ); - Cec_ManFraStop( p ); - return pTemp; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cec/cecCorr.c b/src/aig/cec/cecCorr.c deleted file mode 100644 index 59d091d8..00000000 --- a/src/aig/cec/cecCorr.c +++ /dev/null @@ -1,1137 +0,0 @@ -/**CFile**************************************************************** - - FileName [cecCorr.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Combinational equivalence checking.] - - Synopsis [Latch/signal correspondence computation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cecCorr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cecInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Gia_ManCorrSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes the real value of the literal w/o spec reduction.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Gia_ManCorrSpecReal( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix ) -{ - if ( Gia_ObjIsAnd(pObj) ) - { - Gia_ManCorrSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj), f, nPrefix ); - Gia_ManCorrSpecReduce_rec( pNew, p, Gia_ObjFanin1(pObj), f, nPrefix ); - return Gia_ManHashAnd( pNew, Gia_ObjFanin0CopyF(p, f, pObj), Gia_ObjFanin1CopyF(p, f, pObj) ); - } - if ( f == 0 ) - { - assert( Gia_ObjIsRo(p, pObj) ); - return Gia_ObjCopyF(p, f, pObj); - } - assert( f && Gia_ObjIsRo(p, pObj) ); - pObj = Gia_ObjRoToRi( p, pObj ); - Gia_ManCorrSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj), f-1, nPrefix ); - return Gia_ObjFanin0CopyF( p, f-1, pObj ); -} - -/**Function************************************************************* - - Synopsis [Recursively performs speculative reduction for the object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Gia_ManCorrSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix ) -{ - Gia_Obj_t * pRepr; - int iLitNew; - if ( ~Gia_ObjCopyF(p, f, pObj) ) - return; - if ( f >= nPrefix && (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) - { - Gia_ManCorrSpecReduce_rec( pNew, p, pRepr, f, nPrefix ); - iLitNew = Gia_LitNotCond( Gia_ObjCopyF(p, f, pRepr), Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); - Gia_ObjSetCopyF( p, f, pObj, iLitNew ); - return; - } - assert( Gia_ObjIsCand(pObj) ); - iLitNew = Gia_ManCorrSpecReal( pNew, p, pObj, f, nPrefix ); - Gia_ObjSetCopyF( p, f, pObj, iLitNew ); -} - -/**Function************************************************************* - - Synopsis [Derives SRM for signal correspondence.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Gia_Man_t * Gia_ManCorrSpecReduce( Gia_Man_t * p, int nFrames, int fScorr, Vec_Int_t ** pvOutputs, int fRings ) -{ - Gia_Man_t * pNew, * pTemp; - Gia_Obj_t * pObj, * pRepr; - Vec_Int_t * vXorLits; - int f, i, iPrev, iObj, iPrevNew, iObjNew; - assert( nFrames > 0 ); - assert( Gia_ManRegNum(p) > 0 ); - assert( p->pReprs != NULL ); - p->pCopies = ABC_FALLOC( int, (nFrames+fScorr)*Gia_ManObjNum(p) ); - Gia_ManSetPhase( p ); - pNew = Gia_ManStart( nFrames * Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); - Gia_ManHashAlloc( pNew ); - Gia_ObjSetCopyF( p, 0, Gia_ManConst0(p), 0 ); - Gia_ManForEachRo( p, pObj, i ) - Gia_ObjSetCopyF( p, 0, pObj, Gia_ManAppendCi(pNew) ); - Gia_ManForEachRo( p, pObj, i ) - if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) - Gia_ObjSetCopyF( p, 0, pObj, Gia_ObjCopyF(p, 0, pRepr) ); - for ( f = 0; f < nFrames+fScorr; f++ ) - { - Gia_ObjSetCopyF( p, f, Gia_ManConst0(p), 0 ); - Gia_ManForEachPi( p, pObj, i ) - Gia_ObjSetCopyF( p, f, pObj, Gia_ManAppendCi(pNew) ); - } - *pvOutputs = Vec_IntAlloc( 1000 ); - vXorLits = Vec_IntAlloc( 1000 ); - if ( fRings ) - { - Gia_ManForEachObj1( p, pObj, i ) - { - if ( Gia_ObjIsConst( p, i ) ) - { - iObjNew = Gia_ManCorrSpecReal( pNew, p, pObj, nFrames, 0 ); - iObjNew = Gia_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ); - if ( iObjNew != 0 ) - { - Vec_IntPush( *pvOutputs, 0 ); - Vec_IntPush( *pvOutputs, i ); - Vec_IntPush( vXorLits, iObjNew ); - } - } - else if ( Gia_ObjIsHead( p, i ) ) - { - iPrev = i; - Gia_ClassForEachObj1( p, i, iObj ) - { - iPrevNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iPrev), nFrames, 0 ); - iObjNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iObj), nFrames, 0 ); - iPrevNew = Gia_LitNotCond( iPrevNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) ); - iObjNew = Gia_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) ); - if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 ) - { - Vec_IntPush( *pvOutputs, iPrev ); - Vec_IntPush( *pvOutputs, iObj ); - Vec_IntPush( vXorLits, Gia_ManHashAnd(pNew, iPrevNew, Gia_LitNot(iObjNew)) ); - } - iPrev = iObj; - } - iObj = i; - iPrevNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iPrev), nFrames, 0 ); - iObjNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iObj), nFrames, 0 ); - iPrevNew = Gia_LitNotCond( iPrevNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) ); - iObjNew = Gia_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) ); - if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 ) - { - Vec_IntPush( *pvOutputs, iPrev ); - Vec_IntPush( *pvOutputs, iObj ); - Vec_IntPush( vXorLits, Gia_ManHashAnd(pNew, iPrevNew, Gia_LitNot(iObjNew)) ); - } - } - } - } - else - { - Gia_ManForEachObj1( p, pObj, i ) - { - pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); - if ( pRepr == NULL ) - continue; - iPrevNew = Gia_ObjIsConst(p, i)? 0 : Gia_ManCorrSpecReal( pNew, p, pRepr, nFrames, 0 ); - iObjNew = Gia_ManCorrSpecReal( pNew, p, pObj, nFrames, 0 ); - iObjNew = Gia_LitNotCond( iObjNew, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); - if ( iPrevNew != iObjNew ) - { - Vec_IntPush( *pvOutputs, Gia_ObjId(p, pRepr) ); - Vec_IntPush( *pvOutputs, Gia_ObjId(p, pObj) ); - Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, iPrevNew, iObjNew) ); - } - } - } - Vec_IntForEachEntry( vXorLits, iObjNew, i ) - Gia_ManAppendCo( pNew, iObjNew ); - Vec_IntFree( vXorLits ); - Gia_ManHashStop( pNew ); - ABC_FREE( p->pCopies ); -//Abc_Print( 1, "Before sweeping = %d\n", Gia_ManAndNum(pNew) ); - pNew = Gia_ManCleanup( pTemp = pNew ); -//Abc_Print( 1, "After sweeping = %d\n", Gia_ManAndNum(pNew) ); - Gia_ManStop( pTemp ); - return pNew; -} - - -/**Function************************************************************* - - Synopsis [Derives SRM for signal correspondence.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Gia_Man_t * Gia_ManCorrSpecReduceInit( Gia_Man_t * p, int nFrames, int nPrefix, int fScorr, Vec_Int_t ** pvOutputs, int fRings ) -{ - Gia_Man_t * pNew, * pTemp; - Gia_Obj_t * pObj, * pRepr; - Vec_Int_t * vXorLits; - int f, i, iPrevNew, iObjNew; - assert( (!fScorr && nFrames > 1) || (fScorr && nFrames > 0) || nPrefix ); - assert( Gia_ManRegNum(p) > 0 ); - assert( p->pReprs != NULL ); - p->pCopies = ABC_FALLOC( int, (nFrames+nPrefix+fScorr)*Gia_ManObjNum(p) ); - Gia_ManSetPhase( p ); - pNew = Gia_ManStart( (nFrames+nPrefix) * Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); - Gia_ManHashAlloc( pNew ); - Gia_ManForEachRo( p, pObj, i ) - { - Gia_ManAppendCi(pNew); - Gia_ObjSetCopyF( p, 0, pObj, 0 ); - } - for ( f = 0; f < nFrames+nPrefix+fScorr; f++ ) - { - Gia_ObjSetCopyF( p, f, Gia_ManConst0(p), 0 ); - Gia_ManForEachPi( p, pObj, i ) - Gia_ObjSetCopyF( p, f, pObj, Gia_ManAppendCi(pNew) ); - } - *pvOutputs = Vec_IntAlloc( 1000 ); - vXorLits = Vec_IntAlloc( 1000 ); - for ( f = nPrefix; f < nFrames+nPrefix; f++ ) - { - Gia_ManForEachObj1( p, pObj, i ) - { - pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); - if ( pRepr == NULL ) - continue; - iPrevNew = Gia_ObjIsConst(p, i)? 0 : Gia_ManCorrSpecReal( pNew, p, pRepr, f, nPrefix ); - iObjNew = Gia_ManCorrSpecReal( pNew, p, pObj, f, nPrefix ); - iObjNew = Gia_LitNotCond( iObjNew, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); - if ( iPrevNew != iObjNew ) - { - Vec_IntPush( *pvOutputs, Gia_ObjId(p, pRepr) ); - Vec_IntPush( *pvOutputs, Gia_ObjId(p, pObj) ); - Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, iPrevNew, iObjNew) ); - } - } - } - Vec_IntForEachEntry( vXorLits, iObjNew, i ) - Gia_ManAppendCo( pNew, iObjNew ); - Vec_IntFree( vXorLits ); - Gia_ManHashStop( pNew ); - ABC_FREE( p->pCopies ); -//Abc_Print( 1, "Before sweeping = %d\n", Gia_ManAndNum(pNew) ); - pNew = Gia_ManCleanup( pTemp = pNew ); -//Abc_Print( 1, "After sweeping = %d\n", Gia_ManAndNum(pNew) ); - Gia_ManStop( pTemp ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Initializes simulation info for lcorr/scorr counter-examples.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManStartSimInfo( Vec_Ptr_t * vInfo, int nFlops ) -{ - unsigned * pInfo; - int k, w, nWords; - nWords = Vec_PtrReadWordsSimInfo( vInfo ); - assert( nFlops <= Vec_PtrSize(vInfo) ); - for ( k = 0; k < nFlops; k++ ) - { - pInfo = (unsigned *)Vec_PtrEntry( vInfo, k ); - for ( w = 0; w < nWords; w++ ) - pInfo[w] = 0; - } - for ( k = nFlops; k < Vec_PtrSize(vInfo); k++ ) - { - pInfo = (unsigned *)Vec_PtrEntry( vInfo, k ); - for ( w = 0; w < nWords; w++ ) - pInfo[w] = Gia_ManRandom( 0 ); - } -} - -/**Function************************************************************* - - Synopsis [Remaps simulation info from SRM to the original AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Gia_ManCorrRemapSimInfo( Gia_Man_t * p, Vec_Ptr_t * vInfo ) -{ - Gia_Obj_t * pObj, * pRepr; - unsigned * pInfoObj, * pInfoRepr; - int i, w, nWords; - nWords = Vec_PtrReadWordsSimInfo( vInfo ); - Gia_ManForEachRo( p, pObj, i ) - { - // skip ROs without representatives - pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); - if ( pRepr == NULL || Gia_ObjFailed(p, Gia_ObjId(p,pObj)) ) - continue; - pInfoObj = (unsigned *)Vec_PtrEntry( vInfo, i ); - for ( w = 0; w < nWords; w++ ) - assert( pInfoObj[w] == 0 ); - // skip ROs with constant representatives - if ( Gia_ObjIsConst0(pRepr) ) - continue; - assert( Gia_ObjIsRo(p, pRepr) ); -// Abc_Print( 1, "%d -> %d ", i, Gia_ObjId(p, pRepr) ); - // transfer info from the representative - pInfoRepr = (unsigned *)Vec_PtrEntry( vInfo, Gia_ObjCioId(pRepr) - Gia_ManPiNum(p) ); - for ( w = 0; w < nWords; w++ ) - pInfoObj[w] = pInfoRepr[w]; - } -// Abc_Print( 1, "\n" ); -} - -/**Function************************************************************* - - Synopsis [Collects information about remapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Gia_ManCorrCreateRemapping( Gia_Man_t * p ) -{ - Vec_Int_t * vPairs; - Gia_Obj_t * pObj, * pRepr; - int i; - vPairs = Vec_IntAlloc( 100 ); - Gia_ManForEachRo( p, pObj, i ) - { - // skip ROs without representatives - pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); - if ( pRepr == NULL || Gia_ObjIsConst0(pRepr) || Gia_ObjFailed(p, Gia_ObjId(p,pObj)) ) -// if ( pRepr == NULL || Gia_ObjIsConst0(pRepr) || Gia_ObjIsFailedPair(p, Gia_ObjId(p, pRepr), Gia_ObjId(p, pObj)) ) - continue; - assert( Gia_ObjIsRo(p, pRepr) ); -// Abc_Print( 1, "%d -> %d ", Gia_ObjId(p,pObj), Gia_ObjId(p, pRepr) ); - // remember the pair - Vec_IntPush( vPairs, Gia_ObjCioId(pRepr) - Gia_ManPiNum(p) ); - Vec_IntPush( vPairs, i ); - } - return vPairs; -} - -/**Function************************************************************* - - Synopsis [Remaps simulation info from SRM to the original AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Gia_ManCorrPerformRemapping( Vec_Int_t * vPairs, Vec_Ptr_t * vInfo ) -{ - unsigned * pInfoObj, * pInfoRepr; - int w, i, iObj, iRepr, nWords; - nWords = Vec_PtrReadWordsSimInfo( vInfo ); - Vec_IntForEachEntry( vPairs, iRepr, i ) - { - iObj = Vec_IntEntry( vPairs, ++i ); - pInfoObj = (unsigned *)Vec_PtrEntry( vInfo, iObj ); - pInfoRepr = (unsigned *)Vec_PtrEntry( vInfo, iRepr ); - for ( w = 0; w < nWords; w++ ) - { - assert( pInfoObj[w] == 0 ); - pInfoObj[w] = pInfoRepr[w]; - } - } -} - -/**Function************************************************************* - - Synopsis [Packs one counter-examples into the array of simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -*************************************`**********************************/ -int Cec_ManLoadCounterExamplesTry( Vec_Ptr_t * vInfo, Vec_Ptr_t * vPres, int iBit, int * pLits, int nLits ) -{ - unsigned * pInfo, * pPres; - int i; - for ( i = 0; i < nLits; i++ ) - { - pInfo = (unsigned *)Vec_PtrEntry(vInfo, Gia_Lit2Var(pLits[i])); - pPres = (unsigned *)Vec_PtrEntry(vPres, Gia_Lit2Var(pLits[i])); - if ( Gia_InfoHasBit( pPres, iBit ) && - Gia_InfoHasBit( pInfo, iBit ) == Gia_LitIsCompl(pLits[i]) ) - return 0; - } - for ( i = 0; i < nLits; i++ ) - { - pInfo = (unsigned *)Vec_PtrEntry(vInfo, Gia_Lit2Var(pLits[i])); - pPres = (unsigned *)Vec_PtrEntry(vPres, Gia_Lit2Var(pLits[i])); - Gia_InfoSetBit( pPres, iBit ); - if ( Gia_InfoHasBit( pInfo, iBit ) == Gia_LitIsCompl(pLits[i]) ) - Gia_InfoXorBit( pInfo, iBit ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Performs bitpacking of counter-examples.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManLoadCounterExamples( Vec_Ptr_t * vInfo, Vec_Int_t * vCexStore, int iStart ) -{ - Vec_Int_t * vPat; - Vec_Ptr_t * vPres; - int nWords = Vec_PtrReadWordsSimInfo(vInfo); - int nBits = 32 * nWords; - int k, nSize, iBit = 1, kMax = 0; - vPat = Vec_IntAlloc( 100 ); - vPres = Vec_PtrAllocSimInfo( Vec_PtrSize(vInfo), nWords ); - Vec_PtrCleanSimInfo( vPres, 0, nWords ); - while ( iStart < Vec_IntSize(vCexStore) ) - { - // skip the output number - iStart++; - // get the number of items - nSize = Vec_IntEntry( vCexStore, iStart++ ); - if ( nSize <= 0 ) - continue; - // extract pattern - Vec_IntClear( vPat ); - for ( k = 0; k < nSize; k++ ) - Vec_IntPush( vPat, Vec_IntEntry( vCexStore, iStart++ ) ); - // add pattern to storage - for ( k = 1; k < nBits; k++ ) - if ( Cec_ManLoadCounterExamplesTry( vInfo, vPres, k, (int *)Vec_IntArray(vPat), Vec_IntSize(vPat) ) ) - break; - kMax = ABC_MAX( kMax, k ); - if ( k == nBits-1 ) - break; - } - Vec_PtrFree( vPres ); - Vec_IntFree( vPat ); - return iStart; -} - -/**Function************************************************************* - - Synopsis [Performs bitpacking of counter-examples.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManLoadCounterExamples2( Vec_Ptr_t * vInfo, Vec_Int_t * vCexStore, int iStart ) -{ - unsigned * pInfo; - int nBits = 32 * Vec_PtrReadWordsSimInfo(vInfo); - int k, iLit, nLits, Out, iBit = 1; - while ( iStart < Vec_IntSize(vCexStore) ) - { - // skip the output number -// iStart++; - Out = Vec_IntEntry( vCexStore, iStart++ ); -// Abc_Print( 1, "iBit = %d. Out = %d.\n", iBit, Out ); - // get the number of items - nLits = Vec_IntEntry( vCexStore, iStart++ ); - if ( nLits <= 0 ) - continue; - // add pattern to storage - for ( k = 0; k < nLits; k++ ) - { - iLit = Vec_IntEntry( vCexStore, iStart++ ); - pInfo = (unsigned *)Vec_PtrEntry( vInfo, Gia_Lit2Var(iLit) ); - if ( Gia_InfoHasBit( pInfo, iBit ) == Gia_LitIsCompl(iLit) ) - Gia_InfoXorBit( pInfo, iBit ); - } - if ( ++iBit == nBits ) - break; - } -// Abc_Print( 1, "added %d bits\n", iBit-1 ); - return iStart; -} - -/**Function************************************************************* - - Synopsis [Resimulates counter-examples derived by the SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManResimulateCounterExamples( Cec_ManSim_t * pSim, Vec_Int_t * vCexStore, int nFrames ) -{ - Vec_Int_t * vPairs; - Vec_Ptr_t * vSimInfo; - int RetValue = 0, iStart = 0; - vPairs = Gia_ManCorrCreateRemapping( pSim->pAig ); - Gia_ManSetRefs( pSim->pAig ); -// pSim->pPars->nWords = 63; - pSim->pPars->nFrames = nFrames; - vSimInfo = Vec_PtrAllocSimInfo( Gia_ManRegNum(pSim->pAig) + Gia_ManPiNum(pSim->pAig) * nFrames, pSim->pPars->nWords ); - while ( iStart < Vec_IntSize(vCexStore) ) - { - Cec_ManStartSimInfo( vSimInfo, Gia_ManRegNum(pSim->pAig) ); - iStart = Cec_ManLoadCounterExamples( vSimInfo, vCexStore, iStart ); -// iStart = Cec_ManLoadCounterExamples2( vSimInfo, vCexStore, iStart ); -// Gia_ManCorrRemapSimInfo( pSim->pAig, vSimInfo ); - Gia_ManCorrPerformRemapping( vPairs, vSimInfo ); - RetValue |= Cec_ManSeqResimulate( pSim, vSimInfo ); -// Cec_ManSeqResimulateInfo( pSim->pAig, vSimInfo, NULL ); - } -//Gia_ManEquivPrintOne( pSim->pAig, 85, 0 ); - assert( iStart == Vec_IntSize(vCexStore) ); - Vec_PtrFree( vSimInfo ); - Vec_IntFree( vPairs ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Resimulates counter-examples derived by the SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManResimulateCounterExamplesComb( Cec_ManSim_t * pSim, Vec_Int_t * vCexStore ) -{ - Vec_Ptr_t * vSimInfo; - int RetValue = 0, iStart = 0; - Gia_ManSetRefs( pSim->pAig ); - pSim->pPars->nFrames = 1; - vSimInfo = Vec_PtrAllocSimInfo( Gia_ManCiNum(pSim->pAig), pSim->pPars->nWords ); - while ( iStart < Vec_IntSize(vCexStore) ) - { - Cec_ManStartSimInfo( vSimInfo, 0 ); - iStart = Cec_ManLoadCounterExamples( vSimInfo, vCexStore, iStart ); - RetValue |= Cec_ManSeqResimulate( pSim, vSimInfo ); - } - assert( iStart == Vec_IntSize(vCexStore) ); - Vec_PtrFree( vSimInfo ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Updates equivalence classes by marking those that timed out.] - - Description [Returns 1 if all ndoes are proved.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Gia_ManCheckRefinements( Gia_Man_t * p, Vec_Str_t * vStatus, Vec_Int_t * vOutputs, Cec_ManSim_t * pSim, int fRings ) -{ - int i, status, iRepr, iObj; - int Counter = 0; - assert( 2 * Vec_StrSize(vStatus) == Vec_IntSize(vOutputs) ); - Vec_StrForEachEntry( vStatus, status, i ) - { - iRepr = Vec_IntEntry( vOutputs, 2*i ); - iObj = Vec_IntEntry( vOutputs, 2*i+1 ); - if ( status == 1 ) - continue; - if ( status == 0 ) - { - if ( Gia_ObjHasSameRepr(p, iRepr, iObj) ) - Counter++; -// if ( Gia_ObjHasSameRepr(p, iRepr, iObj) ) -// Abc_Print( 1, "Gia_ManCheckRefinements(): Disproved equivalence (%d,%d) is not refined!\n", iRepr, iObj ); -// if ( Gia_ObjHasSameRepr(p, iRepr, iObj) ) -// Cec_ManSimClassRemoveOne( pSim, iObj ); - continue; - } - if ( status == -1 ) - { -// if ( !Gia_ObjFailed( p, iObj ) ) -// Abc_Print( 1, "Gia_ManCheckRefinements(): Failed equivalence is not marked as failed!\n" ); -// Gia_ObjSetFailed( p, iRepr ); -// Gia_ObjSetFailed( p, iObj ); -// if ( fRings ) -// Cec_ManSimClassRemoveOne( pSim, iRepr ); - Cec_ManSimClassRemoveOne( pSim, iObj ); - continue; - } - } -// if ( Counter ) -// Abc_Print( 1, "Gia_ManCheckRefinements(): Could not refine %d nodes.\n", Counter ); - return 1; -} - - -/**Function************************************************************* - - Synopsis [Duplicates the AIG in the DFS order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Gia_ManCorrReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) -{ - Gia_Obj_t * pRepr; - if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) - { - Gia_ManCorrReduce_rec( pNew, p, pRepr ); - pObj->Value = Gia_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); - return; - } - if ( ~pObj->Value ) - return; - assert( Gia_ObjIsAnd(pObj) ); - Gia_ManCorrReduce_rec( pNew, p, Gia_ObjFanin0(pObj) ); - Gia_ManCorrReduce_rec( pNew, p, Gia_ObjFanin1(pObj) ); - pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Reduces AIG using equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Gia_Man_t * Gia_ManCorrReduce( Gia_Man_t * p ) -{ - Gia_Man_t * pNew; - Gia_Obj_t * pObj; - int i; - Gia_ManSetPhase( p ); - pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); - Gia_ManFillValue( p ); - Gia_ManConst0(p)->Value = 0; - Gia_ManForEachCi( p, pObj, i ) - pObj->Value = Gia_ManAppendCi(pNew); - Gia_ManHashAlloc( pNew ); - Gia_ManForEachCo( p, pObj, i ) - Gia_ManCorrReduce_rec( pNew, p, Gia_ObjFanin0(pObj) ); - Gia_ManForEachCo( p, pObj, i ) - Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); - Gia_ManHashStop( pNew ); - Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); - return pNew; -} - - -/**Function************************************************************* - - Synopsis [Prints statistics during solving.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManRefinedClassPrintStats( Gia_Man_t * p, Vec_Str_t * vStatus, int iIter, int Time ) -{ - int nLits, CounterX = 0, Counter0 = 0, Counter = 0; - int i, Entry, nProve = 0, nDispr = 0, nFail = 0; - for ( i = 1; i < Gia_ManObjNum(p); i++ ) - { - if ( Gia_ObjIsNone(p, i) ) - CounterX++; - else if ( Gia_ObjIsConst(p, i) ) - Counter0++; - else if ( Gia_ObjIsHead(p, i) ) - Counter++; - } - CounterX -= Gia_ManCoNum(p); - nLits = Gia_ManCiNum(p) + Gia_ManAndNum(p) - Counter - CounterX; - if ( iIter == -1 ) - Abc_Print( 1, "BMC : " ); - else - Abc_Print( 1, "%3d : ", iIter ); - Abc_Print( 1, "c =%8d cl =%7d lit =%8d ", Counter0, Counter, nLits ); - if ( vStatus ) - Vec_StrForEachEntry( vStatus, Entry, i ) - { - if ( Entry == 1 ) - nProve++; - else if ( Entry == 0 ) - nDispr++; - else if ( Entry == -1 ) - nFail++; - } - Abc_Print( 1, "p =%6d d =%6d f =%6d ", nProve, nDispr, nFail ); - Abc_PrintTime( 1, "T", Time ); -} - -/**Function************************************************************* - - Synopsis [Runs BMC for the equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManLSCorrespondenceBmc( Gia_Man_t * pAig, Cec_ParCor_t * pPars, int nPrefs ) -{ - Cec_ParSim_t ParsSim, * pParsSim = &ParsSim; - Cec_ParSat_t ParsSat, * pParsSat = &ParsSat; - Vec_Str_t * vStatus; - Vec_Int_t * vOutputs; - Vec_Int_t * vCexStore; - Cec_ManSim_t * pSim; - Gia_Man_t * pSrm; - int fChanges, RetValue; - // prepare simulation manager - Cec_ManSimSetDefaultParams( pParsSim ); - pParsSim->nWords = pPars->nWords; - pParsSim->nFrames = pPars->nRounds; - pParsSim->fVerbose = pPars->fVerbose; - pParsSim->fLatchCorr = pPars->fLatchCorr; - pParsSim->fSeqSimulate = 1; - pSim = Cec_ManSimStart( pAig, pParsSim ); - // prepare SAT solving - Cec_ManSatSetDefaultParams( pParsSat ); - pParsSat->nBTLimit = pPars->nBTLimit; - pParsSat->fVerbose = pPars->fVerbose; - fChanges = 1; - while ( fChanges ) - { - int clkBmc = clock(); - fChanges = 0; - pSrm = Gia_ManCorrSpecReduceInit( pAig, pPars->nFrames, nPrefs, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings ); - if ( Gia_ManPoNum(pSrm) == 0 ) - { - Gia_ManStop( pSrm ); - Vec_IntFree( vOutputs ); - break; - } - pParsSat->nBTLimit *= 10; - if ( pPars->fUseCSat ) - vCexStore = Tas_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0 ); - else - vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus ); - // refine classes with these counter-examples - if ( Vec_IntSize(vCexStore) ) - { - RetValue = Cec_ManResimulateCounterExamples( pSim, vCexStore, pPars->nFrames + 1 + nPrefs ); - Gia_ManCheckRefinements( pAig, vStatus, vOutputs, pSim, pPars->fUseRings ); - fChanges = 1; - } - if ( pPars->fVerbose ) - Cec_ManRefinedClassPrintStats( pAig, vStatus, -1, clock() - clkBmc ); - // recycle - Vec_IntFree( vCexStore ); - Vec_StrFree( vStatus ); - Gia_ManStop( pSrm ); - Vec_IntFree( vOutputs ); - } - Cec_ManSimStop( pSim ); -} - -/**Function************************************************************* - - Synopsis [Internal procedure for register correspondence.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars ) -{ - int nIterMax = 100000; - int nAddFrames = 1; // additional timeframes to simulate - int fRunBmcFirst = 1; - Vec_Str_t * vStatus; - Vec_Int_t * vOutputs; - Vec_Int_t * vCexStore; - Cec_ParSim_t ParsSim, * pParsSim = &ParsSim; - Cec_ParSat_t ParsSat, * pParsSat = &ParsSat; - Cec_ManSim_t * pSim; - Gia_Man_t * pSrm; - int r, RetValue, clkTotal = clock(); - int clkSat = 0, clkSim = 0, clkSrm = 0; - int clk2, clk = clock(); - if ( Gia_ManRegNum(pAig) == 0 ) - { - Abc_Print( 1, "Cec_ManLatchCorrespondence(): Not a sequential AIG.\n" ); - return 0; - } - Gia_ManRandom( 1 ); - // prepare simulation manager - Cec_ManSimSetDefaultParams( pParsSim ); - pParsSim->nWords = pPars->nWords; - pParsSim->nFrames = pPars->nFrames; - pParsSim->fVerbose = pPars->fVerbose; - pParsSim->fLatchCorr = pPars->fLatchCorr; - pParsSim->fConstCorr = pPars->fConstCorr; - pParsSim->fSeqSimulate = 1; - // create equivalence classes of registers - pSim = Cec_ManSimStart( pAig, pParsSim ); - if ( pAig->pReprs == NULL ) - { - Cec_ManSimClassesPrepare( pSim, pPars->nLevelMax ); - Cec_ManSimClassesRefine( pSim ); - } - // prepare SAT solving - Cec_ManSatSetDefaultParams( pParsSat ); - pParsSat->nBTLimit = pPars->nBTLimit; - pParsSat->fVerbose = pPars->fVerbose; - if ( pPars->fVerbose ) - { - Abc_Print( 1, "Obj = %7d. And = %7d. Conf = %5d. Fr = %d. Lcorr = %d. Ring = %d. CSat = %d.\n", - Gia_ManObjNum(pAig), Gia_ManAndNum(pAig), - pPars->nBTLimit, pPars->nFrames, pPars->fLatchCorr, pPars->fUseRings, pPars->fUseCSat ); - Cec_ManRefinedClassPrintStats( pAig, NULL, 0, clock() - clk ); - } - // check the base case - if ( fRunBmcFirst && (!pPars->fLatchCorr || pPars->nFrames > 1) ) - Cec_ManLSCorrespondenceBmc( pAig, pPars, 0 ); - if ( pPars->pFunc ) - { - ((int (*)(void *))pPars->pFunc)( pPars->pData ); - ((int (*)(void *))pPars->pFunc)( pPars->pData ); - } - if ( pPars->nStepsMax == 0 ) - { - Abc_Print( 1, "Stopped signal correspondence after BMC.\n" ); - Cec_ManSimStop( pSim ); - return 1; - } - // perform refinement of equivalence classes - for ( r = 0; r < nIterMax; r++ ) - { - if ( pPars->nStepsMax == r ) - { - Cec_ManSimStop( pSim ); - Abc_Print( 1, "Stopped signal correspondence after %d refiment iterations.\n", r ); - return 1; - } - clk = clock(); - // perform speculative reduction - clk2 = clock(); - pSrm = Gia_ManCorrSpecReduce( pAig, pPars->nFrames, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings ); - assert( Gia_ManRegNum(pSrm) == 0 && Gia_ManPiNum(pSrm) == Gia_ManRegNum(pAig)+(pPars->nFrames+!pPars->fLatchCorr)*Gia_ManPiNum(pAig) ); - clkSrm += clock() - clk2; - if ( Gia_ManCoNum(pSrm) == 0 ) - { - Vec_IntFree( vOutputs ); - Gia_ManStop( pSrm ); - break; - } -//Gia_DumpAiger( pSrm, "corrsrm", r, 2 ); - // found counter-examples to speculation - clk2 = clock(); - if ( pPars->fUseCSat ) - vCexStore = Cbs_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0 ); - else - vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus ); - Gia_ManStop( pSrm ); - clkSat += clock() - clk2; - if ( Vec_IntSize(vCexStore) == 0 ) - { - Vec_IntFree( vCexStore ); - Vec_StrFree( vStatus ); - Vec_IntFree( vOutputs ); - break; - } - // refine classes with these counter-examples - clk2 = clock(); - RetValue = Cec_ManResimulateCounterExamples( pSim, vCexStore, pPars->nFrames + 1 + nAddFrames ); - Vec_IntFree( vCexStore ); - clkSim += clock() - clk2; - Gia_ManCheckRefinements( pAig, vStatus, vOutputs, pSim, pPars->fUseRings ); - if ( pPars->fVerbose ) - Cec_ManRefinedClassPrintStats( pAig, vStatus, r+1, clock() - clk ); - Vec_StrFree( vStatus ); - Vec_IntFree( vOutputs ); -//Gia_ManEquivPrintClasses( pAig, 1, 0 ); - if ( pPars->pFunc ) - ((int (*)(void *))pPars->pFunc)( pPars->pData ); - } - if ( pPars->fVerbose ) - Cec_ManRefinedClassPrintStats( pAig, NULL, r+1, clock() - clk ); - // check the overflow - if ( r == nIterMax ) - Abc_Print( 1, "The refinement was not finished. The result may be incorrect.\n" ); - Cec_ManSimStop( pSim ); - // check the base case - if ( !fRunBmcFirst && (!pPars->fLatchCorr || pPars->nFrames > 1) ) - Cec_ManLSCorrespondenceBmc( pAig, pPars, 0 ); - clkTotal = clock() - clkTotal; - // report the results - if ( pPars->fVerbose ) - { - ABC_PRTP( "Srm ", clkSrm, clkTotal ); - ABC_PRTP( "Sat ", clkSat, clkTotal ); - ABC_PRTP( "Sim ", clkSim, clkTotal ); - ABC_PRTP( "Other", clkTotal-clkSat-clkSrm-clkSim, clkTotal ); - Abc_PrintTime( 1, "TOTAL", clkTotal ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Computes new initial state.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Cec_ManComputeInitState( Gia_Man_t * pAig, int nFrames ) -{ - Gia_Obj_t * pObj, * pObjRo, * pObjRi; - unsigned * pInitState; - int i, f; - Gia_ManRandom( 1 ); -// Abc_Print( 1, "Simulating %d timeframes.\n", nFrames ); - Gia_ManForEachRo( pAig, pObj, i ) - pObj->fMark1 = 0; - for ( f = 0; f < nFrames; f++ ) - { - Gia_ManConst0(pAig)->fMark1 = 0; - Gia_ManForEachPi( pAig, pObj, i ) - pObj->fMark1 = Gia_ManRandom(0) & 1; - Gia_ManForEachAnd( pAig, pObj, i ) - pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) & - (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj)); - Gia_ManForEachRi( pAig, pObj, i ) - pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)); - Gia_ManForEachRiRo( pAig, pObjRi, pObjRo, i ) - pObjRo->fMark1 = pObjRi->fMark1; - } - pInitState = ABC_CALLOC( unsigned, Gia_BitWordNum(Gia_ManRegNum(pAig)) ); - Gia_ManForEachRo( pAig, pObj, i ) - { - if ( pObj->fMark1 ) - Gia_InfoSetBit( pInitState, i ); -// Abc_Print( 1, "%d", pObj->fMark1 ); - } -// Abc_Print( 1, "\n" ); - Gia_ManCleanMark1( pAig ); - return pInitState; -} - -/**Function************************************************************* - - Synopsis [Prints flop equivalences.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManPrintFlopEquivs( Gia_Man_t * p ) -{ - Gia_Obj_t * pObj, * pRepr; - int i; - assert( p->vNamesIn != NULL ); - Gia_ManForEachRo( p, pObj, i ) - { - if ( Gia_ObjIsConst(p, Gia_ObjId(p, pObj)) ) - Abc_Print( 1, "Original flop %s is proved equivalent to constant.\n", Vec_PtrEntry(p->vNamesIn, Gia_ObjCioId(pObj)) ); - else if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) - { - if ( Gia_ObjIsCi(pRepr) ) - Abc_Print( 1, "Original flop %s is proved equivalent to flop %s.\n", - Vec_PtrEntry( p->vNamesIn, Gia_ObjCioId(pObj) ), - Vec_PtrEntry( p->vNamesIn, Gia_ObjCioId(pRepr) ) ); - else - Abc_Print( 1, "Original flop %s is proved equivalent to internal node %d.\n", - Vec_PtrEntry( p->vNamesIn, Gia_ObjCioId(pObj) ), Gia_ObjId(p, pRepr) ); - } - } -} - - -/**Function************************************************************* - - Synopsis [Top-level procedure for register correspondence.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Gia_Man_t * Cec_ManLSCorrespondence( Gia_Man_t * pAig, Cec_ParCor_t * pPars ) -{ - Gia_Man_t * pNew, * pTemp; - unsigned * pInitState; - int RetValue; - ABC_FREE( pAig->pReprs ); - ABC_FREE( pAig->pNexts ); - if ( pPars->nPrefix == 0 ) - RetValue = Cec_ManLSCorrespondenceClasses( pAig, pPars ); - else - { - // compute the cycles AIG - pInitState = Cec_ManComputeInitState( pAig, pPars->nPrefix ); - pTemp = Gia_ManDupFlip( pAig, (int *)pInitState ); - ABC_FREE( pInitState ); - // compute classes of this AIG - RetValue = Cec_ManLSCorrespondenceClasses( pTemp, pPars ); - // transfer the class info - pAig->pReprs = pTemp->pReprs; pTemp->pReprs = NULL; - pAig->pNexts = pTemp->pNexts; pTemp->pNexts = NULL; - // perform additional BMC - pPars->fUseCSat = 0; - pPars->nBTLimit = ABC_MAX( pPars->nBTLimit, 1000 ); - Cec_ManLSCorrespondenceBmc( pAig, pPars, pPars->nPrefix ); -/* - // transfer the class info back - pTemp->pReprs = pAig->pReprs; pAig->pReprs = NULL; - pTemp->pNexts = pAig->pNexts; pAig->pNexts = NULL; - // continue refining - RetValue = Cec_ManLSCorrespondenceClasses( pTemp, pPars ); - // transfer the class info - pAig->pReprs = pTemp->pReprs; pTemp->pReprs = NULL; - pAig->pNexts = pTemp->pNexts; pTemp->pNexts = NULL; -*/ - Gia_ManStop( pTemp ); - } - // derive reduced AIG - if ( pPars->fMakeChoices ) - { - pNew = Gia_ManEquivToChoices( pAig, 1 ); - Gia_ManHasChoices( pNew ); - } - else - { -// Gia_ManEquivImprove( pAig ); - pNew = Gia_ManCorrReduce( pAig ); - pNew = Gia_ManSeqCleanup( pTemp = pNew ); - Gia_ManStop( pTemp ); - //Gia_WriteAiger( pNew, "reduced.aig", 0, 0 ); - } - // report the results - if ( pPars->fVerbose ) - { - Abc_Print( 1, "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n", - Gia_ManAndNum(pAig), Gia_ManAndNum(pNew), - 100.0*(Gia_ManAndNum(pAig)-Gia_ManAndNum(pNew))/(Gia_ManAndNum(pAig)?Gia_ManAndNum(pAig):1), - Gia_ManRegNum(pAig), Gia_ManRegNum(pNew), - 100.0*(Gia_ManRegNum(pAig)-Gia_ManRegNum(pNew))/(Gia_ManRegNum(pAig)?Gia_ManRegNum(pAig):1) ); - } - if ( pPars->nPrefix && (Gia_ManAndNum(pNew) < Gia_ManAndNum(pAig) || Gia_ManRegNum(pNew) < Gia_ManRegNum(pAig)) ) - Abc_Print( 1, "The reduced AIG was produced using %d-th invariants and will not verify.\n", pPars->nPrefix ); - // print verbose info about equivalences - if ( pPars->fVerboseFlops ) - { - if ( pAig->vNamesIn == NULL ) - Abc_Print( 1, "Flop output names are not available. Use command \"&get -n\".\n" ); - else - Cec_ManPrintFlopEquivs( pAig ); - } - return pNew; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cec/cecCorr_updated.c b/src/aig/cec/cecCorr_updated.c deleted file mode 100644 index 8ce1bd74..00000000 --- a/src/aig/cec/cecCorr_updated.c +++ /dev/null @@ -1,1027 +0,0 @@ -/**CFile**************************************************************** - - FileName [cecCorr.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Combinational equivalence checking.] - - Synopsis [Latch/signal correspondence computation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cecCorr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cecInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Gia_ManCorrSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes the real value of the literal w/o spec reduction.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Gia_ManCorrSpecReal( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix ) -{ - if ( Gia_ObjIsAnd(pObj) ) - { - Gia_ManCorrSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj), f, nPrefix ); - Gia_ManCorrSpecReduce_rec( pNew, p, Gia_ObjFanin1(pObj), f, nPrefix ); - return Gia_ManHashAnd( pNew, Gia_ObjFanin0CopyF(p, f, pObj), Gia_ObjFanin1CopyF(p, f, pObj) ); - } - if ( f == 0 ) - { - assert( Gia_ObjIsRo(p, pObj) ); - return Gia_ObjCopyF(p, f, pObj); - } - assert( f && Gia_ObjIsRo(p, pObj) ); - pObj = Gia_ObjRoToRi( p, pObj ); - Gia_ManCorrSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj), f-1, nPrefix ); - return Gia_ObjFanin0CopyF( p, f-1, pObj ); -} - -/**Function************************************************************* - - Synopsis [Recursively performs speculative reduction for the object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Gia_ManCorrSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix ) -{ - Gia_Obj_t * pRepr; - int iLitNew; - if ( ~Gia_ObjCopyF(p, f, pObj) ) - return; - if ( f >= nPrefix && (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) - { - Gia_ManCorrSpecReduce_rec( pNew, p, pRepr, f, nPrefix ); - iLitNew = Gia_LitNotCond( Gia_ObjCopyF(p, f, pRepr), Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); - Gia_ObjSetCopyF( p, f, pObj, iLitNew ); - return; - } - assert( Gia_ObjIsCand(pObj) ); - iLitNew = Gia_ManCorrSpecReal( pNew, p, pObj, f, nPrefix ); - Gia_ObjSetCopyF( p, f, pObj, iLitNew ); -} - -/**Function************************************************************* - - Synopsis [Derives SRM for signal correspondence.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Gia_Man_t * Gia_ManCorrSpecReduce( Gia_Man_t * p, int nFrames, int fScorr, Vec_Int_t ** pvOutputs, int fRings ) -{ - Gia_Man_t * pNew, * pTemp; - Gia_Obj_t * pObj, * pRepr; - Vec_Int_t * vXorLits; - int f, i, iPrev, iObj, iPrevNew, iObjNew; - assert( nFrames > 0 ); - assert( Gia_ManRegNum(p) > 0 ); - assert( p->pReprs != NULL ); - p->pCopies = ABC_FALLOC( int, (nFrames+fScorr)*Gia_ManObjNum(p) ); - Gia_ManSetPhase( p ); - pNew = Gia_ManStart( nFrames * Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); - Gia_ManHashAlloc( pNew ); - Gia_ObjSetCopyF( p, 0, Gia_ManConst0(p), 0 ); - Gia_ManForEachRo( p, pObj, i ) - Gia_ObjSetCopyF( p, 0, pObj, Gia_ManAppendCi(pNew) ); - Gia_ManForEachRo( p, pObj, i ) - if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) - Gia_ObjSetCopyF( p, 0, pObj, Gia_ObjCopyF(p, 0, pRepr) ); - for ( f = 0; f < nFrames+fScorr; f++ ) - { - Gia_ObjSetCopyF( p, f, Gia_ManConst0(p), 0 ); - Gia_ManForEachPi( p, pObj, i ) - Gia_ObjSetCopyF( p, f, pObj, Gia_ManAppendCi(pNew) ); - } - *pvOutputs = Vec_IntAlloc( 1000 ); - vXorLits = Vec_IntAlloc( 1000 ); - if ( fRings ) - { - Gia_ManForEachObj1( p, pObj, i ) - { - if ( Gia_ObjIsConst( p, i ) ) - { - iObjNew = Gia_ManCorrSpecReal( pNew, p, pObj, nFrames, 0 ); - iObjNew = Gia_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ); - if ( iObjNew != 0 ) - { - Vec_IntPush( *pvOutputs, 0 ); - Vec_IntPush( *pvOutputs, i ); - Vec_IntPush( vXorLits, iObjNew ); - } - } - else if ( Gia_ObjIsHead( p, i ) ) - { - iPrev = i; - Gia_ClassForEachObj1( p, i, iObj ) - { - iPrevNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iPrev), nFrames, 0 ); - iObjNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iObj), nFrames, 0 ); - iPrevNew = Gia_LitNotCond( iPrevNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) ); - iObjNew = Gia_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) ); - if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 ) - { - Vec_IntPush( *pvOutputs, iPrev ); - Vec_IntPush( *pvOutputs, iObj ); - Vec_IntPush( vXorLits, Gia_ManHashAnd(pNew, iPrevNew, Gia_LitNot(iObjNew)) ); - } - iPrev = iObj; - } - iObj = i; - iPrevNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iPrev), nFrames, 0 ); - iObjNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iObj), nFrames, 0 ); - iPrevNew = Gia_LitNotCond( iPrevNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) ); - iObjNew = Gia_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) ); - if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 ) - { - Vec_IntPush( *pvOutputs, iPrev ); - Vec_IntPush( *pvOutputs, iObj ); - Vec_IntPush( vXorLits, Gia_ManHashAnd(pNew, iPrevNew, Gia_LitNot(iObjNew)) ); - } - } - } - } - else - { - Gia_ManForEachObj1( p, pObj, i ) - { - pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); - if ( pRepr == NULL ) - continue; - iPrevNew = Gia_ObjIsConst(p, i)? 0 : Gia_ManCorrSpecReal( pNew, p, pRepr, nFrames, 0 ); - iObjNew = Gia_ManCorrSpecReal( pNew, p, pObj, nFrames, 0 ); - iObjNew = Gia_LitNotCond( iObjNew, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); - if ( iPrevNew != iObjNew ) - { - Vec_IntPush( *pvOutputs, Gia_ObjId(p, pRepr) ); - Vec_IntPush( *pvOutputs, Gia_ObjId(p, pObj) ); - Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, iPrevNew, iObjNew) ); - } - } - } - Vec_IntForEachEntry( vXorLits, iObjNew, i ) - Gia_ManAppendCo( pNew, iObjNew ); - Vec_IntFree( vXorLits ); - Gia_ManHashStop( pNew ); - ABC_FREE( p->pCopies ); -//printf( "Before sweeping = %d\n", Gia_ManAndNum(pNew) ); - pNew = Gia_ManCleanup( pTemp = pNew ); -//printf( "After sweeping = %d\n", Gia_ManAndNum(pNew) ); - Gia_ManStop( pTemp ); - return pNew; -} - - -/**Function************************************************************* - - Synopsis [Derives SRM for signal correspondence.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Gia_Man_t * Gia_ManCorrSpecReduceInit( Gia_Man_t * p, int nFrames, int nPrefix, int fScorr, Vec_Int_t ** pvOutputs, int fRings ) -{ - Gia_Man_t * pNew, * pTemp; - Gia_Obj_t * pObj, * pRepr; - Vec_Int_t * vXorLits; - int f, i, iPrevNew, iObjNew; - assert( (!fScorr && nFrames > 1) || (fScorr && nFrames > 0) || nPrefix ); - assert( Gia_ManRegNum(p) > 0 ); - assert( p->pReprs != NULL ); - p->pCopies = ABC_FALLOC( int, (nFrames+nPrefix+fScorr)*Gia_ManObjNum(p) ); - Gia_ManSetPhase( p ); - pNew = Gia_ManStart( (nFrames+nPrefix) * Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); - Gia_ManHashAlloc( pNew ); - Gia_ManForEachRo( p, pObj, i ) - { - Gia_ManAppendCi(pNew); - Gia_ObjSetCopyF( p, 0, pObj, 0 ); - } - for ( f = 0; f < nFrames+nPrefix+fScorr; f++ ) - { - Gia_ObjSetCopyF( p, f, Gia_ManConst0(p), 0 ); - Gia_ManForEachPi( p, pObj, i ) - Gia_ObjSetCopyF( p, f, pObj, Gia_ManAppendCi(pNew) ); - } - *pvOutputs = Vec_IntAlloc( 1000 ); - vXorLits = Vec_IntAlloc( 1000 ); - for ( f = nPrefix; f < nFrames+nPrefix; f++ ) - { - Gia_ManForEachObj1( p, pObj, i ) - { - pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); - if ( pRepr == NULL ) - continue; - iPrevNew = Gia_ObjIsConst(p, i)? 0 : Gia_ManCorrSpecReal( pNew, p, pRepr, f, nPrefix ); - iObjNew = Gia_ManCorrSpecReal( pNew, p, pObj, f, nPrefix ); - iObjNew = Gia_LitNotCond( iObjNew, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); - if ( iPrevNew != iObjNew ) - { - Vec_IntPush( *pvOutputs, Gia_ObjId(p, pRepr) ); - Vec_IntPush( *pvOutputs, Gia_ObjId(p, pObj) ); - Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, iPrevNew, iObjNew) ); - } - } - } - Vec_IntForEachEntry( vXorLits, iObjNew, i ) - Gia_ManAppendCo( pNew, iObjNew ); - Vec_IntFree( vXorLits ); - Gia_ManHashStop( pNew ); - ABC_FREE( p->pCopies ); -//printf( "Before sweeping = %d\n", Gia_ManAndNum(pNew) ); - pNew = Gia_ManCleanup( pTemp = pNew ); -//printf( "After sweeping = %d\n", Gia_ManAndNum(pNew) ); - Gia_ManStop( pTemp ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Initializes simulation info for lcorr/scorr counter-examples.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManStartSimInfo( Vec_Ptr_t * vInfo, int nFlops, int * pInitState ) -{ - unsigned * pInfo; - int k, w, nWords; - nWords = Vec_PtrReadWordsSimInfo( vInfo ); - assert( nFlops <= Vec_PtrSize(vInfo) ); - for ( k = 0; k < nFlops; k++ ) - { - pInfo = Vec_PtrEntry( vInfo, k ); - if ( pInitState && Gia_InfoHasBit(pInitState, k) ) - { - for ( w = 0; w < nWords; w++ ) - pInfo[w] = ~0; -// pInfo[0] <<= 1; - } - else - { - for ( w = 0; w < nWords; w++ ) - pInfo[w] = 0; - } - } - for ( k = nFlops; k < Vec_PtrSize(vInfo); k++ ) - { - pInfo = Vec_PtrEntry( vInfo, k ); - for ( w = 0; w < nWords; w++ ) - pInfo[w] = Gia_ManRandom( 0 ); - } -} - -/**Function************************************************************* - - Synopsis [Remaps simulation info from SRM to the original AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Gia_ManCorrRemapSimInfo( Gia_Man_t * p, Vec_Ptr_t * vInfo ) -{ - Gia_Obj_t * pObj, * pRepr; - unsigned * pInfoObj, * pInfoRepr; - int i, w, nWords; - nWords = Vec_PtrReadWordsSimInfo( vInfo ); - Gia_ManForEachRo( p, pObj, i ) - { - // skip ROs without representatives - pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); - if ( pRepr == NULL || Gia_ObjFailed(p, Gia_ObjId(p,pObj)) ) - continue; - pInfoObj = Vec_PtrEntry( vInfo, i ); - for ( w = 0; w < nWords; w++ ) - assert( pInfoObj[w] == 0 ); - // skip ROs with constant representatives - if ( Gia_ObjIsConst0(pRepr) ) - continue; - assert( Gia_ObjIsRo(p, pRepr) ); -// printf( "%d -> %d ", i, Gia_ObjId(p, pRepr) ); - // transfer info from the representative - pInfoRepr = Vec_PtrEntry( vInfo, Gia_ObjCioId(pRepr) - Gia_ManPiNum(p) ); - for ( w = 0; w < nWords; w++ ) - pInfoObj[w] = pInfoRepr[w]; - } -// printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Collects information about remapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Gia_ManCorrCreateRemapping( Gia_Man_t * p ) -{ - Vec_Int_t * vPairs; - Gia_Obj_t * pObj, * pRepr; - int i; - vPairs = Vec_IntAlloc( 100 ); - Gia_ManForEachRo( p, pObj, i ) - { - // skip ROs without representatives - pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); - if ( pRepr == NULL || Gia_ObjIsConst0(pRepr) || Gia_ObjFailed(p, Gia_ObjId(p,pObj)) ) -// if ( pRepr == NULL || Gia_ObjIsConst0(pRepr) || Gia_ObjIsFailedPair(p, Gia_ObjId(p, pRepr), Gia_ObjId(p, pObj)) ) - continue; - assert( Gia_ObjIsRo(p, pRepr) ); -// printf( "%d -> %d ", Gia_ObjId(p,pObj), Gia_ObjId(p, pRepr) ); - // remember the pair - Vec_IntPush( vPairs, Gia_ObjCioId(pRepr) - Gia_ManPiNum(p) ); - Vec_IntPush( vPairs, i ); - } - return vPairs; -} - -/**Function************************************************************* - - Synopsis [Remaps simulation info from SRM to the original AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Gia_ManCorrPerformRemapping( Vec_Int_t * vPairs, Vec_Ptr_t * vInfo, int * pInitState ) -{ - unsigned * pInfoObj, * pInfoRepr; - int w, i, iObj, iRepr, nWords; - nWords = Vec_PtrReadWordsSimInfo( vInfo ); - Vec_IntForEachEntry( vPairs, iRepr, i ) - { - iObj = Vec_IntEntry( vPairs, ++i ); - pInfoObj = Vec_PtrEntry( vInfo, iObj ); - pInfoRepr = Vec_PtrEntry( vInfo, iRepr ); - for ( w = 0; w < nWords; w++ ) - { - assert( pInitState || pInfoObj[w] == 0 ); - pInfoObj[w] = pInfoRepr[w]; - } - } -} - -/**Function************************************************************* - - Synopsis [Packs one counter-examples into the array of simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -*************************************`**********************************/ -int Cec_ManLoadCounterExamplesTry( Vec_Ptr_t * vInfo, Vec_Ptr_t * vPres, int iBit, int * pLits, int nLits ) -{ - unsigned * pInfo, * pPres; - int i; - for ( i = 0; i < nLits; i++ ) - { - pInfo = Vec_PtrEntry(vInfo, Gia_Lit2Var(pLits[i])); - pPres = Vec_PtrEntry(vPres, Gia_Lit2Var(pLits[i])); - if ( Gia_InfoHasBit( pPres, iBit ) && - Gia_InfoHasBit( pInfo, iBit ) == Gia_LitIsCompl(pLits[i]) ) - return 0; - } - for ( i = 0; i < nLits; i++ ) - { - pInfo = Vec_PtrEntry(vInfo, Gia_Lit2Var(pLits[i])); - pPres = Vec_PtrEntry(vPres, Gia_Lit2Var(pLits[i])); - Gia_InfoSetBit( pPres, iBit ); - if ( Gia_InfoHasBit( pInfo, iBit ) == Gia_LitIsCompl(pLits[i]) ) - Gia_InfoXorBit( pInfo, iBit ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Performs bitpacking of counter-examples.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManLoadCounterExamples( Vec_Ptr_t * vInfo, Vec_Int_t * vCexStore, int iStart ) -{ - Vec_Int_t * vPat; - Vec_Ptr_t * vPres; - int nWords = Vec_PtrReadWordsSimInfo(vInfo); - int nBits = 32 * nWords; - int k, nSize, iBit = 1, kMax = 0; - vPat = Vec_IntAlloc( 100 ); - vPres = Vec_PtrAllocSimInfo( Vec_PtrSize(vInfo), nWords ); - Vec_PtrCleanSimInfo( vPres, 0, nWords ); - while ( iStart < Vec_IntSize(vCexStore) ) - { - // skip the output number - iStart++; - // get the number of items - nSize = Vec_IntEntry( vCexStore, iStart++ ); - if ( nSize <= 0 ) - continue; - // extract pattern - Vec_IntClear( vPat ); - for ( k = 0; k < nSize; k++ ) - Vec_IntPush( vPat, Vec_IntEntry( vCexStore, iStart++ ) ); - // add pattern to storage - for ( k = 1; k < nBits; k++ ) - if ( Cec_ManLoadCounterExamplesTry( vInfo, vPres, k, (int *)Vec_IntArray(vPat), Vec_IntSize(vPat) ) ) - break; - kMax = ABC_MAX( kMax, k ); - if ( k == nBits-1 ) - break; - } - Vec_PtrFree( vPres ); - Vec_IntFree( vPat ); - return iStart; -} - -/**Function************************************************************* - - Synopsis [Performs bitpacking of counter-examples.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManLoadCounterExamples2( Vec_Ptr_t * vInfo, Vec_Int_t * vCexStore, int iStart ) -{ - unsigned * pInfo; - int nBits = 32 * Vec_PtrReadWordsSimInfo(vInfo); - int k, iLit, nLits, Out, iBit = 1; - while ( iStart < Vec_IntSize(vCexStore) ) - { - // skip the output number -// iStart++; - Out = Vec_IntEntry( vCexStore, iStart++ ); -// printf( "iBit = %d. Out = %d.\n", iBit, Out ); - // get the number of items - nLits = Vec_IntEntry( vCexStore, iStart++ ); - if ( nLits <= 0 ) - continue; - // add pattern to storage - for ( k = 0; k < nLits; k++ ) - { - iLit = Vec_IntEntry( vCexStore, iStart++ ); - pInfo = Vec_PtrEntry( vInfo, Gia_Lit2Var(iLit) ); - if ( Gia_InfoHasBit( pInfo, iBit ) == Gia_LitIsCompl(iLit) ) - Gia_InfoXorBit( pInfo, iBit ); - } - if ( ++iBit == nBits ) - break; - } -// printf( "added %d bits\n", iBit-1 ); - return iStart; -} - -/**Function************************************************************* - - Synopsis [Resimulates counter-examples derived by the SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManResimulateCounterExamples( Cec_ManSim_t * pSim, Vec_Int_t * vCexStore, int nFrames, int * pInitState ) -{ - Vec_Int_t * vPairs; - Vec_Ptr_t * vSimInfo; - int RetValue = 0, iStart = 0; - vPairs = Gia_ManCorrCreateRemapping( pSim->pAig ); - Gia_ManSetRefs( pSim->pAig ); -// pSim->pPars->nWords = 63; - pSim->pPars->nRounds = nFrames; - vSimInfo = Vec_PtrAllocSimInfo( Gia_ManRegNum(pSim->pAig) + Gia_ManPiNum(pSim->pAig) * nFrames, pSim->pPars->nWords ); - while ( iStart < Vec_IntSize(vCexStore) ) - { - Cec_ManStartSimInfo( vSimInfo, Gia_ManRegNum(pSim->pAig), pInitState ); - iStart = Cec_ManLoadCounterExamples( vSimInfo, vCexStore, iStart ); -// iStart = Cec_ManLoadCounterExamples2( vSimInfo, vCexStore, iStart ); -// Gia_ManCorrRemapSimInfo( pSim->pAig, vSimInfo ); - Gia_ManCorrPerformRemapping( vPairs, vSimInfo, pInitState ); - RetValue |= Cec_ManSeqResimulate( pSim, vSimInfo ); -// Cec_ManSeqResimulateInfo( pSim->pAig, vSimInfo, NULL ); - } -//Gia_ManEquivPrintOne( pSim->pAig, 85, 0 ); - assert( iStart == Vec_IntSize(vCexStore) ); - Vec_PtrFree( vSimInfo ); - Vec_IntFree( vPairs ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Resimulates counter-examples derived by the SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManResimulateCounterExamplesComb( Cec_ManSim_t * pSim, Vec_Int_t * vCexStore ) -{ - Vec_Ptr_t * vSimInfo; - int RetValue = 0, iStart = 0; - Gia_ManSetRefs( pSim->pAig ); - pSim->pPars->nRounds = 1; - vSimInfo = Vec_PtrAllocSimInfo( Gia_ManCiNum(pSim->pAig), pSim->pPars->nWords ); - while ( iStart < Vec_IntSize(vCexStore) ) - { - Cec_ManStartSimInfo( vSimInfo, 0, NULL ); - iStart = Cec_ManLoadCounterExamples( vSimInfo, vCexStore, iStart ); - RetValue |= Cec_ManSeqResimulate( pSim, vSimInfo ); - } - assert( iStart == Vec_IntSize(vCexStore) ); - Vec_PtrFree( vSimInfo ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Updates equivalence classes by marking those that timed out.] - - Description [Returns 1 if all ndoes are proved.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Gia_ManCheckRefinements( Gia_Man_t * p, Vec_Str_t * vStatus, Vec_Int_t * vOutputs, Cec_ManSim_t * pSim, int fRings ) -{ - int i, status, iRepr, iObj; - int Counter = 0; - assert( 2 * Vec_StrSize(vStatus) == Vec_IntSize(vOutputs) ); - Vec_StrForEachEntry( vStatus, status, i ) - { - iRepr = Vec_IntEntry( vOutputs, 2*i ); - iObj = Vec_IntEntry( vOutputs, 2*i+1 ); - if ( status == 1 ) - continue; - if ( status == 0 ) - { - if ( Gia_ObjHasSameRepr(p, iRepr, iObj) ) - Counter++; -// if ( Gia_ObjHasSameRepr(p, iRepr, iObj) ) -// printf( "Gia_ManCheckRefinements(): Disproved equivalence (%d,%d) is not refined!\n", iRepr, iObj ); -// if ( Gia_ObjHasSameRepr(p, iRepr, iObj) ) -// Cec_ManSimClassRemoveOne( pSim, iObj ); - continue; - } - if ( status == -1 ) - { -// if ( !Gia_ObjFailed( p, iObj ) ) -// printf( "Gia_ManCheckRefinements(): Failed equivalence is not marked as failed!\n" ); -// Gia_ObjSetFailed( p, iRepr ); -// Gia_ObjSetFailed( p, iObj ); -// if ( fRings ) -// Cec_ManSimClassRemoveOne( pSim, iRepr ); - Cec_ManSimClassRemoveOne( pSim, iObj ); - continue; - } - } -// if ( Counter ) -// printf( "Gia_ManCheckRefinements(): Could not refine %d nodes.\n", Counter ); - return 1; -} - - -/**Function************************************************************* - - Synopsis [Duplicates the AIG in the DFS order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Gia_ManCorrReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) -{ - Gia_Obj_t * pRepr; - if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) - { - Gia_ManCorrReduce_rec( pNew, p, pRepr ); - pObj->Value = Gia_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); - return; - } - if ( ~pObj->Value ) - return; - assert( Gia_ObjIsAnd(pObj) ); - Gia_ManCorrReduce_rec( pNew, p, Gia_ObjFanin0(pObj) ); - Gia_ManCorrReduce_rec( pNew, p, Gia_ObjFanin1(pObj) ); - pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Reduces AIG using equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Gia_Man_t * Gia_ManCorrReduce( Gia_Man_t * p ) -{ - Gia_Man_t * pNew; - Gia_Obj_t * pObj; - int i; - Gia_ManSetPhase( p ); - pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); - Gia_ManFillValue( p ); - Gia_ManConst0(p)->Value = 0; - Gia_ManForEachCi( p, pObj, i ) - pObj->Value = Gia_ManAppendCi(pNew); - Gia_ManHashAlloc( pNew ); - Gia_ManForEachCo( p, pObj, i ) - Gia_ManCorrReduce_rec( pNew, p, Gia_ObjFanin0(pObj) ); - Gia_ManForEachCo( p, pObj, i ) - Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); - Gia_ManHashStop( pNew ); - Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); - return pNew; -} - - -/**Function************************************************************* - - Synopsis [Prints statistics during solving.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManRefinedClassPrintStats( Gia_Man_t * p, Vec_Str_t * vStatus, int iIter, int Time ) -{ - int nLits, CounterX = 0, Counter0 = 0, Counter = 0; - int i, Entry, nProve = 0, nDispr = 0, nFail = 0; - for ( i = 1; i < Gia_ManObjNum(p); i++ ) - { - if ( Gia_ObjIsNone(p, i) ) - CounterX++; - else if ( Gia_ObjIsConst(p, i) ) - Counter0++; - else if ( Gia_ObjIsHead(p, i) ) - Counter++; - } - CounterX -= Gia_ManCoNum(p); - nLits = Gia_ManCiNum(p) + Gia_ManAndNum(p) - Counter - CounterX; - if ( iIter == -1 ) - printf( "BMC : " ); - else - printf( "%3d : ", iIter ); - printf( "c =%8d cl =%7d lit =%8d ", Counter0, Counter, nLits ); - if ( vStatus ) - Vec_StrForEachEntry( vStatus, Entry, i ) - { - if ( Entry == 1 ) - nProve++; - else if ( Entry == 0 ) - nDispr++; - else if ( Entry == -1 ) - nFail++; - } - printf( "p =%6d d =%6d f =%6d ", nProve, nDispr, nFail ); - ABC_PRT( "T", Time ); -} - -/**Function************************************************************* - - Synopsis [Computes new initial state.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Cec_ManComputeInitState( Gia_Man_t * pAig, int nFrames ) -{ - Gia_Obj_t * pObj, * pObjRo, * pObjRi; - unsigned * pInitState; - int i, f; - printf( "Simulating %d timeframes.\n", nFrames ); - Gia_ManForEachRo( pAig, pObj, i ) - pObj->fMark1 = 0; - for ( f = 0; f < nFrames; f++ ) - { - Gia_ManConst0(pAig)->fMark1 = 0; - Gia_ManForEachPi( pAig, pObj, i ) - pObj->fMark1 = Gia_ManRandom(0) & 1; -// pObj->fMark1 = 1; - Gia_ManForEachAnd( pAig, pObj, i ) - pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) & - (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj)); - Gia_ManForEachRi( pAig, pObj, i ) - pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)); - Gia_ManForEachRiRo( pAig, pObjRi, pObjRo, i ) - pObjRo->fMark1 = pObjRi->fMark1; - } - pInitState = ABC_CALLOC( unsigned, Gia_BitWordNum(Gia_ManRegNum(pAig)) ); - Gia_ManForEachRo( pAig, pObj, i ) - { - if ( pObj->fMark1 ) - Gia_InfoSetBit( pInitState, i ); -// printf( "%d", pObj->fMark1 ); - } -// printf( "\n" ); - Gia_ManCleanMark1( pAig ); - return pInitState; -} - -/**Function************************************************************* - - Synopsis [Internal procedure for register correspondence.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars ) -{ - int nIterMax = 100000; - int nAddFrames = 1; // additional timeframes to simulate - Vec_Str_t * vStatus; - Vec_Int_t * vOutputs; - Vec_Int_t * vCexStore; - Cec_ParSim_t ParsSim, * pParsSim = &ParsSim; - Cec_ParSat_t ParsSat, * pParsSat = &ParsSat; - Cec_ManSim_t * pSim; - Gia_Man_t * pSrm; - unsigned * pInitState = NULL; - int r, RetValue, clkTotal = clock(); - int clkSat = 0, clkSim = 0, clkSrm = 0; - int clk2, clk = clock(); - ABC_FREE( pAig->pReprs ); - ABC_FREE( pAig->pNexts ); - if ( Gia_ManRegNum(pAig) == 0 ) - { - printf( "Cec_ManLatchCorrespondence(): Not a sequential AIG.\n" ); - return 0; - } - Gia_ManRandom( 1 ); - // derive initial state for resimulation - if ( pPars->nPrefix ) -// pInitState = Cec_ManComputeInitState( pAig, 5+(1<<20)/Gia_ManAndNum(pAig) ); - pInitState = Cec_ManComputeInitState( pAig, 100 ); - // prepare simulation manager - Cec_ManSimSetDefaultParams( pParsSim ); - pParsSim->nWords = pPars->nWords; - pParsSim->nRounds = pPars->nRounds; - pParsSim->fVerbose = pPars->fVerbose; - pParsSim->fLatchCorr = pPars->fLatchCorr; - pParsSim->fSeqSimulate = 1; - // create equivalence classes of registers - pSim = Cec_ManSimStart( pAig, pParsSim, pInitState ); - Cec_ManSimClassesPrepare( pSim ); - Cec_ManSimClassesRefine( pSim ); - // prepare SAT solving - Cec_ManSatSetDefaultParams( pParsSat ); - pParsSat->nBTLimit = pPars->nBTLimit; - pParsSat->fVerbose = pPars->fVerbose; - if ( pPars->fVerbose ) - { - printf( "Obj = %7d. And = %7d. Conf = %5d. Fr = %d. Lcorr = %d. Ring = %d. CSat = %d.\n", - Gia_ManObjNum(pAig), Gia_ManAndNum(pAig), - pPars->nBTLimit, pPars->nFrames, pPars->fLatchCorr, pPars->fUseRings, pPars->fUseCSat ); - Cec_ManRefinedClassPrintStats( pAig, NULL, 0, clock() - clk ); - } - // perform refinement of equivalence classes - for ( r = 0; r < nIterMax; r++ ) - { - clk = clock(); - // perform speculative reduction - clk2 = clock(); - pSrm = Gia_ManCorrSpecReduce( pAig, pPars->nFrames, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings ); - assert( Gia_ManRegNum(pSrm) == 0 && Gia_ManPiNum(pSrm) == Gia_ManRegNum(pAig)+(pPars->nFrames+!pPars->fLatchCorr)*Gia_ManPiNum(pAig) ); - clkSrm += clock() - clk2; - if ( Gia_ManCoNum(pSrm) == 0 ) - { - Vec_IntFree( vOutputs ); - Gia_ManStop( pSrm ); - break; - } -//Gia_DumpAiger( pSrm, "corrsrm", r, 2 ); - // found counter-examples to speculation - clk2 = clock(); - if ( pPars->fUseCSat ) - vCexStore = Cbs_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0 ); - else - vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus ); - Gia_ManStop( pSrm ); - clkSat += clock() - clk2; - if ( Vec_IntSize(vCexStore) == 0 ) - { - Vec_IntFree( vCexStore ); - Vec_StrFree( vStatus ); - Vec_IntFree( vOutputs ); - break; - } - // refine classes with these counter-examples - clk2 = clock(); - RetValue = Cec_ManResimulateCounterExamples( pSim, vCexStore, pPars->nFrames + 1 + nAddFrames, pInitState ); - Vec_IntFree( vCexStore ); - clkSim += clock() - clk2; - Gia_ManCheckRefinements( pAig, vStatus, vOutputs, pSim, pPars->fUseRings ); - if ( pPars->fVerbose ) - Cec_ManRefinedClassPrintStats( pAig, vStatus, r+1, clock() - clk ); - Vec_StrFree( vStatus ); - Vec_IntFree( vOutputs ); -//Gia_ManEquivPrintClasses( pAig, 1, 0 ); - } - ABC_FREE( pInitState ); - // check the base case - if ( (!pPars->fLatchCorr || pPars->nFrames > 1) || pPars->nPrefix ) - { - int fChanges = 1; - while ( fChanges ) - { - int clkBmc = clock(); - fChanges = 0; - pSrm = Gia_ManCorrSpecReduceInit( pAig, pPars->nFrames, pPars->nPrefix, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings ); - if ( Gia_ManPoNum(pSrm) == 0 ) - { - Gia_ManStop( pSrm ); - Vec_IntFree( vOutputs ); - break; - } - pParsSat->nBTLimit *= 10; - if ( pPars->nPrefix ) - { - pParsSat->nBTLimit = 10000; - vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus ); - } - else if ( pPars->fUseCSat ) - vCexStore = Cbs_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0 ); - else - vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus ); - // refine classes with these counter-examples - if ( Vec_IntSize(vCexStore) ) - { - clk2 = clock(); - RetValue = Cec_ManResimulateCounterExamples( pSim, vCexStore, pPars->nFrames + 1 + nAddFrames + pPars->nPrefix, NULL ); - clkSim += clock() - clk2; - Gia_ManCheckRefinements( pAig, vStatus, vOutputs, pSim, pPars->fUseRings ); - fChanges = 1; - } - if ( pPars->fVerbose ) - Cec_ManRefinedClassPrintStats( pAig, vStatus, -1, clock() - clkBmc ); - // recycle - Vec_IntFree( vCexStore ); - Vec_StrFree( vStatus ); - Gia_ManStop( pSrm ); - Vec_IntFree( vOutputs ); - } - } - else - { - if ( pPars->fVerbose ) - Cec_ManRefinedClassPrintStats( pAig, NULL, r+1, clock() - clk ); - } - // check the overflow - if ( r == nIterMax ) - printf( "The refinement was not finished. The result may be incorrect.\n" ); - Cec_ManSimStop( pSim ); - clkTotal = clock() - clkTotal; - // report the results - if ( pPars->fVerbose ) - { - ABC_PRTP( "Srm ", clkSrm, clkTotal ); - ABC_PRTP( "Sat ", clkSat, clkTotal ); - ABC_PRTP( "Sim ", clkSim, clkTotal ); - ABC_PRTP( "Other", clkTotal-clkSat-clkSrm-clkSim, clkTotal ); - ABC_PRT( "TOTAL", clkTotal ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Top-level procedure for register correspondence.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Gia_Man_t * Cec_ManLSCorrespondence( Gia_Man_t * pAig, Cec_ParCor_t * pPars ) -{ - Gia_Man_t * pNew, * pTemp; - int RetValue; - RetValue = Cec_ManLSCorrespondenceClasses( pAig, pPars ); - // derive reduced AIG - if ( pPars->fMakeChoices ) - { - pNew = Gia_ManEquivToChoices( pAig, 1 ); - Gia_ManHasChoices( pNew ); - } - else - { - Gia_ManEquivImprove( pAig ); - pNew = Gia_ManCorrReduce( pAig ); - pNew = Gia_ManSeqCleanup( pTemp = pNew ); - Gia_ManStop( pTemp ); - //Gia_WriteAiger( pNew, "reduced.aig", 0, 0 ); - } - // report the results - if ( pPars->fVerbose ) - { - printf( "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n", - Gia_ManAndNum(pAig), Gia_ManAndNum(pNew), - 100.0*(Gia_ManAndNum(pAig)-Gia_ManAndNum(pNew))/(Gia_ManAndNum(pAig)?Gia_ManAndNum(pAig):1), - Gia_ManRegNum(pAig), Gia_ManRegNum(pNew), - 100.0*(Gia_ManRegNum(pAig)-Gia_ManRegNum(pNew))/(Gia_ManRegNum(pAig)?Gia_ManRegNum(pAig):1) ); - } - return pNew; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cec/cecInt.h b/src/aig/cec/cecInt.h deleted file mode 100644 index 6216eae2..00000000 --- a/src/aig/cec/cecInt.h +++ /dev/null @@ -1,225 +0,0 @@ -/**CFile**************************************************************** - - FileName [cecInt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Combinational equivalence checking.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cecInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __CEC_INT_H__ -#define __CEC_INT_H__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "satSolver.h" -#include "bar.h" -#include "gia.h" -#include "cec.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -// simulation pattern manager -typedef struct Cec_ManPat_t_ Cec_ManPat_t; -struct Cec_ManPat_t_ -{ - Vec_Int_t * vPattern1; // pattern in terms of primary inputs - Vec_Int_t * vPattern2; // pattern in terms of primary inputs - Vec_Str_t * vStorage; // storage for compressed patterns - int iStart; // position in the array where recent patterns begin - int nPats; // total number of recent patterns - int nPatsAll; // total number of all patterns - int nPatLits; // total number of literals in recent patterns - int nPatLitsAll; // total number of literals in all patterns - int nPatLitsMin; // total number of literals in minimized recent patterns - int nPatLitsMinAll; // total number of literals in minimized all patterns - int nSeries; // simulation series - int fVerbose; // verbose stats - // runtime statistics - int timeFind; // detecting the pattern - int timeShrink; // minimizing the pattern - int timeVerify; // verifying the result of minimisation - int timeSort; // sorting literals - int timePack; // packing into sim info structures - int timeTotal; // total runtime - int timeTotalSave; // total runtime for saving -}; - -// SAT solving manager -typedef struct Cec_ManSat_t_ Cec_ManSat_t; -struct Cec_ManSat_t_ -{ - // parameters - Cec_ParSat_t * pPars; - // AIGs used in the package - Gia_Man_t * pAig; // the AIG whose outputs are considered - Vec_Int_t * vStatus; // status for each output - // SAT solving - sat_solver * pSat; // recyclable SAT solver - int nSatVars; // the counter of SAT variables - int * pSatVars; // mapping of each node into its SAT var - Vec_Ptr_t * vUsedNodes; // nodes whose SAT vars are assigned - int nRecycles; // the number of times SAT solver was recycled - int nCallsSince; // the number of calls since the last recycle - Vec_Ptr_t * vFanins; // fanins of the CNF node - // counter-examples - Vec_Int_t * vCex; // the latest counter-example - Vec_Int_t * vVisits; // temporary array for visited nodes - // SAT calls statistics - int nSatUnsat; // the number of proofs - int nSatSat; // the number of failure - int nSatUndec; // the number of timeouts - int nSatTotal; // the number of calls - int nCexLits; - // conflicts - int nConfUnsat; // conflicts in unsat problems - int nConfSat; // conflicts in sat problems - int nConfUndec; // conflicts in undec problems - // runtime stats - int timeSatUnsat; // unsat - int timeSatSat; // sat - int timeSatUndec; // undecided - int timeTotal; // total runtime -}; - -// combinational simulation manager -typedef struct Cec_ManSim_t_ Cec_ManSim_t; -struct Cec_ManSim_t_ -{ - // parameters - Gia_Man_t * pAig; // the AIG to be used for simulation - Cec_ParSim_t * pPars; // simulation parameters - int nWords; // the number of simulation words - // recycable memory - int * pSimInfo; // simulation information offsets - unsigned * pMems; // allocated simulaton memory - int nWordsAlloc; // the number of allocated entries - int nMems; // the number of used entries - int nMemsMax; // the max number of used entries - int MemFree; // next free entry - int nWordsOld; // the number of simulation words after previous relink - // internal simulation info - Vec_Ptr_t * vCiSimInfo; // CI simulation info - Vec_Ptr_t * vCoSimInfo; // CO simulation info - // counter examples - void ** pCexes; // counter-examples for each output - int iOut; // first failed output - int nOuts; // the number of failed outputs - Abc_Cex_t * pCexComb; // counter-example for the first failed output - Abc_Cex_t * pBestState; // the state that led to most of the refinements - // scoring simulation patterns - int * pScores; // counters of refinement for each pattern - // temporaries - Vec_Int_t * vClassOld; // old class numbers - Vec_Int_t * vClassNew; // new class numbers - Vec_Int_t * vClassTemp; // temporary storage - Vec_Int_t * vRefinedC; // refined const reprs -}; - -// combinational simulation manager -typedef struct Cec_ManFra_t_ Cec_ManFra_t; -struct Cec_ManFra_t_ -{ - // parameters - Gia_Man_t * pAig; // the AIG to be used for simulation - Cec_ParFra_t * pPars; // SAT sweeping parameters - // simulation patterns - Vec_Int_t * vXorNodes; // nodes used in speculative reduction - int nAllProved; // total number of proved nodes - int nAllDisproved; // total number of disproved nodes - int nAllFailed; // total number of failed nodes - // runtime stats - int timeSim; // unsat - int timePat; // unsat - int timeSat; // sat - int timeTotal; // total runtime -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== cecCorr.c ============================================================*/ -extern void Cec_ManRefinedClassPrintStats( Gia_Man_t * p, Vec_Str_t * vStatus, int iIter, int Time ); -/*=== cecClass.c ============================================================*/ -extern int Cec_ManSimClassRemoveOne( Cec_ManSim_t * p, int i ); -extern int Cec_ManSimClassesPrepare( Cec_ManSim_t * p, int LevelMax ); -extern int Cec_ManSimClassesRefine( Cec_ManSim_t * p ); -extern int Cec_ManSimSimulateRound( Cec_ManSim_t * p, Vec_Ptr_t * vInfoCis, Vec_Ptr_t * vInfoCos ); -/*=== cecIso.c ============================================================*/ -extern int * Cec_ManDetectIsomorphism( Gia_Man_t * p ); -/*=== cecMan.c ============================================================*/ -extern Cec_ManSat_t * Cec_ManSatCreate( Gia_Man_t * pAig, Cec_ParSat_t * pPars ); -extern void Cec_ManSatPrintStats( Cec_ManSat_t * p ); -extern void Cec_ManSatStop( Cec_ManSat_t * p ); -extern Cec_ManPat_t * Cec_ManPatStart(); -extern void Cec_ManPatPrintStats( Cec_ManPat_t * p ); -extern void Cec_ManPatStop( Cec_ManPat_t * p ); -extern Cec_ManSim_t * Cec_ManSimStart( Gia_Man_t * pAig, Cec_ParSim_t * pPars ); -extern void Cec_ManSimStop( Cec_ManSim_t * p ); -extern Cec_ManFra_t * Cec_ManFraStart( Gia_Man_t * pAig, Cec_ParFra_t * pPars ); -extern void Cec_ManFraStop( Cec_ManFra_t * p ); -/*=== cecPat.c ============================================================*/ -extern void Cec_ManPatSavePattern( Cec_ManPat_t * pPat, Cec_ManSat_t * p, Gia_Obj_t * pObj ); -extern Vec_Ptr_t * Cec_ManPatCollectPatterns( Cec_ManPat_t * pMan, int nInputs, int nWords ); -extern Vec_Ptr_t * Cec_ManPatPackPatterns( Vec_Int_t * vCexStore, int nInputs, int nRegs, int nWordsInit ); -/*=== cecSeq.c ============================================================*/ -extern int Cec_ManSeqResimulate( Cec_ManSim_t * p, Vec_Ptr_t * vInfo ); -extern int Cec_ManSeqResimulateInfo( Gia_Man_t * pAig, Vec_Ptr_t * vSimInfo, Abc_Cex_t * pBestState, int fCheckMiter ); -extern void Cec_ManSeqDeriveInfoInitRandom( Vec_Ptr_t * vInfo, Gia_Man_t * pAig, Abc_Cex_t * pCex ); -extern int Cec_ManCountNonConstOutputs( Gia_Man_t * pAig ); -extern int Cec_ManCheckNonTrivialCands( Gia_Man_t * pAig ); -/*=== cecSolve.c ============================================================*/ -extern int Cec_ObjSatVarValue( Cec_ManSat_t * p, Gia_Obj_t * pObj ); -extern void Cec_ManSatSolve( Cec_ManPat_t * pPat, Gia_Man_t * pAig, Cec_ParSat_t * pPars ); -extern Vec_Str_t * Cec_ManSatSolveSeq( Vec_Ptr_t * vPatts, Gia_Man_t * pAig, Cec_ParSat_t * pPars, int nRegs, int * pnPats ); -extern Vec_Int_t * Cec_ManSatSolveMiter( Gia_Man_t * pAig, Cec_ParSat_t * pPars, Vec_Str_t ** pvStatus ); -extern int Cec_ManSatCheckNode( Cec_ManSat_t * p, Gia_Obj_t * pObj ); -extern int Cec_ManSatCheckNodeTwo( Cec_ManSat_t * p, Gia_Obj_t * pObj1, Gia_Obj_t * pObj2 ); -extern void Cec_ManSavePattern( Cec_ManSat_t * p, Gia_Obj_t * pObj1, Gia_Obj_t * pObj2 ); -extern Vec_Int_t * Cec_ManSatReadCex( Cec_ManSat_t * p ); -/*=== ceFraeep.c ============================================================*/ -extern Gia_Man_t * Cec_ManFraSpecReduction( Cec_ManFra_t * p ); -extern int Cec_ManFraClassesUpdate( Cec_ManFra_t * p, Cec_ManSim_t * pSim, Cec_ManPat_t * pPat, Gia_Man_t * pNew ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/cec/cecIso.c b/src/aig/cec/cecIso.c deleted file mode 100644 index ec237fe5..00000000 --- a/src/aig/cec/cecIso.c +++ /dev/null @@ -1,375 +0,0 @@ -/**CFile**************************************************************** - - FileName [cecIso.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Combinational equivalence checking.] - - Synopsis [Detection of structural isomorphism.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cecIso.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cecInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline unsigned * Cec_ManIsoInfo( unsigned * pStore, int nWords, int Id ) { return pStore + nWords * Id; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes simulation info for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Gia_ManIsoSimulate( Gia_Obj_t * pObj, int Id, unsigned * pStore, int nWords ) -{ - unsigned * pInfo = Cec_ManIsoInfo( pStore, nWords, Id ); - unsigned * pInfo0 = Cec_ManIsoInfo( pStore, nWords, Gia_ObjFaninId0(pObj, Id) ); - unsigned * pInfo1 = Cec_ManIsoInfo( pStore, nWords, Gia_ObjFaninId1(pObj, Id) ); - int w; - if ( Gia_ObjFaninC0(pObj) ) - { - if ( Gia_ObjFaninC1(pObj) ) - for ( w = 0; w < nWords; w++ ) - pInfo[w] = ~(pInfo0[w] | pInfo1[w]); - else - for ( w = 0; w < nWords; w++ ) - pInfo[w] = ~pInfo0[w] & pInfo1[w]; - } - else - { - if ( Gia_ObjFaninC1(pObj) ) - for ( w = 0; w < nWords; w++ ) - pInfo[w] = pInfo0[w] & ~pInfo1[w]; - else - for ( w = 0; w < nWords; w++ ) - pInfo[w] = pInfo0[w] & pInfo1[w]; - } -} - -/**Function************************************************************* - - Synopsis [Copies simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Gia_ManIsoCopy( int IdDest, int IdSour, unsigned * pStore, int nWords ) -{ - unsigned * pInfo0 = Cec_ManIsoInfo( pStore, nWords, IdDest ); - unsigned * pInfo1 = Cec_ManIsoInfo( pStore, nWords, IdSour ); - int w; - for ( w = 0; w < nWords; w++ ) - pInfo0[w] = pInfo1[w]; -} - -/**Function************************************************************* - - Synopsis [Compares simulation info of two nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Gia_ManIsoEqual( int Id0, int Id1, unsigned * pStore, int nWords ) -{ - unsigned * pInfo0 = Cec_ManIsoInfo( pStore, nWords, Id0 ); - unsigned * pInfo1 = Cec_ManIsoInfo( pStore, nWords, Id1 ); - int w; - for ( w = 0; w < nWords; w++ ) - if ( pInfo0[w] != pInfo1[w] ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Generates random simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Gia_ManIsoRandom( int Id, unsigned * pStore, int nWords ) -{ - unsigned * pInfo0 = Cec_ManIsoInfo( pStore, nWords, Id ); - int w; - for ( w = 0; w < nWords; w++ ) - pInfo0[w] = Gia_ManRandom( 0 ); -} - -/**Function************************************************************* - - Synopsis [Computes hash key of the simuation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Gia_ManIsoHashKey( int Id, unsigned * pStore, int nWords, int nTableSize ) -{ - static int s_Primes[16] = { - 1291, 1699, 1999, 2357, 2953, 3313, 3907, 4177, - 4831, 5147, 5647, 6343, 6899, 7103, 7873, 8147 }; - unsigned * pInfo0 = Cec_ManIsoInfo( pStore, nWords, Id ); - unsigned uHash = 0; - int i; - for ( i = 0; i < nWords; i++ ) - uHash ^= pInfo0[i] * s_Primes[i & 0xf]; - return (int)(uHash % nTableSize); - -} - -/**Function************************************************************* - - Synopsis [Adds node to the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Gia_ManIsoTableAdd( Gia_Man_t * p, int Id, unsigned * pStore, int nWords, int * pTable, int nTableSize ) -{ - Gia_Obj_t * pTemp; - int Key, Ent, Counter = 0, Color = Gia_ObjColors( p, Id ); - assert( Color == 1 || Color == 2 ); - Key = Gia_ManIsoHashKey( Id, pStore, nWords, nTableSize ); - for ( Ent = pTable[Key], pTemp = (Ent ? Gia_ManObj(p, Ent) : NULL); pTemp; - Ent = pTemp->Value, pTemp = (Ent ? Gia_ManObj(p, Ent) : NULL) ) - { - if ( Gia_ObjColors( p, Ent ) != Color ) - continue; - if ( !Gia_ManIsoEqual( Id, Ent, pStore, nWords ) ) - continue; - // found node with the same color and signature - mark it and do not add new node - pTemp->fMark0 = 1; - return; - } - // did not find the node with the same color and signature - add new node - pTemp = Gia_ManObj( p, Id ); - assert( pTemp->Value == 0 ); - assert( pTemp->fMark0 == 0 ); - pTemp->Value = pTable[Key]; - pTable[Key] = Id; -} - -/**Function************************************************************* - - Synopsis [Extracts equivalence class candidates from one bin.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Gia_ManIsoExtractClasses( Gia_Man_t * p, int Bin, unsigned * pStore, int nWords, Vec_Int_t * vNodesA, Vec_Int_t * vNodesB ) -{ - Gia_Obj_t * pTemp; - int Ent; - Vec_IntClear( vNodesA ); - Vec_IntClear( vNodesB ); - for ( Ent = Bin, pTemp = (Ent ? Gia_ManObj(p, Ent) : NULL); pTemp; - Ent = pTemp->Value, pTemp = (Ent ? Gia_ManObj(p, Ent) : NULL) ) - { - if ( pTemp->fMark0 ) - { - pTemp->fMark0 = 0; - continue; - } - if ( Gia_ObjColors( p, Ent ) == 1 ) - Vec_IntPush( vNodesA, Ent ); - else - Vec_IntPush( vNodesB, Ent ); - } - return Vec_IntSize(vNodesA) > 0 && Vec_IntSize(vNodesB) > 0; -} - -/**Function************************************************************* - - Synopsis [Matches nodes in the extacted classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Gia_ManIsoMatchNodes( int * pIso, unsigned * pStore, int nWords, Vec_Int_t * vNodesA, Vec_Int_t * vNodesB ) -{ - int k0, k1, IdA, IdB; - Vec_IntForEachEntry( vNodesA, IdA, k0 ) - Vec_IntForEachEntry( vNodesB, IdB, k1 ) - { - if ( Gia_ManIsoEqual( IdA, IdB, pStore, nWords ) ) - { - assert( pIso[IdA] == 0 ); - assert( pIso[IdB] == 0 ); - assert( IdA != IdB ); - pIso[IdA] = IdB; - pIso[IdB] = IdA; - continue; - } - } -} - -/**Function************************************************************* - - Synopsis [Transforms iso into equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManTransformClasses( Gia_Man_t * p ) -{ - Gia_Obj_t * pObj; - int i; - assert( p->pReprs && p->pNexts && p->pIso ); - memset( p->pReprs, 0, sizeof(int) * Gia_ManObjNum(p) ); - memset( p->pNexts, 0, sizeof(int) * Gia_ManObjNum(p) ); - Gia_ManForEachObj( p, pObj, i ) - { - p->pReprs[i].iRepr = GIA_VOID; - if ( p->pIso[i] && p->pIso[i] < i ) - { - p->pReprs[i].iRepr = p->pIso[i]; - p->pNexts[p->pIso[i]] = i; - } - } -} - -/**Function************************************************************* - - Synopsis [Finds node correspondences in the miter.] - - Description [Assumes that the colors are assigned.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int * Cec_ManDetectIsomorphism( Gia_Man_t * p ) -{ - int nWords = 2; - Gia_Obj_t * pObj; - Vec_Int_t * vNodesA, * vNodesB; - unsigned * pStore, Counter; - int i, * pIso, * pTable, nTableSize; - // start equivalence classes - pIso = ABC_CALLOC( int, Gia_ManObjNum(p) ); - Gia_ManForEachObj( p, pObj, i ) - { - if ( Gia_ObjIsCo(pObj) ) - { - assert( Gia_ObjColors(p, i) == 0 ); - continue; - } - assert( Gia_ObjColors(p, i) ); - if ( Gia_ObjColors(p, i) == 3 ) - pIso[i] = i; - } - // start simulation info - pStore = ABC_ALLOC( unsigned, Gia_ManObjNum(p) * nWords ); - // simulate and create table - nTableSize = Gia_PrimeCudd( 100 + Gia_ManObjNum(p)/2 ); - pTable = ABC_CALLOC( int, nTableSize ); - Gia_ManCleanValue( p ); - Gia_ManForEachObj1( p, pObj, i ) - { - if ( Gia_ObjIsCo(pObj) ) - continue; - if ( pIso[i] == 0 ) // simulate - Gia_ManIsoSimulate( pObj, i, pStore, nWords ); - else if ( pIso[i] < i ) // copy - Gia_ManIsoCopy( i, pIso[i], pStore, nWords ); - else // generate - Gia_ManIsoRandom( i, pStore, nWords ); - if ( pIso[i] == 0 ) - Gia_ManIsoTableAdd( p, i, pStore, nWords, pTable, nTableSize ); - } - // create equivalence classes - vNodesA = Vec_IntAlloc( 100 ); - vNodesB = Vec_IntAlloc( 100 ); - for ( i = 0; i < nTableSize; i++ ) - if ( Gia_ManIsoExtractClasses( p, pTable[i], pStore, nWords, vNodesA, vNodesB ) ) - Gia_ManIsoMatchNodes( pIso, pStore, nWords, vNodesA, vNodesB ); - Vec_IntFree( vNodesA ); - Vec_IntFree( vNodesB ); - // collect info - Counter = 0; - Gia_ManForEachObj1( p, pObj, i ) - { - Counter += (pIso[i] && pIso[i] < i); -/* - if ( pIso[i] && pIso[i] < i ) - { - if ( (Gia_ObjIsHead(p,pIso[i]) && Gia_ObjRepr(p,i)==pIso[i]) || - (Gia_ObjIsClass(p,pIso[i]) && Gia_ObjRepr(p,i)==Gia_ObjRepr(p,pIso[i])) ) - Abc_Print( 1, "1" ); - else - Abc_Print( 1, "0" ); - } -*/ - } - Abc_Print( 1, "Computed %d pairs of structurally equivalent nodes.\n", Counter ); -// p->pIso = pIso; -// Cec_ManTransformClasses( p ); - - ABC_FREE( pTable ); - ABC_FREE( pStore ); - return pIso; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cec/cecMan.c b/src/aig/cec/cecMan.c deleted file mode 100644 index f03ec701..00000000 --- a/src/aig/cec/cecMan.c +++ /dev/null @@ -1,297 +0,0 @@ -/**CFile**************************************************************** - - FileName [cecMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Combinational equivalence checking.] - - Synopsis [Manager procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cecMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cecInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cec_ManSat_t * Cec_ManSatCreate( Gia_Man_t * pAig, Cec_ParSat_t * pPars ) -{ - Cec_ManSat_t * p; - // create interpolation manager - p = ABC_ALLOC( Cec_ManSat_t, 1 ); - memset( p, 0, sizeof(Cec_ManSat_t) ); - p->pPars = pPars; - p->pAig = pAig; - // SAT solving - p->nSatVars = 1; - p->pSatVars = ABC_CALLOC( int, Gia_ManObjNum(pAig) ); - p->vUsedNodes = Vec_PtrAlloc( 1000 ); - p->vFanins = Vec_PtrAlloc( 100 ); - p->vCex = Vec_IntAlloc( 100 ); - p->vVisits = Vec_IntAlloc( 100 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Prints statistics of the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManSatPrintStats( Cec_ManSat_t * p ) -{ - Abc_Print( 1, "CO = %8d ", Gia_ManCoNum(p->pAig) ); - Abc_Print( 1, "AND = %8d ", Gia_ManAndNum(p->pAig) ); - Abc_Print( 1, "Conf = %5d ", p->pPars->nBTLimit ); - Abc_Print( 1, "MinVar = %5d ", p->pPars->nSatVarMax ); - Abc_Print( 1, "MinCalls = %5d\n", p->pPars->nCallsRecycle ); - Abc_Print( 1, "Unsat calls %6d (%6.2f %%) Ave conf = %8.1f ", - p->nSatUnsat, p->nSatTotal? 100.0*p->nSatUnsat/p->nSatTotal : 0.0, p->nSatUnsat? 1.0*p->nConfUnsat/p->nSatUnsat :0.0 ); - Abc_PrintTimeP( 1, "Time", p->timeSatUnsat, p->timeTotal ); - Abc_Print( 1, "Sat calls %6d (%6.2f %%) Ave conf = %8.1f ", - p->nSatSat, p->nSatTotal? 100.0*p->nSatSat/p->nSatTotal : 0.0, p->nSatSat? 1.0*p->nConfSat/p->nSatSat : 0.0 ); - Abc_PrintTimeP( 1, "Time", p->timeSatSat, p->timeTotal ); - Abc_Print( 1, "Undef calls %6d (%6.2f %%) Ave conf = %8.1f ", - p->nSatUndec, p->nSatTotal? 100.0*p->nSatUndec/p->nSatTotal : 0.0, p->nSatUndec? 1.0*p->nConfUndec/p->nSatUndec : 0.0 ); - Abc_PrintTimeP( 1, "Time", p->timeSatUndec, p->timeTotal ); - Abc_PrintTime( 1, "Total time", p->timeTotal ); -} - -/**Function************************************************************* - - Synopsis [Frees the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManSatStop( Cec_ManSat_t * p ) -{ - if ( p->pSat ) - sat_solver_delete( p->pSat ); - Vec_IntFree( p->vCex ); - Vec_IntFree( p->vVisits ); - Vec_PtrFree( p->vUsedNodes ); - Vec_PtrFree( p->vFanins ); - ABC_FREE( p->pSatVars ); - ABC_FREE( p ); -} - - - -/**Function************************************************************* - - Synopsis [Creates AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cec_ManPat_t * Cec_ManPatStart() -{ - Cec_ManPat_t * p; - p = ABC_CALLOC( Cec_ManPat_t, 1 ); - p->vStorage = Vec_StrAlloc( 1<<20 ); - p->vPattern1 = Vec_IntAlloc( 1000 ); - p->vPattern2 = Vec_IntAlloc( 1000 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Creates AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManPatPrintStats( Cec_ManPat_t * p ) -{ - Abc_Print( 1, "Latest: P = %8d. L = %10d. Lm = %10d. Ave = %6.1f. MEM =%6.2f Mb\n", - p->nPats, p->nPatLits, p->nPatLitsMin, 1.0 * p->nPatLitsMin/p->nPats, - 1.0*(Vec_StrSize(p->vStorage)-p->iStart)/(1<<20) ); - Abc_Print( 1, "Total: P = %8d. L = %10d. Lm = %10d. Ave = %6.1f. MEM =%6.2f Mb\n", - p->nPatsAll, p->nPatLitsAll, p->nPatLitsMinAll, 1.0 * p->nPatLitsMinAll/p->nPatsAll, - 1.0*Vec_StrSize(p->vStorage)/(1<<20) ); - Abc_PrintTimeP( 1, "Finding ", p->timeFind, p->timeTotal ); - Abc_PrintTimeP( 1, "Shrinking", p->timeShrink, p->timeTotal ); - Abc_PrintTimeP( 1, "Verifying", p->timeVerify, p->timeTotal ); - Abc_PrintTimeP( 1, "Sorting ", p->timeSort, p->timeTotal ); - Abc_PrintTimeP( 1, "Packing ", p->timePack, p->timeTotal ); - Abc_PrintTime( 1, "TOTAL ", p->timeTotal ); -} - -/**Function************************************************************* - - Synopsis [Deletes AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManPatStop( Cec_ManPat_t * p ) -{ - Vec_StrFree( p->vStorage ); - Vec_IntFree( p->vPattern1 ); - Vec_IntFree( p->vPattern2 ); - ABC_FREE( p ); -} - - - -/**Function************************************************************* - - Synopsis [Creates AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cec_ManSim_t * Cec_ManSimStart( Gia_Man_t * pAig, Cec_ParSim_t * pPars ) -{ - Cec_ManSim_t * p; - p = ABC_ALLOC( Cec_ManSim_t, 1 ); - memset( p, 0, sizeof(Cec_ManSim_t) ); - p->pAig = pAig; - p->pPars = pPars; - p->nWords = pPars->nWords; - p->pSimInfo = ABC_CALLOC( int, Gia_ManObjNum(pAig) ); - p->vClassOld = Vec_IntAlloc( 1000 ); - p->vClassNew = Vec_IntAlloc( 1000 ); - p->vClassTemp = Vec_IntAlloc( 1000 ); - p->vRefinedC = Vec_IntAlloc( 10000 ); - p->vCiSimInfo = Vec_PtrAllocSimInfo( Gia_ManCiNum(p->pAig), pPars->nWords ); - if ( pPars->fCheckMiter || Gia_ManRegNum(p->pAig) ) - { - p->vCoSimInfo = Vec_PtrAllocSimInfo( Gia_ManCoNum(p->pAig), pPars->nWords ); - Vec_PtrCleanSimInfo( p->vCoSimInfo, 0, pPars->nWords ); - } - p->iOut = -1; - return p; -} - -/**Function************************************************************* - - Synopsis [Deletes AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManSimStop( Cec_ManSim_t * p ) -{ - Vec_IntFree( p->vClassOld ); - Vec_IntFree( p->vClassNew ); - Vec_IntFree( p->vClassTemp ); - Vec_IntFree( p->vRefinedC ); - if ( p->vCiSimInfo ) - Vec_PtrFree( p->vCiSimInfo ); - if ( p->vCoSimInfo ) - Vec_PtrFree( p->vCoSimInfo ); - ABC_FREE( p->pScores ); - ABC_FREE( p->pCexComb ); - ABC_FREE( p->pCexes ); - ABC_FREE( p->pMems ); - ABC_FREE( p->pSimInfo ); - ABC_FREE( p ); -} - - -/**Function************************************************************* - - Synopsis [Creates AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cec_ManFra_t * Cec_ManFraStart( Gia_Man_t * pAig, Cec_ParFra_t * pPars ) -{ - Cec_ManFra_t * p; - p = ABC_ALLOC( Cec_ManFra_t, 1 ); - memset( p, 0, sizeof(Cec_ManFra_t) ); - p->pAig = pAig; - p->pPars = pPars; - p->vXorNodes = Vec_IntAlloc( 1000 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Deletes AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManFraStop( Cec_ManFra_t * p ) -{ - Vec_IntFree( p->vXorNodes ); - ABC_FREE( p ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cec/cecPat.c b/src/aig/cec/cecPat.c deleted file mode 100644 index 82c12ea9..00000000 --- a/src/aig/cec/cecPat.c +++ /dev/null @@ -1,569 +0,0 @@ -/**CFile**************************************************************** - - FileName [cecPat.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Combinational equivalence checking.] - - Synopsis [Simulation pattern manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cecPat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cecInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Cec_ManPatStoreNum( Cec_ManPat_t * p, int Num ) -{ - unsigned x = (unsigned)Num; - assert( Num >= 0 ); - while ( x & ~0x7f ) - { - Vec_StrPush( p->vStorage, (char)((x & 0x7f) | 0x80) ); - x >>= 7; - } - Vec_StrPush( p->vStorage, (char)x ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Cec_ManPatRestoreNum( Cec_ManPat_t * p ) -{ - int ch, i, x = 0; - for ( i = 0; (ch = Vec_StrEntry(p->vStorage, p->iStart++)) & 0x80; i++ ) - x |= (ch & 0x7f) << (7 * i); - return x | (ch << (7 * i)); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Cec_ManPatStore( Cec_ManPat_t * p, Vec_Int_t * vPat ) -{ - int i, Number, NumberPrev; - assert( Vec_IntSize(vPat) > 0 ); - Cec_ManPatStoreNum( p, Vec_IntSize(vPat) ); - NumberPrev = Vec_IntEntry( vPat, 0 ); - Cec_ManPatStoreNum( p, NumberPrev ); - Vec_IntForEachEntryStart( vPat, Number, i, 1 ) - { - assert( NumberPrev < Number ); - Cec_ManPatStoreNum( p, Number - NumberPrev ); - NumberPrev = Number; - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Cec_ManPatRestore( Cec_ManPat_t * p, Vec_Int_t * vPat ) -{ - int i, Size, Number; - Vec_IntClear( vPat ); - Size = Cec_ManPatRestoreNum( p ); - Number = Cec_ManPatRestoreNum( p ); - Vec_IntPush( vPat, Number ); - for ( i = 1; i < Size; i++ ) - { - Number += Cec_ManPatRestoreNum( p ); - Vec_IntPush( vPat, Number ); - } - assert( Vec_IntSize(vPat) == Size ); -} - - -/**Function************************************************************* - - Synopsis [Derives satisfying assignment.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManPatComputePattern_rec( Cec_ManSat_t * pSat, Gia_Man_t * p, Gia_Obj_t * pObj ) -{ - int Counter = 0; - if ( Gia_ObjIsTravIdCurrent(p, pObj) ) - return 0; - Gia_ObjSetTravIdCurrent(p, pObj); - if ( Gia_ObjIsCi(pObj) ) - { - pObj->fMark1 = Cec_ObjSatVarValue( pSat, pObj ); - return 1; - } - assert( Gia_ObjIsAnd(pObj) ); - Counter += Cec_ManPatComputePattern_rec( pSat, p, Gia_ObjFanin0(pObj) ); - Counter += Cec_ManPatComputePattern_rec( pSat, p, Gia_ObjFanin1(pObj) ); - pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) & - (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj)); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Derives satisfying assignment.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManPatComputePattern1_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vPat ) -{ - if ( Gia_ObjIsTravIdCurrent(p, pObj) ) - return; - Gia_ObjSetTravIdCurrent(p, pObj); - if ( Gia_ObjIsCi(pObj) ) - { - Vec_IntPush( vPat, Gia_Var2Lit( Gia_ObjCioId(pObj), pObj->fMark1==0 ) ); - return; - } - assert( Gia_ObjIsAnd(pObj) ); - if ( pObj->fMark1 == 1 ) - { - Cec_ManPatComputePattern1_rec( p, Gia_ObjFanin0(pObj), vPat ); - Cec_ManPatComputePattern1_rec( p, Gia_ObjFanin1(pObj), vPat ); - } - else - { - assert( (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) == 0 || - (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj)) == 0 ); - if ( (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) == 0 ) - Cec_ManPatComputePattern1_rec( p, Gia_ObjFanin0(pObj), vPat ); - else - Cec_ManPatComputePattern1_rec( p, Gia_ObjFanin1(pObj), vPat ); - } -} - -/**Function************************************************************* - - Synopsis [Derives satisfying assignment.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManPatComputePattern2_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vPat ) -{ - if ( Gia_ObjIsTravIdCurrent(p, pObj) ) - return; - Gia_ObjSetTravIdCurrent(p, pObj); - if ( Gia_ObjIsCi(pObj) ) - { - Vec_IntPush( vPat, Gia_Var2Lit( Gia_ObjCioId(pObj), pObj->fMark1==0 ) ); - return; - } - assert( Gia_ObjIsAnd(pObj) ); - if ( pObj->fMark1 == 1 ) - { - Cec_ManPatComputePattern2_rec( p, Gia_ObjFanin0(pObj), vPat ); - Cec_ManPatComputePattern2_rec( p, Gia_ObjFanin1(pObj), vPat ); - } - else - { - assert( (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) == 0 || - (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj)) == 0 ); - if ( (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj)) == 0 ) - Cec_ManPatComputePattern2_rec( p, Gia_ObjFanin1(pObj), vPat ); - else - Cec_ManPatComputePattern2_rec( p, Gia_ObjFanin0(pObj), vPat ); - } -} - -/**Function************************************************************* - - Synopsis [Derives satisfying assignment.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManPatComputePattern3_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) -{ - int Value0, Value1, Value; - if ( Gia_ObjIsTravIdCurrent(p, pObj) ) - return (pObj->fMark1 << 1) | pObj->fMark0; - Gia_ObjSetTravIdCurrent(p, pObj); - if ( Gia_ObjIsCi(pObj) ) - { - pObj->fMark0 = 1; - pObj->fMark1 = 1; - return GIA_UND; - } - assert( Gia_ObjIsAnd(pObj) ); - Value0 = Cec_ManPatComputePattern3_rec( p, Gia_ObjFanin0(pObj) ); - Value1 = Cec_ManPatComputePattern3_rec( p, Gia_ObjFanin1(pObj) ); - Value = Gia_XsimAndCond( Value0, Gia_ObjFaninC0(pObj), Value1, Gia_ObjFaninC1(pObj) ); - pObj->fMark0 = (Value & 1); - pObj->fMark1 = ((Value >> 1) & 1); - return Value; -} - -/**Function************************************************************* - - Synopsis [Derives satisfying assignment.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManPatVerifyPattern( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vPat ) -{ - Gia_Obj_t * pTemp; - int i, Value; - Gia_ManIncrementTravId( p ); - Vec_IntForEachEntry( vPat, Value, i ) - { - pTemp = Gia_ManCi( p, Gia_Lit2Var(Value) ); -// assert( Gia_LitIsCompl(Value) != (int)pTemp->fMark1 ); - if ( pTemp->fMark1 ) - { - pTemp->fMark0 = 0; - pTemp->fMark1 = 1; - } - else - { - pTemp->fMark0 = 1; - pTemp->fMark1 = 0; - } - Gia_ObjSetTravIdCurrent( p, pTemp ); - } - Value = Cec_ManPatComputePattern3_rec( p, Gia_ObjFanin0(pObj) ); - Value = Gia_XsimNotCond( Value, Gia_ObjFaninC0(pObj) ); - if ( Value != GIA_ONE ) - Abc_Print( 1, "Cec_ManPatVerifyPattern(): Verification failed.\n" ); - assert( Value == GIA_ONE ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManPatComputePattern4_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) -{ - if ( Gia_ObjIsTravIdCurrent(p, pObj) ) - return; - Gia_ObjSetTravIdCurrent(p, pObj); - pObj->fMark0 = 0; - if ( Gia_ObjIsCi(pObj) ) - return; - assert( Gia_ObjIsAnd(pObj) ); - Cec_ManPatComputePattern4_rec( p, Gia_ObjFanin0(pObj) ); - Cec_ManPatComputePattern4_rec( p, Gia_ObjFanin1(pObj) ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManPatCleanMark0( Gia_Man_t * p, Gia_Obj_t * pObj ) -{ - assert( Gia_ObjIsCo(pObj) ); - Gia_ManIncrementTravId( p ); - Cec_ManPatComputePattern4_rec( p, Gia_ObjFanin0(pObj) ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManPatSavePattern( Cec_ManPat_t * pMan, Cec_ManSat_t * p, Gia_Obj_t * pObj ) -{ - Vec_Int_t * vPat; - int nPatLits, clk, clkTotal = clock(); - assert( Gia_ObjIsCo(pObj) ); - pMan->nPats++; - pMan->nPatsAll++; - // compute values in the cone of influence -clk = clock(); - Gia_ManIncrementTravId( p->pAig ); - nPatLits = Cec_ManPatComputePattern_rec( p, p->pAig, Gia_ObjFanin0(pObj) ); - assert( (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) == 1 ); - pMan->nPatLits += nPatLits; - pMan->nPatLitsAll += nPatLits; -pMan->timeFind += clock() - clk; - // compute sensitizing path -clk = clock(); - Vec_IntClear( pMan->vPattern1 ); - Gia_ManIncrementTravId( p->pAig ); - Cec_ManPatComputePattern1_rec( p->pAig, Gia_ObjFanin0(pObj), pMan->vPattern1 ); - // compute sensitizing path - Vec_IntClear( pMan->vPattern2 ); - Gia_ManIncrementTravId( p->pAig ); - Cec_ManPatComputePattern2_rec( p->pAig, Gia_ObjFanin0(pObj), pMan->vPattern2 ); - // compare patterns - vPat = Vec_IntSize(pMan->vPattern1) < Vec_IntSize(pMan->vPattern2) ? pMan->vPattern1 : pMan->vPattern2; - pMan->nPatLitsMin += Vec_IntSize(vPat); - pMan->nPatLitsMinAll += Vec_IntSize(vPat); -pMan->timeShrink += clock() - clk; - // verify pattern using ternary simulation -clk = clock(); - Cec_ManPatVerifyPattern( p->pAig, pObj, vPat ); -pMan->timeVerify += clock() - clk; - // sort pattern -clk = clock(); - Vec_IntSort( vPat, 0 ); -pMan->timeSort += clock() - clk; - // save pattern - Cec_ManPatStore( pMan, vPat ); - pMan->timeTotal += clock() - clkTotal; -} - -/**Function************************************************************* - - Synopsis [Packs patterns into array of simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -*************************************`**********************************/ -int Cec_ManPatCollectTry( Vec_Ptr_t * vInfo, Vec_Ptr_t * vPres, int iBit, int * pLits, int nLits ) -{ - unsigned * pInfo, * pPres; - int i; - for ( i = 0; i < nLits; i++ ) - { - pInfo = (unsigned *)Vec_PtrEntry(vInfo, Gia_Lit2Var(pLits[i])); - pPres = (unsigned *)Vec_PtrEntry(vPres, Gia_Lit2Var(pLits[i])); - if ( Gia_InfoHasBit( pPres, iBit ) && - Gia_InfoHasBit( pInfo, iBit ) == Gia_LitIsCompl(pLits[i]) ) - return 0; - } - for ( i = 0; i < nLits; i++ ) - { - pInfo = (unsigned *)Vec_PtrEntry(vInfo, Gia_Lit2Var(pLits[i])); - pPres = (unsigned *)Vec_PtrEntry(vPres, Gia_Lit2Var(pLits[i])); - Gia_InfoSetBit( pPres, iBit ); - if ( Gia_InfoHasBit( pInfo, iBit ) == Gia_LitIsCompl(pLits[i]) ) - Gia_InfoXorBit( pInfo, iBit ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Packs patterns into array of simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Cec_ManPatCollectPatterns( Cec_ManPat_t * pMan, int nInputs, int nWordsInit ) -{ - Vec_Int_t * vPat = pMan->vPattern1; - Vec_Ptr_t * vInfo, * vPres; - int k, kMax = -1, nPatterns = 0; - int iStartOld = pMan->iStart; - int nWords = nWordsInit; - int nBits = 32 * nWords; - int clk = clock(); - vInfo = Vec_PtrAllocSimInfo( nInputs, nWords ); - Gia_ManRandomInfo( vInfo, 0, 0, nWords ); - vPres = Vec_PtrAllocSimInfo( nInputs, nWords ); - Vec_PtrCleanSimInfo( vPres, 0, nWords ); - while ( pMan->iStart < Vec_StrSize(pMan->vStorage) ) - { - nPatterns++; - Cec_ManPatRestore( pMan, vPat ); - for ( k = 1; k < nBits; k++, k += ((k % (32 * nWordsInit)) == 0) ) - if ( Cec_ManPatCollectTry( vInfo, vPres, k, (int *)Vec_IntArray(vPat), Vec_IntSize(vPat) ) ) - break; - kMax = ABC_MAX( kMax, k ); - if ( k == nBits-1 ) - { - Vec_PtrReallocSimInfo( vInfo ); - Gia_ManRandomInfo( vInfo, 0, nWords, 2*nWords ); - Vec_PtrReallocSimInfo( vPres ); - Vec_PtrCleanSimInfo( vPres, nWords, 2*nWords ); - nWords *= 2; - nBits *= 2; - } - } - Vec_PtrFree( vPres ); - pMan->nSeries = Vec_PtrReadWordsSimInfo(vInfo) / nWordsInit; - pMan->timePack += clock() - clk; - pMan->timeTotal += clock() - clk; - pMan->iStart = iStartOld; - if ( pMan->fVerbose ) - { - Abc_Print( 1, "Total = %5d. Max used = %5d. Full = %5d. Series = %d. ", - nPatterns, kMax, nWordsInit*32, pMan->nSeries ); - ABC_PRT( "Time", clock() - clk ); - Cec_ManPatPrintStats( pMan ); - } - return vInfo; -} - - -/**Function************************************************************* - - Synopsis [Packs patterns into array of simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Cec_ManPatPackPatterns( Vec_Int_t * vCexStore, int nInputs, int nRegs, int nWordsInit ) -{ - Vec_Int_t * vPat; - Vec_Ptr_t * vInfo, * vPres; - int k, nSize, iStart, kMax = 0, nPatterns = 0; - int nWords = nWordsInit; - int nBits = 32 * nWords; -// int RetValue; - assert( nRegs <= nInputs ); - vPat = Vec_IntAlloc( 100 ); - - vInfo = Vec_PtrAllocSimInfo( nInputs, nWords ); - Vec_PtrCleanSimInfo( vInfo, 0, nWords ); - Gia_ManRandomInfo( vInfo, nRegs, 0, nWords ); - - vPres = Vec_PtrAllocSimInfo( nInputs, nWords ); - Vec_PtrCleanSimInfo( vPres, 0, nWords ); - iStart = 0; - while ( iStart < Vec_IntSize(vCexStore) ) - { - nPatterns++; - // skip the output number - iStart++; - // get the number of items - nSize = Vec_IntEntry( vCexStore, iStart++ ); - if ( nSize <= 0 ) - continue; - // extract pattern - Vec_IntClear( vPat ); - for ( k = 0; k < nSize; k++ ) - Vec_IntPush( vPat, Vec_IntEntry( vCexStore, iStart++ ) ); - // add pattern to storage - for ( k = 1; k < nBits; k++, k += ((k % (32 * nWordsInit)) == 0) ) - if ( Cec_ManPatCollectTry( vInfo, vPres, k, (int *)Vec_IntArray(vPat), Vec_IntSize(vPat) ) ) - break; - -// k = kMax + 1; -// RetValue = Cec_ManPatCollectTry( vInfo, vPres, k, (int *)Vec_IntArray(vPat), Vec_IntSize(vPat) ); -// assert( RetValue == 1 ); - - kMax = ABC_MAX( kMax, k ); - if ( k == nBits-1 ) - { - Vec_PtrReallocSimInfo( vInfo ); - Vec_PtrCleanSimInfo( vInfo, nWords, 2*nWords ); - Gia_ManRandomInfo( vInfo, nRegs, nWords, 2*nWords ); - - Vec_PtrReallocSimInfo( vPres ); - Vec_PtrCleanSimInfo( vPres, nWords, 2*nWords ); - nWords *= 2; - nBits *= 2; - } - } -// Abc_Print( 1, "packed %d patterns into %d vectors (out of %d)\n", nPatterns, kMax, nBits ); - Vec_PtrFree( vPres ); - Vec_IntFree( vPat ); - return vInfo; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cec/cecSeq.c b/src/aig/cec/cecSeq.c deleted file mode 100644 index dd561971..00000000 --- a/src/aig/cec/cecSeq.c +++ /dev/null @@ -1,448 +0,0 @@ -/**CFile**************************************************************** - - FileName [cecSeq.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Combinational equivalence checking.] - - Synopsis [Refinement of sequential equivalence classes.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cecSeq.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cecInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Sets register values from the counter-example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManSeqDeriveInfoFromCex( Vec_Ptr_t * vInfo, Gia_Man_t * pAig, Abc_Cex_t * pCex ) -{ - unsigned * pInfo; - int k, i, w, nWords; - assert( pCex->nBits == pCex->nRegs + pCex->nPis * (pCex->iFrame + 1) ); - assert( pCex->nBits - pCex->nRegs + Gia_ManRegNum(pAig) <= Vec_PtrSize(vInfo) ); - nWords = Vec_PtrReadWordsSimInfo( vInfo ); -/* - // user register values - assert( pCex->nRegs == Gia_ManRegNum(pAig) ); - for ( k = 0; k < pCex->nRegs; k++ ) - { - pInfo = (unsigned *)Vec_PtrEntry( vInfo, k ); - for ( w = 0; w < nWords; w++ ) - pInfo[w] = Gia_InfoHasBit( pCex->pData, k )? ~0 : 0; - } -*/ - // print warning about register values - for ( k = 0; k < pCex->nRegs; k++ ) - if ( Gia_InfoHasBit( pCex->pData, k ) ) - break; - if ( k < pCex->nRegs ) - Abc_Print( 0, "The CEX has flop values different from 0, but they are currently not used by \"resim\".\n" ); - - // assign zero register values - for ( k = 0; k < Gia_ManRegNum(pAig); k++ ) - { - pInfo = (unsigned *)Vec_PtrEntry( vInfo, k ); - for ( w = 0; w < nWords; w++ ) - pInfo[w] = 0; - } - for ( i = pCex->nRegs; i < pCex->nBits; i++ ) - { - pInfo = (unsigned *)Vec_PtrEntry( vInfo, k++ ); - for ( w = 0; w < nWords; w++ ) - pInfo[w] = Gia_ManRandom(0); - // set simulation pattern and make sure it is second (first will be erased during simulation) - pInfo[0] = (pInfo[0] << 1) | Gia_InfoHasBit( pCex->pData, i ); - pInfo[0] <<= 1; - } - for ( ; k < Vec_PtrSize(vInfo); k++ ) - { - pInfo = (unsigned *)Vec_PtrEntry( vInfo, k ); - for ( w = 0; w < nWords; w++ ) - pInfo[w] = Gia_ManRandom(0); - } -} - -/**Function************************************************************* - - Synopsis [Sets register values from the counter-example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManSeqDeriveInfoInitRandom( Vec_Ptr_t * vInfo, Gia_Man_t * pAig, Abc_Cex_t * pCex ) -{ - unsigned * pInfo; - int k, w, nWords; - nWords = Vec_PtrReadWordsSimInfo( vInfo ); - assert( pCex == NULL || Gia_ManRegNum(pAig) == pCex->nRegs ); - assert( Gia_ManRegNum(pAig) <= Vec_PtrSize(vInfo) ); - for ( k = 0; k < Gia_ManRegNum(pAig); k++ ) - { - pInfo = (unsigned *)Vec_PtrEntry( vInfo, k ); - for ( w = 0; w < nWords; w++ ) - pInfo[w] = (pCex && Gia_InfoHasBit(pCex->pData, k))? ~0 : 0; - } - - for ( ; k < Vec_PtrSize(vInfo); k++ ) - { - pInfo = (unsigned *)Vec_PtrEntry( vInfo, k ); - for ( w = 0; w < nWords; w++ ) - pInfo[w] = Gia_ManRandom( 0 ); - } -} - -/**Function************************************************************* - - Synopsis [Resimulates the classes using sequential simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManSeqResimulate( Cec_ManSim_t * p, Vec_Ptr_t * vInfo ) -{ - unsigned * pInfo0, * pInfo1; - int f, i, k, w; -// assert( Gia_ManRegNum(p->pAig) > 0 ); - assert( Vec_PtrSize(vInfo) == Gia_ManRegNum(p->pAig) + Gia_ManPiNum(p->pAig) * p->pPars->nFrames ); - for ( k = 0; k < Gia_ManRegNum(p->pAig); k++ ) - { - pInfo0 = (unsigned *)Vec_PtrEntry( vInfo, k ); - pInfo1 = (unsigned *)Vec_PtrEntry( p->vCoSimInfo, Gia_ManPoNum(p->pAig) + k ); - for ( w = 0; w < p->nWords; w++ ) - pInfo1[w] = pInfo0[w]; - } - for ( f = 0; f < p->pPars->nFrames; f++ ) - { - for ( i = 0; i < Gia_ManPiNum(p->pAig); i++ ) - { - pInfo0 = (unsigned *)Vec_PtrEntry( vInfo, k++ ); - pInfo1 = (unsigned *)Vec_PtrEntry( p->vCiSimInfo, i ); - for ( w = 0; w < p->nWords; w++ ) - pInfo1[w] = pInfo0[w]; - } - for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) - { - pInfo0 = (unsigned *)Vec_PtrEntry( p->vCoSimInfo, Gia_ManPoNum(p->pAig) + i ); - pInfo1 = (unsigned *)Vec_PtrEntry( p->vCiSimInfo, Gia_ManPiNum(p->pAig) + i ); - for ( w = 0; w < p->nWords; w++ ) - pInfo1[w] = pInfo0[w]; - } - if ( Cec_ManSimSimulateRound( p, p->vCiSimInfo, p->vCoSimInfo ) ) - return 1; - } - assert( k == Vec_PtrSize(vInfo) ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Resimulates information to refine equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManSeqResimulateInfo( Gia_Man_t * pAig, Vec_Ptr_t * vSimInfo, Abc_Cex_t * pBestState, int fCheckMiter ) -{ - Cec_ParSim_t ParsSim, * pParsSim = &ParsSim; - Cec_ManSim_t * pSim; - int RetValue, clkTotal = clock(); - assert( (Vec_PtrSize(vSimInfo) - Gia_ManRegNum(pAig)) % Gia_ManPiNum(pAig) == 0 ); - Cec_ManSimSetDefaultParams( pParsSim ); - pParsSim->nFrames = (Vec_PtrSize(vSimInfo) - Gia_ManRegNum(pAig)) / Gia_ManPiNum(pAig); - pParsSim->nWords = Vec_PtrReadWordsSimInfo( vSimInfo ); - pParsSim->fCheckMiter = fCheckMiter; - Gia_ManSetRefs( pAig ); - pSim = Cec_ManSimStart( pAig, pParsSim ); - if ( pBestState ) - pSim->pBestState = pBestState; - RetValue = Cec_ManSeqResimulate( pSim, vSimInfo ); - pSim->pBestState = NULL; - Cec_ManSimStop( pSim ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Resimuates one counter-example to refine equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManSeqResimulateCounter( Gia_Man_t * pAig, Cec_ParSim_t * pPars, Abc_Cex_t * pCex ) -{ - Vec_Ptr_t * vSimInfo; - int RetValue, clkTotal = clock(); - if ( pCex == NULL ) - { - Abc_Print( 1, "Cec_ManSeqResimulateCounter(): Counter-example is not available.\n" ); - return -1; - } - if ( pAig->pReprs == NULL ) - { - Abc_Print( 1, "Cec_ManSeqResimulateCounter(): Equivalence classes are not available.\n" ); - return -1; - } - if ( Gia_ManRegNum(pAig) == 0 ) - { - Abc_Print( 1, "Cec_ManSeqResimulateCounter(): Not a sequential AIG.\n" ); - return -1; - } -// if ( Gia_ManRegNum(pAig) != pCex->nRegs || Gia_ManPiNum(pAig) != pCex->nPis ) - if ( Gia_ManPiNum(pAig) != pCex->nPis ) - { - Abc_Print( 1, "Cec_ManSeqResimulateCounter(): The number of PIs in the AIG and the counter-example differ.\n" ); - return -1; - } - if ( pPars->fVerbose ) - Abc_Print( 1, "Resimulating %d timeframes.\n", pPars->nFrames + pCex->iFrame + 1 ); - Gia_ManRandom( 1 ); - vSimInfo = Vec_PtrAllocSimInfo( Gia_ManRegNum(pAig) + - Gia_ManPiNum(pAig) * (pPars->nFrames + pCex->iFrame + 1), 1 ); - Cec_ManSeqDeriveInfoFromCex( vSimInfo, pAig, pCex ); - if ( pPars->fVerbose ) - Gia_ManEquivPrintClasses( pAig, 0, 0 ); - RetValue = Cec_ManSeqResimulateInfo( pAig, vSimInfo, NULL, pPars->fCheckMiter ); - if ( pPars->fVerbose ) - Gia_ManEquivPrintClasses( pAig, 0, 0 ); - Vec_PtrFree( vSimInfo ); - if ( pPars->fVerbose ) - ABC_PRT( "Time", clock() - clkTotal ); -// if ( RetValue && pPars->fCheckMiter ) -// Abc_Print( 1, "Cec_ManSeqResimulateCounter(): An output of the miter is asserted!\n" ); - return RetValue; -} - - -/**Function************************************************************* - - Synopsis [Returns the number of POs that are not const0 cands.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManCountNonConstOutputs( Gia_Man_t * pAig ) -{ - Gia_Obj_t * pObj; - int i, Counter = 0; - if ( pAig->pReprs == NULL ) - return -1; - Gia_ManForEachPo( pAig, pObj, i ) - if ( !Gia_ObjIsConst( pAig, Gia_ObjFaninId0p(pAig, pObj) ) ) - Counter++; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Returns the number of POs that are not const0 cands.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManCheckNonTrivialCands( Gia_Man_t * pAig ) -{ - Gia_Obj_t * pObj; - int i, RetValue = 0; - if ( pAig->pReprs == NULL ) - return 0; - // label internal nodes driving POs - Gia_ManForEachPo( pAig, pObj, i ) - Gia_ObjFanin0(pObj)->fMark0 = 1; - // check if there are non-labled equivs - Gia_ManForEachObj( pAig, pObj, i ) - if ( Gia_ObjIsCand(pObj) && !pObj->fMark0 && Gia_ObjRepr(pAig, i) != GIA_VOID ) - { - RetValue = 1; - break; - } - // clean internal nodes driving POs - Gia_ManForEachPo( pAig, pObj, i ) - Gia_ObjFanin0(pObj)->fMark0 = 0; - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Performs semiformal refinement of equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManSeqSemiformal( Gia_Man_t * pAig, Cec_ParSmf_t * pPars ) -{ - int nAddFrames = 16; // additional timeframes to simulate - int nCountNoRef = 0; - int nFramesReal; - Cec_ParSat_t ParsSat, * pParsSat = &ParsSat; - Vec_Ptr_t * vSimInfo; - Vec_Str_t * vStatus; - Abc_Cex_t * pState; - Gia_Man_t * pSrm, * pReduce, * pAux; - int r, nPats, RetValue = 0; - if ( pAig->pReprs == NULL ) - { - Abc_Print( 1, "Cec_ManSeqSemiformal(): Equivalence classes are not available.\n" ); - return -1; - } - if ( Gia_ManRegNum(pAig) == 0 ) - { - Abc_Print( 1, "Cec_ManSeqSemiformal(): Not a sequential AIG.\n" ); - return -1; - } - Gia_ManRandom( 1 ); - // prepare starting pattern - pState = Abc_CexAlloc( Gia_ManRegNum(pAig), 0, 0 ); - pState->iFrame = -1; - pState->iPo = -1; - // prepare SAT solving - Cec_ManSatSetDefaultParams( pParsSat ); - pParsSat->nBTLimit = pPars->nBTLimit; - pParsSat->fVerbose = pPars->fVerbose; - if ( pParsSat->fVerbose ) - { - Abc_Print( 1, "Starting: " ); - Gia_ManEquivPrintClasses( pAig, 0, 0 ); - } - // perform the given number of BMC rounds - Gia_ManCleanMark0( pAig ); - for ( r = 0; r < pPars->nRounds; r++ ) - { - if ( !Cec_ManCheckNonTrivialCands(pAig) ) - { - Abc_Print( 1, "Cec_ManSeqSemiformal: There are only trivial equiv candidates left (PO drivers). Quitting.\n" ); - break; - } -// Abc_CexPrint( pState ); - // derive speculatively reduced model -// pSrm = Gia_ManSpecReduceInit( pAig, pState, pPars->nFrames, pPars->fDualOut ); - pSrm = Gia_ManSpecReduceInitFrames( pAig, pState, pPars->nFrames, &nFramesReal, pPars->fDualOut, pPars->nMinOutputs ); - if ( pSrm == NULL ) - { - Abc_Print( 1, "Quitting refinement because miter could not be unrolled.\n" ); - break; - } - assert( Gia_ManRegNum(pSrm) == 0 && Gia_ManPiNum(pSrm) == (Gia_ManPiNum(pAig) * nFramesReal) ); - if ( pPars->fVerbose ) - Abc_Print( 1, "Unrolled for %d frames.\n", nFramesReal ); - // allocate room for simulation info - vSimInfo = Vec_PtrAllocSimInfo( Gia_ManRegNum(pAig) + - Gia_ManPiNum(pAig) * (nFramesReal + nAddFrames), pPars->nWords ); - Cec_ManSeqDeriveInfoInitRandom( vSimInfo, pAig, pState ); - // fill in simulation info with counter-examples - vStatus = Cec_ManSatSolveSeq( vSimInfo, pSrm, pParsSat, Gia_ManRegNum(pAig), &nPats ); - Vec_StrFree( vStatus ); - Gia_ManStop( pSrm ); - // resimulate and refine the classes - RetValue = Cec_ManSeqResimulateInfo( pAig, vSimInfo, pState, pPars->fCheckMiter ); - Vec_PtrFree( vSimInfo ); - assert( pState->iPo >= 0 ); // hit counter - pState->iPo = -1; - if ( pPars->fVerbose ) - { - Abc_Print( 1, "BMC = %3d ", nPats ); - Gia_ManEquivPrintClasses( pAig, 0, 0 ); - } - - // write equivalence classes - Gia_WriteAiger( pAig, "gore.aig", 0, 0 ); - // reduce the model - pReduce = Gia_ManSpecReduce( pAig, 0, 0, 1, 0, 0 ); - if ( pReduce ) - { - pReduce = Gia_ManSeqStructSweep( pAux = pReduce, 1, 1, 0 ); - Gia_ManStop( pAux ); - Gia_WriteAiger( pReduce, "gsrm.aig", 0, 0 ); -// Abc_Print( 1, "Speculatively reduced model was written into file \"%s\".\n", "gsrm.aig" ); -// Gia_ManPrintStatsShort( pReduce ); - Gia_ManStop( pReduce ); - } - - if ( RetValue ) - { - Abc_Print( 1, "Cec_ManSeqSemiformal(): An output of the miter is asserted. Refinement stopped.\n" ); - break; - } - // decide when to stop - if ( nPats > 0 ) - nCountNoRef = 0; - else if ( ++nCountNoRef == pPars->nNonRefines ) - break; - } - ABC_FREE( pState ); - if ( pPars->fCheckMiter ) - { - int nNonConsts = Cec_ManCountNonConstOutputs( pAig ); - if ( nNonConsts ) - Abc_Print( 1, "The number of POs that are not const-0 candidates = %d.\n", nNonConsts ); - } - return RetValue; -} - -//&r s13207.aig; &ps; ≡ &ps; &semi -R 2 -vm -//&r bug/50/temp.aig; &ps; &equiv -smv; &semi -v -//r mentor/1_05c.blif; st; &get; &ps; &equiv -smv; &semi -mv -//&r bug/50/hdl1.aig; &ps; &equiv -smv; &semi -mv; &srm; &r gsrm.aig; &ps - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cec/cecSim.c b/src/aig/cec/cecSim.c deleted file mode 100644 index 92f8fc2e..00000000 --- a/src/aig/cec/cecSim.c +++ /dev/null @@ -1,53 +0,0 @@ -/**CFile**************************************************************** - - FileName [cecSim.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Combinational equivalence checking.] - - Synopsis [Simulation manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cecSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cecInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cec/cecSolve.c b/src/aig/cec/cecSolve.c deleted file mode 100644 index e86c2f35..00000000 --- a/src/aig/cec/cecSolve.c +++ /dev/null @@ -1,1023 +0,0 @@ -/**CFile**************************************************************** - - FileName [cecSolve.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Combinational equivalence checking.] - - Synopsis [Performs one round of SAT solving.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cecSolve.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cecInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline int Cec_ObjSatNum( Cec_ManSat_t * p, Gia_Obj_t * pObj ) { return p->pSatVars[Gia_ObjId(p->pAig,pObj)]; } -static inline void Cec_ObjSetSatNum( Cec_ManSat_t * p, Gia_Obj_t * pObj, int Num ) { p->pSatVars[Gia_ObjId(p->pAig,pObj)] = Num; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns value of the SAT variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ObjSatVarValue( Cec_ManSat_t * p, Gia_Obj_t * pObj ) -{ - return sat_solver_var_value( p->pSat, Cec_ObjSatNum(p, pObj) ); -} - -/**Function************************************************************* - - Synopsis [Addes clauses to the solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_AddClausesMux( Cec_ManSat_t * p, Gia_Obj_t * pNode ) -{ - Gia_Obj_t * pNodeI, * pNodeT, * pNodeE; - int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE; - - assert( !Gia_IsComplement( pNode ) ); - assert( Gia_ObjIsMuxType( pNode ) ); - // get nodes (I = if, T = then, E = else) - pNodeI = Gia_ObjRecognizeMux( pNode, &pNodeT, &pNodeE ); - // get the variable numbers - VarF = Cec_ObjSatNum(p,pNode); - VarI = Cec_ObjSatNum(p,pNodeI); - VarT = Cec_ObjSatNum(p,Gia_Regular(pNodeT)); - VarE = Cec_ObjSatNum(p,Gia_Regular(pNodeE)); - // get the complementation flags - fCompT = Gia_IsComplement(pNodeT); - fCompE = Gia_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); - if ( p->pPars->fPolarFlip ) - { - if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); - if ( Gia_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] ); - if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); - } - 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); - if ( p->pPars->fPolarFlip ) - { - if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); - if ( Gia_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] ); - if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); - } - 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); - if ( p->pPars->fPolarFlip ) - { - if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); - if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); - if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); - } - 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); - if ( p->pPars->fPolarFlip ) - { - if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); - if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); - if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); - } - 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); - if ( p->pPars->fPolarFlip ) - { - if ( Gia_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] ); - if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); - if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); - } - 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); - if ( p->pPars->fPolarFlip ) - { - if ( Gia_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] ); - if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); - if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); - } - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); - assert( RetValue ); -} - -/**Function************************************************************* - - Synopsis [Addes clauses to the solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_AddClausesSuper( Cec_ManSat_t * p, Gia_Obj_t * pNode, Vec_Ptr_t * vSuper ) -{ - Gia_Obj_t * pFanin; - int * pLits, nLits, RetValue, i; - assert( !Gia_IsComplement(pNode) ); - assert( Gia_ObjIsAnd( pNode ) ); - // create storage for literals - nLits = Vec_PtrSize(vSuper) + 1; - pLits = ABC_ALLOC( int, nLits ); - // suppose AND-gate is A & B = C - // add !A => !C or A + !C - Vec_PtrForEachEntry( Gia_Obj_t *, vSuper, pFanin, i ) - { - pLits[0] = toLitCond(Cec_ObjSatNum(p,Gia_Regular(pFanin)), Gia_IsComplement(pFanin)); - pLits[1] = toLitCond(Cec_ObjSatNum(p,pNode), 1); - if ( p->pPars->fPolarFlip ) - { - if ( Gia_Regular(pFanin)->fPhase ) pLits[0] = lit_neg( pLits[0] ); - if ( pNode->fPhase ) pLits[1] = lit_neg( pLits[1] ); - } - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); - assert( RetValue ); - } - // add A & B => C or !A + !B + C - Vec_PtrForEachEntry( Gia_Obj_t *, vSuper, pFanin, i ) - { - pLits[i] = toLitCond(Cec_ObjSatNum(p,Gia_Regular(pFanin)), !Gia_IsComplement(pFanin)); - if ( p->pPars->fPolarFlip ) - { - if ( Gia_Regular(pFanin)->fPhase ) pLits[i] = lit_neg( pLits[i] ); - } - } - pLits[nLits-1] = toLitCond(Cec_ObjSatNum(p,pNode), 0); - if ( p->pPars->fPolarFlip ) - { - if ( pNode->fPhase ) pLits[nLits-1] = lit_neg( pLits[nLits-1] ); - } - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits ); - assert( RetValue ); - ABC_FREE( pLits ); -} - -/**Function************************************************************* - - Synopsis [Collects the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_CollectSuper_rec( Gia_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes ) -{ - // if the new node is complemented or a PI, another gate begins - if ( Gia_IsComplement(pObj) || Gia_ObjIsCi(pObj) || - (!fFirst && Gia_ObjValue(pObj) > 1) || - (fUseMuxes && Gia_ObjIsMuxType(pObj)) ) - { - Vec_PtrPushUnique( vSuper, pObj ); - return; - } - // go through the branches - Cec_CollectSuper_rec( Gia_ObjChild0(pObj), vSuper, 0, fUseMuxes ); - Cec_CollectSuper_rec( Gia_ObjChild1(pObj), vSuper, 0, fUseMuxes ); -} - -/**Function************************************************************* - - Synopsis [Collects the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_CollectSuper( Gia_Obj_t * pObj, int fUseMuxes, Vec_Ptr_t * vSuper ) -{ - assert( !Gia_IsComplement(pObj) ); - assert( !Gia_ObjIsCi(pObj) ); - Vec_PtrClear( vSuper ); - Cec_CollectSuper_rec( pObj, vSuper, 1, fUseMuxes ); -} - -/**Function************************************************************* - - Synopsis [Updates the solver clause database.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ObjAddToFrontier( Cec_ManSat_t * p, Gia_Obj_t * pObj, Vec_Ptr_t * vFrontier ) -{ - assert( !Gia_IsComplement(pObj) ); - if ( Cec_ObjSatNum(p,pObj) ) - return; - assert( Cec_ObjSatNum(p,pObj) == 0 ); - if ( Gia_ObjIsConst0(pObj) ) - return; - Vec_PtrPush( p->vUsedNodes, pObj ); - Cec_ObjSetSatNum( p, pObj, p->nSatVars++ ); - if ( Gia_ObjIsAnd(pObj) ) - Vec_PtrPush( vFrontier, pObj ); -} - -/**Function************************************************************* - - Synopsis [Updates the solver clause database.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_CnfNodeAddToSolver( Cec_ManSat_t * p, Gia_Obj_t * pObj ) -{ - Vec_Ptr_t * vFrontier; - Gia_Obj_t * pNode, * pFanin; - int i, k, fUseMuxes = 1; - // quit if CNF is ready - if ( Cec_ObjSatNum(p,pObj) ) - return; - if ( Gia_ObjIsCi(pObj) ) - { - Vec_PtrPush( p->vUsedNodes, pObj ); - Cec_ObjSetSatNum( p, pObj, p->nSatVars++ ); - sat_solver_setnvars( p->pSat, p->nSatVars ); - return; - } - assert( Gia_ObjIsAnd(pObj) ); - // start the frontier - vFrontier = Vec_PtrAlloc( 100 ); - Cec_ObjAddToFrontier( p, pObj, vFrontier ); - // explore nodes in the frontier - Vec_PtrForEachEntry( Gia_Obj_t *, vFrontier, pNode, i ) - { - // create the supergate - assert( Cec_ObjSatNum(p,pNode) ); - if ( fUseMuxes && Gia_ObjIsMuxType(pNode) ) - { - Vec_PtrClear( p->vFanins ); - Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin0( Gia_ObjFanin0(pNode) ) ); - Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin0( Gia_ObjFanin1(pNode) ) ); - Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin1( Gia_ObjFanin0(pNode) ) ); - Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin1( Gia_ObjFanin1(pNode) ) ); - Vec_PtrForEachEntry( Gia_Obj_t *, p->vFanins, pFanin, k ) - Cec_ObjAddToFrontier( p, Gia_Regular(pFanin), vFrontier ); - Cec_AddClausesMux( p, pNode ); - } - else - { - Cec_CollectSuper( pNode, fUseMuxes, p->vFanins ); - Vec_PtrForEachEntry( Gia_Obj_t *, p->vFanins, pFanin, k ) - Cec_ObjAddToFrontier( p, Gia_Regular(pFanin), vFrontier ); - Cec_AddClausesSuper( p, pNode, p->vFanins ); - } - assert( Vec_PtrSize(p->vFanins) > 1 ); - } - Vec_PtrFree( vFrontier ); -} - - -/**Function************************************************************* - - Synopsis [Recycles the SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManSatSolverRecycle( Cec_ManSat_t * p ) -{ - int Lit; - if ( p->pSat ) - { - Gia_Obj_t * pObj; - int i; - Vec_PtrForEachEntry( Gia_Obj_t *, p->vUsedNodes, pObj, i ) - Cec_ObjSetSatNum( p, pObj, 0 ); - Vec_PtrClear( p->vUsedNodes ); -// memset( p->pSatVars, 0, sizeof(int) * Gia_ManObjNumMax(p->pAigTotal) ); - sat_solver_delete( p->pSat ); - } - p->pSat = sat_solver_new(); - p->pSat->factors = ABC_CALLOC( double, 1 ); - sat_solver_setnvars( p->pSat, 1000 ); - // var 0 is not used - // var 1 is reserved for const0 node - add the clause - p->nSatVars = 1; -// p->nSatVars = 0; - Lit = toLitCond( p->nSatVars, 1 ); - if ( p->pPars->fPolarFlip ) - Lit = lit_neg( Lit ); - sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ); - Cec_ObjSetSatNum( p, Gia_ManConst0(p->pAig), p->nSatVars++ ); - - p->nRecycles++; - p->nCallsSince = 0; -} - -/**Function************************************************************* - - Synopsis [Sets variable activities in the cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_SetActivityFactors_rec( Cec_ManSat_t * p, Gia_Obj_t * pObj, int LevelMin, int LevelMax ) -{ - float dActConeBumpMax = 20.0; - int iVar; - // skip visited variables - if ( Gia_ObjIsTravIdCurrent(p->pAig, pObj) ) - return; - Gia_ObjSetTravIdCurrent(p->pAig, pObj); - // add the PI to the list - if ( Gia_ObjLevel(p->pAig, pObj) <= LevelMin || Gia_ObjIsCi(pObj) ) - return; - // set the factor of this variable - // (LevelMax-LevelMin) / (pObj->Level-LevelMin) = p->pPars->dActConeBumpMax / ThisBump - if ( (iVar = Cec_ObjSatNum(p,pObj)) ) - { - p->pSat->factors[iVar] = dActConeBumpMax * (Gia_ObjLevel(p->pAig, pObj) - LevelMin)/(LevelMax - LevelMin); - veci_push(&p->pSat->act_vars, iVar); - } - // explore the fanins - Cec_SetActivityFactors_rec( p, Gia_ObjFanin0(pObj), LevelMin, LevelMax ); - Cec_SetActivityFactors_rec( p, Gia_ObjFanin1(pObj), LevelMin, LevelMax ); -} - -/**Function************************************************************* - - Synopsis [Sets variable activities in the cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_SetActivityFactors( Cec_ManSat_t * p, Gia_Obj_t * pObj ) -{ - float dActConeRatio = 0.5; - int LevelMin, LevelMax; - // reset the active variables - veci_resize(&p->pSat->act_vars, 0); - // prepare for traversal - Gia_ManIncrementTravId( p->pAig ); - // determine the min and max level to visit - assert( dActConeRatio > 0 && dActConeRatio < 1 ); - LevelMax = Gia_ObjLevel(p->pAig,pObj); - LevelMin = (int)(LevelMax * (1.0 - dActConeRatio)); - // traverse - Cec_SetActivityFactors_rec( p, pObj, LevelMin, LevelMax ); -//Cec_PrintActivity( p ); - return 1; -} - - -/**Function************************************************************* - - Synopsis [Runs equivalence test for the two nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManSatCheckNode( Cec_ManSat_t * p, Gia_Obj_t * pObj ) -{ - Gia_Obj_t * pObjR = Gia_Regular(pObj); - int nBTLimit = p->pPars->nBTLimit; - int Lit, RetValue, status, clk, clk2, nConflicts; - - if ( pObj == Gia_ManConst0(p->pAig) ) - return 1; - if ( pObj == Gia_ManConst1(p->pAig) ) - { - assert( 0 ); - return 0; - } - - p->nCallsSince++; // experiment with this!!! - p->nSatTotal++; - - // check if SAT solver needs recycling - if ( p->pSat == NULL || - (p->pPars->nSatVarMax && - p->nSatVars > p->pPars->nSatVarMax && - p->nCallsSince > p->pPars->nCallsRecycle) ) - Cec_ManSatSolverRecycle( p ); - - // if the nodes do not have SAT variables, allocate them -clk2 = clock(); - Cec_CnfNodeAddToSolver( p, pObjR ); -//ABC_PRT( "cnf", clock() - clk2 ); -//Abc_Print( 1, "%d \n", p->pSat->size ); - -clk2 = clock(); -// Cec_SetActivityFactors( p, pObjR ); -//ABC_PRT( "act", clock() - clk2 ); - - // propage unit clauses - if ( p->pSat->qtail != p->pSat->qhead ) - { - status = sat_solver_simplify(p->pSat); - assert( status != 0 ); - assert( p->pSat->qtail == p->pSat->qhead ); - } - - // solve under assumptions - // A = 1; B = 0 OR A = 1; B = 1 - Lit = toLitCond( Cec_ObjSatNum(p,pObjR), Gia_IsComplement(pObj) ); - if ( p->pPars->fPolarFlip ) - { - if ( pObjR->fPhase ) Lit = lit_neg( Lit ); - } -//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 ); -clk = clock(); - nConflicts = p->pSat->stats.conflicts; - -clk2 = clock(); - RetValue = sat_solver_solve( p->pSat, &Lit, &Lit + 1, - (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); -//ABC_PRT( "sat", clock() - clk2 ); - - if ( RetValue == l_False ) - { -p->timeSatUnsat += clock() - clk; - Lit = lit_neg( Lit ); - RetValue = sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ); - assert( RetValue ); - p->nSatUnsat++; - p->nConfUnsat += p->pSat->stats.conflicts - nConflicts; -//Abc_Print( 1, "UNSAT after %d conflicts\n", p->pSat->stats.conflicts - nConflicts ); - return 1; - } - else if ( RetValue == l_True ) - { -p->timeSatSat += clock() - clk; - p->nSatSat++; - p->nConfSat += p->pSat->stats.conflicts - nConflicts; -//Abc_Print( 1, "SAT after %d conflicts\n", p->pSat->stats.conflicts - nConflicts ); - return 0; - } - else // if ( RetValue == l_Undef ) - { -p->timeSatUndec += clock() - clk; - p->nSatUndec++; - p->nConfUndec += p->pSat->stats.conflicts - nConflicts; -//Abc_Print( 1, "UNDEC after %d conflicts\n", p->pSat->stats.conflicts - nConflicts ); - return -1; - } -} - -/**Function************************************************************* - - Synopsis [Runs equivalence test for the two nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManSatCheckNodeTwo( Cec_ManSat_t * p, Gia_Obj_t * pObj1, Gia_Obj_t * pObj2 ) -{ - Gia_Obj_t * pObjR1 = Gia_Regular(pObj1); - Gia_Obj_t * pObjR2 = Gia_Regular(pObj2); - int nBTLimit = p->pPars->nBTLimit; - int Lits[2], RetValue, status, clk, clk2, nConflicts; - - if ( pObj1 == Gia_ManConst0(p->pAig) || pObj2 == Gia_ManConst0(p->pAig) || pObj1 == Gia_Not(pObj2) ) - return 1; - if ( pObj1 == Gia_ManConst1(p->pAig) && (pObj2 == NULL || pObj2 == Gia_ManConst1(p->pAig)) ) - { - assert( 0 ); - return 0; - } - - p->nCallsSince++; // experiment with this!!! - p->nSatTotal++; - - // check if SAT solver needs recycling - if ( p->pSat == NULL || - (p->pPars->nSatVarMax && - p->nSatVars > p->pPars->nSatVarMax && - p->nCallsSince > p->pPars->nCallsRecycle) ) - Cec_ManSatSolverRecycle( p ); - - // if the nodes do not have SAT variables, allocate them -clk2 = clock(); - Cec_CnfNodeAddToSolver( p, pObjR1 ); - Cec_CnfNodeAddToSolver( p, pObjR2 ); -//ABC_PRT( "cnf", clock() - clk2 ); -//Abc_Print( 1, "%d \n", p->pSat->size ); - -clk2 = clock(); -// Cec_SetActivityFactors( p, pObjR1 ); -// Cec_SetActivityFactors( p, pObjR2 ); -//ABC_PRT( "act", clock() - clk2 ); - - // propage unit clauses - if ( p->pSat->qtail != p->pSat->qhead ) - { - status = sat_solver_simplify(p->pSat); - assert( status != 0 ); - assert( p->pSat->qtail == p->pSat->qhead ); - } - - // solve under assumptions - // A = 1; B = 0 OR A = 1; B = 1 - Lits[0] = toLitCond( Cec_ObjSatNum(p,pObjR1), Gia_IsComplement(pObj1) ); - Lits[1] = toLitCond( Cec_ObjSatNum(p,pObjR2), Gia_IsComplement(pObj2) ); - if ( p->pPars->fPolarFlip ) - { - if ( pObjR1->fPhase ) Lits[0] = lit_neg( Lits[0] ); - if ( pObjR2->fPhase ) Lits[1] = lit_neg( Lits[1] ); - } -//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 ); -clk = clock(); - nConflicts = p->pSat->stats.conflicts; - -clk2 = clock(); - RetValue = sat_solver_solve( p->pSat, Lits, Lits + 2, - (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); -//ABC_PRT( "sat", clock() - clk2 ); - - if ( RetValue == l_False ) - { -p->timeSatUnsat += clock() - clk; - Lits[0] = lit_neg( Lits[0] ); - Lits[1] = lit_neg( Lits[1] ); - RetValue = sat_solver_addclause( p->pSat, Lits, Lits + 2 ); - assert( RetValue ); - p->nSatUnsat++; - p->nConfUnsat += p->pSat->stats.conflicts - nConflicts; -//Abc_Print( 1, "UNSAT after %d conflicts\n", p->pSat->stats.conflicts - nConflicts ); - return 1; - } - else if ( RetValue == l_True ) - { -p->timeSatSat += clock() - clk; - p->nSatSat++; - p->nConfSat += p->pSat->stats.conflicts - nConflicts; -//Abc_Print( 1, "SAT after %d conflicts\n", p->pSat->stats.conflicts - nConflicts ); - return 0; - } - else // if ( RetValue == l_Undef ) - { -p->timeSatUndec += clock() - clk; - p->nSatUndec++; - p->nConfUndec += p->pSat->stats.conflicts - nConflicts; -//Abc_Print( 1, "UNDEC after %d conflicts\n", p->pSat->stats.conflicts - nConflicts ); - return -1; - } -} - - -/**Function************************************************************* - - Synopsis [Performs one round of solving for the POs of the AIG.] - - Description [Labels the nodes that have been proved (pObj->fMark1) - and returns the set of satisfying assignments.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManSatSolve( Cec_ManPat_t * pPat, Gia_Man_t * pAig, Cec_ParSat_t * pPars ) -{ - Bar_Progress_t * pProgress = NULL; - Cec_ManSat_t * p; - Gia_Obj_t * pObj; - int i, status, clk = clock(), clk2; - // reset the manager - if ( pPat ) - { - pPat->iStart = Vec_StrSize(pPat->vStorage); - pPat->nPats = 0; - pPat->nPatLits = 0; - pPat->nPatLitsMin = 0; - } - Gia_ManSetPhase( pAig ); - Gia_ManLevelNum( pAig ); - Gia_ManIncrementTravId( pAig ); - p = Cec_ManSatCreate( pAig, pPars ); - pProgress = Bar_ProgressStart( stdout, Gia_ManPoNum(pAig) ); - Gia_ManForEachCo( pAig, pObj, i ) - { - if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) - { - pObj->fMark0 = 0; - pObj->fMark1 = 1; - continue; - } - Bar_ProgressUpdate( pProgress, i, "SAT..." ); -clk2 = clock(); - status = Cec_ManSatCheckNode( p, Gia_ObjChild0(pObj) ); - pObj->fMark0 = (status == 0); - pObj->fMark1 = (status == 1); -/* - if ( status == -1 ) - { - Gia_Man_t * pTemp = Gia_ManDupDfsCone( pAig, pObj ); - Gia_WriteAiger( pTemp, "gia_hard.aig", 0, 0 ); - Gia_ManStop( pTemp ); - Abc_Print( 1, "Dumping hard cone into file \"%s\".\n", "gia_hard.aig" ); - } -*/ - if ( status != 0 ) - continue; - // save the pattern - if ( pPat ) - { - int clk3 = clock(); - Cec_ManPatSavePattern( pPat, p, pObj ); - pPat->timeTotalSave += clock() - clk3; - } - // quit if one of them is solved - if ( pPars->fCheckMiter ) - break; - } - p->timeTotal = clock() - clk; - Bar_ProgressStop( pProgress ); - if ( pPars->fVerbose ) - Cec_ManSatPrintStats( p ); - Cec_ManSatStop( p ); -} - - - -/**Function************************************************************* - - Synopsis [Returns the pattern stored.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Cec_ManSatReadCex( Cec_ManSat_t * pSat ) -{ - return pSat->vCex; -} - -/**Function************************************************************* - - Synopsis [Save values in the cone of influence.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManSatSolveSeq_rec( Cec_ManSat_t * pSat, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Ptr_t * vInfo, int iPat, int nRegs ) -{ - if ( Gia_ObjIsTravIdCurrent(p, pObj) ) - return; - Gia_ObjSetTravIdCurrent(p, pObj); - if ( Gia_ObjIsCi(pObj) ) - { - unsigned * pInfo = (unsigned *)Vec_PtrEntry( vInfo, nRegs + Gia_ObjCioId(pObj) ); - if ( Cec_ObjSatVarValue( pSat, pObj ) != Gia_InfoHasBit( pInfo, iPat ) ) - Gia_InfoXorBit( pInfo, iPat ); - pSat->nCexLits++; -// Vec_IntPush( pSat->vCex, Gia_Var2Lit( Gia_ObjCioId(pObj), !Cec_ObjSatVarValue(pSat, pObj) ) ); - return; - } - assert( Gia_ObjIsAnd(pObj) ); - Cec_ManSatSolveSeq_rec( pSat, p, Gia_ObjFanin0(pObj), vInfo, iPat, nRegs ); - Cec_ManSatSolveSeq_rec( pSat, p, Gia_ObjFanin1(pObj), vInfo, iPat, nRegs ); -} - -/**Function************************************************************* - - Synopsis [Performs one round of solving for the POs of the AIG.] - - Description [Labels the nodes that have been proved (pObj->fMark1) - and returns the set of satisfying assignments.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Str_t * Cec_ManSatSolveSeq( Vec_Ptr_t * vPatts, Gia_Man_t * pAig, Cec_ParSat_t * pPars, int nRegs, int * pnPats ) -{ - Bar_Progress_t * pProgress = NULL; - Vec_Str_t * vStatus; - Cec_ManSat_t * p; - Gia_Obj_t * pObj; - int iPat = 0, nPatsInit, nPats; - int i, status, clk = clock(); - nPatsInit = nPats = 32 * Vec_PtrReadWordsSimInfo(vPatts); - Gia_ManSetPhase( pAig ); - Gia_ManLevelNum( pAig ); - Gia_ManIncrementTravId( pAig ); - p = Cec_ManSatCreate( pAig, pPars ); - vStatus = Vec_StrAlloc( Gia_ManPoNum(pAig) ); - pProgress = Bar_ProgressStart( stdout, Gia_ManPoNum(pAig) ); - Gia_ManForEachCo( pAig, pObj, i ) - { - Bar_ProgressUpdate( pProgress, i, "SAT..." ); - if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) - { - if ( Gia_ObjFaninC0(pObj) ) - { -// Abc_Print( 1, "Constant 1 output of SRM!!!\n" ); - Vec_StrPush( vStatus, 0 ); - } - else - { -// Abc_Print( 1, "Constant 0 output of SRM!!!\n" ); - Vec_StrPush( vStatus, 1 ); - } - continue; - } - status = Cec_ManSatCheckNode( p, Gia_ObjChild0(pObj) ); -//Abc_Print( 1, "output %d status = %d\n", i, status ); - Vec_StrPush( vStatus, (char)status ); - if ( status != 0 ) - continue; - // resize storage - if ( iPat == nPats ) - { - int nWords = Vec_PtrReadWordsSimInfo(vPatts); - Vec_PtrReallocSimInfo( vPatts ); - Vec_PtrCleanSimInfo( vPatts, nWords, 2*nWords ); - nPats = 32 * Vec_PtrReadWordsSimInfo(vPatts); - } - if ( iPat % nPatsInit == 0 ) - iPat++; - // save the pattern - Gia_ManIncrementTravId( pAig ); -// Vec_IntClear( p->vCex ); - Cec_ManSatSolveSeq_rec( p, pAig, Gia_ObjFanin0(pObj), vPatts, iPat++, nRegs ); -// Gia_SatVerifyPattern( pAig, pObj, p->vCex, p->vVisits ); -// Cec_ManSatAddToStore( p->vCexStore, p->vCex ); -// if ( iPat == nPats ) -// break; - // quit if one of them is solved -// if ( pPars->fFirstStop ) -// break; -// if ( iPat == 32 * 15 * 16 - 1 ) -// break; - } - p->timeTotal = clock() - clk; - Bar_ProgressStop( pProgress ); - if ( pPars->fVerbose ) - Cec_ManSatPrintStats( p ); -// Abc_Print( 1, "Total number of cex literals = %d. (Ave = %d)\n", p->nCexLits, p->nCexLits/p->nSatSat ); - Cec_ManSatStop( p ); - if ( pnPats ) - *pnPats = iPat-1; - return vStatus; -} - - -/**Function************************************************************* - - Synopsis [Save values in the cone of influence.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out ) -{ - int i, Entry; - Vec_IntPush( vCexStore, Out ); - if ( vCex == NULL ) // timeout - { - Vec_IntPush( vCexStore, -1 ); - return; - } - // write the counter-example - Vec_IntPush( vCexStore, Vec_IntSize(vCex) ); - Vec_IntForEachEntry( vCex, Entry, i ) - Vec_IntPush( vCexStore, Entry ); -} - -/**Function************************************************************* - - Synopsis [Save values in the cone of influence.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManSatSolveMiter_rec( Cec_ManSat_t * pSat, Gia_Man_t * p, Gia_Obj_t * pObj ) -{ - if ( Gia_ObjIsTravIdCurrent(p, pObj) ) - return; - Gia_ObjSetTravIdCurrent(p, pObj); - if ( Gia_ObjIsCi(pObj) ) - { - pSat->nCexLits++; - Vec_IntPush( pSat->vCex, Gia_Var2Lit( Gia_ObjCioId(pObj), !Cec_ObjSatVarValue(pSat, pObj) ) ); - return; - } - assert( Gia_ObjIsAnd(pObj) ); - Cec_ManSatSolveMiter_rec( pSat, p, Gia_ObjFanin0(pObj) ); - Cec_ManSatSolveMiter_rec( pSat, p, Gia_ObjFanin1(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Save patterns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManSavePattern( Cec_ManSat_t * p, Gia_Obj_t * pObj1, Gia_Obj_t * pObj2 ) -{ - Vec_IntClear( p->vCex ); - Gia_ManIncrementTravId( p->pAig ); - Cec_ManSatSolveMiter_rec( p, p->pAig, Gia_Regular(pObj1) ); - if ( pObj2 ) - Cec_ManSatSolveMiter_rec( p, p->pAig, Gia_Regular(pObj2) ); -} - -/**Function************************************************************* - - Synopsis [Performs one round of solving for the POs of the AIG.] - - Description [Labels the nodes that have been proved (pObj->fMark1) - and returns the set of satisfying assignments.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Cec_ManSatSolveMiter( Gia_Man_t * pAig, Cec_ParSat_t * pPars, Vec_Str_t ** pvStatus ) -{ - Bar_Progress_t * pProgress = NULL; - Vec_Int_t * vCexStore; - Vec_Str_t * vStatus; - Cec_ManSat_t * p; - Gia_Obj_t * pObj; - int i, status, clk = clock(); - // prepare AIG - Gia_ManSetPhase( pAig ); - Gia_ManLevelNum( pAig ); - Gia_ManIncrementTravId( pAig ); - // create resulting data-structures - vStatus = Vec_StrAlloc( Gia_ManPoNum(pAig) ); - vCexStore = Vec_IntAlloc( 10000 ); - // perform solving - p = Cec_ManSatCreate( pAig, pPars ); - pProgress = Bar_ProgressStart( stdout, Gia_ManPoNum(pAig) ); - Gia_ManForEachCo( pAig, pObj, i ) - { - Vec_IntClear( p->vCex ); - Bar_ProgressUpdate( pProgress, i, "SAT..." ); - if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) - { - if ( Gia_ObjFaninC0(pObj) ) - { -// Abc_Print( 1, "Constant 1 output of SRM!!!\n" ); - Cec_ManSatAddToStore( vCexStore, p->vCex, i ); // trivial counter-example - Vec_StrPush( vStatus, 0 ); - } - else - { -// Abc_Print( 1, "Constant 0 output of SRM!!!\n" ); - Vec_StrPush( vStatus, 1 ); - } - continue; - } - status = Cec_ManSatCheckNode( p, Gia_ObjChild0(pObj) ); - Vec_StrPush( vStatus, (char)status ); - if ( status == -1 ) - { - Cec_ManSatAddToStore( vCexStore, NULL, i ); // timeout - continue; - } - if ( status == 1 ) - continue; - assert( status == 0 ); - // save the pattern -// Gia_ManIncrementTravId( pAig ); -// Cec_ManSatSolveMiter_rec( p, pAig, Gia_ObjFanin0(pObj) ); - Cec_ManSavePattern( p, Gia_ObjFanin0(pObj), NULL ); -// Gia_SatVerifyPattern( pAig, pObj, p->vCex, p->vVisits ); - Cec_ManSatAddToStore( vCexStore, p->vCex, i ); - } - p->timeTotal = clock() - clk; - Bar_ProgressStop( pProgress ); -// if ( pPars->fVerbose ) -// Cec_ManSatPrintStats( p ); - Cec_ManSatStop( p ); - *pvStatus = vStatus; - return vCexStore; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cec/cecSweep.c b/src/aig/cec/cecSweep.c deleted file mode 100644 index 7d59515e..00000000 --- a/src/aig/cec/cecSweep.c +++ /dev/null @@ -1,299 +0,0 @@ -/**CFile**************************************************************** - - FileName [cecSweep.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Combinational equivalence checking.] - - Synopsis [SAT sweeping manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cecSweep.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cecInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs limited speculative reduction.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Gia_Man_t * Cec_ManFraSpecReduction( Cec_ManFra_t * p ) -{ - Gia_Man_t * pNew, * pTemp; - Gia_Obj_t * pObj, * pRepr = NULL; - int iRes0, iRes1, iRepr, iNode, iMiter; - int i, fCompl, * piCopies, * pDepths; - Gia_ManSetPhase( p->pAig ); - Vec_IntClear( p->vXorNodes ); - if ( p->pPars->nLevelMax ) - Gia_ManLevelNum( p->pAig ); - pNew = Gia_ManStart( Gia_ManObjNum(p->pAig) ); - pNew->pName = Gia_UtilStrsav( p->pAig->pName ); - Gia_ManHashAlloc( pNew ); - piCopies = ABC_FALLOC( int, Gia_ManObjNum(p->pAig) ); - pDepths = ABC_CALLOC( int, Gia_ManObjNum(p->pAig) ); - piCopies[0] = 0; - Gia_ManForEachObj1( p->pAig, pObj, i ) - { - if ( Gia_ObjIsCi(pObj) ) - { - piCopies[i] = Gia_ManAppendCi( pNew ); - continue; - } - if ( Gia_ObjIsCo(pObj) ) - continue; - if ( piCopies[Gia_ObjFaninId0(pObj,i)] == -1 || - piCopies[Gia_ObjFaninId1(pObj,i)] == -1 ) - continue; - iRes0 = Gia_LitNotCond( piCopies[Gia_ObjFaninId0(pObj,i)], Gia_ObjFaninC0(pObj) ); - iRes1 = Gia_LitNotCond( piCopies[Gia_ObjFaninId1(pObj,i)], Gia_ObjFaninC1(pObj) ); - iNode = piCopies[i] = Gia_ManHashAnd( pNew, iRes0, iRes1 ); - pDepths[i] = ABC_MAX( pDepths[Gia_ObjFaninId0(pObj,i)], pDepths[Gia_ObjFaninId1(pObj,i)] ); - if ( Gia_ObjRepr(p->pAig, i) == GIA_VOID || Gia_ObjFailed(p->pAig, i) ) - continue; - assert( Gia_ObjRepr(p->pAig, i) < i ); - iRepr = piCopies[Gia_ObjRepr(p->pAig, i)]; - if ( iRepr == -1 ) - continue; - if ( Gia_LitRegular(iNode) == Gia_LitRegular(iRepr) ) - continue; - if ( p->pPars->nLevelMax && - (Gia_ObjLevel(p->pAig, pObj) > p->pPars->nLevelMax || - Gia_ObjLevel(p->pAig, pRepr) > p->pPars->nLevelMax) ) - continue; - if ( p->pPars->fDualOut ) - { -// if ( i % 1000 == 0 && Gia_ObjRepr(p->pAig, i) ) -// Gia_ManEquivPrintOne( p->pAig, Gia_ObjRepr(p->pAig, i), 0 ); - if ( p->pPars->fColorDiff ) - { - if ( !Gia_ObjDiffColors( p->pAig, Gia_ObjRepr(p->pAig, i), i ) ) - continue; - } - else - { - if ( !Gia_ObjDiffColors2( p->pAig, Gia_ObjRepr(p->pAig, i), i ) ) - continue; - } - } - pRepr = Gia_ManObj( p->pAig, Gia_ObjRepr(p->pAig, i) ); - fCompl = Gia_ObjPhaseReal(pObj) ^ Gia_ObjPhaseReal(pRepr); - piCopies[i] = Gia_LitNotCond( iRepr, fCompl ); - if ( Gia_ObjProved(p->pAig, i) ) - continue; - // produce speculative miter - iMiter = Gia_ManHashXor( pNew, iNode, piCopies[i] ); - Gia_ManAppendCo( pNew, iMiter ); - Vec_IntPush( p->vXorNodes, Gia_ObjRepr(p->pAig, i) ); - Vec_IntPush( p->vXorNodes, i ); - // add to the depth of this node - pDepths[i] = 1 + ABC_MAX( pDepths[i], pDepths[Gia_ObjRepr(p->pAig, i)] ); - if ( p->pPars->nDepthMax && pDepths[i] >= p->pPars->nDepthMax ) - piCopies[i] = -1; - } - ABC_FREE( piCopies ); - ABC_FREE( pDepths ); - Gia_ManHashStop( pNew ); - Gia_ManSetRegNum( pNew, 0 ); - pNew = Gia_ManCleanup( pTemp = pNew ); - Gia_ManStop( pTemp ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManFraClassesUpdate_rec( Gia_Obj_t * pObj ) -{ - int Result; - if ( pObj->fMark0 ) - return 1; - if ( Gia_ObjIsCi(pObj) || Gia_ObjIsConst0(pObj) ) - return 0; - Result = (Cec_ManFraClassesUpdate_rec( Gia_ObjFanin0(pObj) ) | - Cec_ManFraClassesUpdate_rec( Gia_ObjFanin1(pObj) )); - return pObj->fMark0 = Result; -} - -/**Function************************************************************* - - Synopsis [Creates simulation info for this round.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_ManFraCreateInfo( Cec_ManSim_t * p, Vec_Ptr_t * vCiInfo, Vec_Ptr_t * vInfo, int nSeries ) -{ - unsigned * pRes0, * pRes1; - int i, w; - for ( i = 0; i < Gia_ManCiNum(p->pAig); i++ ) - { - pRes0 = (unsigned *)Vec_PtrEntry( vCiInfo, i ); - pRes1 = (unsigned *)Vec_PtrEntry( vInfo, i ); - pRes1 += p->nWords * nSeries; - for ( w = 0; w < p->nWords; w++ ) - pRes0[w] = pRes1[w]; - } -} - -/**Function************************************************************* - - Synopsis [Updates equivalence classes using the patterns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_ManFraClassesUpdate( Cec_ManFra_t * p, Cec_ManSim_t * pSim, Cec_ManPat_t * pPat, Gia_Man_t * pNew ) -{ - Vec_Ptr_t * vInfo; - Gia_Obj_t * pObj, * pObjOld, * pReprOld; - int i, k, iRepr, iNode, clk; -clk = clock(); - vInfo = Cec_ManPatCollectPatterns( pPat, Gia_ManCiNum(p->pAig), pSim->nWords ); -p->timePat += clock() - clk; -clk = clock(); - if ( vInfo != NULL ) - { - Gia_ManSetRefs( p->pAig ); - for ( i = 0; i < pPat->nSeries; i++ ) - { - Cec_ManFraCreateInfo( pSim, pSim->vCiSimInfo, vInfo, i ); - if ( Cec_ManSimSimulateRound( pSim, pSim->vCiSimInfo, pSim->vCoSimInfo ) ) - { - Vec_PtrFree( vInfo ); - return 1; - } - } - Vec_PtrFree( vInfo ); - } -p->timeSim += clock() - clk; - assert( Vec_IntSize(p->vXorNodes) == 2*Gia_ManCoNum(pNew) ); - // mark the transitive fanout of failed nodes - if ( p->pPars->nDepthMax != 1 ) - { - Gia_ManCleanMark0( p->pAig ); - Gia_ManCleanMark1( p->pAig ); - Gia_ManForEachCo( pNew, pObj, k ) - { - iRepr = Vec_IntEntry( p->vXorNodes, 2*k ); - iNode = Vec_IntEntry( p->vXorNodes, 2*k+1 ); - if ( pObj->fMark0 == 0 && pObj->fMark1 == 1 ) // proved - continue; -// Gia_ManObj(p->pAig, iRepr)->fMark0 = 1; - Gia_ManObj(p->pAig, iNode)->fMark0 = 1; - } - // mark the nodes reachable through the failed nodes - Gia_ManForEachAnd( p->pAig, pObjOld, k ) - pObjOld->fMark0 |= (Gia_ObjFanin0(pObjOld)->fMark0 | Gia_ObjFanin1(pObjOld)->fMark0); - // unmark the disproved nodes - Gia_ManForEachCo( pNew, pObj, k ) - { - iRepr = Vec_IntEntry( p->vXorNodes, 2*k ); - iNode = Vec_IntEntry( p->vXorNodes, 2*k+1 ); - if ( pObj->fMark0 == 0 && pObj->fMark1 == 1 ) // proved - continue; - pObjOld = Gia_ManObj(p->pAig, iNode); - assert( pObjOld->fMark0 == 1 ); - if ( Gia_ObjFanin0(pObjOld)->fMark0 == 0 && Gia_ObjFanin1(pObjOld)->fMark0 == 0 ) - pObjOld->fMark1 = 1; - } - // clean marks - Gia_ManForEachAnd( p->pAig, pObjOld, k ) - if ( pObjOld->fMark1 ) - { - pObjOld->fMark0 = 0; - pObjOld->fMark1 = 0; - } - } - // set the results - p->nAllProved = p->nAllDisproved = p->nAllFailed = 0; - Gia_ManForEachCo( pNew, pObj, k ) - { - iRepr = Vec_IntEntry( p->vXorNodes, 2*k ); - iNode = Vec_IntEntry( p->vXorNodes, 2*k+1 ); - pReprOld = Gia_ManObj(p->pAig, iRepr); - pObjOld = Gia_ManObj(p->pAig, iNode); - if ( pObj->fMark1 ) - { // proved - assert( pObj->fMark0 == 0 ); - assert( !Gia_ObjProved(p->pAig, iNode) ); - if ( pReprOld->fMark0 == 0 && pObjOld->fMark0 == 0 ) -// if ( pObjOld->fMark0 == 0 ) - { - assert( iRepr == Gia_ObjRepr(p->pAig, iNode) ); - Gia_ObjSetProved( p->pAig, iNode ); - p->nAllProved++; - } - } - else if ( pObj->fMark0 ) - { // disproved - assert( pObj->fMark1 == 0 ); - if ( pReprOld->fMark0 == 0 && pObjOld->fMark0 == 0 ) -// if ( pObjOld->fMark0 == 0 ) - { - if ( iRepr == Gia_ObjRepr(p->pAig, iNode) ) - Abc_Print( 1, "Cec_ManFraClassesUpdate(): Error! Node is not refined!\n" ); - p->nAllDisproved++; - } - } - else - { // failed - assert( pObj->fMark0 == 0 ); - assert( pObj->fMark1 == 0 ); - assert( !Gia_ObjFailed(p->pAig, iNode) ); - assert( !Gia_ObjProved(p->pAig, iNode) ); - Gia_ObjSetFailed( p->pAig, iNode ); - p->nAllFailed++; - } - } - return 0; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cec/cecSynth.c b/src/aig/cec/cecSynth.c deleted file mode 100644 index 52b50a43..00000000 --- a/src/aig/cec/cecSynth.c +++ /dev/null @@ -1,380 +0,0 @@ -/**CFile**************************************************************** - - FileName [cecSynth.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Combinational equivalence checking.] - - Synopsis [Partitioned sequential synthesis.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cecSynth.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cecInt.h" -#include "giaAig.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Populate sequential synthesis parameters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cec_SeqSynthesisSetDefaultParams( Cec_ParSeq_t * p ) -{ - memset( p, 0, sizeof(Cec_ParSeq_t) ); - p->fUseLcorr = 0; // enables latch correspondence - p->fUseScorr = 0; // enables signal correspondence - p->nBTLimit = 1000; // (scorr/lcorr) conflict limit at a node - p->nFrames = 1; // (scorr only) the number of timeframes - p->nLevelMax = -1; // (scorr only) the max number of levels - p->fConsts = 1; // (scl only) merging constants - p->fEquivs = 1; // (scl only) merging equivalences - p->fUseMiniSat = 0; // enables MiniSat in lcorr/scorr - p->nMinDomSize = 100; // the size of minimum clock domain - p->fVeryVerbose = 0; // verbose stats - p->fVerbose = 0; // verbose stats -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_SeqReadMinDomSize( Cec_ParSeq_t * p ) -{ - return p->nMinDomSize; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_SeqReadVerbose( Cec_ParSeq_t * p ) -{ - return p->fVerbose; -} - -/**Function************************************************************* - - Synopsis [Computes partitioning of registers.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Gia_Man_t * Gia_ManRegCreatePart( Gia_Man_t * p, Vec_Int_t * vPart, int * pnCountPis, int * pnCountRegs, int ** ppMapBack ) -{ - Gia_Man_t * pNew; - Gia_Obj_t * pObj; - Vec_Int_t * vNodes, * vRoots; - int i, iOut, nCountPis, nCountRegs; - int * pMapBack; - // collect/mark nodes/PIs in the DFS order from the roots - Gia_ManIncrementTravId( p ); - vRoots = Vec_IntAlloc( Vec_IntSize(vPart) ); - Vec_IntForEachEntry( vPart, iOut, i ) - Vec_IntPush( vRoots, Gia_ObjId(p, Gia_ManCo(p, Gia_ManPoNum(p)+iOut)) ); - vNodes = Gia_ManCollectNodesCis( p, Vec_IntArray(vRoots), Vec_IntSize(vRoots) ); - Vec_IntFree( vRoots ); - // unmark register outputs - Vec_IntForEachEntry( vPart, iOut, i ) - Gia_ObjSetTravIdPrevious( p, Gia_ManCi(p, Gia_ManPiNum(p)+iOut) ); - // count pure PIs - nCountPis = nCountRegs = 0; - Gia_ManForEachPi( p, pObj, i ) - nCountPis += Gia_ObjIsTravIdCurrent(p, pObj); - // count outputs of other registers - Gia_ManForEachRo( p, pObj, i ) - nCountRegs += Gia_ObjIsTravIdCurrent(p, pObj); // should be !Gia_... ??? - if ( pnCountPis ) - *pnCountPis = nCountPis; - if ( pnCountRegs ) - *pnCountRegs = nCountRegs; - // clean old manager - Gia_ManFillValue(p); - Gia_ManConst0(p)->Value = 0; - // create the new manager - pNew = Gia_ManStart( Vec_IntSize(vNodes) ); - // create the PIs - Gia_ManForEachCi( p, pObj, i ) - if ( Gia_ObjIsTravIdCurrent(p, pObj) ) - pObj->Value = Gia_ManAppendCi(pNew); - // add variables for the register outputs - // create fake POs to hold the register outputs - Vec_IntForEachEntry( vPart, iOut, i ) - { - pObj = Gia_ManCi(p, Gia_ManPiNum(p)+iOut); - pObj->Value = Gia_ManAppendCi(pNew); - Gia_ManAppendCo( pNew, pObj->Value ); - Gia_ObjSetTravIdCurrent( p, pObj ); // added - } - // create the nodes - Gia_ManForEachObjVec( vNodes, p, pObj, i ) - if ( Gia_ObjIsAnd(pObj) ) - pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); - // add real POs for the registers - Vec_IntForEachEntry( vPart, iOut, i ) - { - pObj = Gia_ManCo( p, Gia_ManPoNum(p)+iOut ); - Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); - } - Gia_ManSetRegNum( pNew, Vec_IntSize(vPart) ); - // create map - if ( ppMapBack ) - { - pMapBack = ABC_FALLOC( int, Gia_ManObjNum(pNew) ); - // map constant nodes - pMapBack[0] = 0; - // logic cones of register outputs - Gia_ManForEachObjVec( vNodes, p, pObj, i ) - { -// pObjNew = Aig_Regular(pObj->pData); -// pMapBack[pObjNew->Id] = pObj->Id; - assert( Gia_Lit2Var(Gia_ObjValue(pObj)) >= 0 ); - assert( Gia_Lit2Var(Gia_ObjValue(pObj)) < Gia_ManObjNum(pNew) ); - pMapBack[ Gia_Lit2Var(Gia_ObjValue(pObj)) ] = Gia_ObjId(p, pObj); - } - // map register outputs - Vec_IntForEachEntry( vPart, iOut, i ) - { - pObj = Gia_ManCi(p, Gia_ManPiNum(p)+iOut); -// pObjNew = pObj->pData; -// pMapBack[pObjNew->Id] = pObj->Id; - assert( Gia_Lit2Var(Gia_ObjValue(pObj)) >= 0 ); - assert( Gia_Lit2Var(Gia_ObjValue(pObj)) < Gia_ManObjNum(pNew) ); - pMapBack[ Gia_Lit2Var(Gia_ObjValue(pObj)) ] = Gia_ObjId(p, pObj); - } - *ppMapBack = pMapBack; - } - Vec_IntFree( vNodes ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Transfers the classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Gia_TransferMappedClasses( Gia_Man_t * pPart, int * pMapBack, int * pReprs ) -{ - Gia_Obj_t * pObj; - int i, Id1, Id2, nClasses; - if ( pPart->pReprs == NULL ) - return 0; - nClasses = 0; - Gia_ManForEachObj( pPart, pObj, i ) - { - if ( Gia_ObjRepr(pPart, i) == GIA_VOID ) - continue; - assert( i < Gia_ManObjNum(pPart) ); - assert( Gia_ObjRepr(pPart, i) < Gia_ManObjNum(pPart) ); - Id1 = pMapBack[ i ]; - Id2 = pMapBack[ Gia_ObjRepr(pPart, i) ]; - if ( Id1 == Id2 ) - continue; - if ( Id1 < Id2 ) - pReprs[Id2] = Id1; - else - pReprs[Id1] = Id2; - nClasses++; - } - return nClasses; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Gia_ManFindRepr_rec( int * pReprs, int Id ) -{ - if ( pReprs[Id] == 0 ) - return 0; - if ( pReprs[Id] == ~0 ) - return Id; - return Gia_ManFindRepr_rec( pReprs, pReprs[Id] ); -} - -/**Function************************************************************* - - Synopsis [Normalizes equivalences.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Gia_ManNormalizeEquivalences( Gia_Man_t * p, int * pReprs ) -{ - int i, iRepr; - assert( p->pReprs == NULL ); - assert( p->pNexts == NULL ); - p->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) ); - for ( i = 0; i < Gia_ManObjNum(p); i++ ) - Gia_ObjSetRepr( p, i, GIA_VOID ); - for ( i = 0; i < Gia_ManObjNum(p); i++ ) - { - if ( pReprs[i] == ~0 ) - continue; - iRepr = Gia_ManFindRepr_rec( pReprs, i ); - Gia_ObjSetRepr( p, i, iRepr ); - } - p->pNexts = Gia_ManDeriveNexts( p ); -} - -/**Function************************************************************* - - Synopsis [Partitioned sequential synthesis.] - - Description [Returns AIG annotated with equivalence classes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cec_SequentialSynthesisPart( Gia_Man_t * p, Cec_ParSeq_t * pPars ) -{ - int fPrintParts = 0; - char Buffer[100]; - Gia_Man_t * pTemp; - Vec_Ptr_t * vParts = (Vec_Ptr_t *)p->vClockDoms; - Vec_Int_t * vPart; - int * pMapBack, * pReprs; - int i, nCountPis, nCountRegs; - int nClasses, clk = clock(); - - // save parameters - if ( fPrintParts ) - { - // print partitions - Abc_Print( 1, "The following clock domains are used:\n" ); - Vec_PtrForEachEntry( Vec_Int_t *, vParts, vPart, i ) - { - pTemp = Gia_ManRegCreatePart( p, vPart, &nCountPis, &nCountRegs, NULL ); - sprintf( Buffer, "part%03d.aig", i ); - Gia_WriteAiger( pTemp, Buffer, 0, 0 ); - Abc_Print( 1, "part%03d.aig : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d.\n", - i, Vec_IntSize(vPart), Gia_ManCiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Gia_ManAndNum(pTemp) ); - Gia_ManStop( pTemp ); - } - } - - // perform sequential synthesis for clock domains - pReprs = ABC_FALLOC( int, Gia_ManObjNum(p) ); - Vec_PtrForEachEntry( Vec_Int_t *, vParts, vPart, i ) - { - pTemp = Gia_ManRegCreatePart( p, vPart, &nCountPis, &nCountRegs, &pMapBack ); - if ( nCountPis > 0 ) - { - if ( pPars->fUseScorr ) - { - Cec_ParCor_t CorPars, * pCorPars = &CorPars; - Cec_ManCorSetDefaultParams( pCorPars ); - pCorPars->nBTLimit = pPars->nBTLimit; - pCorPars->nLevelMax = pPars->nLevelMax; - pCorPars->fVerbose = pPars->fVeryVerbose; - pCorPars->fUseCSat = 1; - Cec_ManLSCorrespondenceClasses( pTemp, pCorPars ); - } - else if ( pPars->fUseLcorr ) - { - Cec_ParCor_t CorPars, * pCorPars = &CorPars; - Cec_ManCorSetDefaultParams( pCorPars ); - pCorPars->fLatchCorr = 1; - pCorPars->nBTLimit = pPars->nBTLimit; - pCorPars->fVerbose = pPars->fVeryVerbose; - pCorPars->fUseCSat = 1; - Cec_ManLSCorrespondenceClasses( pTemp, pCorPars ); - } - else - { -// pNew = Gia_ManSeqStructSweep( pTemp, pPars->fConsts, pPars->fEquivs, pPars->fVerbose ); -// Gia_ManStop( pNew ); - Gia_ManSeqCleanupClasses( pTemp, pPars->fConsts, pPars->fEquivs, pPars->fVerbose ); - } -//Abc_Print( 1, "Part equivalences = %d.\n", Gia_ManEquivCountLitsAll(pTemp) ); - nClasses = Gia_TransferMappedClasses( pTemp, pMapBack, pReprs ); - if ( pPars->fVerbose ) - { - Abc_Print( 1, "%3d : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d. Cl = %5d.\n", - i, Vec_IntSize(vPart), Gia_ManCiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Gia_ManAndNum(pTemp), nClasses ); - } - } - Gia_ManStop( pTemp ); - ABC_FREE( pMapBack ); - } - - // generate resulting equivalences - Gia_ManNormalizeEquivalences( p, pReprs ); -//Abc_Print( 1, "Total equivalences = %d.\n", Gia_ManEquivCountLitsAll(p) ); - ABC_FREE( pReprs ); - if ( pPars->fVerbose ) - { - Abc_PrintTime( 1, "Total time", clock() - clk ); - } - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cec/module.make b/src/aig/cec/module.make deleted file mode 100644 index 42e0cd1b..00000000 --- a/src/aig/cec/module.make +++ /dev/null @@ -1,13 +0,0 @@ -SRC += src/aig/cec/cecCec.c \ - src/aig/cec/cecChoice.c \ - src/aig/cec/cecClass.c \ - src/aig/cec/cecCore.c \ - src/aig/cec/cecCorr.c \ - src/aig/cec/cecIso.c \ - src/aig/cec/cecMan.c \ - src/aig/cec/cecPat.c \ - src/aig/cec/cecSeq.c \ - src/aig/cec/cecSim.c \ - src/aig/cec/cecSolve.c \ - src/aig/cec/cecSynth.c \ - src/aig/cec/cecSweep.c diff --git a/src/aig/cgt/cgt.h b/src/aig/cgt/cgt.h deleted file mode 100644 index aa8f9338..00000000 --- a/src/aig/cgt/cgt.h +++ /dev/null @@ -1,86 +0,0 @@ -/**CFile**************************************************************** - - FileName [cgt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Clock gating package.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cgt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __CGT_H__ -#define __CGT_H__ - - -/* - The algorithm implemented in this package is based on the paper: - A. Hurst. "Automatic synthesis of clock gating logic with controlled - netlist perturbation", DAC 2008. -*/ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Cgt_Par_t_ Cgt_Par_t; -struct Cgt_Par_t_ -{ - int nLevelMax; // the max number of levels to look for clock-gates - int nCandMax; // the max number of candidates at each node - int nOdcMax; // the max number of ODC levels to consider - int nConfMax; // the max number of conflicts at a node - int nVarsMin; // the min number of variables to recycle the SAT solver - int nFlopsMin; // the min number of flops needed to recycle the SAT solver - int fAreaOnly; // derive clock gating to minimize area - int fVerbose; // verbosity flag - int fVeryVerbose; // verbosity flag -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== cgtCore.c ==========================================================*/ -extern void Cgt_SetDefaultParams( Cgt_Par_t * p ); -extern Vec_Vec_t * Cgt_ClockGatingCandidates( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars ); -extern Aig_Man_t * Cgt_ClockGating( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/cgt/cgtAig.c b/src/aig/cgt/cgtAig.c deleted file mode 100644 index 428fcd1a..00000000 --- a/src/aig/cgt/cgtAig.c +++ /dev/null @@ -1,601 +0,0 @@ -/**CFile**************************************************************** - - FileName [cgtAig.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Clock gating package.] - - Synopsis [Creates AIG to compute clock-gating.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cgtAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cgtInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes transitive fanout cone of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cgt_ManDetectCandidates_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nLevelMax, Vec_Ptr_t * vCands ) -{ - if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) - return; - Aig_ObjSetTravIdCurrent(pAig, pObj); - if ( Aig_ObjIsNode(pObj) ) - { - Cgt_ManDetectCandidates_rec( pAig, Aig_ObjFanin0(pObj), nLevelMax, vCands ); - Cgt_ManDetectCandidates_rec( pAig, Aig_ObjFanin1(pObj), nLevelMax, vCands ); - } - if ( Aig_ObjLevel(pObj) <= nLevelMax ) - Vec_PtrPush( vCands, pObj ); -} - -/**Function************************************************************* - - Synopsis [Computes transitive fanout cone of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cgt_ManDetectCandidates( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nLevelMax, Vec_Ptr_t * vCands ) -{ - Vec_PtrClear( vCands ); - if ( !Aig_ObjIsNode(pObj) ) - return; - Aig_ManIncrementTravId( pAig ); - Cgt_ManDetectCandidates_rec( pAig, pObj, nLevelMax, vCands ); -} - -/**Function************************************************************* - - Synopsis [Computes transitive fanout cone of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cgt_ManDetectFanout_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nOdcMax, Vec_Ptr_t * vFanout ) -{ - Aig_Obj_t * pFanout; - int f, iFanout; - if ( Aig_ObjIsPo(pObj) || Aig_ObjLevel(pObj) > nOdcMax ) - return; - if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) - return; - Aig_ObjSetTravIdCurrent(pAig, pObj); - Vec_PtrPush( vFanout, pObj ); - Aig_ObjForEachFanout( pAig, pObj, pFanout, iFanout, f ) - Cgt_ManDetectFanout_rec( pAig, pFanout, nOdcMax, vFanout ); -} - -/**Function************************************************************* - - Synopsis [Computes transitive fanout cone of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cgt_ManDetectFanout( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nOdcMax, Vec_Ptr_t * vFanout ) -{ - Aig_Obj_t * pFanout; - int i, k, f, iFanout; - // collect visited nodes - Vec_PtrClear( vFanout ); - Aig_ManIncrementTravId( pAig ); - Cgt_ManDetectFanout_rec( pAig, pObj, nOdcMax, vFanout ); - // remove those nodes whose fanout is included - k = 0; - Vec_PtrForEachEntry( Aig_Obj_t *, vFanout, pObj, i ) - { - // go through the fanouts of this node - Aig_ObjForEachFanout( pAig, pObj, pFanout, iFanout, f ) - if ( !Aig_ObjIsTravIdCurrent(pAig, pFanout) ) - break; - if ( f == Aig_ObjRefs(pObj) ) // all fanouts are included - continue; - Vec_PtrWriteEntry( vFanout, k++, pObj ); - } - Vec_PtrShrink( vFanout, k ); - Vec_PtrSort( vFanout, (int (*)(void))Aig_ObjCompareIdIncrease ); - assert( Vec_PtrSize(vFanout) > 0 ); -} - -/**Function************************************************************* - - Synopsis [Computes visited nodes in the topological order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cgt_ManCollectVisited_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vVisited ) -{ - if ( Aig_ObjIsPi(pObj) ) - return; - if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) - return; - Aig_ObjSetTravIdCurrent(pAig, pObj); - assert( Aig_ObjIsNode(pObj) ); - Cgt_ManCollectVisited_rec( pAig, Aig_ObjFanin0(pObj), vVisited ); - Cgt_ManCollectVisited_rec( pAig, Aig_ObjFanin1(pObj), vVisited ); - Vec_PtrPush( vVisited, pObj ); -} - -/**Function************************************************************* - - Synopsis [Computes visited nodes in the topological order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cgt_ManCollectVisited( Aig_Man_t * pAig, Vec_Ptr_t * vFanout, Vec_Ptr_t * vVisited ) -{ - Aig_Obj_t * pObj; - int i; - Vec_PtrClear( vVisited ); - Aig_ManIncrementTravId( pAig ); - Vec_PtrForEachEntry( Aig_Obj_t *, vFanout, pObj, i ) - Cgt_ManCollectVisited_rec( pAig, pObj, vVisited ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Aig_Obj_t * Aig_ObjChild0CopyVec( Vec_Ptr_t * vCopy, Aig_Obj_t * pObj ) -{ return Aig_NotCond((Aig_Obj_t *)Vec_PtrEntry(vCopy, Aig_ObjFaninId0(pObj)), Aig_ObjFaninC0(pObj)); } -static inline Aig_Obj_t * Aig_ObjChild1CopyVec( Vec_Ptr_t * vCopy, Aig_Obj_t * pObj ) -{ return Aig_NotCond((Aig_Obj_t *)Vec_PtrEntry(vCopy, Aig_ObjFaninId1(pObj)), Aig_ObjFaninC1(pObj)); } - -/**Function************************************************************* - - Synopsis [Derives miter for clock-gating.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Cgt_ManConstructCareCondition( Cgt_Man_t * p, Aig_Man_t * pNew, Aig_Obj_t * pObjLo, Vec_Ptr_t * vCopy0, Vec_Ptr_t * vCopy1 ) -{ - Aig_Obj_t * pMiter, * pObj, * pTemp; - int i; - assert( Aig_ObjIsPi(pObjLo) ); - // detect nodes and their cone - Cgt_ManDetectFanout( p->pAig, pObjLo, p->pPars->nOdcMax, p->vFanout ); - Cgt_ManCollectVisited( p->pAig, p->vFanout, p->vVisited ); - // add new variables if the observability condition depends on PI variables - Vec_PtrForEachEntry( Aig_Obj_t *, p->vVisited, pObj, i ) - { - assert( Aig_ObjIsNode(pObj) ); - if ( Saig_ObjIsPi(p->pAig, Aig_ObjFanin0(pObj)) && Vec_PtrEntry(vCopy0, Aig_ObjFaninId0(pObj)) == NULL ) - { - pTemp = Aig_ObjCreatePi( pNew ); - Vec_PtrWriteEntry( vCopy0, Aig_ObjFaninId0(pObj), pTemp ); - Vec_PtrWriteEntry( vCopy1, Aig_ObjFaninId0(pObj), pTemp ); - } - if ( Saig_ObjIsPi(p->pAig, Aig_ObjFanin1(pObj)) && Vec_PtrEntry(vCopy0, Aig_ObjFaninId1(pObj)) == NULL ) - { - pTemp = Aig_ObjCreatePi( pNew ); - Vec_PtrWriteEntry( vCopy0, Aig_ObjFaninId1(pObj), pTemp ); - Vec_PtrWriteEntry( vCopy1, Aig_ObjFaninId1(pObj), pTemp ); - } - } - // construct AIGs for the nodes - Vec_PtrForEachEntry( Aig_Obj_t *, p->vVisited, pObj, i ) - { - pTemp = Aig_And( pNew, Aig_ObjChild0CopyVec(vCopy0, pObj), Aig_ObjChild1CopyVec(vCopy0, pObj) ); - Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObj), pTemp ); - pTemp = Aig_And( pNew, Aig_ObjChild0CopyVec(vCopy1, pObj), Aig_ObjChild1CopyVec(vCopy1, pObj) ); - Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObj), pTemp ); - } - // construct the care miter - pMiter = Aig_ManConst0( pNew ); - Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanout, pObj, i ) - { - pTemp = Aig_Exor( pNew, (Aig_Obj_t *)Vec_PtrEntry(vCopy0, Aig_ObjId(pObj)), (Aig_Obj_t *)Vec_PtrEntry(vCopy1, Aig_ObjId(pObj)) ); - pMiter = Aig_Or( pNew, pMiter, pTemp ); - } - return pMiter; -} - -/**Function************************************************************* - - Synopsis [Derives AIG for clock-gating.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Cgt_ManDeriveAigForGating( Cgt_Man_t * p ) -{ - Aig_Man_t * pNew; - Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pCare, * pMiter; - Vec_Ptr_t * vCopy0, * vCopy1; - int i; - assert( Aig_ManRegNum(p->pAig) ); - pNew = Aig_ManStart( Aig_ManObjNumMax(p->pAig) ); - pNew->pName = Aig_UtilStrsav( "CG_miter" ); - // build the first frame - Aig_ManConst1(p->pAig)->pData = Aig_ManConst1(pNew); - Aig_ManForEachPi( p->pAig, pObj, i ) - pObj->pData = Aig_ObjCreatePi( pNew ); - Aig_ManForEachNode( p->pAig, pObj, i ) - pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); -// Saig_ManForEachPo( p->pAig, pObj, i ) -// pObj->pData = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); - if ( p->pPars->nOdcMax > 0 ) - { - // create storage for observability conditions - vCopy0 = Vec_PtrStart( Aig_ManObjNumMax(p->pAig) ); - vCopy1 = Vec_PtrStart( Aig_ManObjNumMax(p->pAig) ); - // initialize register outputs - Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) - { - Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) ); - Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) ); - } - // compute observability condition for each latch output - Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) - { - // set the constants - Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObjLo), Aig_ManConst0(pNew) ); - Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObjLo), Aig_ManConst1(pNew) ); - // compute condition - pCare = Cgt_ManConstructCareCondition( p, pNew, pObjLo, vCopy0, vCopy1 ); - // restore the values - Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) ); - Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) ); - // compute the miter - pMiter = Aig_Exor( pNew, (Aig_Obj_t *)pObjLo->pData, Aig_ObjChild0Copy(pObjLi) ); - pMiter = Aig_And( pNew, pMiter, pCare ); - pObjLi->pData = Aig_ObjCreatePo( pNew, pMiter ); - } - Vec_PtrFree( vCopy0 ); - Vec_PtrFree( vCopy1 ); - } - else - { - // construct clock-gating miters for each register input - Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) - { - pMiter = Aig_Exor( pNew, (Aig_Obj_t *)pObjLo->pData, Aig_ObjChild0Copy(pObjLi) ); - pObjLi->pData = Aig_ObjCreatePo( pNew, pMiter ); - } - } - Aig_ManCleanup( pNew ); - Aig_ManSetPioNumbers( pNew ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Adds relevant constraints.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Cgt_ManConstructCare_rec( Aig_Man_t * pCare, Aig_Obj_t * pObj, Aig_Man_t * pNew ) -{ - Aig_Obj_t * pObj0, * pObj1; - if ( Aig_ObjIsTravIdCurrent( pCare, pObj ) ) - return (Aig_Obj_t *)pObj->pData; - Aig_ObjSetTravIdCurrent( pCare, pObj ); - if ( Aig_ObjIsPi(pObj) ) - return (Aig_Obj_t *)(pObj->pData = NULL); - pObj0 = Cgt_ManConstructCare_rec( pCare, Aig_ObjFanin0(pObj), pNew ); - if ( pObj0 == NULL ) - return (Aig_Obj_t *)(pObj->pData = NULL); - pObj1 = Cgt_ManConstructCare_rec( pCare, Aig_ObjFanin1(pObj), pNew ); - if ( pObj1 == NULL ) - return (Aig_Obj_t *)(pObj->pData = NULL); - pObj0 = Aig_NotCond( pObj0, Aig_ObjFaninC0(pObj) ); - pObj1 = Aig_NotCond( pObj1, Aig_ObjFaninC1(pObj) ); - return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, pObj0, pObj1 )); -} - -/**Function************************************************************* - - Synopsis [Builds constraints belonging to the given partition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cgt_ManConstructCare( Aig_Man_t * pNew, Aig_Man_t * pCare, Vec_Vec_t * vSuppsInv, Vec_Ptr_t * vLeaves ) -{ - Vec_Int_t * vOuts; - Aig_Obj_t * pLeaf, * pPi, * pPo, * pObjAig; - int i, k, iOut; - // go through the PIs of the partition - // label the corresponding PIs of the care set - Aig_ManIncrementTravId( pCare ); - Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pLeaf, i ) - { - pPi = Aig_ManPi( pCare, Aig_ObjPioNum(pLeaf) ); - Aig_ObjSetTravIdCurrent( pCare, pPi ); - pPi->pData = pLeaf->pData; - } - // construct the constraints - Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pLeaf, i ) - { - vOuts = Vec_VecEntryInt( vSuppsInv, Aig_ObjPioNum(pLeaf) ); - Vec_IntForEachEntry( vOuts, iOut, k ) - { - pPo = Aig_ManPo( pCare, iOut ); - if ( Aig_ObjIsTravIdCurrent( pCare, pPo ) ) - continue; - Aig_ObjSetTravIdCurrent( pCare, pPo ); - if ( Aig_ObjFanin0(pPo) == Aig_ManConst1(pCare) ) - continue; - pObjAig = Cgt_ManConstructCare_rec( pCare, Aig_ObjFanin0(pPo), pNew ); - if ( pObjAig == NULL ) - continue; - pObjAig = Aig_NotCond( pObjAig, Aig_ObjFaninC0(pPo) ); - Aig_ObjCreatePo( pNew, pObjAig ); - } - } -} - -/**Function************************************************************* - - Synopsis [Duplicates the AIG recursively.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Cgt_ManDupPartition_rec( Aig_Man_t * pNew, Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vLeaves ) -{ - if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) - return (Aig_Obj_t *)pObj->pData; - Aig_ObjSetTravIdCurrent(pAig, pObj); - if ( Aig_ObjIsPi(pObj) ) - { - pObj->pData = Aig_ObjCreatePi( pNew ); - Vec_PtrPush( vLeaves, pObj ); - return (Aig_Obj_t *)pObj->pData; - } - Cgt_ManDupPartition_rec( pNew, pAig, Aig_ObjFanin0(pObj), vLeaves ); - Cgt_ManDupPartition_rec( pNew, pAig, Aig_ObjFanin1(pObj), vLeaves ); - return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) )); -} - -/**Function************************************************************* - - Synopsis [Duplicates register outputs starting from the given one.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Cgt_ManDupPartition( Aig_Man_t * pFrame, int nVarsMin, int nFlopsMin, int iStart, Aig_Man_t * pCare, Vec_Vec_t * vSuppsInv, int * pnOutputs ) -{ - Vec_Ptr_t * vRoots, * vLeaves, * vPos; - Aig_Man_t * pNew; - Aig_Obj_t * pObj; - int i; - assert( Aig_ManRegNum(pFrame) == 0 ); - vRoots = Vec_PtrAlloc( 100 ); - vLeaves = Vec_PtrAlloc( 100 ); - vPos = Vec_PtrAlloc( 100 ); - pNew = Aig_ManStart( nVarsMin ); - pNew->pName = Aig_UtilStrsav( "partition" ); - Aig_ManIncrementTravId( pFrame ); - Aig_ManConst1(pFrame)->pData = Aig_ManConst1(pNew); - Aig_ObjSetTravIdCurrent( pFrame, Aig_ManConst1(pFrame) ); - for ( i = iStart; i < iStart + nFlopsMin && i < Aig_ManPoNum(pFrame); i++ ) - { - pObj = Aig_ManPo( pFrame, i ); - Cgt_ManDupPartition_rec( pNew, pFrame, Aig_ObjFanin0(pObj), vLeaves ); - Vec_PtrPush( vRoots, Aig_ObjChild0Copy(pObj) ); - Vec_PtrPush( vPos, pObj ); - } - for ( ; Aig_ManObjNum(pNew) < nVarsMin && i < Aig_ManPoNum(pFrame); i++ ) - { - pObj = Aig_ManPo( pFrame, i ); - Cgt_ManDupPartition_rec( pNew, pFrame, Aig_ObjFanin0(pObj), vLeaves ); - Vec_PtrPush( vRoots, Aig_ObjChild0Copy(pObj) ); - Vec_PtrPush( vPos, pObj ); - } - assert( nFlopsMin >= Vec_PtrSize(vRoots) || Vec_PtrSize(vRoots) >= nFlopsMin ); - // create constaints - if ( pCare ) - Cgt_ManConstructCare( pNew, pCare, vSuppsInv, vLeaves ); - // create POs - Vec_PtrForEachEntry( Aig_Obj_t *, vPos, pObj, i ) - pObj->pData = (Aig_Obj_t *)Aig_ObjCreatePo( pNew, (Aig_Obj_t *)Vec_PtrEntry(vRoots, i) ); - if ( pnOutputs != NULL ) - *pnOutputs = Vec_PtrSize( vPos ); - Vec_PtrFree( vRoots ); - Vec_PtrFree( vLeaves ); - Vec_PtrFree( vPos ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Implements one clock-gate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Cgt_ManBuildClockGate( Aig_Man_t * pNew, Vec_Ptr_t * vGates ) -{ - Aig_Obj_t * pGate, * pTotal; - int i; - assert( Vec_PtrSize(vGates) > 0 ); - pTotal = Aig_ManConst0(pNew); - Vec_PtrForEachEntry( Aig_Obj_t *, vGates, pGate, i ) - { - if ( Aig_Regular(pGate)->pNext ) - pGate = Aig_NotCond( Aig_Regular(pGate)->pNext, Aig_IsComplement(pGate) ); - else - pGate = Aig_NotCond( (Aig_Obj_t *)Aig_Regular(pGate)->pData, Aig_IsComplement(pGate) ); - pTotal = Aig_Or( pNew, pTotal, pGate ); - } - return pTotal; -} - -/**Function************************************************************* - - Synopsis [Derives AIG after clock-gating.] - - Description [The array contains, for each flop, its gate if present.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Cgt_ManDeriveGatedAig( Aig_Man_t * pAig, Vec_Vec_t * vGates, int fReduce, int * pnUsedNodes ) -{ - Aig_Man_t * pNew; - Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo, * pGateNew; - Vec_Ptr_t * vOne; - int i, k; - Aig_ManCleanNext( pAig ); - // label nodes - Vec_VecForEachEntry( Aig_Obj_t *, vGates, pObj, i, k ) - { - if ( Aig_IsComplement(pObj) ) - Aig_Regular(pObj)->fMarkB = 1; - else - Aig_Regular(pObj)->fMarkA = 1; - } - // construct AIG - assert( Aig_ManRegNum(pAig) ); - pNew = Aig_ManStart( Aig_ManObjNumMax(pAig) ); - pNew->pName = Aig_UtilStrsav( pAig->pName ); - pNew->pSpec = Aig_UtilStrsav( pAig->pSpec ); - Aig_ManConst1(pAig)->pData = Aig_ManConst1(pNew); - Aig_ManForEachPi( pAig, pObj, i ) - pObj->pData = Aig_ObjCreatePi( pNew ); - if ( fReduce ) - { - Aig_ManForEachNode( pAig, pObj, i ) - { - assert( !(pObj->fMarkA && pObj->fMarkB) ); - pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - if ( pObj->fMarkA ) - { - pObj->pNext = (Aig_Obj_t *)pObj->pData; - pObj->pData = Aig_ManConst0(pNew); - } - else if ( pObj->fMarkB ) - { - pObj->pNext = (Aig_Obj_t *)pObj->pData; - pObj->pData = Aig_ManConst1(pNew); - } - } - } - else - { - Aig_ManForEachNode( pAig, pObj, i ) - pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - } - if ( pnUsedNodes != NULL ) - *pnUsedNodes = Aig_ManNodeNum(pNew); - Saig_ManForEachPo( pAig, pObj, i ) - pObj->pData = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); - Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) - { - vOne = Vec_VecEntry( vGates, i ); - if ( Vec_PtrSize(vOne) == 0 ) - pObjNew = Aig_ObjChild0Copy(pObjLi); - else - { -// pGateNew = Aig_NotCond( Aig_Regular(pGate)->pData, Aig_IsComplement(pGate) ); - pGateNew = Cgt_ManBuildClockGate( pNew, vOne ); - pObjNew = Aig_Mux( pNew, pGateNew, (Aig_Obj_t *)pObjLo->pData, Aig_ObjChild0Copy(pObjLi) ); - } - pObjLi->pData = Aig_ObjCreatePo( pNew, pObjNew ); - } - Aig_ManCleanup( pNew ); - Aig_ManSetRegNum( pNew, Aig_ManRegNum(pAig) ); - // unlabel nodes - Aig_ManCleanMarkAB( pAig ); - Aig_ManCleanNext( pAig ); - return pNew; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cgt/cgtCore.c b/src/aig/cgt/cgtCore.c deleted file mode 100644 index d4229ce6..00000000 --- a/src/aig/cgt/cgtCore.c +++ /dev/null @@ -1,321 +0,0 @@ -/**CFile**************************************************************** - - FileName [cgtCore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Clock gating package.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cgtCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cgtInt.h" -#include "bar.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [This procedure sets default parameters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cgt_SetDefaultParams( Cgt_Par_t * p ) -{ - memset( p, 0, sizeof(Cgt_Par_t) ); - p->nLevelMax = 25; // the max number of levels to look for clock-gates - p->nCandMax = 1000; // the max number of candidates at each node - p->nOdcMax = 0; // the max number of ODC levels to consider - p->nConfMax = 10; // the max number of conflicts at a node - p->nVarsMin = 1000; // the min number of vars to recycle the SAT solver - p->nFlopsMin = 5; // the min number of flops to recycle the SAT solver - p->fAreaOnly = 0; // derive clock-gating to minimize area - p->fVerbose = 1; // verbosity flag -} - -/**Function************************************************************* - - Synopsis [Returns 1 if simulation does not filter out this candidate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cgt_SimulationFilter( Cgt_Man_t * p, Aig_Obj_t * pCandPart, Aig_Obj_t * pMiterPart ) -{ - unsigned * pInfoCand, * pInfoMiter; - int w, nWords = Aig_BitWordNum( p->nPatts ); - pInfoCand = (unsigned *)Vec_PtrEntry( p->vPatts, Aig_ObjId(Aig_Regular(pCandPart)) ); - pInfoMiter = (unsigned *)Vec_PtrEntry( p->vPatts, Aig_ObjId(pMiterPart) ); - // C => !M -- true is the same as C & M -- false - if ( !Aig_IsComplement(pCandPart) ) - { - for ( w = 0; w < nWords; w++ ) - if ( pInfoCand[w] & pInfoMiter[w] ) - return 0; - } - else - { - for ( w = 0; w < nWords; w++ ) - if ( ~pInfoCand[w] & pInfoMiter[w] ) - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Saves one simulation pattern.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cgt_SimulationRecord( Cgt_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i; - Aig_ManForEachObj( p->pPart, pObj, i ) - if ( sat_solver_var_value( p->pSat, p->pCnf->pVarNums[i] ) ) - Aig_InfoSetBit( (unsigned *)Vec_PtrEntry(p->vPatts, i), p->nPatts ); - p->nPatts++; - if ( p->nPatts == 32 * p->nPattWords ) - { - Vec_PtrReallocSimInfo( p->vPatts ); - Vec_PtrCleanSimInfo( p->vPatts, p->nPattWords, 2 * p->nPattWords ); - p->nPattWords *= 2; - } -} - -/**Function************************************************************* - - Synopsis [Performs clock-gating for the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cgt_ClockGatingRangeCheck( Cgt_Man_t * p, int iStart, int nOutputs ) -{ - Vec_Ptr_t * vNodes = p->vFanout; - Aig_Obj_t * pMiter, * pCand, * pMiterFrame, * pCandFrame, * pMiterPart, * pCandPart; - int i, k, RetValue, nCalls; - assert( Vec_VecSize(p->vGatesAll) == Aig_ManPoNum(p->pFrame) ); - // go through all the registers inputs of this range - for ( i = iStart; i < iStart + nOutputs; i++ ) - { - nCalls = p->nCalls; - pMiter = Saig_ManLi( p->pAig, i ); - Cgt_ManDetectCandidates( p->pAig, Aig_ObjFanin0(pMiter), p->pPars->nLevelMax, vNodes ); - // go through the candidates of this PO - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pCand, k ) - { - // get the corresponding nodes from the frames - pCandFrame = (Aig_Obj_t *)pCand->pData; - pMiterFrame = (Aig_Obj_t *)pMiter->pData; - // get the corresponding nodes from the part - pCandPart = (Aig_Obj_t *)pCandFrame->pData; - pMiterPart = (Aig_Obj_t *)pMiterFrame->pData; - // try direct polarity - if ( Cgt_SimulationFilter( p, pCandPart, pMiterPart ) ) - { - RetValue = Cgt_CheckImplication( p, pCandPart, pMiterPart ); - if ( RetValue == 1 ) - { - Vec_VecPush( p->vGatesAll, i, pCand ); - continue; - } - if ( RetValue == 0 ) - Cgt_SimulationRecord( p ); - } - else - p->nCallsFiltered++; - // try reverse polarity - if ( Cgt_SimulationFilter( p, Aig_Not(pCandPart), pMiterPart ) ) - { - RetValue = Cgt_CheckImplication( p, Aig_Not(pCandPart), pMiterPart ); - if ( RetValue == 1 ) - { - Vec_VecPush( p->vGatesAll, i, Aig_Not(pCand) ); - continue; - } - if ( RetValue == 0 ) - Cgt_SimulationRecord( p ); - } - else - p->nCallsFiltered++; - } - - if ( p->pPars->fVerbose ) - { -// printf( "Flop %3d : Cand = %4d. Gate = %4d. SAT calls = %3d.\n", -// i, Vec_PtrSize(vNodes), Vec_PtrSize(Vec_VecEntry(p->vGatesAll, i)), p->nCalls-nCalls ); - } - - } -} - -/**Function************************************************************* - - Synopsis [Performs clock-gating for the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cgt_ClockGatingRange( Cgt_Man_t * p, int iStart ) -{ - int nOutputs, iStop, clk, clkTotal = clock(); - int nCallsUnsat = p->nCallsUnsat; - int nCallsSat = p->nCallsSat; - int nCallsUndec = p->nCallsUndec; - int nCallsFiltered = p->nCallsFiltered; -clk = clock(); - p->pPart = Cgt_ManDupPartition( p->pFrame, p->pPars->nVarsMin, p->pPars->nFlopsMin, iStart, p->pCare, p->vSuppsInv, &nOutputs ); - p->pCnf = Cnf_DeriveSimple( p->pPart, nOutputs ); - p->pSat = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, 1, 0 ); - sat_solver_compress( p->pSat ); - p->vPatts = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p->pPart), p->nPattWords ); - Vec_PtrCleanSimInfo( p->vPatts, 0, p->nPattWords ); -p->timePrepare += clock() - clk; - Cgt_ClockGatingRangeCheck( p, iStart, nOutputs ); - iStop = iStart + nOutputs; - if ( p->pPars->fVeryVerbose ) - { - printf( "%5d : D =%4d. C =%5d. Var =%6d. Pr =%5d. Cex =%5d. F =%4d. Saved =%6d. ", - iStart, iStop-iStart, Aig_ManPoNum(p->pPart)-nOutputs, p->pSat->size, - p->nCallsUnsat-nCallsUnsat, - p->nCallsSat -nCallsSat, - p->nCallsUndec-nCallsUndec, - p->nCallsFiltered-nCallsFiltered ); - ABC_PRT( "Time", clock() - clkTotal ); - } - Cgt_ManClean( p ); - p->nRecycles++; - return iStop; -} - -/**Function************************************************************* - - Synopsis [Performs clock-gating for the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Vec_t * Cgt_ClockGatingCandidates( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars ) -{ - Bar_Progress_t * pProgress = NULL; - Cgt_Par_t Pars; - Cgt_Man_t * p; - Vec_Vec_t * vGatesAll; - int iStart, clk = clock(), clkTotal = clock(); - // reset random numbers - Aig_ManRandom( 1 ); - if ( pPars == NULL ) - Cgt_SetDefaultParams( pPars = &Pars ); - p = Cgt_ManCreate( pAig, pCare, pPars ); - p->pFrame = Cgt_ManDeriveAigForGating( p ); -p->timeAig += clock() - clk; - assert( Aig_ManPoNum(p->pFrame) == Saig_ManRegNum(p->pAig) ); - pProgress = Bar_ProgressStart( stdout, Aig_ManPoNum(p->pFrame) ); - for ( iStart = 0; iStart < Aig_ManPoNum(p->pFrame); ) - { - Bar_ProgressUpdate( pProgress, iStart, NULL ); - iStart = Cgt_ClockGatingRange( p, iStart ); - } - Bar_ProgressStop( pProgress ); - vGatesAll = p->vGatesAll; - p->vGatesAll = NULL; -p->timeTotal = clock() - clkTotal; - Cgt_ManStop( p ); - return vGatesAll; -} - -/**Function************************************************************* - - Synopsis [Performs clock-gating for the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Cgt_ClockGating( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars ) -{ - Aig_Man_t * pGated; - Vec_Vec_t * vGatesAll; - Vec_Vec_t * vGates; - int nNodesUsed, clk = clock(); - vGatesAll = Cgt_ClockGatingCandidates( pAig, pCare, pPars ); - if ( pPars->fAreaOnly ) - vGates = Cgt_ManDecideArea( pAig, vGatesAll, pPars->nOdcMax, pPars->fVerbose ); - else - vGates = Cgt_ManDecideSimple( pAig, vGatesAll, pPars->nOdcMax, pPars->fVerbose ); - if ( pPars->fVerbose ) - { -// printf( "Before CG: " ); -// Aig_ManPrintStats( pAig ); - } - pGated = Cgt_ManDeriveGatedAig( pAig, vGates, pPars->fAreaOnly, &nNodesUsed ); - if ( pPars->fVerbose ) - { -// printf( "After CG: " ); -// Aig_ManPrintStats( pGated ); - printf( "Nodes: Before CG = %6d. After CG = %6d. (%6.2f %%). Total after CG = %6d.\n", - Aig_ManNodeNum(pAig), nNodesUsed, - 100.0*nNodesUsed/Aig_ManNodeNum(pAig), - Aig_ManNodeNum(pGated) ); - } - Vec_VecFree( vGates ); - Vec_VecFree( vGatesAll ); - return pGated; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cgt/cgtDecide.c b/src/aig/cgt/cgtDecide.c deleted file mode 100644 index 383ff970..00000000 --- a/src/aig/cgt/cgtDecide.c +++ /dev/null @@ -1,301 +0,0 @@ -/**CFile**************************************************************** - - FileName [cgtMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Clock gating package.] - - Synopsis [Decide what gate to use for what flop.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cgtMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cgtInt.h" -#include "sswInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -extern int Ssw_SmlCheckXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo, Aig_Obj_t * pCand ); -extern int Ssw_SmlCountXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo, Aig_Obj_t * pCand ); -extern int Ssw_SmlCountEqual( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo ); -extern int Ssw_SmlNodeCountOnesReal( Ssw_Sml_t * p, Aig_Obj_t * pObj ); -extern int Ssw_SmlNodeCountOnesRealVec( Ssw_Sml_t * p, Vec_Ptr_t * vObjs ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Collects POs in the transitive fanout.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cgt_ManCollectFanoutPos_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vFanout ) -{ - Aig_Obj_t * pFanout; - int f, iFanout; - if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) - return; - Aig_ObjSetTravIdCurrent(pAig, pObj); - if ( Aig_ObjIsPo(pObj) ) - { - Vec_PtrPush( vFanout, pObj ); - return; - } - Aig_ObjForEachFanout( pAig, pObj, pFanout, iFanout, f ) - Cgt_ManCollectFanoutPos_rec( pAig, pFanout, vFanout ); -} - -/**Function************************************************************* - - Synopsis [Collects POs in the transitive fanout.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cgt_ManCollectFanoutPos( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vFanout ) -{ - Vec_PtrClear( vFanout ); - Aig_ManIncrementTravId( pAig ); - Cgt_ManCollectFanoutPos_rec( pAig, pObj, vFanout ); -} - -/**Function************************************************************* - - Synopsis [Checks if all PO fanouts can be gated by this node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cgt_ManCheckGateComplete( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, Aig_Obj_t * pGate, Vec_Ptr_t * vFanout ) -{ - Vec_Ptr_t * vGates; - Aig_Obj_t * pObj; - int i; - Vec_PtrForEachEntry( Aig_Obj_t *, vFanout, pObj, i ) - { - if ( Saig_ObjIsPo(pAig, pObj) ) - return 0; - vGates = Vec_VecEntry( vGatesAll, Aig_ObjPioNum(pObj) - Saig_ManPoNum(pAig) ); - if ( Vec_PtrFind( vGates, pGate ) == -1 ) - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Computes the set of complete clock gates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Cgt_ManCompleteGates( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose ) -{ - Vec_Ptr_t * vFanout, * vGatesFull; - Aig_Obj_t * pGate, * pGateR; - int i, k; - vFanout = Vec_PtrAlloc( 100 ); - vGatesFull = Vec_PtrAlloc( 100 ); - Vec_VecForEachEntry( Aig_Obj_t *, vGatesAll, pGate, i, k ) - { - pGateR = Aig_Regular(pGate); - if ( pGateR->fMarkA ) - continue; - pGateR->fMarkA = 1; - Cgt_ManCollectFanoutPos( pAig, pGateR, vFanout ); - if ( Cgt_ManCheckGateComplete( pAig, vGatesAll, pGate, vFanout ) ) - Vec_PtrPush( vGatesFull, pGate ); - } - Vec_PtrFree( vFanout ); - Vec_VecForEachEntry( Aig_Obj_t *, vGatesAll, pGate, i, k ) - Aig_Regular(pGate)->fMarkA = 0; - return vGatesFull; -} - -/**Function************************************************************* - - Synopsis [Calculates coverage.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Cgt_ManComputeCoverage( Aig_Man_t * pAig, Vec_Vec_t * vGates ) -{ - int nFrames = 32; - int nWords = 1; - Ssw_Sml_t * pSml; - Vec_Ptr_t * vOne; - int i, nTransTotal = 0, nTransSaved = 0; - pSml = Ssw_SmlSimulateSeq( pAig, 0, nFrames, nWords ); - Vec_VecForEachLevel( vGates, vOne, i ) - { - nTransSaved += Ssw_SmlNodeCountOnesRealVec( pSml, vOne ); - nTransTotal += 32 * nFrames * nWords; - } - Ssw_SmlStop( pSml ); - return (float)100.0*nTransSaved/nTransTotal; -} - -/**Function************************************************************* - - Synopsis [Chooses what clock-gate to use for this register.] - - Description [Currently uses the naive approach: For each register, - choose the clock gate, which covers most of the transitions.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Vec_t * Cgt_ManDecideSimple( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose ) -{ - int nFrames = 32; - int nWords = 1; - Ssw_Sml_t * pSml; - Vec_Vec_t * vGates; - Vec_Ptr_t * vCands; - Aig_Obj_t * pObjLi, * pObjLo, * pCand, * pCandBest; - int i, k, nHitsCur, nHitsMax, Counter = 0, clk = clock(); - int nTransTotal = 0, nTransSaved = 0; - vGates = Vec_VecStart( Saig_ManRegNum(pAig) ); - pSml = Ssw_SmlSimulateSeq( pAig, 0, nFrames, nWords ); - Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) - { - nHitsMax = 0; - pCandBest = NULL; - vCands = Vec_VecEntry( vGatesAll, i ); - Vec_PtrForEachEntry( Aig_Obj_t *, vCands, pCand, k ) - { - // check if this is indeed a clock-gate - if ( nOdcMax == 0 && !Ssw_SmlCheckXorImplication( pSml, pObjLi, pObjLo, pCand ) ) - printf( "Clock gate candidate is invalid!\n" ); - // find its characteristic number - nHitsCur = Ssw_SmlNodeCountOnesReal( pSml, pCand ); - if ( nHitsMax < nHitsCur ) - { - nHitsMax = nHitsCur; - pCandBest = pCand; - } - } - if ( pCandBest != NULL ) - { - Vec_VecPush( vGates, i, pCandBest ); - Counter++; - nTransSaved += nHitsMax; - } - nTransTotal += 32 * nFrames * nWords; - } - Ssw_SmlStop( pSml ); - if ( fVerbose ) - { - printf( "Gating signals = %6d. Gated flops = %6d. (Total flops = %6d.)\n", - Vec_VecSizeSize(vGatesAll), Counter, Saig_ManRegNum(pAig) ); -// printf( "Gated transitions = %5.2f %%. (%5.2f %%.) ", -// 100.0*nTransSaved/nTransTotal, Cgt_ManComputeCoverage(pAig, vGates) ); - printf( "Gated transitions = %5.2f %%. ", Cgt_ManComputeCoverage(pAig, vGates) ); - ABC_PRT( "Time", clock() - clk ); - } -/* - { - Vec_Ptr_t * vCompletes; - vCompletes = Cgt_ManCompleteGates( pAig, vGatesAll, nOdcMax, fVerbose ); - printf( "Complete gates = %d. \n", Vec_PtrSize(vCompletes) ); - Vec_PtrFree( vCompletes ); - } -*/ - return vGates; -} - -/**Function************************************************************* - - Synopsis [Computes the set of complete clock gates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Vec_t * Cgt_ManDecideArea( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose ) -{ - Vec_Vec_t * vGates; - Vec_Ptr_t * vCompletes, * vOne; - Aig_Obj_t * pGate; - int i, k, Counter = 0, clk = clock(); - // derive and label complete gates - vCompletes = Cgt_ManCompleteGates( pAig, vGatesAll, nOdcMax, fVerbose ); - // label complete gates - Vec_PtrForEachEntry( Aig_Obj_t *, vCompletes, pGate, i ) - Aig_Regular(pGate)->fMarkA = 1; - // select only complete gates - vGates = Vec_VecStart( Saig_ManRegNum(pAig) ); - Vec_VecForEachEntry( Aig_Obj_t *, vGatesAll, pGate, i, k ) - if ( Aig_Regular(pGate)->fMarkA ) - Vec_VecPush( vGates, i, pGate ); - // unlabel complete gates - Vec_PtrForEachEntry( Aig_Obj_t *, vCompletes, pGate, i ) - Aig_Regular(pGate)->fMarkA = 0; - // count the number of gated flops - Vec_VecForEachLevel( vGates, vOne, i ) - { - Counter += (int)(Vec_PtrSize(vOne) > 0); -// printf( "%d ", Vec_PtrSize(vOne) ); - } -// printf( "\n" ); - if ( fVerbose ) - { - printf( "Gating signals = %6d. Gated flops = %6d. (Total flops = %6d.)\n", - Vec_VecSizeSize(vGatesAll), Counter, Saig_ManRegNum(pAig) ); - printf( "Complete gates = %6d. Gated transitions = %5.2f %%. ", - Vec_PtrSize(vCompletes), Cgt_ManComputeCoverage(pAig, vGates) ); - ABC_PRT( "Time", clock() - clk ); - } - Vec_PtrFree( vCompletes ); - return vGates; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cgt/cgtInt.h b/src/aig/cgt/cgtInt.h deleted file mode 100644 index 8cce2381..00000000 --- a/src/aig/cgt/cgtInt.h +++ /dev/null @@ -1,122 +0,0 @@ -/**CFile**************************************************************** - - FileName [cgtInt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Clock gating package.] - - Synopsis [Internal declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cgtInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __CGT_INT_H__ -#define __CGT_INT_H__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "saig.h" -#include "satSolver.h" -#include "cnf.h" -#include "cgt.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Cgt_Man_t_ Cgt_Man_t; -struct Cgt_Man_t_ -{ - // user's data - Cgt_Par_t * pPars; // user's parameters - Aig_Man_t * pAig; // user's AIG manager - // user's constraints - Aig_Man_t * pCare; // constraint cones - Vec_Vec_t * vSuppsInv; // inverse support of the constraints - // result of clock-gating - Vec_Vec_t * vGatesAll; // the computed clock-gates - Vec_Ptr_t * vGates; // the selected clock-gates - // internal data - Aig_Man_t * pFrame; // clock gate AIG manager - Vec_Ptr_t * vFanout; // temporary storage for fanouts - Vec_Ptr_t * vVisited; // temporary storage for visited nodes - // SAT solving - Aig_Man_t * pPart; // partition - Cnf_Dat_t * pCnf; // CNF of the partition - sat_solver * pSat; // SAT solver - Vec_Ptr_t * vPatts; // simulation patterns - int nPatts; // the number of patterns accumulated - int nPattWords; // the number of pattern words - // statistics - int nRecycles; // recycles - int nCalls; // total calls - int nCallsSat; // satisfiable calls - int nCallsUnsat; // unsatisfiable calls - int nCallsUndec; // undecided calls - int nCallsFiltered; // filtered out calls - int timeAig; // constructing AIG - int timePrepare; // partitioning and SAT solving - int timeSat; // total runtime - int timeSatSat; // satisfiable runtime - int timeSatUnsat; // unsatisfiable runtime - int timeSatUndec; // undecided runtime - int timeDecision; // making decision about what gates to use - int timeOther; // other runtime - int timeTotal; // total runtime -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== cgtAig.c ==========================================================*/ -extern void Cgt_ManDetectCandidates( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nLevelMax, Vec_Ptr_t * vCands ); -extern Aig_Man_t * Cgt_ManDeriveAigForGating( Cgt_Man_t * p ); -extern Aig_Man_t * Cgt_ManDupPartition( Aig_Man_t * pAig, int nVarsMin, int nFlopsMin, int iStart, Aig_Man_t * pCare, Vec_Vec_t * vSuppsInv, int * pnOutputs ); -extern Aig_Man_t * Cgt_ManDeriveGatedAig( Aig_Man_t * pAig, Vec_Vec_t * vGates, int fReduce, int * pnUsedNodes ); -/*=== cgtDecide.c ==========================================================*/ -extern Vec_Vec_t * Cgt_ManDecideSimple( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose ); -extern Vec_Vec_t * Cgt_ManDecideArea( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose ); -/*=== cgtMan.c ==========================================================*/ -extern Cgt_Man_t * Cgt_ManCreate( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars ); -extern void Cgt_ManClean( Cgt_Man_t * p ); -extern void Cgt_ManStop( Cgt_Man_t * p ); -/*=== cgtSat.c ==========================================================*/ -extern int Cgt_CheckImplication( Cgt_Man_t * p, Aig_Obj_t * pGate, Aig_Obj_t * pFlop ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/cgt/cgtMan.c b/src/aig/cgt/cgtMan.c deleted file mode 100644 index 7744226d..00000000 --- a/src/aig/cgt/cgtMan.c +++ /dev/null @@ -1,179 +0,0 @@ -/**CFile**************************************************************** - - FileName [cgtMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Clock gating package.] - - Synopsis [Manipulation of clock gating manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cgtMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cgtInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cgt_Man_t * Cgt_ManCreate( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars ) -{ - Cgt_Man_t * p; - // prepare the sequential AIG - assert( Saig_ManRegNum(pAig) > 0 ); - Aig_ManFanoutStart( pAig ); - Aig_ManSetPioNumbers( pAig ); - // create interpolation manager - p = ABC_ALLOC( Cgt_Man_t, 1 ); - memset( p, 0, sizeof(Cgt_Man_t) ); - p->pPars = pPars; - p->pAig = pAig; - p->vGatesAll = Vec_VecStart( Saig_ManRegNum(pAig) ); - p->vFanout = Vec_PtrAlloc( 1000 ); - p->vVisited = Vec_PtrAlloc( 1000 ); - p->nPattWords = 16; - if ( pCare == NULL ) - return p; - // check out the constraints - if ( Aig_ManPiNum(pCare) != Aig_ManPiNum(pAig) ) - { - printf( "The PI count of care (%d) and AIG (%d) differ. Careset is not used.\n", - Aig_ManPiNum(pCare), Aig_ManPiNum(pAig) ); - return p; - } - p->pCare = pCare; - p->vSuppsInv = (Vec_Vec_t *)Aig_ManSupportsInverse( p->pCare ); - return p; -} - -/**Function************************************************************* - - Synopsis [Creates the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cgt_ManClean( Cgt_Man_t * p ) -{ - if ( p->pPart ) - { - Aig_ManStop( p->pPart ); - p->pPart = NULL; - } - if ( p->pCnf ) - { - Cnf_DataFree( p->pCnf ); - p->pCnf = NULL; - } - if ( p->pSat ) - { - sat_solver_delete( p->pSat ); - p->pSat = NULL; - } - if ( p->vPatts ) - { - Vec_PtrFree( p->vPatts ); - p->vPatts = NULL; - } -} - - -/**Function************************************************************* - - Synopsis [Prints stats of the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cgt_ManPrintStats( Cgt_Man_t * p ) -{ - printf( "Params: LevMax = %d. CandMax = %d. OdcMax = %d. ConfMax = %d. VarMin = %d. FlopMin = %d.\n", - p->pPars->nLevelMax, p->pPars->nCandMax, p->pPars->nOdcMax, - p->pPars->nConfMax, p->pPars->nVarsMin, p->pPars->nFlopsMin ); - printf( "SAT : Calls = %d. Unsat = %d. Sat = %d. Fails = %d. Recycles = %d. ", - p->nCalls, p->nCallsUnsat, p->nCallsSat, p->nCallsUndec, p->nRecycles ); - ABC_PRT( "Time", p->timeTotal ); -/* - p->timeOther = p->timeTotal-p->timeAig-p->timePrepare-p->timeSat-p->timeDecision; - ABC_PRTP( "AIG ", p->timeAig, p->timeTotal ); - ABC_PRTP( "Prepare ", p->timePrepare, p->timeTotal ); - ABC_PRTP( "SAT solving", p->timeSat, p->timeTotal ); - ABC_PRTP( " unsat ", p->timeSatUnsat, p->timeTotal ); - ABC_PRTP( " sat ", p->timeSatSat, p->timeTotal ); - ABC_PRTP( " undecided", p->timeSatUndec, p->timeTotal ); - ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); - ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); -*/ -} - -/**Function************************************************************* - - Synopsis [Frees the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cgt_ManStop( Cgt_Man_t * p ) -{ - if ( p->pPars->fVerbose ) - Cgt_ManPrintStats( p ); - if ( p->pFrame ) - Aig_ManStop( p->pFrame ); - Cgt_ManClean( p ); - Vec_PtrFree( p->vFanout ); - Vec_PtrFree( p->vVisited ); - if ( p->vGates ) - Vec_PtrFree( p->vGates ); - if ( p->vGatesAll ) - Vec_VecFree( p->vGatesAll ); - if ( p->vSuppsInv ) - Vec_VecFree( p->vSuppsInv ); - ABC_FREE( p ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cgt/cgtSat.c b/src/aig/cgt/cgtSat.c deleted file mode 100644 index 0a2a1daa..00000000 --- a/src/aig/cgt/cgtSat.c +++ /dev/null @@ -1,97 +0,0 @@ -/**CFile**************************************************************** - - FileName [cgtSat.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Clock gating package.] - - Synopsis [Checking implications using SAT.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cgtSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cgtInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - - -/**Function************************************************************* - - Synopsis [Runs equivalence test for the two nodes.] - - Description [Both nodes should be regular and different from each other.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cgt_CheckImplication( Cgt_Man_t * p, Aig_Obj_t * pGate, Aig_Obj_t * pMiter ) -{ - int nBTLimit = p->pPars->nConfMax; - int pLits[2], RetValue, clk; - p->nCalls++; - - // sanity checks - assert( p->pSat && p->pCnf ); - assert( !Aig_IsComplement(pMiter) ); - assert( Aig_Regular(pGate) != pMiter ); - - // solve under assumptions - // G => !M -- true G & M -- false - pLits[0] = toLitCond( p->pCnf->pVarNums[Aig_Regular(pGate)->Id], Aig_IsComplement(pGate) ); - pLits[1] = toLitCond( p->pCnf->pVarNums[pMiter->Id], 0 ); - -clk = clock(); - RetValue = sat_solver_solve( p->pSat, pLits, pLits + 2, (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); -p->timeSat += clock() - clk; - if ( RetValue == 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 ); - sat_solver_compress( p->pSat ); - p->nCallsUnsat++; - return 1; - } - else if ( RetValue == l_True ) - { -p->timeSatSat += clock() - clk; - p->nCallsSat++; - return 0; - } - else // if ( RetValue1 == l_Undef ) - { -p->timeSatUndec += clock() - clk; - p->nCallsUndec++; - return -1; - } - return -2; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cgt/module.make b/src/aig/cgt/module.make deleted file mode 100644 index 911d8d1f..00000000 --- a/src/aig/cgt/module.make +++ /dev/null @@ -1,5 +0,0 @@ -SRC += src/aig/cgt/cgtAig.c \ - src/aig/cgt/cgtCore.c \ - src/aig/cgt/cgtDecide.c \ - src/aig/cgt/cgtMan.c \ - src/aig/cgt/cgtSat.c diff --git a/src/aig/cnf/cnf.h b/src/aig/cnf/cnf.h deleted file mode 100644 index 129375d2..00000000 --- a/src/aig/cnf/cnf.h +++ /dev/null @@ -1,195 +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__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include - -#include "vec.h" -#include "aig.h" -#include "darInt.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// 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) - int * pObj2Clause; // the mapping of objects into clauses - int * pObj2Count; // the mapping of objects into clause number -}; - -// 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 (Cnf_Cut_t *)pObj->pData; } -static inline void Cnf_ObjSetBestCut( Aig_Obj_t * pObj, Cnf_Cut_t * pCut ) { pObj->pData = pCut; } - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -// iterator over the clauses -#define Cnf_CnfForClause( p, pBeg, pEnd, i ) \ - for ( i = 0; i < p->nClauses && (pBeg = p->pClauses[i]) && (pEnd = p->pClauses[i+1]); i++ ) - -// 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 Vec_Int_t * Cnf_DeriveMappingArray( Aig_Man_t * pAig ); -extern Cnf_Dat_t * Cnf_Derive( Aig_Man_t * pAig, int nOutputs ); -extern Cnf_Dat_t * Cnf_DeriveOther( Aig_Man_t * pAig ); -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 ); -/*=== cnfFast.c ========================================================*/ -extern void Cnf_CollectLeaves( Aig_Obj_t * pRoot, Vec_Ptr_t * vSuper, int fStopCompl ); -extern void Cnf_ComputeClauses( Aig_Man_t * p, Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, - Vec_Ptr_t * vNodes, Vec_Int_t * vMap, Vec_Int_t * vCover, Vec_Int_t * vClauses ); -extern void Cnf_DeriveFastMark( Aig_Man_t * p ); -extern Cnf_Dat_t * Cnf_DeriveFast( Aig_Man_t * p, int nOutputs ); -/*=== 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 Cnf_Dat_t * Cnf_DataAlloc( Aig_Man_t * pAig, int nVars, int nClauses, int nLiterals ); -extern Cnf_Dat_t * Cnf_DataDup( Cnf_Dat_t * p ); -extern void Cnf_DataFree( Cnf_Dat_t * p ); -extern void Cnf_DataLift( Cnf_Dat_t * p, int nVarsPlus ); -extern void Cnf_DataFlipLastLiteral( Cnf_Dat_t * p ); -extern void Cnf_DataPrint( Cnf_Dat_t * p, int fReadable ); -extern void Cnf_DataWriteIntoFile( Cnf_Dat_t * p, char * pFileName, int fReadable ); -extern void * Cnf_DataWriteIntoSolver( Cnf_Dat_t * p, int nFrames, int fInit ); -extern void * Cnf_DataWriteIntoSolverInt( void * pSat, Cnf_Dat_t * p, int nFrames, int fInit ); -extern int Cnf_DataWriteOrClause( void * pSat, Cnf_Dat_t * pCnf ); -extern int Cnf_DataWriteAndClauses( void * p, Cnf_Dat_t * pCnf ); -extern void Cnf_DataTranformPolarity( Cnf_Dat_t * pCnf, int fTransformPos ); -extern int Cnf_DataAddXorClause( void * pSat, int iVarA, int iVarB, int iVarC ); -/*=== 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 ); -extern Vec_Int_t * Cnf_DataCollectCiSatNums( Cnf_Dat_t * pCnf, Aig_Man_t * p ); -extern Vec_Int_t * Cnf_DataCollectCoSatNums( Cnf_Dat_t * pCnf, Aig_Man_t * p ); -/*=== cnfWrite.c ========================================================*/ -extern Vec_Int_t * Cnf_ManWriteCnfMapping( Cnf_Man_t * p, Vec_Ptr_t * vMapped ); -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_ManWriteCnfOther( Cnf_Man_t * p, Vec_Ptr_t * vMapped ); -extern Cnf_Dat_t * Cnf_DeriveSimple( Aig_Man_t * p, int nOutputs ); -extern Cnf_Dat_t * Cnf_DeriveSimpleForRetiming( Aig_Man_t * p ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/cnf/cnfCore.c b/src/aig/cnf/cnfCore.c deleted file mode 100644 index eb46e704..00000000 --- a/src/aig/cnf/cnfCore.c +++ /dev/null @@ -1,296 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Cnf_Man_t * s_pManCnf = NULL; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Converts AIG into the SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Cnf_DeriveMappingArray( Aig_Man_t * pAig ) -{ - Vec_Int_t * vResult; - Cnf_Man_t * p; - 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, 0 ); - vResult = Cnf_ManWriteCnfMapping( p, vMapped ); - Vec_PtrFree( vMapped ); - Aig_MmFixedStop( pMemCuts, 0 ); -p->timeSave = clock() - clk; - - // reset reference counters - Aig_ManResetRefs( pAig ); -//ABC_PRT( "Cuts ", p->timeCuts ); -//ABC_PRT( "Map ", p->timeMap ); -//ABC_PRT( "Saving ", p->timeSave ); - return vResult; -} - -/**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 ); -//ABC_PRT( "Cuts ", p->timeCuts ); -//ABC_PRT( "Map ", p->timeMap ); -//ABC_PRT( "Saving ", p->timeSave ); - return pCnf; -} - -/**Function************************************************************* - - Synopsis [Converts AIG into the SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cnf_Dat_t * Cnf_DeriveOther( Aig_Man_t * pAig ) -{ - 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_ManWriteCnfOther( p, vMapped ); - Vec_PtrFree( vMapped ); - Aig_MmFixedStop( pMemCuts, 0 ); -p->timeSave = clock() - clk; - - // reset reference counters - Aig_ManResetRefs( pAig ); -//ABC_PRT( "Cuts ", p->timeCuts ); -//ABC_PRT( "Map ", p->timeMap ); -//ABC_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 ); -ABC_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 ); -*/ -ABC_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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cnf/cnfCut.c b/src/aig/cnf/cnfCut.c deleted file mode 100644 index d41fc1fc..00000000 --- a/src/aig/cnf/cnfCut.c +++ /dev/null @@ -1,376 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cnf/cnfData.c b/src/aig/cnf/cnfData.c deleted file mode 100644 index 3d3cdf37..00000000 --- a/src/aig/cnf/cnfData.c +++ /dev/null @@ -1,4789 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static const char s_Data3[82] = "!#&()*+,-.0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ[]abcdefghijklmnopqrstuvwxyz|"; - -static const 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] = (char)(-1); - for ( i = 0; i < 81; i++ ) - Map[(int)s_Data3[i]] = (char)i; - - // count the number of strings - for ( Size = 0; s_Data4[Size] && Size < 100000; Size++ ); - assert( Size < 100000 ); - - // allocate memory - pMemory = ABC_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] = (char)(-1); - else - pMemory[i*75+k] = Map[(int)s_Data4[i][k]]; - - // set pointers and compute SOP sizes - pSopSizes = ABC_ALLOC( char, 65536 ); - pSops = ABC_ALLOC( char *, 65536 ); - pSopSizes[0] = 0; - pSops[0] = NULL; - pPrev = pMemory; - for ( k = 0, i = 1; i < 65536; k++ ) - if ( pMemory[k] == (char)(-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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cnf/cnfFast.c b/src/aig/cnf/cnfFast.c deleted file mode 100644 index afa05a05..00000000 --- a/src/aig/cnf/cnfFast.c +++ /dev/null @@ -1,697 +0,0 @@ -/**CFile**************************************************************** - - FileName [cnfFast.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: cnfFast.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cnf.h" -#include "kit.h" - -ABC_NAMESPACE_IMPL_START - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Detects multi-input gate rooted at this node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_CollectLeaves_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper, int fStopCompl ) -{ - if ( pRoot != pObj && (pObj->fMarkA || (fStopCompl && Aig_IsComplement(pObj))) ) - { - Vec_PtrPushUnique( vSuper, fStopCompl ? pObj : Aig_Regular(pObj) ); - return; - } - assert( Aig_ObjIsNode(pObj) ); - if ( fStopCompl ) - { - Cnf_CollectLeaves_rec( pRoot, Aig_ObjChild0(pObj), vSuper, 1 ); - Cnf_CollectLeaves_rec( pRoot, Aig_ObjChild1(pObj), vSuper, 1 ); - } - else - { - Cnf_CollectLeaves_rec( pRoot, Aig_ObjFanin0(pObj), vSuper, 0 ); - Cnf_CollectLeaves_rec( pRoot, Aig_ObjFanin1(pObj), vSuper, 0 ); - } -} - -/**Function************************************************************* - - Synopsis [Detects multi-input gate rooted at this node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_CollectLeaves( Aig_Obj_t * pRoot, Vec_Ptr_t * vSuper, int fStopCompl ) -{ - assert( !Aig_IsComplement(pRoot) ); - Vec_PtrClear( vSuper ); - Cnf_CollectLeaves_rec( pRoot, pRoot, vSuper, fStopCompl ); -} - -/**Function************************************************************* - - Synopsis [Collects nodes inside the cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_CollectVolume_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) -{ - if ( Aig_ObjIsTravIdCurrent( p, pObj ) ) - return; - Aig_ObjSetTravIdCurrent( p, pObj ); - assert( Aig_ObjIsNode(pObj) ); - Cnf_CollectVolume_rec( p, Aig_ObjFanin0(pObj), vNodes ); - Cnf_CollectVolume_rec( p, Aig_ObjFanin1(pObj), vNodes ); - Vec_PtrPush( vNodes, pObj ); -} - -/**Function************************************************************* - - Synopsis [Collects nodes inside the cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_CollectVolume( Aig_Man_t * p, Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes ) -{ - Aig_Obj_t * pObj; - int i; - Aig_ManIncrementTravId( p ); - Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i ) - Aig_ObjSetTravIdCurrent( p, pObj ); - Vec_PtrClear( vNodes ); - Cnf_CollectVolume_rec( p, pRoot, vNodes ); -} - -/**Function************************************************************* - - Synopsis [Derive truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -word Cnf_CutDeriveTruth( Aig_Man_t * p, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes ) -{ - static word Truth6[6] = { - 0xAAAAAAAAAAAAAAAA, - 0xCCCCCCCCCCCCCCCC, - 0xF0F0F0F0F0F0F0F0, - 0xFF00FF00FF00FF00, - 0xFFFF0000FFFF0000, - 0xFFFFFFFF00000000 - }; - static word C[2] = { 0, ~0 }; - static word S[256]; - Aig_Obj_t * pObj; - int i; - assert( Vec_PtrSize(vLeaves) <= 6 && Vec_PtrSize(vNodes) > 0 ); - assert( Vec_PtrSize(vLeaves) + Vec_PtrSize(vNodes) <= 256 ); - Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i ) - { - pObj->iData = i; - S[pObj->iData] = Truth6[i]; - } - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) - { - pObj->iData = Vec_PtrSize(vLeaves) + i; - S[pObj->iData] = (S[Aig_ObjFanin0(pObj)->iData] ^ C[Aig_ObjFaninC0(pObj)]) & - (S[Aig_ObjFanin1(pObj)->iData] ^ C[Aig_ObjFaninC1(pObj)]); - } - return S[pObj->iData]; -} - - -/**Function************************************************************* - - Synopsis [Collects nodes inside the cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Cnf_ObjGetLit( Vec_Int_t * vMap, Aig_Obj_t * pObj, int fCompl ) -{ - int iSatVar = vMap ? Vec_IntEntry(vMap, Aig_ObjId(pObj)) : Aig_ObjId(pObj); - assert( iSatVar > 0 ); - return iSatVar + iSatVar + fCompl; -} - -/**Function************************************************************* - - Synopsis [Collects nodes inside the cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_ComputeClauses( Aig_Man_t * p, Aig_Obj_t * pRoot, - Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes, Vec_Int_t * vMap, Vec_Int_t * vCover, Vec_Int_t * vClauses ) -{ - Aig_Obj_t * pLeaf; - int c, k, Cube, OutLit, RetValue; - word Truth; - assert( pRoot->fMarkA ); - - Vec_IntClear( vClauses ); - - OutLit = Cnf_ObjGetLit( vMap, pRoot, 0 ); - // detect cone - Cnf_CollectLeaves( pRoot, vLeaves, 0 ); - Cnf_CollectVolume( p, pRoot, vLeaves, vNodes ); - assert( pRoot == Vec_PtrEntryLast(vNodes) ); - // check if this is an AND-gate - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pLeaf, k ) - { - if ( Aig_ObjFaninC0(pLeaf) && !Aig_ObjFanin0(pLeaf)->fMarkA ) - break; - if ( Aig_ObjFaninC1(pLeaf) && !Aig_ObjFanin1(pLeaf)->fMarkA ) - break; - } - if ( k == Vec_PtrSize(vNodes) ) - { - Cnf_CollectLeaves( pRoot, vLeaves, 1 ); - // write big clause - Vec_IntPush( vClauses, 0 ); - Vec_IntPush( vClauses, OutLit ); - Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pLeaf, k ) - Vec_IntPush( vClauses, Cnf_ObjGetLit(vMap, Aig_Regular(pLeaf), !Aig_IsComplement(pLeaf)) ); - // write small clauses - Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pLeaf, k ) - { - Vec_IntPush( vClauses, 0 ); - Vec_IntPush( vClauses, OutLit ^ 1 ); - Vec_IntPush( vClauses, Cnf_ObjGetLit(vMap, Aig_Regular(pLeaf), Aig_IsComplement(pLeaf)) ); - } - return; - } - if ( Vec_PtrSize(vLeaves) > 6 ) - printf( "FastCnfGeneration: Internal error!!!\n" ); - assert( Vec_PtrSize(vLeaves) <= 6 ); - - Truth = Cnf_CutDeriveTruth( p, vLeaves, vNodes ); - if ( Truth == 0 || Truth == ~0 ) - { - Vec_IntPush( vClauses, 0 ); - Vec_IntPush( vClauses, (Truth == 0) ? (OutLit ^ 1) : OutLit ); - return; - } - - RetValue = Kit_TruthIsop( (unsigned *)&Truth, Vec_PtrSize(vLeaves), vCover, 0 ); - assert( RetValue >= 0 ); - - Vec_IntForEachEntry( vCover, Cube, c ) - { - Vec_IntPush( vClauses, 0 ); - Vec_IntPush( vClauses, OutLit ); - for ( k = 0; k < Vec_PtrSize(vLeaves); k++, Cube >>= 2 ) - { - if ( (Cube & 3) == 0 ) - continue; - assert( (Cube & 3) != 3 ); - Vec_IntPush( vClauses, Cnf_ObjGetLit(vMap, (Aig_Obj_t *)Vec_PtrEntry(vLeaves,k), (Cube&3)!=1) ); - } - } - - Truth = ~Truth; - - RetValue = Kit_TruthIsop( (unsigned *)&Truth, Vec_PtrSize(vLeaves), vCover, 0 ); - assert( RetValue >= 0 ); - Vec_IntForEachEntry( vCover, Cube, c ) - { - Vec_IntPush( vClauses, 0 ); - Vec_IntPush( vClauses, OutLit ^ 1 ); - for ( k = 0; k < Vec_PtrSize(vLeaves); k++, Cube >>= 2 ) - { - if ( (Cube & 3) == 0 ) - continue; - assert( (Cube & 3) != 3 ); - Vec_IntPush( vClauses, Cnf_ObjGetLit(vMap, (Aig_Obj_t *)Vec_PtrEntry(vLeaves,k), (Cube&3)!=1) ); - } - } -} - - - -/**Function************************************************************* - - Synopsis [Marks AIG for CNF computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_DeriveFastMark( Aig_Man_t * p ) -{ - Vec_Int_t * vSupps; - Vec_Ptr_t * vLeaves, * vNodes; - Aig_Obj_t * pObj, * pTemp, * pObjC, * pObj0, * pObj1; - int i, k, nFans, Counter; - - vLeaves = Vec_PtrAlloc( 100 ); - vNodes = Vec_PtrAlloc( 100 ); - vSupps = Vec_IntStart( Aig_ManObjNumMax(p) ); - - // mark CIs - Aig_ManForEachPi( p, pObj, i ) - pObj->fMarkA = 1; - - // mark CO drivers - Aig_ManForEachPo( p, pObj, i ) - Aig_ObjFanin0(pObj)->fMarkA = 1; - - // mark MUX/XOR nodes - Aig_ManForEachNode( p, pObj, i ) - { - assert( !pObj->fMarkB ); - if ( !Aig_ObjIsMuxType(pObj) ) - continue; - pObj0 = Aig_ObjFanin0(pObj); - if ( pObj0->fMarkB || Aig_ObjRefs(pObj0) > 1 ) - continue; - pObj1 = Aig_ObjFanin1(pObj); - if ( pObj1->fMarkB || Aig_ObjRefs(pObj1) > 1 ) - continue; - // mark nodes - pObj->fMarkB = 1; - pObj0->fMarkB = 1; - pObj1->fMarkB = 1; - // mark inputs and outputs - pObj->fMarkA = 1; - Aig_ObjFanin0(pObj0)->fMarkA = 1; - Aig_ObjFanin1(pObj0)->fMarkA = 1; - Aig_ObjFanin0(pObj1)->fMarkA = 1; - Aig_ObjFanin1(pObj1)->fMarkA = 1; - } - - // mark nodes with multiple fanouts and pointed to by complemented edges - Aig_ManForEachNode( p, pObj, i ) - { - // mark nodes with many fanouts - if ( Aig_ObjRefs(pObj) > 1 ) - pObj->fMarkA = 1; - // mark nodes pointed to by a complemented edge - if ( Aig_ObjFaninC0(pObj) && !Aig_ObjFanin0(pObj)->fMarkB ) - Aig_ObjFanin0(pObj)->fMarkA = 1; - if ( Aig_ObjFaninC1(pObj) && !Aig_ObjFanin1(pObj)->fMarkB ) - Aig_ObjFanin1(pObj)->fMarkA = 1; - } - - // compute supergate size for internal marked nodes - Aig_ManForEachNode( p, pObj, i ) - { - if ( !pObj->fMarkA ) - continue; - if ( pObj->fMarkB ) - { - if ( !Aig_ObjIsMuxType(pObj) ) - continue; - pObjC = Aig_ObjRecognizeMux( pObj, &pObj1, &pObj0 ); - pObj0 = Aig_Regular(pObj0); - pObj1 = Aig_Regular(pObj1); - assert( pObj0->fMarkA ); - assert( pObj1->fMarkA ); -// if ( pObj0 == pObj1 ) -// continue; - nFans = 1 + (pObj0 == pObj1); - if ( !pObj0->fMarkB && !Aig_ObjIsPi(pObj0) && Aig_ObjRefs(pObj0) == nFans && Vec_IntEntry(vSupps, Aig_ObjId(pObj0)) < 3 ) - { - pObj0->fMarkA = 0; - continue; - } - if ( !pObj1->fMarkB && !Aig_ObjIsPi(pObj1) && Aig_ObjRefs(pObj1) == nFans && Vec_IntEntry(vSupps, Aig_ObjId(pObj1)) < 3 ) - { - pObj1->fMarkA = 0; - continue; - } - continue; - } - - Cnf_CollectLeaves( pObj, vLeaves, 1 ); - Vec_IntWriteEntry( vSupps, Aig_ObjId(pObj), Vec_PtrSize(vLeaves) ); - if ( Vec_PtrSize(vLeaves) >= 6 ) - continue; - Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pTemp, k ) - { - pTemp = Aig_Regular(pTemp); - assert( pTemp->fMarkA ); - if ( pTemp->fMarkB || Aig_ObjIsPi(pTemp) || Aig_ObjRefs(pTemp) > 1 ) - continue; - assert( Vec_IntEntry(vSupps, Aig_ObjId(pTemp)) > 0 ); - if ( Vec_PtrSize(vLeaves) - 1 + Vec_IntEntry(vSupps, Aig_ObjId(pTemp)) > 6 ) - continue; - pTemp->fMarkA = 0; - Vec_IntWriteEntry( vSupps, Aig_ObjId(pObj), 6 ); -//printf( "%d %d ", Vec_PtrSize(vLeaves), Vec_IntEntry(vSupps, Aig_ObjId(pTemp)) ); - break; - } - } - Aig_ManCleanMarkB( p ); - - // check CO drivers - Counter = 0; - Aig_ManForEachPo( p, pObj, i ) - Counter += !Aig_ObjFanin0(pObj)->fMarkA; - if ( Counter ) - printf( "PO-driver rule is violated %d times.\n", Counter ); - - // check that the AND-gates are fine - Counter = 0; - Aig_ManForEachNode( p, pObj, i ) - { - assert( pObj->fMarkB == 0 ); - if ( !pObj->fMarkA ) - continue; - Cnf_CollectLeaves( pObj, vLeaves, 0 ); - if ( Vec_PtrSize(vLeaves) <= 6 ) - continue; - Cnf_CollectVolume( p, pObj, vLeaves, vNodes ); - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pTemp, k ) - { - if ( Aig_ObjFaninC0(pTemp) && !Aig_ObjFanin0(pTemp)->fMarkA ) - Counter++; - if ( Aig_ObjFaninC1(pTemp) && !Aig_ObjFanin1(pTemp)->fMarkA ) - Counter++; - } - } - if ( Counter ) - printf( "AND-gate rule is violated %d times.\n", Counter ); - - Vec_PtrFree( vLeaves ); - Vec_PtrFree( vNodes ); - Vec_IntFree( vSupps ); -} - - -/**Function************************************************************* - - Synopsis [Counts the number of clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cnf_CutCountClauses( Aig_Man_t * p, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes, Vec_Int_t * vCover ) -{ - word Truth; - Aig_Obj_t * pObj; - int i, RetValue, nSize = 0; - if ( Vec_PtrSize(vLeaves) > 6 ) - { - // make sure this is an AND gate - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) - { - if ( Aig_ObjFaninC0(pObj) && !Aig_ObjFanin0(pObj)->fMarkA ) - printf( "Unusual 1!\n" ); - if ( Aig_ObjFaninC1(pObj) && !Aig_ObjFanin1(pObj)->fMarkA ) - printf( "Unusual 2!\n" ); - continue; - - assert( !Aig_ObjFaninC0(pObj) || Aig_ObjFanin0(pObj)->fMarkA ); - assert( !Aig_ObjFaninC1(pObj) || Aig_ObjFanin1(pObj)->fMarkA ); - } - return Vec_PtrSize(vLeaves) + 1; - } - Truth = Cnf_CutDeriveTruth( p, vLeaves, vNodes ); - - RetValue = Kit_TruthIsop( (unsigned *)&Truth, Vec_PtrSize(vLeaves), vCover, 0 ); - assert( RetValue >= 0 ); - nSize += Vec_IntSize(vCover); - - Truth = ~Truth; - - RetValue = Kit_TruthIsop( (unsigned *)&Truth, Vec_PtrSize(vLeaves), vCover, 0 ); - assert( RetValue >= 0 ); - nSize += Vec_IntSize(vCover); - return nSize; -} - -/**Function************************************************************* - - Synopsis [Counts the size of the CNF, assuming marks are set.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cnf_CountCnfSize( Aig_Man_t * p ) -{ - Vec_Ptr_t * vLeaves, * vNodes; - Vec_Int_t * vCover; - Aig_Obj_t * pObj; - int nVars = 0, nClauses = 0; - int i, nSize; - - vLeaves = Vec_PtrAlloc( 100 ); - vNodes = Vec_PtrAlloc( 100 ); - vCover = Vec_IntAlloc( 1 << 16 ); - - Aig_ManForEachObj( p, pObj, i ) - nVars += pObj->fMarkA; - - Aig_ManForEachNode( p, pObj, i ) - { - if ( !pObj->fMarkA ) - continue; - Cnf_CollectLeaves( pObj, vLeaves, 0 ); - Cnf_CollectVolume( p, pObj, vLeaves, vNodes ); - assert( pObj == Vec_PtrEntryLast(vNodes) ); - - nSize = Cnf_CutCountClauses( p, vLeaves, vNodes, vCover ); -// printf( "%d(%d) ", Vec_PtrSize(vLeaves), nSize ); - - nClauses += nSize; - } -// printf( "\n" ); - printf( "Vars = %d Clauses = %d\n", nVars, nClauses ); - - Vec_PtrFree( vLeaves ); - Vec_PtrFree( vNodes ); - Vec_IntFree( vCover ); - return nClauses; -} - -/**Function************************************************************* - - Synopsis [Derives CNF from the marked AIG.] - - Description [Assumes that marking is such that when we traverse from each - marked node, the logic cone has 6 inputs or less, or it is a multi-input AND.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cnf_Dat_t * Cnf_DeriveFastClauses( Aig_Man_t * p, int nOutputs ) -{ - Cnf_Dat_t * pCnf; - Vec_Int_t * vLits, * vClas, * vMap, * vTemp; - Vec_Ptr_t * vLeaves, * vNodes; - Vec_Int_t * vCover; - Aig_Obj_t * pObj; - int i, k, nVars, Entry, OutLit, DriLit; - - vLits = Vec_IntAlloc( 1 << 16 ); - vClas = Vec_IntAlloc( 1 << 12 ); - vMap = Vec_IntStartFull( Aig_ManObjNumMax(p) ); - - // assign variables for the outputs - nVars = 1; - if ( nOutputs ) - { - if ( Aig_ManRegNum(p) == 0 ) - { - assert( nOutputs == Aig_ManPoNum(p) ); - Aig_ManForEachPo( p, pObj, i ) - Vec_IntWriteEntry( vMap, Aig_ObjId(pObj), nVars++ ); - } - else - { - assert( nOutputs == Aig_ManRegNum(p) ); - Aig_ManForEachLiSeq( p, pObj, i ) - Vec_IntWriteEntry( vMap, Aig_ObjId(pObj), nVars++ ); - } - } - // assign variables to the internal nodes - Aig_ManForEachNodeReverse( p, pObj, i ) - if ( pObj->fMarkA ) - Vec_IntWriteEntry( vMap, Aig_ObjId(pObj), nVars++ ); - // assign variables to the PIs and constant node - Aig_ManForEachPi( p, pObj, i ) - Vec_IntWriteEntry( vMap, Aig_ObjId(pObj), nVars++ ); - Vec_IntWriteEntry( vMap, Aig_ObjId(Aig_ManConst1(p)), nVars++ ); - - // create clauses - vLeaves = Vec_PtrAlloc( 100 ); - vNodes = Vec_PtrAlloc( 100 ); - vCover = Vec_IntAlloc( 1 << 16 ); - vTemp = Vec_IntAlloc( 100 ); - Aig_ManForEachNodeReverse( p, pObj, i ) - { - if ( !pObj->fMarkA ) - continue; - Cnf_ComputeClauses( p, pObj, vLeaves, vNodes, vMap, vCover, vTemp ); - Vec_IntForEachEntry( vTemp, Entry, k ) - { - if ( Entry == 0 ) - Vec_IntPush( vClas, Vec_IntSize(vLits) ); - else - Vec_IntPush( vLits, Entry ); - } - } - Vec_PtrFree( vLeaves ); - Vec_PtrFree( vNodes ); - Vec_IntFree( vCover ); - Vec_IntFree( vTemp ); - - // create clauses for the outputs - Aig_ManForEachPo( p, pObj, i ) - { - DriLit = Cnf_ObjGetLit( vMap, Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj) ); - if ( i < Aig_ManPoNum(p) - nOutputs ) - { - Vec_IntPush( vClas, Vec_IntSize(vLits) ); - Vec_IntPush( vLits, DriLit ); - } - else - { - OutLit = Cnf_ObjGetLit( vMap, pObj, 0 ); - // first clause - Vec_IntPush( vClas, Vec_IntSize(vLits) ); - Vec_IntPush( vLits, OutLit ); - Vec_IntPush( vLits, DriLit ^ 1 ); - // second clause - Vec_IntPush( vClas, Vec_IntSize(vLits) ); - Vec_IntPush( vLits, OutLit ^ 1 ); - Vec_IntPush( vLits, DriLit ); - } - } - - // write the constant literal - OutLit = Cnf_ObjGetLit( vMap, Aig_ManConst1(p), 0 ); - Vec_IntPush( vClas, Vec_IntSize(vLits) ); - Vec_IntPush( vLits, OutLit ); - - // create structure - pCnf = ABC_CALLOC( Cnf_Dat_t, 1 ); - pCnf->pMan = p; - pCnf->nVars = nVars; - pCnf->nLiterals = Vec_IntSize( vLits ); - pCnf->nClauses = Vec_IntSize( vClas ); - pCnf->pClauses = ABC_ALLOC( int *, pCnf->nClauses + 1 ); - pCnf->pClauses[0] = Vec_IntReleaseArray( vLits ); - Vec_IntForEachEntry( vClas, Entry, i ) - pCnf->pClauses[i] = pCnf->pClauses[0] + Entry; - pCnf->pClauses[pCnf->nClauses] = pCnf->pClauses[0] + pCnf->nLiterals; - pCnf->pVarNums = Vec_IntReleaseArray( vMap ); - - // cleanup - Vec_IntFree( vLits ); - Vec_IntFree( vClas ); - Vec_IntFree( vMap ); - return pCnf; -} - -/**Function************************************************************* - - Synopsis [Fast CNF computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cnf_Dat_t * Cnf_DeriveFast( Aig_Man_t * p, int nOutputs ) -{ - Cnf_Dat_t * pCnf = NULL; - int clk, clkTotal = clock(); -// printf( "\n" ); - Aig_ManCleanMarkAB( p ); - // create initial marking - clk = clock(); - Cnf_DeriveFastMark( p ); -// Abc_PrintTime( 1, "Marking", clock() - clk ); - // compute CNF size - clk = clock(); - pCnf = Cnf_DeriveFastClauses( p, nOutputs ); -// Abc_PrintTime( 1, "Clauses", clock() - clk ); - // derive the resulting CNF - Aig_ManCleanMarkA( p ); -// Abc_PrintTime( 1, "TOTAL ", clock() - clkTotal ); - -// printf( "Vars = %6d. Clauses = %7d. Literals = %8d. \n", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals ); - -// Cnf_DataFree( pCnf ); -// pCnf = NULL; - return pCnf; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cnf/cnfMan.c b/src/aig/cnf/cnfMan.c deleted file mode 100644 index 6b107651..00000000 --- a/src/aig/cnf/cnfMan.c +++ /dev/null @@ -1,693 +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" -#include "satSolver2.h" -#include "zlib.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 = ABC_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] = ABC_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 ); - ABC_FREE( p->pTruths[0] ); - Aig_MmFlexStop( p->pMemCuts, 0 ); - ABC_FREE( p->pSopSizes ); - ABC_FREE( p->pSops[1] ); - ABC_FREE( p->pSops ); - ABC_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 [Allocates the new CNF.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cnf_Dat_t * Cnf_DataAlloc( Aig_Man_t * pAig, int nVars, int nClauses, int nLiterals ) -{ - Cnf_Dat_t * pCnf; - int i; - pCnf = ABC_ALLOC( Cnf_Dat_t, 1 ); - memset( pCnf, 0, sizeof(Cnf_Dat_t) ); - pCnf->pMan = pAig; - pCnf->nVars = nVars; - pCnf->nClauses = nClauses; - pCnf->nLiterals = nLiterals; - pCnf->pClauses = ABC_ALLOC( int *, nClauses + 1 ); - pCnf->pClauses[0] = ABC_ALLOC( int, nLiterals ); - pCnf->pClauses[nClauses] = pCnf->pClauses[0] + nLiterals; - pCnf->pVarNums = ABC_ALLOC( int, Aig_ManObjNumMax(pAig) ); -// memset( pCnf->pVarNums, 0xff, sizeof(int) * Aig_ManObjNumMax(pAig) ); - for ( i = 0; i < Aig_ManObjNumMax(pAig); i++ ) - pCnf->pVarNums[i] = -1; - return pCnf; -} - -/**Function************************************************************* - - Synopsis [Allocates the new CNF.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cnf_Dat_t * Cnf_DataDup( Cnf_Dat_t * p ) -{ - Cnf_Dat_t * pCnf; - int i; - pCnf = Cnf_DataAlloc( p->pMan, p->nVars, p->nClauses, p->nLiterals ); - memcpy( pCnf->pClauses[0], p->pClauses[0], sizeof(int) * p->nLiterals ); - memcpy( pCnf->pVarNums, p->pVarNums, sizeof(int) * Aig_ManObjNumMax(p->pMan) ); - for ( i = 1; i < p->nClauses; i++ ) - pCnf->pClauses[i] = pCnf->pClauses[0] + (p->pClauses[i] - p->pClauses[0]); - return pCnf; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_DataFree( Cnf_Dat_t * p ) -{ - if ( p == NULL ) - return; - ABC_FREE( p->pObj2Clause ); - ABC_FREE( p->pObj2Count ); - ABC_FREE( p->pClauses[0] ); - ABC_FREE( p->pClauses ); - ABC_FREE( p->pVarNums ); - ABC_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] >= 0 ) - 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_DataFlipLastLiteral( Cnf_Dat_t * p ) -{ - p->pClauses[0][p->nLiterals-1] = lit_neg( p->pClauses[0][p->nLiterals-1] ); -} - -/**Function************************************************************* - - Synopsis [Writes CNF into a file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_DataPrint( Cnf_Dat_t * p, int fReadable ) -{ - FILE * pFile = stdout; - int * pLit, * pStop, i; - fprintf( pFile, "p cnf %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, "\n" ); - } - fprintf( pFile, "\n" ); -} - -/**Function************************************************************* - - Synopsis [Writes CNF into a file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_DataWriteIntoFileGz( Cnf_Dat_t * p, char * pFileName, int fReadable ) -{ - gzFile pFile; - int * pLit, * pStop, i; - pFile = gzopen( pFileName, "wb" ); - if ( pFile == NULL ) - { - printf( "Cnf_WriteIntoFile(): Output file cannot be opened.\n" ); - return; - } - gzprintf( pFile, "c Result of efficient AIG-to-CNF conversion using package CNF\n" ); - gzprintf( pFile, "p cnf %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++ ) - gzprintf( pFile, "%d ", fReadable? Cnf_Lit2Var2(*pLit) : Cnf_Lit2Var(*pLit) ); - gzprintf( pFile, "0\n" ); - } - gzprintf( pFile, "\n" ); - gzclose( pFile ); -} - -/**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; - if ( !strncmp(pFileName+strlen(pFileName)-3,".gz",3) ) - { - Cnf_DataWriteIntoFileGz( p, pFileName, fReadable ); - return; - } - 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 cnf %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_DataWriteIntoSolverInt( void * pSolver, Cnf_Dat_t * p, int nFrames, int fInit ) -{ - sat_solver * pSat = (sat_solver *)pSolver; - int i, f, status; - assert( nFrames > 0 ); - assert( pSat ); -// 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; -} - -/**Function************************************************************* - - Synopsis [Writes CNF into a file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Cnf_DataWriteIntoSolver( Cnf_Dat_t * p, int nFrames, int fInit ) -{ - return Cnf_DataWriteIntoSolverInt( sat_solver_new(), p, nFrames, fInit ); -} - -/**Function************************************************************* - - Synopsis [Writes CNF into a file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Cnf_DataWriteIntoSolver2( Cnf_Dat_t * p, int nFrames, int fInit ) -{ - sat_solver2 * pSat; - int i, f, status; - assert( nFrames > 0 ); - pSat = sat_solver2_new(); - sat_solver2_setnvars( pSat, p->nVars * nFrames ); - for ( i = 0; i < p->nClauses; i++ ) - { - if ( !sat_solver2_addclause( pSat, p->pClauses[i], p->pClauses[i+1] ) ) - { - sat_solver2_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_solver2_addclause( pSat, Lits, Lits + 2 ) ) - { - sat_solver2_delete( pSat ); - return NULL; - } - Lits[0]++; - Lits[1]--; - if ( !sat_solver2_addclause( pSat, Lits, Lits + 2 ) ) - { - sat_solver2_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_solver2_addclause( pSat, p->pClauses[i], p->pClauses[i+1] ) ) - { - sat_solver2_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_solver2_addclause( pSat, Lits, Lits + 1 ) ) - { - sat_solver2_delete( pSat ); - return NULL; - } - } - } - status = sat_solver2_simplify(pSat); - if ( status == 0 ) - { - sat_solver2_delete( pSat ); - return NULL; - } - return pSat; -} - -/**Function************************************************************* - - Synopsis [Adds the OR-clause.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cnf_DataWriteOrClause( void * p, Cnf_Dat_t * pCnf ) -{ - sat_solver * pSat = (sat_solver *)p; - Aig_Obj_t * pObj; - int i, * pLits; - pLits = ABC_ALLOC( int, Aig_ManPoNum(pCnf->pMan) ); - Aig_ManForEachPo( pCnf->pMan, pObj, i ) - pLits[i] = toLitCond( pCnf->pVarNums[pObj->Id], 0 ); - if ( !sat_solver_addclause( pSat, pLits, pLits + Aig_ManPoNum(pCnf->pMan) ) ) - { - ABC_FREE( pLits ); - return 0; - } - ABC_FREE( pLits ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Adds the OR-clause.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cnf_DataWriteOrClause2( void * p, Cnf_Dat_t * pCnf ) -{ - sat_solver2 * pSat = (sat_solver2 *)p; - Aig_Obj_t * pObj; - int i, * pLits; - pLits = ABC_ALLOC( int, Aig_ManPoNum(pCnf->pMan) ); - Aig_ManForEachPo( pCnf->pMan, pObj, i ) - pLits[i] = toLitCond( pCnf->pVarNums[pObj->Id], 0 ); - if ( !sat_solver2_addclause( pSat, pLits, pLits + Aig_ManPoNum(pCnf->pMan) ) ) - { - ABC_FREE( pLits ); - return 0; - } - ABC_FREE( pLits ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Adds the OR-clause.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cnf_DataWriteAndClauses( void * p, Cnf_Dat_t * pCnf ) -{ - sat_solver * pSat = (sat_solver *)p; - Aig_Obj_t * pObj; - int i, Lit; - Aig_ManForEachPo( pCnf->pMan, pObj, i ) - { - Lit = toLitCond( pCnf->pVarNums[pObj->Id], 0 ); - if ( !sat_solver_addclause( pSat, &Lit, &Lit+1 ) ) - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Transforms polarity of the internal veriables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_DataTranformPolarity( Cnf_Dat_t * pCnf, int fTransformPos ) -{ - Aig_Obj_t * pObj; - int * pVarToPol; - int i, iVar; - // create map from the variable number to its polarity - pVarToPol = ABC_CALLOC( int, pCnf->nVars ); - Aig_ManForEachObj( pCnf->pMan, pObj, i ) - { - if ( !fTransformPos && Aig_ObjIsPo(pObj) ) - continue; - if ( pCnf->pVarNums[pObj->Id] >= 0 ) - pVarToPol[ pCnf->pVarNums[pObj->Id] ] = pObj->fPhase; - } - // transform literals - for ( i = 0; i < pCnf->nLiterals; i++ ) - { - iVar = lit_var(pCnf->pClauses[0][i]); - assert( iVar < pCnf->nVars ); - if ( pVarToPol[iVar] ) - pCnf->pClauses[0][i] = lit_neg( pCnf->pClauses[0][i] ); - } - ABC_FREE( pVarToPol ); -} - -/**Function************************************************************* - - Synopsis [Adds constraints for the two-input AND-gate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cnf_DataAddXorClause( void * pSat, int iVarA, int iVarB, int iVarC ) -{ - lit Lits[3]; - assert( iVarA > 0 && iVarB > 0 && iVarC > 0 ); - - Lits[0] = toLitCond( iVarA, 1 ); - Lits[1] = toLitCond( iVarB, 1 ); - Lits[2] = toLitCond( iVarC, 1 ); - if ( !sat_solver_addclause( (sat_solver *)pSat, Lits, Lits + 3 ) ) - return 0; - - Lits[0] = toLitCond( iVarA, 1 ); - Lits[1] = toLitCond( iVarB, 0 ); - Lits[2] = toLitCond( iVarC, 0 ); - if ( !sat_solver_addclause( (sat_solver *)pSat, Lits, Lits + 3 ) ) - return 0; - - Lits[0] = toLitCond( iVarA, 0 ); - Lits[1] = toLitCond( iVarB, 1 ); - Lits[2] = toLitCond( iVarC, 0 ); - if ( !sat_solver_addclause( (sat_solver *)pSat, Lits, Lits + 3 ) ) - return 0; - - Lits[0] = toLitCond( iVarA, 0 ); - Lits[1] = toLitCond( iVarB, 0 ); - Lits[2] = toLitCond( iVarC, 1 ); - if ( !sat_solver_addclause( (sat_solver *)pSat, Lits, Lits + 3 ) ) - return 0; - - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cnf/cnfMap.c b/src/aig/cnf/cnfMap.c deleted file mode 100644 index 8907485e..00000000 --- a/src/aig/cnf/cnfMap.c +++ /dev/null @@ -1,362 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 ); - pCut->uSign = 10 * 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( Aig_Obj_t *, 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 = ABC_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 = ABC_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 ); - ABC_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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cnf/cnfPost.c b/src/aig/cnf/cnfPost.c deleted file mode 100644 index f7491889..00000000 --- a/src/aig/cnf/cnfPost.c +++ /dev/null @@ -1,238 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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( (Cnf_Cut_t *)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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cnf/cnfUtil.c b/src/aig/cnf/cnfUtil.c deleted file mode 100644 index 236b6bfa..00000000 --- a/src/aig/cnf/cnfUtil.c +++ /dev/null @@ -1,238 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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( Aig_Obj_t *, 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( Aig_Obj_t *, vSuper, pLeaf, i ) - aArea += Cnf_ManScanMapping_rec( p, Aig_Regular(pLeaf), vMapped, fPreorder ); - Vec_PtrFree( vSuper ); - //////////////////////////// - pObj->fMarkB = 1; - } - else - { - pCutBest = (Cnf_Cut_t *)pObj->pData; -// assert( pCutBest->nFanins > 0 ); - 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; -} - -/**Function************************************************************* - - Synopsis [Returns the array of CI IDs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Cnf_DataCollectCiSatNums( 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 [Returns the array of CI IDs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Cnf_DataCollectCoSatNums( Cnf_Dat_t * pCnf, Aig_Man_t * p ) -{ - Vec_Int_t * vCoIds; - Aig_Obj_t * pObj; - int i; - vCoIds = Vec_IntAlloc( Aig_ManPoNum(p) ); - Aig_ManForEachPo( p, pObj, i ) - Vec_IntPush( vCoIds, pCnf->pVarNums[pObj->Id] ); - return vCoIds; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cnf/cnfWrite.c b/src/aig/cnf/cnfWrite.c deleted file mode 100644 index 54c28967..00000000 --- a/src/aig/cnf/cnfWrite.c +++ /dev/null @@ -1,806 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Derives CNF mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Cnf_ManWriteCnfMapping( Cnf_Man_t * p, Vec_Ptr_t * vMapped ) -{ - Vec_Int_t * vResult; - Aig_Obj_t * pObj; - Cnf_Cut_t * pCut; - int i, k, nOffset; - nOffset = Aig_ManObjNumMax(p->pManAig); - vResult = Vec_IntStart( nOffset ); - Vec_PtrForEachEntry( Aig_Obj_t *, vMapped, pObj, i ) - { - assert( Aig_ObjIsNode(pObj) ); - pCut = Cnf_ObjBestCut( pObj ); - assert( pCut->nFanins < 5 ); - Vec_IntWriteEntry( vResult, Aig_ObjId(pObj), nOffset ); - Vec_IntPush( vResult, *Cnf_CutTruth(pCut) ); - for ( k = 0; k < pCut->nFanins; k++ ) - Vec_IntPush( vResult, pCut->pFanins[k] ); - for ( ; k < 4; k++ ) - Vec_IntPush( vResult, -1 ); - nOffset += 5; - } - return vResult; -} - - - -/**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 ) -{ - int fChangeVariableOrder = 0; // should be set to 0 to improve performance - 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( Aig_Obj_t *, 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 = ABC_CALLOC( Cnf_Dat_t, 1 ); - pCnf->pMan = p->pManAig; - pCnf->nLiterals = nLiterals; - pCnf->nClauses = nClauses; - pCnf->pClauses = ABC_ALLOC( int *, nClauses + 1 ); - pCnf->pClauses[0] = ABC_ALLOC( int, nLiterals ); - pCnf->pClauses[nClauses] = pCnf->pClauses[0] + nLiterals; - // create room for variable numbers - pCnf->pVarNums = ABC_ALLOC( int, Aig_ManObjNumMax(p->pManAig) ); -// memset( pCnf->pVarNums, 0xff, sizeof(int) * Aig_ManObjNumMax(p->pManAig) ); - for ( i = 0; i < Aig_ManObjNumMax(p->pManAig); i++ ) - pCnf->pVarNums[i] = -1; - - if ( !fChangeVariableOrder ) - { - // assign variables to the last (nOutputs) POs - Number = 1; - if ( nOutputs ) - { - if ( Aig_ManRegNum(p->pManAig) == 0 ) - { - assert( nOutputs == Aig_ManPoNum(p->pManAig) ); - Aig_ManForEachPo( p->pManAig, pObj, i ) - pCnf->pVarNums[pObj->Id] = Number++; - } - else - { - 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( Aig_Obj_t *, 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; - } - else - { - // assign variables to the last (nOutputs) POs - Number = Aig_ManObjNumMax(p->pManAig) + 1; - pCnf->nVars = Number + 1; - if ( nOutputs ) - { - if ( Aig_ManRegNum(p->pManAig) == 0 ) - { - assert( nOutputs == Aig_ManPoNum(p->pManAig) ); - Aig_ManForEachPo( p->pManAig, pObj, i ) - pCnf->pVarNums[pObj->Id] = Number--; - } - else - { - 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( Aig_Obj_t *, 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--; - assert( Number >= 0 ); - } - - // assign the clauses - vSopTemp = Vec_IntAlloc( 1 << 16 ); - pLits = pCnf->pClauses[0]; - pClas = pCnf->pClauses; - Vec_PtrForEachEntry( Aig_Obj_t *, 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 ); -//Cnf_DataPrint( pCnf, 1 ); - return pCnf; -} - - -/**Function************************************************************* - - Synopsis [Derives CNF for the mapping.] - - Description [Derives CNF with obj IDs as SAT vars and mapping of - objects into clauses (pObj2Clause and pObj2Count).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cnf_Dat_t * Cnf_ManWriteCnfOther( Cnf_Man_t * p, Vec_Ptr_t * vMapped ) -{ - 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; - - // count the number of literals and clauses - nLiterals = 1 + 4 * Aig_ManPoNum( p->pManAig ); - nClauses = 1 + 2 * Aig_ManPoNum( p->pManAig ); - Vec_PtrForEachEntry( Aig_Obj_t *, 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]); - } - } - - // allocate CNF - pCnf = ABC_CALLOC( Cnf_Dat_t, 1 ); - pCnf->pMan = p->pManAig; - pCnf->nLiterals = nLiterals; - pCnf->nClauses = nClauses; - pCnf->pClauses = ABC_ALLOC( int *, nClauses + 1 ); - pCnf->pClauses[0] = ABC_ALLOC( int, nLiterals ); - pCnf->pClauses[nClauses] = pCnf->pClauses[0] + nLiterals; - // create room for variable numbers - pCnf->pObj2Clause = ABC_ALLOC( int, Aig_ManObjNumMax(p->pManAig) ); - pCnf->pObj2Count = ABC_ALLOC( int, Aig_ManObjNumMax(p->pManAig) ); - for ( i = 0; i < Aig_ManObjNumMax(p->pManAig); i++ ) - pCnf->pObj2Clause[i] = pCnf->pObj2Count[i] = -1; - pCnf->nVars = Aig_ManObjNumMax(p->pManAig); - - // clear the PI counters - Aig_ManForEachPi( p->pManAig, pObj, i ) - pCnf->pObj2Count[pObj->Id] = 0; - - // assign the clauses - vSopTemp = Vec_IntAlloc( 1 << 16 ); - pLits = pCnf->pClauses[0]; - pClas = pCnf->pClauses; - Vec_PtrForEachEntry( Aig_Obj_t *, vMapped, pObj, i ) - { - // remember the starting clause - pCnf->pObj2Clause[pObj->Id] = pClas - pCnf->pClauses; - pCnf->pObj2Count[pObj->Id] = 0; - - // get the best cut - pCut = Cnf_ObjBestCut( pObj ); - // save variables of this cut - OutVar = pObj->Id; - for ( k = 0; k < (int)pCut->nFanins; k++ ) - { - pVars[k] = 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 ); - } - pCnf->pObj2Count[pObj->Id] += Vec_IntSize(vCover); - - // 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 ); - } - pCnf->pObj2Count[pObj->Id] += Vec_IntSize(vCover); - } - Vec_IntFree( vSopTemp ); - - // write the output literals - Aig_ManForEachPo( p->pManAig, pObj, i ) - { - // remember the starting clause - pCnf->pObj2Clause[pObj->Id] = pClas - pCnf->pClauses; - pCnf->pObj2Count[pObj->Id] = 2; - // get variables - OutVar = Aig_ObjFanin0(pObj)->Id; - PoVar = 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); - } - - // remember the starting clause - pCnf->pObj2Clause[Aig_ManConst1(p->pManAig)->Id] = pClas - pCnf->pClauses; - pCnf->pObj2Count[Aig_ManConst1(p->pManAig)->Id] = 1; - // write the constant literal - OutVar = Aig_ManConst1(p->pManAig)->Id; - *pClas++ = pLits; - *pLits++ = 2 * OutVar; - - // verify that the correct number of literals and clauses was written - assert( pLits - pCnf->pClauses[0] == nLiterals ); - assert( pClas - pCnf->pClauses == nClauses ); -//Cnf_DataPrint( pCnf, 1 ); - return pCnf; -} - - -/**Function************************************************************* - - Synopsis [Derives a simple CNF for the AIG.] - - Description [The last argument lists 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 = ABC_ALLOC( Cnf_Dat_t, 1 ); - memset( pCnf, 0, sizeof(Cnf_Dat_t) ); - pCnf->pMan = p; - pCnf->nLiterals = nLiterals; - pCnf->nClauses = nClauses; - pCnf->pClauses = ABC_ALLOC( int *, nClauses + 1 ); - pCnf->pClauses[0] = ABC_ALLOC( int, nLiterals ); - pCnf->pClauses[nClauses] = pCnf->pClauses[0] + nLiterals; - - // create room for variable numbers - pCnf->pVarNums = ABC_ALLOC( int, Aig_ManObjNumMax(p) ); -// memset( pCnf->pVarNums, 0xff, sizeof(int) * Aig_ManObjNumMax(p) ); - for ( i = 0; i < Aig_ManObjNumMax(p); i++ ) - pCnf->pVarNums[i] = -1; - // 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; -} - -/**Function************************************************************* - - Synopsis [Derives a simple CNF for backward retiming computation.] - - 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_DeriveSimpleForRetiming( Aig_Man_t * p ) -{ - 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) + 5 * Aig_ManPoNum(p); - nClauses = 1 + 3 * Aig_ManNodeNum(p) + 3 * Aig_ManPoNum(p); - - // allocate CNF - pCnf = ABC_ALLOC( Cnf_Dat_t, 1 ); - memset( pCnf, 0, sizeof(Cnf_Dat_t) ); - pCnf->pMan = p; - pCnf->nLiterals = nLiterals; - pCnf->nClauses = nClauses; - pCnf->pClauses = ABC_ALLOC( int *, nClauses + 1 ); - pCnf->pClauses[0] = ABC_ALLOC( int, nLiterals ); - pCnf->pClauses[nClauses] = pCnf->pClauses[0] + nLiterals; - - // create room for variable numbers - pCnf->pVarNums = ABC_ALLOC( int, Aig_ManObjNumMax(p) ); -// memset( pCnf->pVarNums, 0xff, sizeof(int) * Aig_ManObjNumMax(p) ); - for ( i = 0; i < Aig_ManObjNumMax(p); i++ ) - pCnf->pVarNums[i] = -1; - // assign variables to the last (nOutputs) POs - Number = 1; - 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; - // 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 ]; - 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); - // final clause (init-state is always 0 -> set the output to 0) - *pClas++ = pLits; - *pLits++ = 2 * PoVar + 1; - } - - // 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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cnf/cnf_.c b/src/aig/cnf/cnf_.c deleted file mode 100644 index acf75093..00000000 --- a/src/aig/cnf/cnf_.c +++ /dev/null @@ -1,53 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/cnf/module.make b/src/aig/cnf/module.make deleted file mode 100644 index 596fe31b..00000000 --- a/src/aig/cnf/module.make +++ /dev/null @@ -1,9 +0,0 @@ -SRC += src/aig/cnf/cnfCore.c \ - src/aig/cnf/cnfCut.c \ - src/aig/cnf/cnfData.c \ - src/aig/cnf/cnfFast.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 c1bf7a73..00000000 --- a/src/aig/csw/csw.h +++ /dev/null @@ -1,69 +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__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/csw/cswCore.c b/src/aig/csw/cswCore.c deleted file mode 100644 index e1bdca00..00000000 --- a/src/aig/csw/cswCore.c +++ /dev/null @@ -1,99 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/csw/cswCut.c b/src/aig/csw/cswCut.c deleted file mode 100644 index bb6677c2..00000000 --- a/src/aig/csw/cswCut.c +++ /dev/null @@ -1,607 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/csw/cswInt.h b/src/aig/csw/cswInt.h deleted file mode 100644 index 3a06f3f1..00000000 --- a/src/aig/csw/cswInt.h +++ /dev/null @@ -1,161 +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__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include - -#include "aig.h" -#include "dar.h" -#include "kit.h" -#include "csw.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/csw/cswMan.c b/src/aig/csw/cswMan.c deleted file mode 100644 index 8b6e538b..00000000 --- a/src/aig/csw/cswMan.c +++ /dev/null @@ -1,130 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 = ABC_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 = ABC_ALLOC( int, Aig_ManObjNumMax(pMan) ); - p->pEquiv = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pMan) ); - p->pCuts = ABC_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 = ABC_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] = ABC_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 ); - ABC_PRTP( "Cuts ", p->timeCuts, p->timeTotal ); - ABC_PRTP( "Hashing ", p->timeHash, p->timeTotal ); - ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); - ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); - } - ABC_FREE( p->puTemp[0] ); - Aig_MmFixedStop( p->pMemCuts, 0 ); - ABC_FREE( p->pnRefs ); - ABC_FREE( p->pEquiv ); - ABC_FREE( p->pCuts ); - ABC_FREE( p->pTable ); - ABC_FREE( p ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/csw/cswTable.c b/src/aig/csw/cswTable.c deleted file mode 100644 index 9bab0a01..00000000 --- a/src/aig/csw/cswTable.c +++ /dev/null @@ -1,166 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/csw/csw_.c b/src/aig/csw/csw_.c deleted file mode 100644 index c12607d3..00000000 --- a/src/aig/csw/csw_.c +++ /dev/null @@ -1,53 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - 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 0a3b5eb7..00000000 --- a/src/aig/dar/dar.h +++ /dev/null @@ -1,116 +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__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 fPower; // enables power-aware rewriting - int fRecycle; // enables cut recycling - 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(); -extern void Dar_LibPrepare( int nSubgraphs ); -extern int Dar_LibReturnClass( unsigned uTruth ); -/*=== darBalance.c ========================================================*/ -extern Aig_Man_t * Dar_ManBalance( Aig_Man_t * p, int fUpdateLevel ); -extern Aig_Man_t * Dar_ManBalanceXor( Aig_Man_t * pAig, int fExor, int fUpdateLevel, int fVerbose ); -extern void Dar_BalancePrintStats( Aig_Man_t * p ); -/*=== 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 fPower, int fVerbose ); -extern Aig_Man_t * Dar_ManCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fFanout, int fPower, int fVerbose ); -extern Aig_Man_t * Dar_ManChoice( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fConstruct, int nConfMax, int nLevelMax, int fVerbose ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/dar/darBalance.c b/src/aig/dar/darBalance.c deleted file mode 100644 index 6e9e7e21..00000000 --- a/src/aig/dar/darBalance.c +++ /dev/null @@ -1,645 +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" -#include "tim.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//#define USE_LUTSIZE_BALANCE - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**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 ) - { - if ( Aig_ObjIsExor(pRoot) ) - { - assert( !Aig_IsComplement(pObj) ); - // check if the node occurs in the same polarity - Vec_PtrRemove( vSuper, pObj ); - Aig_Regular(pObj)->fMarkB = 0; -//printf( " Duplicated EXOR input!!! " ); - return 1; - } - else - { - // 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_PtrSize(vSuper) > 10000) ) - { - 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( RetValue != 0 || vNodes->nSize > 1 ); - // unmark the visited nodes - Vec_PtrForEachEntry( Aig_Obj_t *, 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 [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 = (Aig_Obj_t *)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 = (Aig_Obj_t *)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 = (Aig_Obj_t *)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 = (Aig_Obj_t *)Vec_PtrEntry( vSuper, RightBound + 1 ); - pObj2 = (Aig_Obj_t *)Vec_PtrEntry( vSuper, RightBound ); - if ( Aig_Regular(pObj1) == p->pConst1 || Aig_Regular(pObj2) == p->pConst1 || Aig_Regular(pObj1) == Aig_Regular(pObj2) ) - return; - // find the first node that can be shared - for ( i = RightBound; i >= LeftBound; i-- ) - { - pObj3 = (Aig_Obj_t *)Vec_PtrEntry( vSuper, i ); - if ( Aig_Regular(pObj3) == p->pConst1 ) - { - Vec_PtrWriteEntry( vSuper, i, pObj2 ); - Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); - return; - } - if ( Aig_Regular(pObj1) == Aig_Regular(pObj3) ) - { - if ( pObj3 == pObj2 ) - return; - 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 = Aig_ManRandom(0) % (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 [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; - Diff = Aig_ObjId(Aig_Regular(*pp1)) - Aig_ObjId(Aig_Regular(*pp2)); - if ( Diff > 0 ) - return -1; - if ( Diff < 0 ) - return 1; - return 0; -} - -/**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 = (Aig_Obj_t *)vStore->pArray[i ]; - pObj2 = (Aig_Obj_t *)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; - } -} - -/**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, (int (*)(void))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 = (Aig_Obj_t *)Vec_PtrPop(vSuper); - pObj2 = (Aig_Obj_t *)Vec_PtrPop(vSuper); - Dar_BalancePushUniqueOrderByLevel( vSuper, Aig_Oper(p, pObj1, pObj2, Type) ); - } - return (Aig_Obj_t *)Vec_PtrEntry(vSuper, 0); -} - - -/**Function************************************************************* - - Synopsis [Returns affective support size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_BaseSize( Aig_Man_t * p, Aig_Obj_t * pObj, int nLutSize ) -{ - int nBaseSize; - pObj = Aig_Regular(pObj); - if ( Aig_ObjIsConst1(pObj) ) - return 0; - if ( Aig_ObjLevel(pObj) >= nLutSize ) - return 1; - nBaseSize = Aig_SupportSize( p, pObj ); - if ( nBaseSize >= nLutSize ) - return 1; - return nBaseSize; -} - -/**Function************************************************************* - - Synopsis [Builds implication supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Dar_BalanceBuildSuperTop( Aig_Man_t * p, Vec_Ptr_t * vSuper, Aig_Type_t Type, int fUpdateLevel, int nLutSize ) -{ - Vec_Ptr_t * vSubset; - Aig_Obj_t * pObj; - int i, nBaseSizeAll, nBaseSize; - assert( vSuper->nSize > 1 ); - // sort the new nodes by level in the decreasing order - Vec_PtrSort( vSuper, (int (*)(void))Aig_NodeCompareLevelsDecrease ); - // add one LUT at a time - while ( Vec_PtrSize(vSuper) > 1 ) - { - // isolate the group of nodes with nLutSize inputs - nBaseSizeAll = 0; - vSubset = Vec_PtrAlloc( nLutSize ); - Vec_PtrForEachEntryReverse( Aig_Obj_t *, vSuper, pObj, i ) - { - nBaseSize = Aig_BaseSize( p, pObj, nLutSize ); - if ( nBaseSizeAll + nBaseSize > nLutSize && Vec_PtrSize(vSubset) > 1 ) - break; - nBaseSizeAll += nBaseSize; - Vec_PtrPush( vSubset, pObj ); - } - // remove them from vSuper - Vec_PtrShrink( vSuper, Vec_PtrSize(vSuper) - Vec_PtrSize(vSubset) ); - // create the new supergate - pObj = Dar_BalanceBuildSuper( p, vSubset, Type, fUpdateLevel ); - Vec_PtrFree( vSubset ); - // add the new output - Dar_BalancePushUniqueOrderByLevel( vSuper, pObj ); - } - return (Aig_Obj_t *)Vec_PtrEntry(vSuper, 0); -} - -/**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 (Aig_Obj_t *)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 (Aig_Obj_t *)(pObjOld->pData = Aig_ManConst0(pNew)); - if ( vSuper->nSize == 1 ) - return (Aig_Obj_t *)Vec_PtrEntry(vSuper, 0); - if ( Vec_PtrSize(vSuper) < 2 ) - printf( "Dar_Balance_rec: Internal error!\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((Aig_Obj_t *)vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel ); - vSuper->pArray[i] = Aig_NotCond( pObjNew, Aig_IsComplement((Aig_Obj_t *)vSuper->pArray[i]) ); - } - // build the supergate -#ifdef USE_LUTSIZE_BALANCE - pObjNew = Dar_BalanceBuildSuperTop( pNew, vSuper, Aig_ObjType(pObjOld), fUpdateLevel, 6 ); -#else - pObjNew = Dar_BalanceBuildSuper( pNew, vSuper, Aig_ObjType(pObjOld), fUpdateLevel ); -#endif - // make sure the balanced node is not assigned -// assert( pObjOld->Level >= Aig_Regular(pObjNew)->Level ); - assert( pObjOld->pData == NULL ); - if ( pNew->pManHaig != NULL ) - { - Aig_Obj_t * pObjNewR = Aig_Regular(pObjNew); -// printf( "Balancing HAIG node %d equivalent to HAIG node %d (over = %d).\n", -// pObjNewR->pHaig->Id, pObjOld->pHaig->Id, pObjNewR->pHaig->pHaig != NULL ); - assert( pObjNewR->pHaig != NULL ); - assert( !Aig_IsComplement(pObjNewR->pHaig) ); - assert( pNew->pManHaig->vEquPairs != NULL ); - Vec_IntPush( pNew->pManHaig->vEquPairs, pObjNewR->pHaig->Id ); - Vec_IntPush( pNew->pManHaig->vEquPairs, pObjOld->pHaig->Id ); - } - else - Aig_Regular(pObjNew)->pHaig = pObjOld->pHaig; - return (Aig_Obj_t *)(pObjOld->pData = pObjNew); -} - -/**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; - assert( Aig_ManVerifyTopoOrder(p) ); - // create the new manager - pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->pSpec = Aig_UtilStrsav( p->pSpec ); - pNew->nAsserts = p->nAsserts; - pNew->nConstrs = p->nConstrs; - if ( p->vFlopNums ) - pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); - // pass the HAIG manager - if ( p->pManHaig != NULL ) - { - pNew->pManHaig = p->pManHaig; p->pManHaig = NULL; - Aig_ManConst1(pNew)->pHaig = Aig_ManConst1(pNew->pManHaig); - } - // map the PI nodes - Aig_ManCleanData( p ); - Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); - vStore = Vec_VecAlloc( 50 ); - if ( p->pManTime != NULL ) - { - float arrTime; - Tim_ManIncrementTravId( (Tim_Man_t *)p->pManTime ); - Aig_ManSetPioNumbers( p ); - Aig_ManForEachObj( p, pObj, i ) - { - if ( Aig_ObjIsNode(pObj) || Aig_ObjIsConst1(pObj) ) - continue; - if ( Aig_ObjIsPi(pObj) ) - { - // copy the PI - pObjNew = Aig_ObjCreatePi(pNew); - pObj->pData = pObjNew; - pObjNew->pHaig = pObj->pHaig; - // set the arrival time of the new PI - arrTime = Tim_ManGetCiArrival( (Tim_Man_t *)p->pManTime, Aig_ObjPioNum(pObj) ); - pObjNew->Level = (int)arrTime; - } - else if ( Aig_ObjIsPo(pObj) ) - { - // perform balancing - 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) ); - // save arrival time of the output - arrTime = (float)Aig_Regular(pObjNew)->Level; - Tim_ManSetCoArrival( (Tim_Man_t *)p->pManTime, Aig_ObjPioNum(pObj), arrTime ); - // create PO - pObjNew = Aig_ObjCreatePo( pNew, pObjNew ); - pObjNew->pHaig = pObj->pHaig; - } - else - assert( 0 ); - } - Aig_ManCleanPioNumbers( p ); - pNew->pManTime = Tim_ManDup( (Tim_Man_t *)p->pManTime, 0 ); - } - else - { - Aig_ManForEachPi( p, pObj, i ) - { - pObjNew = Aig_ObjCreatePi(pNew); - pObjNew->Level = pObj->Level; - pObj->pData = pObjNew; - pObjNew->pHaig = pObj->pHaig; - } - 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) ); - pObjNew = Aig_ObjCreatePo( pNew, pObjNew ); - pObjNew->pHaig = pObj->pHaig; - } - } - Vec_VecFree( vStore ); - // remove dangling nodes - Aig_ManCleanup( pNew ); - Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); - // check the resulting AIG - if ( !Aig_ManCheck(pNew) ) - printf( "Dar_ManBalance(): The check has failed.\n" ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Reproduces script "compress2".] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Dar_ManBalanceXor( Aig_Man_t * pAig, int fExor, int fUpdateLevel, int fVerbose ) -{ - Aig_Man_t * pAigXor, * pRes; - if ( fExor ) - { - pAigXor = Aig_ManDupExor( pAig ); - if ( fVerbose ) - Dar_BalancePrintStats( pAigXor ); - pRes = Dar_ManBalance( pAigXor, fUpdateLevel ); - Aig_ManStop( pAigXor ); - } - else - { - pRes = Dar_ManBalance( pAig, fUpdateLevel ); - } - return pRes; -} - -/**Function************************************************************* - - Synopsis [Inserts a new node in the order by levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_BalancePrintStats( Aig_Man_t * p ) -{ - Vec_Ptr_t * vSuper; - Aig_Obj_t * pObj, * pTemp; - int i, k; - if ( Aig_ManExorNum(p) == 0 ) - { - printf( "There is no EXOR gates.\n" ); - return; - } - Aig_ManForEachExor( p, pObj, i ) - { - Aig_ObjFanin0(pObj)->fMarkA = 1; - Aig_ObjFanin1(pObj)->fMarkA = 1; - assert( !Aig_ObjFaninC0(pObj) ); - assert( !Aig_ObjFaninC1(pObj) ); - } - vSuper = Vec_PtrAlloc( 1000 ); - Aig_ManForEachExor( p, pObj, i ) - { - if ( pObj->fMarkA && pObj->nRefs == 1 ) - continue; - Vec_PtrClear( vSuper ); - Dar_BalanceCone_rec( pObj, pObj, vSuper ); - Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pTemp, k ) - pTemp->fMarkB = 0; - if ( Vec_PtrSize(vSuper) < 3 ) - continue; - printf( " %d(", Vec_PtrSize(vSuper) ); - Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pTemp, k ) - printf( " %d", pTemp->Level ); - printf( " )" ); - } - Vec_PtrFree( vSuper ); - Aig_ManForEachObj( p, pObj, i ) - pObj->fMarkA = 0; - printf( "\n" ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/dar/darCore.c b/src/aig/dar/darCore.c deleted file mode 100644 index 6ca3082d..00000000 --- a/src/aig/dar/darCore.c +++ /dev/null @@ -1,344 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// 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] ) - -//////////////////////////////////////////////////////////////////////// -/// 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->fPower = 0; - pPars->fRecycle = 1; - pPars->fVerbose = 0; - pPars->fVeryVerbose = 0; -} - -#define MAX_VAL 10 - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dar_ManRewrite( Aig_Man_t * pAig, Dar_RwrPar_t * pPars ) -{ - extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ); - 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, Counter = 0; - int nMffcSize, nMffcGains[MAX_VAL+1][MAX_VAL+1] = {{0}}; - // prepare the library - Dar_LibPrepare( pPars->nSubgMax ); - // create rewriting manager - p = Dar_ManStart( pAig, pPars ); - if ( pPars->fPower ) - pAig->vProbs = Saig_ManComputeSwitchProbs( pAig, 48, 16, 1 ); - // 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 ) -// if ( p->pPars->fUseZeros && i > nNodesOld ) - break; - if ( pPars->fRecycle && ++Counter % 50000 == 0 && Aig_DagSize(pObj) < Vec_PtrSize(p->vCutNodes)/100 ) - { -// printf( "Counter = %7d. Node = %7d. Dag = %5d. Vec = %5d.\n", -// Counter, i, Aig_DagSize(pObj), Vec_PtrSize(p->vCutNodes) ); -// fflush( stdout ); - Dar_ManCutsRestart( p, pObj ); - } - - // 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_ObjSetCuts( pObj, NULL ); - 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, p->pPars->fUpdateLevel ); - continue; - } - - // evaluate the cuts - p->GainBest = -1; - nMffcSize = -1; - Required = pAig->vLevelR? Aig_ObjRequiredLevel(pAig, pObj) : ABC_INFINITY; - Dar_ObjForEachCut( pObj, pCut, k ) - { - int nLeavesOld = pCut->nLeaves; - if ( pCut->nLeaves == 3 ) - pCut->pLeaves[pCut->nLeaves++] = 0; - Dar_LibEval( p, pObj, pCut, Required, &nMffcSize ); - pCut->nLeaves = nLeavesOld; - } - // check the best gain - if ( !(p->GainBest > 0 || (p->GainBest == 0 && p->pPars->fUseZeros)) ) - { -// Aig_ObjOrderAdvance( pAig ); - continue; - } -// nMffcGains[p->GainBest < MAX_VAL ? p->GainBest : MAX_VAL][nMffcSize < MAX_VAL ? nMffcSize : MAX_VAL]++; - // 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, 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 ); -/* - printf( "Distribution of gain (row) by MFFC size (column) %s 0-costs:\n", p->pPars->fUseZeros? "with":"without" ); - for ( k = 0; k <= MAX_VAL; k++ ) - printf( "<%4d> ", k ); - printf( "\n" ); - for ( i = 0; i <= MAX_VAL; i++ ) - { - for ( k = 0; k <= MAX_VAL; k++ ) - printf( "%6d ", nMffcGains[i][k] ); - printf( "\n" ); - } -*/ - -p->timeTotal = clock() - clkStart; -p->timeOther = p->timeTotal - p->timeCuts - p->timeEval; - -// Bar_ProgressStop( pProgress ); - 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 ); - } - if ( pAig->vProbs ) - { - Vec_IntFree( pAig->vProbs ); - pAig->vProbs = NULL; - } - // 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 ); - Aig_MmFixedRestart( p->pMemCuts ); - Dar_ObjPrepareCuts( p, Aig_ManConst1(p->pAig) ); - Aig_ManForEachPi( pAig, pObj, i ) - Dar_ObjPrepareCuts( p, pObj ); - // 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 ", - (int)sizeof(Dar_Cut_t), (int)4, 1.0*Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20) ); - ABC_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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/dar/darCut.c b/src/aig/dar/darCut.c deleted file mode 100644 index b272b388..00000000 --- a/src/aig/dar/darCut.c +++ /dev/null @@ -1,752 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 ); - memset( pCutSet, 0, p->pPars->nCutsMax * sizeof(Dar_Cut_t) ); - Dar_ObjSetCuts( pObj, pCutSet ); - Dar_ObjForEachCutAll( pObj, pCut, i ) - pCut->fUsed = 0; - Vec_PtrPush( p->vCutNodes, pObj ); - // 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 ); - if ( p->nCutMemUsed < Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20) ) - p->nCutMemUsed = Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20); - return pCutSet; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_ManCutsRestart( Dar_Man_t * p, Aig_Obj_t * pRoot ) -{ - Aig_Obj_t * pObj; - int i; - Dar_ObjSetCuts( Aig_ManConst1(p->pAig), NULL ); - Vec_PtrForEachEntry( Aig_Obj_t *, p->vCutNodes, pObj, i ) - if ( !Aig_ObjIsNone(pObj) ) - Dar_ObjSetCuts( pObj, NULL ); - Vec_PtrClear( p->vCutNodes ); - Aig_MmFixedRestart( p->pMemCuts ); - Dar_ObjPrepareCuts( p, Aig_ManConst1(p->pAig) ); -} - -/**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_ObjIsPi(pObj) ) - return Dar_ObjPrepareCuts( p, 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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/dar/darData.c b/src/aig/dar/darData.c deleted file mode 100644 index 17963c4a..00000000 --- a/src/aig/dar/darData.c +++ /dev/null @@ -1,11294 +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" - -ABC_NAMESPACE_IMPL_START - -//////////////////////////////////////////////////////////////////////// -/// 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" - -ABC_NAMESPACE_IMPL_START - - -/**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 = ABC_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 = ABC_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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/dar/darInt.h b/src/aig/dar/darInt.h deleted file mode 100644 index 23e89d3c..00000000 --- a/src/aig/dar/darInt.h +++ /dev/null @@ -1,171 +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__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include - -//#include "bar.h" -#include "vec.h" -#include "aig.h" -#include "dar.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 - Vec_Ptr_t * vCutNodes; // the nodes with cuts allocated - // 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 (Dar_Cut_t *)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_ManCutsRestart( Dar_Man_t * p, Aig_Obj_t * pRoot ); -extern void Dar_ManCutsFree( Dar_Man_t * p ); -extern Dar_Cut_t * Dar_ObjPrepareCuts( Dar_Man_t * p, Aig_Obj_t * pObj ); -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_LibReturnCanonicals( unsigned * pCanons ); -extern void Dar_LibEval( Dar_Man_t * p, Aig_Obj_t * pRoot, Dar_Cut_t * pCut, int Required, int * pnMffcSize ); -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 ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/dar/darLib.c b/src/aig/dar/darLib.c deleted file mode 100644 index bf78577c..00000000 --- a/src/aig/dar/darLib.c +++ /dev/null @@ -1,1339 +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" -#include "gia.h" -#include "dar.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 -{ - union { - Aig_Obj_t * pFunc; // the corresponding AIG node if it exists - int iGunc; }; // 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 - float dProb; // probability of the node being 1 - 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 = ABC_ALLOC( Dar_Lib_t, 1 ); - memset( p, 0, sizeof(Dar_Lib_t) ); - // allocate objects - p->nObjs = nObjs; - p->pObjs = ABC_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]; - } -// ABC_PRT( "Library start", clock() - clk ); - return p; -} - -/**Function************************************************************* - - Synopsis [Frees the library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_LibFree( Dar_Lib_t * p ) -{ - ABC_FREE( p->pObjs ); - ABC_FREE( p->pDatas ); - ABC_FREE( p->pNodesMem ); - ABC_FREE( p->pNodes0Mem ); - ABC_FREE( p->pSubgrMem ); - ABC_FREE( p->pSubgr0Mem ); - ABC_FREE( p->pPriosMem ); - ABC_FREE( p->pPlaceMem ); - ABC_FREE( p->pScoreMem ); - ABC_FREE( p->pPerms4 ); - ABC_FREE( p->puCanons ); - ABC_FREE( p->pPhases ); - ABC_FREE( p->pPerms ); - ABC_FREE( p->pMap ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Returns canonical truth tables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dar_LibReturnClass( unsigned uTruth ) -{ - return s_DarLib->pMap[uTruth & 0xffff]; -} - - -/**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 = ABC_ALLOC( int, Vec_IntSize(vOuts) ); - p->pSubgr0Mem = ABC_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 = ABC_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 = ABC_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 = ABC_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 = ABC_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 = ABC_ALLOC( int, p->nNodesTotal ); - p->pNodes0Mem = ABC_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; - ABC_FREE( p->pDatas ); - // allocate datas - p->nDatas = nDatas; - p->pDatas = ABC_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] = ABC_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 = ABC_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 ); -// ABC_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; - // copy the propability of node being one - if ( p->pPars->fPower ) - { - float Prob = Aig_Int2Float( Vec_IntEntry( p->pAig->vProbs, Aig_ObjId(Aig_Regular(pFanin)) ) ); - s_DarLib->pDatas[i].dProb = Aig_IsComplement(pFanin)? 1.0-Prob : Prob; - } - } - 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, float * pPower ) -{ - 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_NodeMffcLabel( p, pRoot, pPower ); - // 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, Aig_Obj_t * pRoot ) -{ - 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 + ABC_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 ); - if ( Aig_Regular(pFanin0) == pRoot || Aig_Regular(pFanin1) == pRoot ) - continue; - 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, Aig_Regular(pData->pFunc)); - // assign the probability - if ( p->pPars->fPower ) - { - float Prob = Aig_Int2Float( Vec_IntEntry( p->pAig->vProbs, Aig_ObjId(Aig_Regular(pData->pFunc)) ) ); - pData->dProb = Aig_IsComplement(pData->pFunc)? 1.0-Prob : Prob; - } - } - } -} - -/**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, float * pPower ) -{ - Dar_LibDat_t * pData; - float Power0, Power1; - int Area; - if ( pPower ) - *pPower = (float)0.0; - pData = s_DarLib->pDatas + pObj->Num; - if ( pData->TravId == Out ) - return 0; - pData->TravId = Out; - if ( pObj->fTerm ) - { - if ( pPower ) - *pPower = pData->dProb; - return 0; - } - assert( pObj->Num > 3 ); - if ( pData->Level > Required ) - return 0xff; - if ( pData->pFunc && !pData->fMffc ) - { - if ( pPower ) - *pPower = pData->dProb; - return 0; - } - // 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, pPower? &Power0 : NULL ); - if ( Area > nNodesSaved ) - return 0xff; - Area += Dar_LibEval_rec( Dar_LibObj(s_DarLib, pObj->Fan1), Out, nNodesSaved, Required+1, pPower? &Power1 : NULL ); - if ( Area > nNodesSaved ) - return 0xff; - if ( pPower ) - { - Dar_LibDat_t * pData0 = s_DarLib->pDatas + Dar_LibObj(s_DarLib, pObj->Fan0)->Num; - Dar_LibDat_t * pData1 = s_DarLib->pDatas + Dar_LibObj(s_DarLib, pObj->Fan1)->Num; - pData->dProb = (pObj->fCompl0? 1.0 - pData0->dProb : pData0->dProb)* - (pObj->fCompl1? 1.0 - pData1->dProb : pData1->dProb); - *pPower = Power0 + 2.0 * pData0->dProb * (1.0 - pData0->dProb) + - Power1 + 2.0 * pData1->dProb * (1.0 - pData1->dProb); - } - 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 * pnMffcSize ) -{ - int fTraining = 0; - float PowerSaved, PowerAdded; - 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, p->pPars->fPower? &PowerSaved : NULL ); - // evaluate the cut - Class = s_DarLib->pMap[pCut->uTruth]; - Dar_LibEvalAssignNums( p, Class, pRoot ); - // 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, p->pPars->fPower? &PowerAdded : NULL ); - nNodesGained = nNodesSaved - nNodesAdded; - if ( p->pPars->fPower && PowerSaved < PowerAdded ) - continue; - 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 ); - *pnMffcSize = nNodesSaved; - } -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 = (Aig_Obj_t *)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) ); -} - - - - - - -/**Function************************************************************* - - Synopsis [Matches the cut with its canonical form.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dar2_LibCutMatch( Gia_Man_t * p, Vec_Int_t * vCutLits, unsigned uTruth ) -{ - unsigned uPhase; - char * pPerm; - int i; - assert( Vec_IntSize(vCutLits) == 4 ); - // get the fanin permutation - uPhase = s_DarLib->pPhases[uTruth]; - pPerm = s_DarLib->pPerms4[ (int)s_DarLib->pPerms[uTruth] ]; - // collect fanins with the corresponding permutation/phase - for ( i = 0; i < Vec_IntSize(vCutLits); i++ ) - { -// pFanin = Gia_ManObj( p, pCut->pLeaves[ (int)pPerm[i] ] ); -// pFanin = Gia_ManObj( p, Vec_IntEntry( vCutLits, (int)pPerm[i] ) ); -// pFanin = Gia_ObjFromLit( p, Vec_IntEntry( vCutLits, (int)pPerm[i] ) ); - s_DarLib->pDatas[i].iGunc = Gia_LitNotCond( Vec_IntEntry(vCutLits, (int)pPerm[i]), ((uPhase >> i) & 1) ); - s_DarLib->pDatas[i].Level = Gia_ObjLevel( p, Gia_Regular(Gia_ObjFromLit(p, s_DarLib->pDatas[i].iGunc)) ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Assigns numbers to the nodes of one class.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar2_LibEvalAssignNums( Gia_Man_t * p, int Class ) -{ - Dar_LibObj_t * pObj; - Dar_LibDat_t * pData, * pData0, * pData1; - int iFanin0, iFanin1, i, iLit; - 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->iGunc = -1; - 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 + ABC_MAX(pData0->Level, pData1->Level); - if ( pData0->iGunc == -1 || pData1->iGunc == -1 ) - continue; - iFanin0 = Gia_LitNotCond( pData0->iGunc, pObj->fCompl0 ); - iFanin1 = Gia_LitNotCond( pData1->iGunc, pObj->fCompl1 ); - // compute the resulting literal - if ( iFanin0 == 0 || iFanin1 == 0 || iFanin0 == Gia_LitNot(iFanin1) ) - iLit = 0; - else if ( iFanin0 == 1 || iFanin0 == iFanin1 ) - iLit = iFanin1; - else if ( iFanin1 == 1 ) - iLit = iFanin0; - else - { - iLit = Gia_ManHashLookup( p, Gia_ObjFromLit(p, iFanin0), Gia_ObjFromLit(p, iFanin1) ); - if ( iLit == 0 ) - iLit = -1; - } - pData->iGunc = iLit; - if ( pData->iGunc >= 0 ) - { - // update the level to be more accurate - pData->Level = Gia_ObjLevel( p, Gia_Regular(Gia_ObjFromLit(p, pData->iGunc)) ); - // mark the node if it is part of MFFC -// pData->fMffc = Gia_ObjIsTravIdCurrentArray(p, Gia_Regular(pData->pGunc)); - } - } -} - -/**Function************************************************************* - - Synopsis [Evaluates one cut.] - - Description [Returns the best gain.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dar2_LibEval_rec( Dar_LibObj_t * pObj, int Out ) -{ - Dar_LibDat_t * pData; - int Area; - pData = s_DarLib->pDatas + pObj->Num; - if ( pData->TravId == Out ) - return 0; - pData->TravId = Out; - if ( pObj->fTerm ) - return 0; - assert( pObj->Num > 3 ); - if ( pData->iGunc >= 0 )//&& !pData->fMffc ) - return 0; - // this is a new node - get a bound on the area of its branches -// nNodesSaved--; - Area = Dar2_LibEval_rec( Dar_LibObj(s_DarLib, pObj->Fan0), Out ); -// if ( Area > nNodesSaved ) -// return 0xff; - Area += Dar2_LibEval_rec( Dar_LibObj(s_DarLib, pObj->Fan1), Out ); -// if ( Area > nNodesSaved ) -// return 0xff; - return Area + 1; -} - -/**Function************************************************************* - - Synopsis [Evaluates one cut.] - - Description [Returns the best gain.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dar2_LibEval( Gia_Man_t * p, Vec_Int_t * vCutLits, unsigned uTruth, int fKeepLevel, Vec_Int_t * vLeavesBest2 ) -{ - int p_OutBest = -1; - int p_OutNumBest = -1; - int p_LevelBest = 1000000; - int p_GainBest = -1000000; - int p_ClassBest = -1; - int fTraining = 0; - Dar_LibObj_t * pObj; - int Out, k, Class, nNodesSaved, nNodesAdded, nNodesGained, clk; - clk = clock(); - assert( Vec_IntSize(vCutLits) == 4 ); - assert( (uTruth >> 16) == 0 ); - // check if the cut exits and assigns leaves and their levels - if ( !Dar2_LibCutMatch(p, vCutLits, uTruth) ) - return -1; - // mark MFFC of the node -// nNodesSaved = Dar2_LibCutMarkMffc( p->pAig, pRoot, pCut->nLeaves, p->pPars->fPower? &PowerSaved : NULL ); - nNodesSaved = 0; - // evaluate the cut - Class = s_DarLib->pMap[uTruth]; - Dar2_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]); -// nNodesAdded = Dar2_LibEval_rec( pObj, Out, nNodesSaved - !p->pPars->fUseZeros, Required, p->pPars->fPower? &PowerAdded : NULL ); - nNodesAdded = Dar2_LibEval_rec( pObj, Out ); - nNodesGained = nNodesSaved - nNodesAdded; - if ( fKeepLevel ) - { - if ( s_DarLib->pDatas[pObj->Num].Level > p_LevelBest || - (s_DarLib->pDatas[pObj->Num].Level == p_LevelBest && nNodesGained <= p_GainBest) ) - continue; - } - else - { - if ( nNodesGained < p_GainBest || - (nNodesGained == p_GainBest && s_DarLib->pDatas[pObj->Num].Level >= p_LevelBest) ) - continue; - } - // remember this possibility - Vec_IntClear( vLeavesBest2 ); - for ( k = 0; k < Vec_IntSize(vCutLits); k++ ) - Vec_IntPush( vLeavesBest2, s_DarLib->pDatas[k].iGunc ); - 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; - assert( p_OutBest != -1 ); - return p_OutBest; -} - -/**Function************************************************************* - - Synopsis [Clears the fields of the nodes used i this cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar2_LibBuildClear_rec( Dar_LibObj_t * pObj, int * pCounter ) -{ - if ( pObj->fTerm ) - return; - pObj->Num = (*pCounter)++; - s_DarLib->pDatas[ pObj->Num ].iGunc = -1; - Dar2_LibBuildClear_rec( Dar_LibObj(s_DarLib, pObj->Fan0), pCounter ); - Dar2_LibBuildClear_rec( Dar_LibObj(s_DarLib, pObj->Fan1), pCounter ); -} - -/**Function************************************************************* - - Synopsis [Reconstructs the best cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dar2_LibBuildBest_rec( Gia_Man_t * p, Dar_LibObj_t * pObj ) -{ - Gia_Obj_t * pNode; - Dar_LibDat_t * pData; - int iFanin0, iFanin1; - pData = s_DarLib->pDatas + pObj->Num; - if ( pData->iGunc >= 0 ) - return pData->iGunc; - iFanin0 = Dar2_LibBuildBest_rec( p, Dar_LibObj(s_DarLib, pObj->Fan0) ); - iFanin1 = Dar2_LibBuildBest_rec( p, Dar_LibObj(s_DarLib, pObj->Fan1) ); - iFanin0 = Gia_LitNotCond( iFanin0, pObj->fCompl0 ); - iFanin1 = Gia_LitNotCond( iFanin1, pObj->fCompl1 ); - pData->iGunc = Gia_ManHashAnd( p, iFanin0, iFanin1 ); - pNode = Gia_ManObj( p, Gia_Lit2Var(pData->iGunc) ); - if ( Gia_ObjIsAnd( pNode ) ) - Gia_ObjSetAndLevel( p, pNode ); - Gia_ObjSetPhase( pNode ); - return pData->iGunc; -} - -/**Function************************************************************* - - Synopsis [Reconstructs the best cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dar2_LibBuildBest( Gia_Man_t * p, Vec_Int_t * vLeavesBest2, int OutBest ) -{ - int i, iLeaf, Counter = 4; - assert( Vec_IntSize(vLeavesBest2) == 4 ); - Vec_IntForEachEntry( vLeavesBest2, iLeaf, i ) - s_DarLib->pDatas[i].iGunc = iLeaf; - Dar2_LibBuildClear_rec( Dar_LibObj(s_DarLib, OutBest), &Counter ); - return Dar2_LibBuildBest_rec( p, Dar_LibObj(s_DarLib, OutBest) ); -} - -/**Function************************************************************* - - Synopsis [Evaluate and build the new node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dar_LibEvalBuild( Gia_Man_t * p, Vec_Int_t * vCutLits, unsigned uTruth, int fKeepLevel, Vec_Int_t * vLeavesBest2 ) -{ - int OutBest = Dar2_LibEval( p, vCutLits, uTruth, fKeepLevel, vLeavesBest2 ); - return Dar2_LibBuildBest( p, vLeavesBest2, OutBest ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/dar/darMan.c b/src/aig/dar/darMan.c deleted file mode 100644 index 59150103..00000000 --- a/src/aig/dar/darMan.c +++ /dev/null @@ -1,174 +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" - -ABC_NAMESPACE_IMPL_START - -//////////////////////////////////////////////////////////////////////// -/// 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; - Aig_ManCleanData( pAig ); - p = ABC_ALLOC( Dar_Man_t, 1 ); - memset( p, 0, sizeof(Dar_Man_t) ); - p->pPars = pPars; - p->pAig = pAig; - p->vCutNodes = Vec_PtrAlloc( 1000 ); - p->pMemCuts = Aig_MmFixedStart( p->pPars->nCutsMax * sizeof(Dar_Cut_t), 1024 ); - 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->vCutNodes ) - Vec_PtrFree( p->vCutNodes ); - if ( p->pMemCuts ) - Aig_MmFixedStop( p->pMemCuts, 0 ); - if ( p->vLeavesBest ) - Vec_PtrFree( p->vLeavesBest ); - ABC_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) ); - ABC_PRT( "Cuts ", p->timeCuts ); - ABC_PRT( "Eval ", p->timeEval ); - ABC_PRT( "Other ", p->timeOther ); - ABC_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 ); -// ABC_PRTP( "T", p->ClassTimes[i], p->timeEval ); - printf( "\n" ); - } - fflush( stdout ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -#if 0 - -ABC_NAMESPACE_IMPL_END - -#include "kit.h" - -ABC_NAMESPACE_IMPL_START - -void Dar_ManPrintScript() -{ - unsigned pCanons[222]; - int i; - Dar_LibReturnCanonicals( pCanons ); - for ( i = 1; i < 222; i++ ) - { - Kit_DsdNtk_t * pNtk; - pNtk = Kit_DsdDecompose( pCanons + i, 4 ); - printf( " \"" ); - Kit_DsdPrint( stdout, pNtk ); - printf( "\", /* %3d */\n", i ); - Kit_DsdNtkFree( pNtk ); - } -} -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/dar/darPrec.c b/src/aig/dar/darPrec.c deleted file mode 100644 index 4d164123..00000000 --- a/src/aig/dar/darPrec.c +++ /dev/null @@ -1,394 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 = ABC_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 ABC_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 = ABC_ALLOC( int, nMints ); - pMintsP = ABC_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]); - } - - ABC_FREE( pMints ); - ABC_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 = ABC_CALLOC( unsigned short, nFuncs ); - uPhases = ABC_CALLOC( char, nFuncs ); - uPerms = ABC_CALLOC( char, nFuncs ); - uMap = ABC_CALLOC( 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; - uMap[uPerm] = uMap[uTruth]; - - uPerm = ~uPerm & 0xFFFF; - uCanons[uPerm] = uTruth; - uPhases[uPerm] = i | 16; - uPerms[uPerm] = k; - uMap[uPerm] = uMap[uTruth]; - } - 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; - uMap[uPerm] = uMap[uTruth]; - - uPerm = ~uPerm & 0xFFFF; - uCanons[uPerm] = uTruth; - uPhases[uPerm] = i | 16; - uPerms[uPerm] = k; - uMap[uPerm] = uMap[uTruth]; - } - else - assert( uCanons[uPerm] == uTruth ); - } - } - } - for ( uTruth = 1; uTruth < 0xffff; uTruth++ ) - assert( uMap[uTruth] != 0 ); - uPhases[(1<<16)-1] = 16; - assert( nClasses == 222 ); - ABC_FREE( pPerms4 ); - if ( puCanons ) - *puCanons = uCanons; - else - ABC_FREE( uCanons ); - if ( puPhases ) - *puPhases = uPhases; - else - ABC_FREE( uPhases ); - if ( puPerms ) - *puPerms = uPerms; - else - ABC_FREE( uPerms ); - if ( puMap ) - *puMap = uMap; - else - ABC_FREE( uMap ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/dar/darRefact.c b/src/aig/dar/darRefact.c deleted file mode 100644 index d13856ba..00000000 --- a/src/aig/dar/darRefact.c +++ /dev/null @@ -1,636 +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" - -#include "bdc.h" -#include "bdcInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 - // bi-decomposition - Bdc_Par_t DecPars; // decomposition parameters - Bdc_Man_t * pManDec; // decomposition manager - // 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 = ABC_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( 1024, Kit_TruthWordNum(pPars->nLeafMax) ); - p->vMemory = Vec_IntAlloc( 1 << 16 ); - p->vCutNodes = Vec_PtrAlloc( 256 ); - p->vLeavesBest = Vec_PtrAlloc( pPars->nLeafMax ); - // alloc bi-decomposition manager - p->DecPars.nVarsMax = pPars->nLeafMax; - p->DecPars.fVerbose = pPars->fVerbose; - p->DecPars.fVeryVerbose = 0; -// p->pManDec = Bdc_ManAlloc( &p->DecPars ); - 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) ); - ABC_PRT( "Cuts ", p->timeCuts ); - ABC_PRT( "Eval ", p->timeEval ); - ABC_PRT( "Other ", p->timeOther ); - ABC_PRT( "TOTAL ", p->timeTotal ); -} - -/**Function************************************************************* - - Synopsis [Stops the rewriting manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_ManRefStop( Ref_Man_t * p ) -{ - if ( p->pManDec ) - Bdc_ManFree( p->pManDec ); - 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 ); - ABC_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((Aig_Obj_t *)pNode->pFunc)->Level; - assert( Aig_Regular((Aig_Obj_t *)pNode->pFunc)->Level < (1<<24)-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 = (Aig_Obj_t *)pNode0->pFunc; - pAnd1 = (Aig_Obj_t *)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 + ABC_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( (Aig_Obj_t *)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( (Aig_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); - pAnd1 = Aig_NotCond( (Aig_Obj_t *)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( (Aig_Obj_t *)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 = Aig_NodeMffcSupp( p->pAig, pObj, 0, NULL ); - p->pGraphBest = Kit_GraphCreateConst0(); - Vec_PtrCopy( p->vLeavesBest, vCut ); - return p->GainBest; - } - if ( Kit_TruthIsConst1(pTruth, Vec_PtrSize(vCut)) ) - { - p->GainBest = Aig_NodeMffcSupp( p->pAig, pObj, 0, NULL ); - 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 ); -/* -{ - int RetValue; - RetValue = Bdc_ManDecompose( p->pManDec, pTruth, NULL, Vec_PtrSize(vCut), NULL, 1000 ); - printf( "Graph = %d. Bidec = %d.\n", Kit_GraphNodeNum(pGraphCur), RetValue ); -} -*/ - 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 ); -// Kit_TruthNot( pTruth, pTruth, Vec_PtrSize(vCut) ); - if ( RetValue > -1 ) - { - pGraphCur = Kit_SopFactor( p->vMemory, 1, Vec_PtrSize(vCut), p->vMemory ); -/* -{ - int RetValue; - RetValue = Bdc_ManDecompose( p->pManDec, pTruth, NULL, Vec_PtrSize(vCut), NULL, 1000 ); - printf( "Graph = %d. Bidec = %d.\n", Kit_GraphNodeNum(pGraphCur), RetValue ); -} -*/ - 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( Aig_Obj_t *, 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 = ABC_MAX( 0, Aig_ObjLevel(pObj) - 10 ); - nNodesSaved = Aig_NodeMffcSupp( 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_NodeMffcLabelCut( p->pAig, pObj, vCut ); - } - else if ( Vec_PtrSize(vCut) < p->pPars->nLeafMax - 2 && p->pPars->fExtend ) - { - if ( !Dar_ObjCutLevelAchieved(vCut, nLevelMin) ) - { - if ( Aig_NodeMffcExtendCut( pAig, pObj, vCut, vCut2 ) ) - { - nNodesSaved2 = Aig_NodeMffcLabelCut( 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) : ABC_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, 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 ); -/* - Aig_ManForEachObj( p->pAig, pObj, i ) - if ( Aig_ObjIsNode(pObj) && Aig_ObjRefs(pObj) == 0 ) - { - printf( "Unreferenced " ); - Aig_ObjPrintVerbose( pObj, 0 ); - printf( "\n" ); - } -*/ - // remove dangling nodes (they should not be here!) - Aig_ManCleanup( 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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/dar/darResub.c b/src/aig/dar/darResub.c deleted file mode 100644 index 44367207..00000000 --- a/src/aig/dar/darResub.c +++ /dev/null @@ -1,53 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/dar/darScript.c b/src/aig/dar/darScript.c deleted file mode 100644 index 884eed07..00000000 --- a/src/aig/dar/darScript.c +++ /dev/null @@ -1,927 +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 "dch.h" -#include "gia.h" -#include "giaAig.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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_ManDupDfs( pAig ); - Dar_ManRewrite( pAig, pPars ); - pAig = Aig_ManDupDfs( pTemp = pAig ); - Aig_ManStop( pTemp ); - return pAig; -} - -/**Function************************************************************* - - Synopsis [Reproduces script "rwsat".] - - 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; -//printf( "1" ); - pAig = Aig_ManDupDfs( pAig ); - if ( fVerbose ) printf( "Starting: " ), Aig_ManPrintStats( pAig ); - -//printf( "2" ); - // balance - if ( fBalance ) - { - pAig = Dar_ManBalance( pTemp = pAig, 0 ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); - } - -//Aig_ManDumpBlif( pAig, "inter.blif", NULL, NULL ); -//printf( "3" ); - // rewrite - Dar_ManRewrite( pAig, pParsRwr ); - pAig = Aig_ManDupDfs( pTemp = pAig ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "Rewrite: " ), Aig_ManPrintStats( pAig ); - -//printf( "4" ); - // refactor - Dar_ManRefactor( pAig, pParsRef ); - pAig = Aig_ManDupDfs( pTemp = pAig ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "Refactor: " ), Aig_ManPrintStats( pAig ); - -//printf( "5" ); - // balance - if ( fBalance ) - { - pAig = Dar_ManBalance( pTemp = pAig, 0 ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); - } - -//printf( "6" ); - // rewrite - Dar_ManRewrite( pAig, pParsRwr ); - pAig = Aig_ManDupDfs( pTemp = pAig ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "Rewrite: " ), Aig_ManPrintStats( pAig ); - -//printf( "7" ); - return pAig; -} - -/**Function************************************************************* - - Synopsis [Performs one iteration of AIG rewriting.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_ManHaigPrintStats( Aig_Man_t * pAig ) -{ - Aig_Obj_t * pObj; - int Counter, i; - Counter = 0; - Aig_ManForEachNode( pAig, pObj, i ) - Counter += (pObj->pHaig != NULL); - printf( "Total nodes = %6d. Equiv nodes = %6d.\n", Aig_ManNodeNum(pAig), Counter ); -} - -/**Function************************************************************* - - Synopsis [Reproduces script "compress".] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, 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->fPower = fPower; - - pParsRwr->fVerbose = 0;//fVerbose; - pParsRef->fVerbose = 0;//fVerbose; - - pAig = Aig_ManDupDfs( pAig ); - if ( fVerbose ) printf( "Starting: " ), Aig_ManPrintStats( pAig ); -/* - // balance - if ( fBalance ) - { - pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); - } -*/ - // rewrite - Dar_ManRewrite( pAig, pParsRwr ); - pAig = Aig_ManDupDfs( pTemp = pAig ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "Rewrite: " ), Aig_ManPrintStats( pAig ); - - // refactor - Dar_ManRefactor( pAig, pParsRef ); - pAig = Aig_ManDupDfs( pTemp = pAig ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "Refactor: " ), Aig_ManPrintStats( pAig ); - - // balance - if ( fBalance ) - { - pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); - } - - pParsRwr->fUseZeros = 1; - pParsRef->fUseZeros = 1; - - // rewrite - Dar_ManRewrite( pAig, pParsRwr ); - pAig = Aig_ManDupDfs( pTemp = pAig ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "RewriteZ: " ), 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 fFanout, int fPower, 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->fFanout = fFanout; - pParsRwr->fPower = fPower; - - pParsRwr->fVerbose = 0;//fVerbose; - pParsRef->fVerbose = 0;//fVerbose; - - pAig = Aig_ManDupDfs( pAig ); - if ( fVerbose ) printf( "Starting: " ), Aig_ManPrintStats( pAig ); -/* - // balance - if ( fBalance ) - { - pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); - } -*/ - // rewrite -// Dar_ManRewrite( pAig, pParsRwr ); - pParsRwr->fUpdateLevel = 0; // disable level update - Dar_ManRewrite( pAig, pParsRwr ); - pParsRwr->fUpdateLevel = fUpdateLevel; // reenable level update if needed - - pAig = Aig_ManDupDfs( pTemp = pAig ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "Rewrite: " ), Aig_ManPrintStats( pAig ); - - // refactor - Dar_ManRefactor( pAig, pParsRef ); - pAig = Aig_ManDupDfs( pTemp = pAig ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "Refactor: " ), Aig_ManPrintStats( pAig ); - - // balance -// if ( fBalance ) - { - pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); - } - - // rewrite - Dar_ManRewrite( pAig, pParsRwr ); - pAig = Aig_ManDupDfs( pTemp = pAig ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "Rewrite: " ), Aig_ManPrintStats( pAig ); - - pParsRwr->fUseZeros = 1; - pParsRef->fUseZeros = 1; - - // rewrite - Dar_ManRewrite( pAig, pParsRwr ); - pAig = Aig_ManDupDfs( pTemp = pAig ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "RewriteZ: " ), Aig_ManPrintStats( pAig ); - - // balance - if ( fBalance ) - { - pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); - } - - // refactor - Dar_ManRefactor( pAig, pParsRef ); - pAig = Aig_ManDupDfs( pTemp = pAig ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "RefactorZ: " ), Aig_ManPrintStats( pAig ); - - // rewrite - Dar_ManRewrite( pAig, pParsRwr ); - pAig = Aig_ManDupDfs( pTemp = pAig ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "RewriteZ: " ), Aig_ManPrintStats( pAig ); - - // balance - if ( fBalance ) - { - pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "Balance: " ), 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 fPower, 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; - Aig_Obj_t * pObj; - int i; - - vAigs = Vec_PtrAlloc( 3 ); - pAig = Aig_ManDupDfs(pAig); - Vec_PtrPush( vAigs, pAig ); - - Aig_ManForEachObj( pAig, pObj, i ) - pObj->pHaig = pObj; - - pAig = Dar_ManCompress(pAig, fBalance, fUpdateLevel, fPower, fVerbose); - Vec_PtrPush( vAigs, pAig ); -//Aig_ManPrintStats( pAig ); - - Aig_ManForEachObj( pAig, pObj, i ) - { - pObj->pNext = pObj->pHaig; - pObj->pHaig = pObj; - } - - pAig = Dar_ManCompress2(pAig, fBalance, fUpdateLevel, 1, fPower, fVerbose); - Vec_PtrPush( vAigs, pAig ); -//Aig_ManPrintStats( pAig ); - - pAig = (Aig_Man_t *)Vec_PtrEntry( vAigs, 1 ); - Aig_ManForEachObj( pAig, pObj, i ) - pObj->pHaig = pObj->pNext; - - return vAigs; -} - -/**Function************************************************************* - - Synopsis [Reproduces script "compress2".] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Dar_ManChoice( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fConstruct, int nConfMax, int nLevelMax, 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, 0, fVerbose ); - - // swap the first and last network - // this should lead to the primary choice being "better" because of synthesis - // (it is also important when constructing choices) - if ( !fConstruct ) - { - pMan = (Aig_Man_t *)Vec_PtrPop( vAigs ); - Vec_PtrPush( vAigs, Vec_PtrEntry(vAigs,0) ); - Vec_PtrWriteEntry( vAigs, 0, pMan ); - } - -if ( fVerbose ) -{ -ABC_PRT( "Synthesis time", clock() - clk ); -} -clk = clock(); - if ( fConstruct ) - pMan = Aig_ManChoiceConstructive( vAigs, fVerbose ); - else - pMan = Aig_ManChoicePartitioned( vAigs, 300, nConfMax, nLevelMax, fVerbose ); - Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pTemp, i ) - Aig_ManStop( pTemp ); - Vec_PtrFree( vAigs ); -if ( fVerbose ) -{ -ABC_PRT( "Choicing time ", clock() - clk ); -} - return pMan; -// return NULL; -} - - -/**Function************************************************************* - - Synopsis [Reproduces script "compress".] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Dar_NewCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, 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->fPower = fPower; - - pParsRwr->fVerbose = 0;//fVerbose; - pParsRef->fVerbose = 0;//fVerbose; - -// pAig = Aig_ManDupDfs( pAig ); - if ( fVerbose ) printf( "Starting: " ), Aig_ManPrintStats( pAig ); - - // rewrite - Dar_ManRewrite( pAig, pParsRwr ); - pAig = Aig_ManDupDfs( pTemp = pAig ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "Rewrite: " ), Aig_ManPrintStats( pAig ); - - // refactor - Dar_ManRefactor( pAig, pParsRef ); - pAig = Aig_ManDupDfs( pTemp = pAig ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "Refactor: " ), Aig_ManPrintStats( pAig ); - - // balance - if ( fBalance ) - { - pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); - } - - pParsRwr->fUseZeros = 1; - pParsRef->fUseZeros = 1; - - // rewrite - Dar_ManRewrite( pAig, pParsRwr ); - pAig = Aig_ManDupDfs( pTemp = pAig ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "RewriteZ: " ), Aig_ManPrintStats( pAig ); - - return pAig; -} - -/**Function************************************************************* - - Synopsis [Reproduces script "compress2".] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Dar_NewCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fFanout, int fPower, int fLightSynth, 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->fFanout = fFanout; - pParsRwr->fPower = fPower; - - pParsRwr->fVerbose = 0;//fVerbose; - pParsRef->fVerbose = 0;//fVerbose; - -// pAig = Aig_ManDupDfs( pAig ); - if ( fVerbose ) printf( "Starting: " ), Aig_ManPrintStats( pAig ); - - // skip if lighter synthesis is requested - if ( !fLightSynth ) - { - // rewrite - //Dar_ManRewrite( pAig, pParsRwr ); -// pParsRwr->fUpdateLevel = 0; // disable level update // this change was requested in July and later disabled - Dar_ManRewrite( pAig, pParsRwr ); -// pParsRwr->fUpdateLevel = fUpdateLevel; // reenable level update if needed - - pAig = Aig_ManDupDfs( pTemp = pAig ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "Rewrite: " ), Aig_ManPrintStats( pAig ); - - // refactor - Dar_ManRefactor( pAig, pParsRef ); - pAig = Aig_ManDupDfs( pTemp = pAig ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "Refactor: " ), Aig_ManPrintStats( pAig ); - } - - // balance - pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); - - // skip if lighter synthesis is requested - if ( !fLightSynth ) - { - // rewrite - Dar_ManRewrite( pAig, pParsRwr ); - pAig = Aig_ManDupDfs( pTemp = pAig ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "Rewrite: " ), Aig_ManPrintStats( pAig ); - } - - pParsRwr->fUseZeros = 1; - pParsRef->fUseZeros = 1; - - // rewrite - Dar_ManRewrite( pAig, pParsRwr ); - pAig = Aig_ManDupDfs( pTemp = pAig ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "RewriteZ: " ), Aig_ManPrintStats( pAig ); - - // skip if lighter synthesis is requested - if ( !fLightSynth ) - { - // balance - if ( fBalance ) - { - pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); - } - } - - // refactor - Dar_ManRefactor( pAig, pParsRef ); - pAig = Aig_ManDupDfs( pTemp = pAig ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "RefactorZ: " ), Aig_ManPrintStats( pAig ); - - // skip if lighter synthesis is requested - if ( !fLightSynth ) - { - // rewrite - Dar_ManRewrite( pAig, pParsRwr ); - pAig = Aig_ManDupDfs( pTemp = pAig ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "RewriteZ: " ), Aig_ManPrintStats( pAig ); - } - - // balance - if ( fBalance ) - { - pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); - Aig_ManStop( pTemp ); - if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); - } - return pAig; -} - -/**Function************************************************************* - - Synopsis [Count the number of nodes with very high fanout count.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dar_NewChoiceSynthesisGuard( Aig_Man_t * pAig ) -{ - Aig_Obj_t * pObj; - int i, Count = 0; - Aig_ManForEachNode( pAig, pObj, i ) - if ( Aig_ObjRefs(pObj) > 1000 ) - Count += Aig_ObjRefs(pObj) / 1000; - return (int)(Count > 10); -} - -/**Function************************************************************* - - Synopsis [Reproduces script "compress2".] - - Description [Takes AIG manager, consumes it, and produces GIA manager.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Gia_Man_t * Dar_NewChoiceSynthesis( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fLightSynth, 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 * vGias; - Gia_Man_t * pGia, * pTemp; - int i; - - if ( fUpdateLevel && Dar_NewChoiceSynthesisGuard(pAig) ) - { - if ( fVerbose ) - printf( "Warning: Due to high fanout count of some nodes, level updating is disabled.\n" ); - fUpdateLevel = 0; - } - - vGias = Vec_PtrAlloc( 3 ); - pGia = Gia_ManFromAig(pAig); - Vec_PtrPush( vGias, pGia ); - - pAig = Dar_NewCompress( pAig, fBalance, fUpdateLevel, fPower, fVerbose ); - pGia = Gia_ManFromAig(pAig); - Vec_PtrPush( vGias, pGia ); -//Aig_ManPrintStats( pAig ); - - pAig = Dar_NewCompress2( pAig, fBalance, fUpdateLevel, 1, fPower, fLightSynth, fVerbose ); - pGia = Gia_ManFromAig(pAig); - Vec_PtrPush( vGias, pGia ); -//Aig_ManPrintStats( pAig ); - - Aig_ManStop( pAig ); - - // swap around the first and the last - pTemp = (Gia_Man_t *)Vec_PtrPop( vGias ); - Vec_PtrPush( vGias, Vec_PtrEntry(vGias,0) ); - Vec_PtrWriteEntry( vGias, 0, pTemp ); - -// Aig_Man_t * pAig; -// int i; -// printf( "Choicing will be performed with %d AIGs:\n", Vec_PtrSize(p->vAigs) ); -// Vec_PtrForEachEntry( Aig_Man_t *, p->vAigs, pAig, i ) -// Aig_ManPrintStats( pAig ); - - // derive the miter - pGia = Gia_ManChoiceMiter( vGias ); - - // cleanup - Vec_PtrForEachEntry( Gia_Man_t *, vGias, pTemp, i ) - Gia_ManStop( pTemp ); - Vec_PtrFree( vGias ); - return pGia; -} - -/**Function************************************************************* - - Synopsis [Reproduces script "compress2".] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -/* -Aig_Man_t * Dar_ManChoiceNew( Aig_Man_t * pAig, Dch_Pars_t * pPars ) -{ - extern Aig_Man_t * Dch_ComputeChoices( Vec_Ptr_t * vAigs, Dch_Pars_t * pPars ); - extern Aig_Man_t * Cec_ComputeChoices( Vec_Ptr_t * vAigs, Dch_Pars_t * pPars ); - - int fVerbose = pPars->fVerbose; - int fConstruct = 0; - Aig_Man_t * pMan, * pTemp; - Vec_Ptr_t * vAigs; - int i, clk; - -clk = clock(); -// vAigs = Dar_ManChoiceSynthesisExt(); -// vAigs = Dar_ManChoiceSynthesis( pAig, 1, 1, pPars->fPower, fVerbose ); - vAigs = Dar_ManChoiceSynthesis( pAig, 1, 1, pPars->fPower, 0 ); - - // swap the first and last network - // this should lead to the primary choice being "better" because of synthesis - // (it is also important when constructing choices) - if ( !fConstruct ) - { - pMan = Vec_PtrPop( vAigs ); - Vec_PtrPush( vAigs, Vec_PtrEntry(vAigs,0) ); - Vec_PtrWriteEntry( vAigs, 0, pMan ); - } - -if ( fVerbose ) -{ -//ABC_PRT( "Synthesis time", clock() - clk ); -} - pPars->timeSynth = clock() - clk; - -clk = clock(); - // perform choice computation - if ( pPars->fUseGia ) - pMan = Cec_ComputeChoices( vAigs, pPars ); - else - pMan = Dch_ComputeChoices( vAigs, pPars ); - - // reconstruct the network - pMan = Aig_ManDupDfsGuided( pTemp = pMan, Vec_PtrEntry(vAigs,0) ); - Aig_ManStop( pTemp ); - // duplicate the timing manager - pTemp = Vec_PtrEntry( vAigs, 0 ); - if ( pTemp->pManTime ) - { - extern void * Tim_ManDup( void * p, int fDiscrete ); - pMan->pManTime = Tim_ManDup( pTemp->pManTime, 0 ); - } - // reset levels - Aig_ManChoiceLevel( pMan ); - ABC_FREE( pMan->pName ); - ABC_FREE( pMan->pSpec ); - pMan->pName = Aig_UtilStrsav( pTemp->pName ); - pMan->pSpec = Aig_UtilStrsav( pTemp->pSpec ); - - // cleanup - Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pTemp, i ) - Aig_ManStop( pTemp ); - Vec_PtrFree( vAigs ); - -if ( fVerbose ) -{ -//ABC_PRT( "Choicing time ", clock() - clk ); -} - return pMan; -// return NULL; -} -*/ - -/**Function************************************************************* - - Synopsis [Reproduces script "compress2".] - - Description [Consumes the input AIG to reduce memory usage.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Dar_ManChoiceNewAig( Aig_Man_t * pAig, Dch_Pars_t * pPars ) -{ -// extern Aig_Man_t * Dch_DeriveTotalAig( Vec_Ptr_t * vAigs ); - extern Aig_Man_t * Dch_ComputeChoices( Aig_Man_t * pAig, Dch_Pars_t * pPars ); - int fVerbose = pPars->fVerbose; - Aig_Man_t * pMan, * pTemp; - Vec_Ptr_t * vAigs; - Vec_Ptr_t * vPios; - void * pManTime; - char * pName, * pSpec; - int i, clk; - -clk = clock(); - vAigs = Dar_ManChoiceSynthesis( pAig, 1, 1, pPars->fPower, fVerbose ); -pPars->timeSynth = clock() - clk; - // swap the first and last network - // this should lead to the primary choice being "better" because of synthesis - // (it is also important when constructing choices) - pMan = (Aig_Man_t *)Vec_PtrPop( vAigs ); - Vec_PtrPush( vAigs, Vec_PtrEntry(vAigs,0) ); - Vec_PtrWriteEntry( vAigs, 0, pMan ); - - // derive the total AIG - pMan = Dch_DeriveTotalAig( vAigs ); - // cleanup - Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pTemp, i ) - Aig_ManStop( pTemp ); - Vec_PtrFree( vAigs ); - - // compute choices - pMan = Dch_ComputeChoices( pTemp = pMan, pPars ); - Aig_ManStop( pTemp ); - - // save useful things - pManTime = pAig->pManTime; pAig->pManTime = NULL; - pName = Aig_UtilStrsav( pAig->pName ); - pSpec = Aig_UtilStrsav( pAig->pSpec ); - - // create guidence - vPios = Aig_ManOrderPios( pMan, pAig ); - Aig_ManStop( pAig ); - - // reconstruct the network - pMan = Aig_ManDupDfsGuided( pTemp = pMan, vPios ); - Aig_ManStop( pTemp ); - Vec_PtrFree( vPios ); - - // reset levels - pMan->pManTime = pManTime; - Aig_ManChoiceLevel( pMan ); - - // copy names - ABC_FREE( pMan->pName ); - ABC_FREE( pMan->pSpec ); - pMan->pName = pName; - pMan->pSpec = pSpec; - return pMan; -} - -/**Function************************************************************* - - Synopsis [Reproduces script "compress2".] - - Description [Consumes the input AIG to reduce memory usage.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Dar_ManChoiceNew( Aig_Man_t * pAig, Dch_Pars_t * pPars ) -{ - extern Aig_Man_t * Cec_ComputeChoices( Gia_Man_t * pGia, Dch_Pars_t * pPars ); -// extern Aig_Man_t * Dch_DeriveTotalAig( Vec_Ptr_t * vAigs ); - extern Aig_Man_t * Dch_ComputeChoices( Aig_Man_t * pAig, Dch_Pars_t * pPars ); - int fVerbose = pPars->fVerbose; - Aig_Man_t * pMan, * pTemp; - Gia_Man_t * pGia; - Vec_Ptr_t * vPios; - void * pManTime; - char * pName, * pSpec; - int clk; - - // save useful things - pManTime = pAig->pManTime; pAig->pManTime = NULL; - pName = Aig_UtilStrsav( pAig->pName ); - pSpec = Aig_UtilStrsav( pAig->pSpec ); - - // perform synthesis -clk = clock(); - pGia = Dar_NewChoiceSynthesis( Aig_ManDupDfs(pAig), 1, 1, pPars->fPower, pPars->fLightSynth, pPars->fVerbose ); -pPars->timeSynth = clock() - clk; - - // perform choice computation - if ( pPars->fUseGia ) - pMan = Cec_ComputeChoices( pGia, pPars ); - else - { - pMan = Gia_ManToAigSkip( pGia, 3 ); - Gia_ManStop( pGia ); - pMan = Dch_ComputeChoices( pTemp = pMan, pPars ); - Aig_ManStop( pTemp ); - } - - // create guidence - vPios = Aig_ManOrderPios( pMan, pAig ); - Aig_ManStop( pAig ); - - // reconstruct the network - pMan = Aig_ManDupDfsGuided( pTemp = pMan, vPios ); - Aig_ManStop( pTemp ); - Vec_PtrFree( vPios ); - - // reset levels - pMan->pManTime = pManTime; - Aig_ManChoiceLevel( pMan ); - - // copy names - ABC_FREE( pMan->pName ); - ABC_FREE( pMan->pSpec ); - pMan->pName = pName; - pMan->pSpec = pSpec; - return pMan; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/dar/dar_.c b/src/aig/dar/dar_.c deleted file mode 100644 index 323abed2..00000000 --- a/src/aig/dar/dar_.c +++ /dev/null @@ -1,53 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - 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/dch/dch.h b/src/aig/dch/dch.h deleted file mode 100644 index 69f340e5..00000000 --- a/src/aig/dch/dch.h +++ /dev/null @@ -1,90 +0,0 @@ -/**CFile**************************************************************** - - FileName [dch.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Choice computation for tech-mapping.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 29, 2008.] - - Revision [$Id: dch.h,v 1.00 2008/07/29 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __DCH_H__ -#define __DCH_H__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -// choicing parameters -typedef struct Dch_Pars_t_ Dch_Pars_t; -struct Dch_Pars_t_ -{ - int nWords; // the number of simulation words - int nBTLimit; // conflict limit at a node - int nSatVarMax; // the max number of SAT variables - int fSynthesis; // set to 1 to perform synthesis - int fPolarFlip; // uses polarity adjustment - int fSimulateTfo; // uses simulation of TFO classes - int fPower; // uses power-aware rewriting - int fUseGia; // uses GIA package - int fUseCSat; // uses circuit-based solver - int fLightSynth; // uses lighter version of synthesis - int fVerbose; // verbose stats - int timeSynth; // synthesis runtime - int nNodesAhead; // the lookahead in terms of nodes - int nCallsRecycle; // calls to perform before recycling SAT solver -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== dchAig.c ==========================================================*/ -extern Aig_Man_t * Dch_DeriveTotalAig( Vec_Ptr_t * vAigs ); -/*=== dchCore.c ==========================================================*/ -extern void Dch_ManSetDefaultParams( Dch_Pars_t * p ); -extern int Dch_ManReadVerbose( Dch_Pars_t * p ); -extern Aig_Man_t * Dch_ComputeChoices( Aig_Man_t * pAig, Dch_Pars_t * pPars ); -extern void Dch_ComputeEquivalences( Aig_Man_t * pAig, Dch_Pars_t * pPars ); -/*=== dchScript.c ==========================================================*/ -extern Aig_Man_t * Dar_ManChoiceNew( Aig_Man_t * pAig, Dch_Pars_t * pPars ); - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/dch/dchAig.c b/src/aig/dch/dchAig.c deleted file mode 100644 index 91a00c63..00000000 --- a/src/aig/dch/dchAig.c +++ /dev/null @@ -1,119 +0,0 @@ -/**CFile**************************************************************** - - FileName [dchAig.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Choice computation for tech-mapping.] - - Synopsis [AIG manipulation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 29, 2008.] - - Revision [$Id: dchAig.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "dchInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Derives the cumulative AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_DeriveTotalAig_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - if ( pObj->pData ) - return; - Dch_DeriveTotalAig_rec( p, Aig_ObjFanin0(pObj) ); - Dch_DeriveTotalAig_rec( p, Aig_ObjFanin1(pObj) ); - pObj->pData = Aig_And( p, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Derives the cumulative AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Dch_DeriveTotalAig( Vec_Ptr_t * vAigs ) -{ - Aig_Man_t * pAig, * pAig2, * pAigTotal; - Aig_Obj_t * pObj, * pObjPi, * pObjPo; - int i, k, nNodes; - assert( Vec_PtrSize(vAigs) > 0 ); - // make sure they have the same number of PIs/POs - nNodes = 0; - pAig = (Aig_Man_t *)Vec_PtrEntry( vAigs, 0 ); - Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig2, i ) - { - assert( Aig_ManPiNum(pAig) == Aig_ManPiNum(pAig2) ); - assert( Aig_ManPoNum(pAig) == Aig_ManPoNum(pAig2) ); - nNodes += Aig_ManNodeNum(pAig2); - Aig_ManCleanData( pAig2 ); - } - // map constant nodes - pAigTotal = Aig_ManStart( nNodes ); - Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig2, k ) - Aig_ManConst1(pAig2)->pData = Aig_ManConst1(pAigTotal); - // map primary inputs - Aig_ManForEachPi( pAig, pObj, i ) - { - pObjPi = Aig_ObjCreatePi( pAigTotal ); - Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig2, k ) - Aig_ManPi( pAig2, i )->pData = pObjPi; - } - // construct the AIG in the order of POs - Aig_ManForEachPo( pAig, pObj, i ) - { - Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig2, k ) - { - pObjPo = Aig_ManPo( pAig2, i ); - Dch_DeriveTotalAig_rec( pAigTotal, Aig_ObjFanin0(pObjPo) ); - } - Aig_ObjCreatePo( pAigTotal, Aig_ObjChild0Copy(pObj) ); - } -/* - // mark the cone of the first AIG - Aig_ManIncrementTravId( pAigTotal ); - Aig_ManForEachObj( pAig, pObj, i ) - if ( pObj->pData ) - Aig_ObjSetTravIdCurrent( pAigTotal, pObj->pData ); -*/ - // cleanup should not be done - return pAigTotal; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/dch/dchChoice.c b/src/aig/dch/dchChoice.c deleted file mode 100644 index 1772f8aa..00000000 --- a/src/aig/dch/dchChoice.c +++ /dev/null @@ -1,508 +0,0 @@ -/**CFile**************************************************************** - - FileName [dchChoice.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Choice computation for tech-mapping.] - - Synopsis [Contrustion of choices.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 29, 2008.] - - Revision [$Id: dchChoice.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "dchInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Counts the number of representatives.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dch_DeriveChoiceCountReprs( Aig_Man_t * pAig ) -{ - Aig_Obj_t * pObj, * pRepr; - int i, nReprs = 0; - Aig_ManForEachObj( pAig, pObj, i ) - { - pRepr = Aig_ObjRepr( pAig, pObj ); - if ( pRepr == NULL ) - continue; - assert( pRepr->Id < pObj->Id ); - nReprs++; - } - return nReprs; -} - -/**Function************************************************************* - - Synopsis [Counts the number of equivalences.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dch_DeriveChoiceCountEquivs( Aig_Man_t * pAig ) -{ - Aig_Obj_t * pObj, * pTemp, * pPrev; - int i, nEquivs = 0, Counter = 0; - Aig_ManForEachObj( pAig, pObj, i ) - { - if ( !Aig_ObjIsChoice(pAig, pObj) ) - continue; - for ( pPrev = pObj, pTemp = Aig_ObjEquiv(pAig, pObj); pTemp; - pPrev = pTemp, pTemp = Aig_ObjEquiv(pAig, pTemp) ) - { - if ( pTemp->nRefs > 0 ) - { - // remove referenced node from equivalence class - assert( pAig->pEquivs[pPrev->Id] == pTemp ); - pAig->pEquivs[pPrev->Id] = pAig->pEquivs[pTemp->Id]; - pAig->pEquivs[pTemp->Id] = NULL; - // how about the need to continue iterating over the list? - // pPrev = pTemp ??? - Counter++; - } - nEquivs++; - } - } -// printf( "Removed %d classes.\n", Counter ); - - if ( Counter ) - Dch_DeriveChoiceCountEquivs( pAig ); -// if ( Counter ) -// printf( "Removed %d equiv nodes because of non-zero ref counter.\n", Counter ); - return nEquivs; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the choice node of pRepr is in the TFI of pObj.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dch_ObjCheckTfi_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - // check the trivial cases - if ( pObj == NULL ) - return 0; - if ( Aig_ObjIsPi(pObj) ) - return 0; - if ( pObj->fMarkA ) - return 1; - // skip the visited node - if ( Aig_ObjIsTravIdCurrent( p, pObj ) ) - return 0; - Aig_ObjSetTravIdCurrent( p, pObj ); - // check the children - if ( Dch_ObjCheckTfi_rec( p, Aig_ObjFanin0(pObj) ) ) - return 1; - if ( Dch_ObjCheckTfi_rec( p, Aig_ObjFanin1(pObj) ) ) - return 1; - // check equivalent nodes - return Dch_ObjCheckTfi_rec( p, Aig_ObjEquiv(p, pObj) ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the choice node of pRepr is in the TFI of pObj.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dch_ObjCheckTfi( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr ) -{ - Aig_Obj_t * pTemp; - int RetValue; - assert( !Aig_IsComplement(pObj) ); - assert( !Aig_IsComplement(pRepr) ); - // mark nodes of the choice node - for ( pTemp = pRepr; pTemp; pTemp = Aig_ObjEquiv(p, pTemp) ) - pTemp->fMarkA = 1; - // traverse the new node - Aig_ManIncrementTravId( p ); - RetValue = Dch_ObjCheckTfi_rec( p, pObj ); - // unmark nodes of the choice node - for ( pTemp = pRepr; pTemp; pTemp = Aig_ObjEquiv(p, pTemp) ) - pTemp->fMarkA = 0; - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Returns representatives of fanin in approapriate polarity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Aig_Obj_t * Aig_ObjGetRepr( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - Aig_Obj_t * pRepr; - if ( (pRepr = Aig_ObjRepr(p, Aig_Regular(pObj))) ) - return Aig_NotCond( pRepr, Aig_Regular(pObj)->fPhase ^ pRepr->fPhase ^ Aig_IsComplement(pObj) ); - return pObj; -} - -static inline Aig_Obj_t * Aig_ObjChild0CopyRepr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_ObjGetRepr( p, Aig_ObjChild0Copy(pObj) ); } -static inline Aig_Obj_t * Aig_ObjChild1CopyRepr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_ObjGetRepr( p, Aig_ObjChild1Copy(pObj) ); } - -/**Function************************************************************* - - Synopsis [Derives the AIG with choices from representatives.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_DeriveChoiceAigNode( Aig_Man_t * pAigNew, Aig_Man_t * pAigOld, Aig_Obj_t * pObj ) -{ - Aig_Obj_t * pRepr, * pObjNew, * pReprNew; - // get the new node - pObj->pData = Aig_And( pAigNew, - Aig_ObjChild0CopyRepr(pAigNew, pObj), - Aig_ObjChild1CopyRepr(pAigNew, pObj) ); - pRepr = Aig_ObjRepr( pAigOld, pObj ); - if ( pRepr == NULL ) - return; - // get the corresponding new nodes - pObjNew = Aig_Regular((Aig_Obj_t *)pObj->pData); - pReprNew = Aig_Regular((Aig_Obj_t *)pRepr->pData); - if ( pObjNew == pReprNew ) - return; - // skip the earlier nodes - if ( pReprNew->Id > pObjNew->Id ) - return; - assert( pReprNew->Id < pObjNew->Id ); - // set the representatives - Aig_ObjSetRepr( pAigNew, pObjNew, pReprNew ); - // skip used nodes - if ( pObjNew->nRefs > 0 ) - return; - assert( pObjNew->nRefs == 0 ); - // update new nodes of the object - if ( !Aig_ObjIsNode(pRepr) ) - return; - // skip choices with combinational loops - if ( Dch_ObjCheckTfi( pAigNew, pObjNew, pReprNew ) ) - return; - // add choice - pAigNew->pEquivs[pObjNew->Id] = pAigNew->pEquivs[pReprNew->Id]; - pAigNew->pEquivs[pReprNew->Id] = pObjNew; -} - -/**Function************************************************************* - - Synopsis [Derives the AIG with choices from representatives.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Dch_DeriveChoiceAig_old( Aig_Man_t * pAig ) -{ - Aig_Man_t * pChoices, * pTemp; - Aig_Obj_t * pObj; - int i; - // start recording equivalences - pChoices = Aig_ManStart( Aig_ManObjNumMax(pAig) ); - pChoices->pEquivs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) ); - pChoices->pReprs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) ); - // map constants and PIs - Aig_ManCleanData( pAig ); - Aig_ManConst1(pAig)->pData = Aig_ManConst1(pChoices); - Aig_ManForEachPi( pAig, pObj, i ) - pObj->pData = Aig_ObjCreatePi( pChoices ); - // construct choices for the internal nodes - assert( pAig->pReprs != NULL ); - Aig_ManForEachNode( pAig, pObj, i ) - Dch_DeriveChoiceAigNode( pChoices, pAig, pObj ); - Aig_ManForEachPo( pAig, pObj, i ) - Aig_ObjCreatePo( pChoices, Aig_ObjChild0CopyRepr(pChoices, pObj) ); - Dch_DeriveChoiceCountEquivs( pChoices ); - // there is no need for cleanup - ABC_FREE( pChoices->pReprs ); - pChoices = Aig_ManDupDfs( pTemp = pChoices ); - Aig_ManStop( pTemp ); - return pChoices; -} - - - - -/**Function************************************************************* - - Synopsis [Checks for combinational loops in the AIG.] - - Description [Returns 1 if combinational loop is detected.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManCheckAcyclic_rec( Aig_Man_t * p, Aig_Obj_t * pNode, int fVerbose ) -{ - Aig_Obj_t * pFanin; - int fAcyclic; - if ( Aig_ObjIsPi(pNode) || Aig_ObjIsConst1(pNode) ) - return 1; - assert( Aig_ObjIsNode(pNode) ); - // make sure the node is not visited - assert( !Aig_ObjIsTravIdPrevious(p, pNode) ); - // check if the node is part of the combinational loop - if ( Aig_ObjIsTravIdCurrent(p, pNode) ) - { - if ( fVerbose ) - Abc_Print( 1, "Network \"%s\" contains combinational loop!\n", p->pSpec? p->pSpec : NULL ); - if ( fVerbose ) - Abc_Print( 1, "Node \"%d\" is encountered twice on the following path to the COs:\n", Aig_ObjId(pNode) ); - return 0; - } - // mark this node as a node on the current path - Aig_ObjSetTravIdCurrent( p, pNode ); - - // visit the transitive fanin - pFanin = Aig_ObjFanin0(pNode); - // check if the fanin is visited - if ( !Aig_ObjIsTravIdPrevious(p, pFanin) ) - { - // traverse the fanin's cone searching for the loop - if ( !(fAcyclic = Aig_ManCheckAcyclic_rec(p, pFanin, fVerbose)) ) - { - // return as soon as the loop is detected - if ( fVerbose ) - Abc_Print( 1, " %d ->", Aig_ObjId(pFanin) ); - return 0; - } - } - - // visit the transitive fanin - pFanin = Aig_ObjFanin1(pNode); - // check if the fanin is visited - if ( !Aig_ObjIsTravIdPrevious(p, pFanin) ) - { - // traverse the fanin's cone searching for the loop - if ( !(fAcyclic = Aig_ManCheckAcyclic_rec(p, pFanin, fVerbose)) ) - { - // return as soon as the loop is detected - if ( fVerbose ) - Abc_Print( 1, " %d ->", Aig_ObjId(pFanin) ); - return 0; - } - } - - // visit choices - if ( Aig_ObjRepr(p, pNode) == NULL && Aig_ObjEquiv(p, pNode) != NULL ) - { - for ( pFanin = Aig_ObjEquiv(p, pNode); pFanin; pFanin = Aig_ObjEquiv(p, pFanin) ) - { - // check if the fanin is visited - if ( Aig_ObjIsTravIdPrevious(p, pFanin) ) - continue; - // traverse the fanin's cone searching for the loop - if ( (fAcyclic = Aig_ManCheckAcyclic_rec(p, pFanin, fVerbose)) ) - continue; - // return as soon as the loop is detected - if ( fVerbose ) - Abc_Print( 1, " %d", Aig_ObjId(pFanin) ); - if ( fVerbose ) - Abc_Print( 1, " (choice of %d) -> ", Aig_ObjId(pNode) ); - return 0; - } - } - // mark this node as a visited node - Aig_ObjSetTravIdPrevious( p, pNode ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Checks for combinational loops in the AIG.] - - Description [Returns 1 if there is no combinational loops.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManCheckAcyclic( Aig_Man_t * p, int fVerbose ) -{ - Aig_Obj_t * pNode; - int fAcyclic; - int i; - // set the traversal ID for this DFS ordering - Aig_ManIncrementTravId( p ); - Aig_ManIncrementTravId( p ); - // 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; - Aig_ManForEachPo( p, pNode, i ) - { - pNode = Aig_ObjFanin0(pNode); - if ( Aig_ObjIsTravIdPrevious(p, pNode) ) - continue; - // traverse the output logic cone - if ( (fAcyclic = Aig_ManCheckAcyclic_rec(p, pNode, fVerbose)) ) - continue; - // stop as soon as the first loop is detected - if ( fVerbose ) - Abc_Print( 1, " CO %d\n", i ); - break; - } - return fAcyclic; -} - -/**Function************************************************************* - - Synopsis [Removes combinational loop.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManFixLoopProblem( Aig_Man_t * p, int fVerbose ) -{ - Aig_Obj_t * pObj; - int i, Counter = 0, Counter2 = 0; - Aig_ManForEachObj( p, pObj, i ) - { - if ( !Aig_ObjIsTravIdCurrent(p, pObj) ) - continue; - Counter2++; - if ( Aig_ObjRepr(p, pObj) == NULL && Aig_ObjEquiv(p, pObj) != NULL ) - { - Aig_ObjSetEquiv(p, pObj, NULL); - Counter++; - } - } - if ( fVerbose ) - Abc_Print( 1, "Fixed %d choice nodes on the path with %d objects.\n", Counter, Counter2 ); -} - - -/**Function************************************************************* - - Synopsis [Derives the AIG with choices from representatives.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Dch_DeriveChoiceAigInt( Aig_Man_t * pAig ) -{ - Aig_Man_t * pChoices; - Aig_Obj_t * pObj; - int i; - // start recording equivalences - pChoices = Aig_ManStart( Aig_ManObjNumMax(pAig) ); - pChoices->pEquivs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) ); - pChoices->pReprs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) ); - // map constants and PIs - Aig_ManCleanData( pAig ); - Aig_ManConst1(pAig)->pData = Aig_ManConst1(pChoices); - Aig_ManForEachPi( pAig, pObj, i ) - pObj->pData = Aig_ObjCreatePi( pChoices ); - // construct choices for the internal nodes - assert( pAig->pReprs != NULL ); - Aig_ManForEachNode( pAig, pObj, i ) - Dch_DeriveChoiceAigNode( pChoices, pAig, pObj ); - Aig_ManForEachPo( pAig, pObj, i ) - Aig_ObjCreatePo( pChoices, Aig_ObjChild0CopyRepr(pChoices, pObj) ); - Dch_DeriveChoiceCountEquivs( pChoices ); - Aig_ManSetRegNum( pChoices, Aig_ManRegNum(pAig) ); - return pChoices; -} - -/**Function************************************************************* - - Synopsis [Derives the AIG with choices from representatives.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Dch_DeriveChoiceAig( Aig_Man_t * pAig ) -{ - extern int Aig_ManCheckAcyclic( Aig_Man_t * pAig, int fVerbose ); - Aig_Man_t * pChoices, * pTemp; - int fVerbose = 0; - pChoices = Dch_DeriveChoiceAigInt( pAig ); -// pChoices = Dch_DeriveChoiceAigInt( pTemp = pChoices ); -// Aig_ManStop( pTemp ); - // there is no need for cleanup - ABC_FREE( pChoices->pReprs ); - while ( !Aig_ManCheckAcyclic( pChoices, fVerbose ) ) - { - if ( fVerbose ) - Abc_Print( 1, "There is a loop!\n" ); - Aig_ManFixLoopProblem( pChoices, fVerbose ); - } - pChoices = Aig_ManDupDfs( pTemp = pChoices ); - Aig_ManStop( pTemp ); - return pChoices; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/dch/dchClass.c b/src/aig/dch/dchClass.c deleted file mode 100644 index 83a3bc2e..00000000 --- a/src/aig/dch/dchClass.c +++ /dev/null @@ -1,611 +0,0 @@ -/**CFile**************************************************************** - - FileName [dchClass.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Choice computation for tech-mapping.] - - Synopsis [Representation of candidate equivalence classes.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 29, 2008.] - - Revision [$Id: dchClass.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "dchInt.h" - -ABC_NAMESPACE_IMPL_START - - -/* - 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 topo order of their representatives. -*/ - -// internal representation of candidate equivalence classes -struct Dch_Cla_t_ -{ - // class information - Aig_Man_t * pAig; // original AIG manager - Aig_Obj_t *** pId2Class; // non-const classes by ID of repr node - int * pClassSizes; // sizes of each equivalence class - // statistics - int nClasses; // the total number of non-const classes - int nCands1; // the total number of const candidates - int nLits; // the number of literals in all classes - // memory - Aig_Obj_t ** pMemClasses; // memory allocated for equivalence classes - Aig_Obj_t ** pMemClassesFree; // memory allocated for equivalence classes to be used - // temporary data - Vec_Ptr_t * vClassOld; // old equivalence class after splitting - Vec_Ptr_t * vClassNew; // new equivalence class(es) after splitting - // procedures used for class refinement - void * pManData; - unsigned (*pFuncNodeHash) (void *,Aig_Obj_t *); // returns hash key of the node - int (*pFuncNodeIsConst) (void *,Aig_Obj_t *); // returns 1 if the node is a constant - int (*pFuncNodesAreEqual) (void *,Aig_Obj_t *, Aig_Obj_t *); // returns 1 if nodes are equal up to a complement -}; - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline Aig_Obj_t * Dch_ObjNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj ) { return ppNexts[pObj->Id]; } -static inline void Dch_ObjSetNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { ppNexts[pObj->Id] = pNext; } - -// iterator through the equivalence classes -#define Dch_ManForEachClass( p, ppClass, i ) \ - for ( i = 0; i < Aig_ManObjNumMax(p->pAig); i++ ) \ - if ( ((ppClass) = p->pId2Class[i]) == NULL ) {} else -// iterator through the nodes in one class -#define Dch_ClassForEachNode( p, pRepr, pNode, i ) \ - for ( i = 0; i < p->pClassSizes[pRepr->Id]; i++ ) \ - if ( ((pNode) = p->pId2Class[pRepr->Id][i]) == NULL ) {} else - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates one equivalence class.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Dch_ObjAddClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, Aig_Obj_t ** pClass, int nSize ) -{ - assert( p->pId2Class[pRepr->Id] == NULL ); - p->pId2Class[pRepr->Id] = pClass; - assert( p->pClassSizes[pRepr->Id] == 0 ); - assert( nSize > 1 ); - p->pClassSizes[pRepr->Id] = nSize; - p->nClasses++; - p->nLits += nSize - 1; -} - -/**Function************************************************************* - - Synopsis [Removes one equivalence class.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Aig_Obj_t ** Dch_ObjRemoveClass( Dch_Cla_t * p, Aig_Obj_t * pRepr ) -{ - Aig_Obj_t ** pClass = p->pId2Class[pRepr->Id]; - int nSize; - assert( pClass != NULL ); - p->pId2Class[pRepr->Id] = NULL; - nSize = p->pClassSizes[pRepr->Id]; - assert( nSize > 1 ); - p->nClasses--; - p->nLits -= nSize - 1; - p->pClassSizes[pRepr->Id] = 0; - return pClass; -} - -/**Function************************************************************* - - Synopsis [Starts representation of equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dch_Cla_t * Dch_ClassesStart( Aig_Man_t * pAig ) -{ - Dch_Cla_t * p; - p = ABC_ALLOC( Dch_Cla_t, 1 ); - memset( p, 0, sizeof(Dch_Cla_t) ); - p->pAig = pAig; - p->pId2Class = ABC_CALLOC( Aig_Obj_t **, Aig_ManObjNumMax(pAig) ); - p->pClassSizes = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); - p->vClassOld = Vec_PtrAlloc( 100 ); - p->vClassNew = Vec_PtrAlloc( 100 ); - assert( pAig->pReprs == NULL ); - Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) ); - return p; -} - -/**Function************************************************************* - - Synopsis [Starts representation of equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_ClassesSetData( Dch_Cla_t * p, void * pManData, - unsigned (*pFuncNodeHash)(void *,Aig_Obj_t *), // returns hash key of the node - int (*pFuncNodeIsConst)(void *,Aig_Obj_t *), // returns 1 if the node is a constant - int (*pFuncNodesAreEqual)(void *,Aig_Obj_t *, Aig_Obj_t *) ) // returns 1 if nodes are equal up to a complement -{ - p->pManData = pManData; - p->pFuncNodeHash = pFuncNodeHash; - p->pFuncNodeIsConst = pFuncNodeIsConst; - p->pFuncNodesAreEqual = pFuncNodesAreEqual; -} - -/**Function************************************************************* - - Synopsis [Stop representation of equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_ClassesStop( Dch_Cla_t * p ) -{ - if ( p->vClassNew ) Vec_PtrFree( p->vClassNew ); - if ( p->vClassOld ) Vec_PtrFree( p->vClassOld ); - ABC_FREE( p->pId2Class ); - ABC_FREE( p->pClassSizes ); - ABC_FREE( p->pMemClasses ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Stop representation of equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dch_ClassesLitNum( Dch_Cla_t * p ) -{ - return p->nLits; -} - -/**Function************************************************************* - - Synopsis [Stop representation of equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t ** Dch_ClassesReadClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, int * pnSize ) -{ - assert( p->pId2Class[pRepr->Id] != NULL ); - assert( p->pClassSizes[pRepr->Id] > 1 ); - *pnSize = p->pClassSizes[pRepr->Id]; - return p->pId2Class[pRepr->Id]; -} - -/**Function************************************************************* - - Synopsis [Checks candidate equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_ClassesCheck( Dch_Cla_t * p ) -{ - Aig_Obj_t * pObj, * pPrev, ** ppClass; - int i, k, nLits, nClasses, nCands1; - nClasses = nLits = 0; - Dch_ManForEachClass( p, ppClass, k ) - { - pPrev = NULL; - Dch_ClassForEachNode( p, ppClass[0], pObj, i ) - { - if ( i == 0 ) - assert( Aig_ObjRepr(p->pAig, pObj) == NULL ); - else - { - assert( Aig_ObjRepr(p->pAig, pObj) == ppClass[0] ); - assert( pPrev->Id < pObj->Id ); - nLits++; - } - pPrev = pObj; - } - nClasses++; - } - nCands1 = 0; - Aig_ManForEachObj( p->pAig, pObj, i ) - nCands1 += Dch_ObjIsConst1Cand( p->pAig, pObj ); - assert( p->nLits == nLits ); - assert( p->nCands1 == nCands1 ); - assert( p->nClasses == nClasses ); -} - -/**Function************************************************************* - - Synopsis [Prints simulation classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_ClassesPrintOne( Dch_Cla_t * p, Aig_Obj_t * pRepr ) -{ - Aig_Obj_t * pObj; - int i; - Abc_Print( 1, "{ " ); - Dch_ClassForEachNode( p, pRepr, pObj, i ) - Abc_Print( 1, "%d(%d,%d) ", pObj->Id, pObj->Level, Aig_SupportSize(p->pAig,pObj) ); - Abc_Print( 1, "}\n" ); -} - -/**Function************************************************************* - - Synopsis [Prints simulation classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_ClassesPrint( Dch_Cla_t * p, int fVeryVerbose ) -{ - Aig_Obj_t ** ppClass; - Aig_Obj_t * pObj; - int i; - Abc_Print( 1, "Equivalence classes: Const1 = %5d. Class = %5d. Lit = %5d.\n", - p->nCands1, p->nClasses, p->nLits ); - if ( !fVeryVerbose ) - return; - Abc_Print( 1, "Constants { " ); - Aig_ManForEachObj( p->pAig, pObj, i ) - if ( Dch_ObjIsConst1Cand( p->pAig, pObj ) ) - Abc_Print( 1, "%d(%d,%d) ", pObj->Id, pObj->Level, Aig_SupportSize(p->pAig,pObj) ); - Abc_Print( 1, "}\n" ); - Dch_ManForEachClass( p, ppClass, i ) - { - Abc_Print( 1, "%3d (%3d) : ", i, p->pClassSizes[i] ); - Dch_ClassesPrintOne( p, ppClass[0] ); - } - Abc_Print( 1, "\n" ); -} - -/**Function************************************************************* - - Synopsis [Creates initial simulation classes.] - - Description [Assumes that simulation info is assigned.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_ClassesPrepare( Dch_Cla_t * p, int fLatchCorr, int nMaxLevs ) -{ - Aig_Obj_t ** ppTable, ** ppNexts, ** ppClassNew; - Aig_Obj_t * pObj, * pTemp, * pRepr; - int i, k, nTableSize, nNodes, iEntry, nEntries, nEntries2; - - // allocate the hash table hashing simulation info into nodes - nTableSize = Aig_PrimeCudd( Aig_ManObjNumMax(p->pAig)/4 ); - ppTable = ABC_CALLOC( Aig_Obj_t *, nTableSize ); - ppNexts = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) ); - - // add all the nodes to the hash table - nEntries = 0; - 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; - } - // check if the node belongs to the class of constant 1 - if ( p->pFuncNodeIsConst( p->pManData, pObj ) ) - { - Dch_ObjSetConst1Cand( p->pAig, pObj ); - p->nCands1++; - continue; - } - // hash the node by its simulation info - iEntry = p->pFuncNodeHash( p->pManData, pObj ) % nTableSize; - // add the node to the class - if ( ppTable[iEntry] == NULL ) - ppTable[iEntry] = pObj; - else - { - // set the representative of this node - pRepr = ppTable[iEntry]; - Aig_ObjSetRepr( p->pAig, pObj, pRepr ); - // add node to the table - if ( Dch_ObjNext( ppNexts, pRepr ) == NULL ) - { // this will be the second entry - p->pClassSizes[pRepr->Id]++; - nEntries++; - } - // add the entry to the list - Dch_ObjSetNext( ppNexts, pObj, Dch_ObjNext( ppNexts, pRepr ) ); - Dch_ObjSetNext( ppNexts, pRepr, pObj ); - p->pClassSizes[pRepr->Id]++; - nEntries++; - } - } - - // allocate room for classes - p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, nEntries + p->nCands1 ); - p->pMemClassesFree = p->pMemClasses + nEntries; - - // copy the entries into storage in the topological order - nEntries2 = 0; - Aig_ManForEachObj( p->pAig, pObj, i ) - { - if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) ) - continue; - nNodes = p->pClassSizes[pObj->Id]; - // skip the nodes that are not representatives of non-trivial classes - if ( nNodes == 0 ) - continue; - assert( nNodes > 1 ); - // add the nodes to the class in the topological order - ppClassNew = p->pMemClasses + nEntries2; - ppClassNew[0] = pObj; - for ( pTemp = Dch_ObjNext(ppNexts, pObj), k = 1; pTemp; - pTemp = Dch_ObjNext(ppNexts, pTemp), k++ ) - { - ppClassNew[nNodes-k] = pTemp; - } - // add the class of nodes - p->pClassSizes[pObj->Id] = 0; - Dch_ObjAddClass( p, pObj, ppClassNew, nNodes ); - // increment the number of entries - nEntries2 += nNodes; - } - assert( nEntries == nEntries2 ); - ABC_FREE( ppTable ); - ABC_FREE( ppNexts ); - // now it is time to refine the classes - Dch_ClassesRefine( p ); - Dch_ClassesCheck( p ); -} - -/**Function************************************************************* - - Synopsis [Iteratively refines the classes after simulation.] - - Description [Returns the number of refinements performed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dch_ClassesRefineOneClass( Dch_Cla_t * p, Aig_Obj_t * pReprOld, int fRecursive ) -{ - Aig_Obj_t ** pClassOld, ** pClassNew; - Aig_Obj_t * pObj, * pReprNew; - int i; - - // split the class - Vec_PtrClear( p->vClassOld ); - Vec_PtrClear( p->vClassNew ); - Dch_ClassForEachNode( p, pReprOld, pObj, i ) - if ( p->pFuncNodesAreEqual(p->pManData, pReprOld, pObj) ) - Vec_PtrPush( p->vClassOld, pObj ); - else - Vec_PtrPush( p->vClassNew, pObj ); - // check if splitting happened - if ( Vec_PtrSize(p->vClassNew) == 0 ) - return 0; - - // get the new representative - pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 ); - assert( Vec_PtrSize(p->vClassOld) > 0 ); - assert( Vec_PtrSize(p->vClassNew) > 0 ); - - // create old class - pClassOld = Dch_ObjRemoveClass( p, pReprOld ); - Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassOld, pObj, i ) - { - pClassOld[i] = pObj; - Aig_ObjSetRepr( p->pAig, pObj, i? pReprOld : NULL ); - } - // create new class - pClassNew = pClassOld + i; - Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i ) - { - pClassNew[i] = pObj; - Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL ); - } - - // put classes back - if ( Vec_PtrSize(p->vClassOld) > 1 ) - Dch_ObjAddClass( p, pReprOld, pClassOld, Vec_PtrSize(p->vClassOld) ); - if ( Vec_PtrSize(p->vClassNew) > 1 ) - Dch_ObjAddClass( p, pReprNew, pClassNew, Vec_PtrSize(p->vClassNew) ); - - // check if the class should be recursively refined - if ( fRecursive && Vec_PtrSize(p->vClassNew) > 1 ) - return 1 + Dch_ClassesRefineOneClass( p, pReprNew, 1 ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Refines the classes after simulation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dch_ClassesRefine( Dch_Cla_t * p ) -{ - Aig_Obj_t ** ppClass; - int i, nRefis = 0; - Dch_ManForEachClass( p, ppClass, i ) - nRefis += Dch_ClassesRefineOneClass( p, ppClass[0], 0 ); - return nRefis; -} - - -/**Function************************************************************* - - Synopsis [Returns equivalence class of the given node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_ClassesCollectOneClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, Vec_Ptr_t * vRoots ) -{ - Aig_Obj_t * pObj; - int i; - Vec_PtrClear( vRoots ); - Dch_ClassForEachNode( p, pRepr, pObj, i ) - Vec_PtrPush( vRoots, pObj ); - assert( Vec_PtrSize(vRoots) > 1 ); -} - -/**Function************************************************************* - - Synopsis [Returns equivalence class of the given node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_ClassesCollectConst1Group( Dch_Cla_t * p, Aig_Obj_t * pObj, int nNodes, Vec_Ptr_t * vRoots ) -{ - int i, Limit; - Vec_PtrClear( vRoots ); - Limit = ABC_MIN( pObj->Id + nNodes, Aig_ManObjNumMax(p->pAig) ); - for ( i = pObj->Id; i < Limit; i++ ) - { - pObj = Aig_ManObj( p->pAig, i ); - if ( pObj && Dch_ObjIsConst1Cand( p->pAig, pObj ) ) - Vec_PtrPush( vRoots, pObj ); - } -} - -/**Function************************************************************* - - Synopsis [Refine the group of constant 1 nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dch_ClassesRefineConst1Group( Dch_Cla_t * p, Vec_Ptr_t * vRoots, int fRecursive ) -{ - Aig_Obj_t * pObj, * pReprNew, ** ppClassNew; - int i; - if ( Vec_PtrSize(vRoots) == 0 ) - return 0; - // collect the nodes to be refined - Vec_PtrClear( p->vClassNew ); - Vec_PtrForEachEntry( Aig_Obj_t *, vRoots, pObj, i ) - if ( !p->pFuncNodeIsConst( p->pManData, pObj ) ) - Vec_PtrPush( p->vClassNew, pObj ); - // check if there is a new class - if ( Vec_PtrSize(p->vClassNew) == 0 ) - return 0; - p->nCands1 -= Vec_PtrSize(p->vClassNew); - pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 ); - Aig_ObjSetRepr( p->pAig, pReprNew, NULL ); - if ( Vec_PtrSize(p->vClassNew) == 1 ) - return 1; - // create a new class composed of these nodes - ppClassNew = p->pMemClassesFree; - p->pMemClassesFree += Vec_PtrSize(p->vClassNew); - Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i ) - { - ppClassNew[i] = pObj; - Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL ); - } - Dch_ObjAddClass( p, pReprNew, ppClassNew, Vec_PtrSize(p->vClassNew) ); - // refine them recursively - if ( fRecursive ) - return 1 + Dch_ClassesRefineOneClass( p, pReprNew, 1 ); - return 1; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/dch/dchCnf.c b/src/aig/dch/dchCnf.c deleted file mode 100644 index 4175a123..00000000 --- a/src/aig/dch/dchCnf.c +++ /dev/null @@ -1,334 +0,0 @@ -/**CFile**************************************************************** - - FileName [dchCnf.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Choice computation for tech-mapping.] - - Synopsis [Computation of CNF.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 29, 2008.] - - Revision [$Id: dchCnf.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "dchInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Addes clauses to the solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_AddClausesMux( Dch_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 = Dch_ObjSatNum(p,pNode); - VarI = Dch_ObjSatNum(p,pNodeI); - VarT = Dch_ObjSatNum(p,Aig_Regular(pNodeT)); - VarE = Dch_ObjSatNum(p,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); - if ( p->pPars->fPolarFlip ) - { - if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); - if ( Aig_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] ); - if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); - } - 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); - if ( p->pPars->fPolarFlip ) - { - if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); - if ( Aig_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] ); - if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); - } - 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); - if ( p->pPars->fPolarFlip ) - { - if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); - if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); - if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); - } - 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); - if ( p->pPars->fPolarFlip ) - { - if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); - if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); - if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); - } - 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); - if ( p->pPars->fPolarFlip ) - { - if ( Aig_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] ); - if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); - if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); - } - 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); - if ( p->pPars->fPolarFlip ) - { - if ( Aig_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] ); - if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); - if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); - } - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); - assert( RetValue ); -} - -/**Function************************************************************* - - Synopsis [Addes clauses to the solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_AddClausesSuper( Dch_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 = ABC_ALLOC( int, nLits ); - // suppose AND-gate is A & B = C - // add !A => !C or A + !C - Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i ) - { - pLits[0] = toLitCond(Dch_ObjSatNum(p,Aig_Regular(pFanin)), Aig_IsComplement(pFanin)); - pLits[1] = toLitCond(Dch_ObjSatNum(p,pNode), 1); - if ( p->pPars->fPolarFlip ) - { - if ( Aig_Regular(pFanin)->fPhase ) pLits[0] = lit_neg( pLits[0] ); - if ( pNode->fPhase ) pLits[1] = lit_neg( pLits[1] ); - } - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); - assert( RetValue ); - } - // add A & B => C or !A + !B + C - Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i ) - { - pLits[i] = toLitCond(Dch_ObjSatNum(p,Aig_Regular(pFanin)), !Aig_IsComplement(pFanin)); - if ( p->pPars->fPolarFlip ) - { - if ( Aig_Regular(pFanin)->fPhase ) pLits[i] = lit_neg( pLits[i] ); - } - } - pLits[nLits-1] = toLitCond(Dch_ObjSatNum(p,pNode), 0); - if ( p->pPars->fPolarFlip ) - { - if ( pNode->fPhase ) pLits[nLits-1] = lit_neg( pLits[nLits-1] ); - } - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits ); - assert( RetValue ); - ABC_FREE( pLits ); -} - -/**Function************************************************************* - - Synopsis [Collects the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_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 - Dch_CollectSuper_rec( Aig_ObjChild0(pObj), vSuper, 0, fUseMuxes ); - Dch_CollectSuper_rec( Aig_ObjChild1(pObj), vSuper, 0, fUseMuxes ); -} - -/**Function************************************************************* - - Synopsis [Collects the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_CollectSuper( Aig_Obj_t * pObj, int fUseMuxes, Vec_Ptr_t * vSuper ) -{ - assert( !Aig_IsComplement(pObj) ); - assert( !Aig_ObjIsPi(pObj) ); - Vec_PtrClear( vSuper ); - Dch_CollectSuper_rec( pObj, vSuper, 1, fUseMuxes ); -} - -/**Function************************************************************* - - Synopsis [Updates the solver clause database.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_ObjAddToFrontier( Dch_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vFrontier ) -{ - assert( !Aig_IsComplement(pObj) ); - if ( Dch_ObjSatNum(p,pObj) ) - return; - assert( Dch_ObjSatNum(p,pObj) == 0 ); - if ( Aig_ObjIsConst1(pObj) ) - return; - Vec_PtrPush( p->vUsedNodes, pObj ); - Dch_ObjSetSatNum( p, pObj, p->nSatVars++ ); - if ( Aig_ObjIsNode(pObj) ) - Vec_PtrPush( vFrontier, pObj ); -} - -/**Function************************************************************* - - Synopsis [Updates the solver clause database.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_CnfNodeAddToSolver( Dch_Man_t * p, Aig_Obj_t * pObj ) -{ - Vec_Ptr_t * vFrontier; - Aig_Obj_t * pNode, * pFanin; - int i, k, fUseMuxes = 1; - // quit if CNF is ready - if ( Dch_ObjSatNum(p,pObj) ) - return; - // start the frontier - vFrontier = Vec_PtrAlloc( 100 ); - Dch_ObjAddToFrontier( p, pObj, vFrontier ); - // explore nodes in the frontier - Vec_PtrForEachEntry( Aig_Obj_t *, vFrontier, pNode, i ) - { - // create the supergate - assert( Dch_ObjSatNum(p,pNode) ); - if ( fUseMuxes && Aig_ObjIsMuxType(pNode) ) - { - Vec_PtrClear( p->vFanins ); - Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin0( Aig_ObjFanin0(pNode) ) ); - Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin0( Aig_ObjFanin1(pNode) ) ); - Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin1( Aig_ObjFanin0(pNode) ) ); - Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin1( Aig_ObjFanin1(pNode) ) ); - Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanins, pFanin, k ) - Dch_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier ); - Dch_AddClausesMux( p, pNode ); - } - else - { - Dch_CollectSuper( pNode, fUseMuxes, p->vFanins ); - Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanins, pFanin, k ) - Dch_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier ); - Dch_AddClausesSuper( p, pNode, p->vFanins ); - } - assert( Vec_PtrSize(p->vFanins) > 1 ); - } - Vec_PtrFree( vFrontier ); -} - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/dch/dchCore.c b/src/aig/dch/dchCore.c deleted file mode 100644 index bc78682b..00000000 --- a/src/aig/dch/dchCore.c +++ /dev/null @@ -1,158 +0,0 @@ -/**CFile**************************************************************** - - FileName [dchCore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Choice computation for tech-mapping.] - - Synopsis [The core procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 29, 2008.] - - Revision [$Id: dchCore.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "dchInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [This procedure sets default parameters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_ManSetDefaultParams( Dch_Pars_t * p ) -{ - memset( p, 0, sizeof(Dch_Pars_t) ); - p->nWords = 8; // the number of simulation words - p->nBTLimit = 1000; // conflict limit at a node - p->nSatVarMax = 5000; // the max number of SAT variables - p->fSynthesis = 1; // derives three snapshots - p->fPolarFlip = 1; // uses polarity adjustment - p->fSimulateTfo = 1; // simulate TFO - p->fPower = 0; // power-aware rewriting - p->fLightSynth = 0; // uses lighter version of synthesis - p->fVerbose = 0; // verbose stats - p->nNodesAhead = 1000; // the lookahead in terms of nodes - p->nCallsRecycle = 100; // calls to perform before recycling SAT solver -} - -/**Function************************************************************* - - Synopsis [Returns verbose parameter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dch_ManReadVerbose( Dch_Pars_t * p ) -{ - return p->fVerbose; -} - -/**Function************************************************************* - - Synopsis [Performs computation of AIGs with choices.] - - Description [Takes several AIGs and performs choicing.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Dch_ComputeChoices( Aig_Man_t * pAig, Dch_Pars_t * pPars ) -{ - Dch_Man_t * p; - Aig_Man_t * pResult; - int clk, clkTotal = clock(); - // reset random numbers - Aig_ManRandom(1); - // start the choicing manager - p = Dch_ManCreate( pAig, pPars ); - // compute candidate equivalence classes -clk = clock(); - p->ppClasses = Dch_CreateCandEquivClasses( pAig, pPars->nWords, pPars->fVerbose ); -p->timeSimInit = clock() - clk; -// Dch_ClassesPrint( p->ppClasses, 0 ); - p->nLits = Dch_ClassesLitNum( p->ppClasses ); - // perform SAT sweeping - Dch_ManSweep( p ); - // free memory ahead of time -p->timeTotal = clock() - clkTotal; - Dch_ManStop( p ); - // create choices - ABC_FREE( pAig->pTable ); - pResult = Dch_DeriveChoiceAig( pAig ); - // count the number of representatives - if ( pPars->fVerbose ) - Abc_Print( 1, "STATS: Reprs = %6d. Equivs = %6d. Choices = %6d.\n", - Dch_DeriveChoiceCountReprs( pAig ), - Dch_DeriveChoiceCountEquivs( pResult ), - Aig_ManChoiceNum( pResult ) ); - return pResult; -} - -/**Function************************************************************* - - Synopsis [Performs computation of AIGs with choices.] - - Description [Takes several AIGs and performs choicing.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_ComputeEquivalences( Aig_Man_t * pAig, Dch_Pars_t * pPars ) -{ - Dch_Man_t * p; - int clk, clkTotal = clock(); - // reset random numbers - Aig_ManRandom(1); - // start the choicing manager - p = Dch_ManCreate( pAig, pPars ); - // compute candidate equivalence classes -clk = clock(); - p->ppClasses = Dch_CreateCandEquivClasses( pAig, pPars->nWords, pPars->fVerbose ); -p->timeSimInit = clock() - clk; -// Dch_ClassesPrint( p->ppClasses, 0 ); - p->nLits = Dch_ClassesLitNum( p->ppClasses ); - // perform SAT sweeping - Dch_ManSweep( p ); - // free memory ahead of time -p->timeTotal = clock() - clkTotal; - Dch_ManStop( p ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/dch/dchInt.h b/src/aig/dch/dchInt.h deleted file mode 100644 index 6072d97b..00000000 --- a/src/aig/dch/dchInt.h +++ /dev/null @@ -1,170 +0,0 @@ -/**CFile**************************************************************** - - FileName [dchInt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Choice computation for tech-mapping.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 29, 2008.] - - Revision [$Id: dchInt.h,v 1.00 2008/07/29 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __DCH_INT_H__ -#define __DCH_INT_H__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "aig.h" -#include "satSolver.h" -#include "dch.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -// equivalence classes -typedef struct Dch_Cla_t_ Dch_Cla_t; - -// choicing manager -typedef struct Dch_Man_t_ Dch_Man_t; -struct Dch_Man_t_ -{ - // parameters - Dch_Pars_t * pPars; // choicing parameters - // AIGs used in the package -// Vec_Ptr_t * vAigs; // user-given AIGs - Aig_Man_t * pAigTotal; // intermediate AIG - Aig_Man_t * pAigFraig; // final AIG - // equivalence classes - Dch_Cla_t * ppClasses; // equivalence classes of nodes - Aig_Obj_t ** pReprsProved; // equivalences proved - // SAT solving - sat_solver * pSat; // recyclable SAT solver - int nSatVars; // the counter of SAT variables - int * pSatVars; // mapping of each node into its SAT var - Vec_Ptr_t * vUsedNodes; // nodes whose SAT vars are assigned - int nRecycles; // the number of times SAT solver was recycled - int nCallsSince; // the number of calls since the last recycle - Vec_Ptr_t * vFanins; // fanins of the CNF node - Vec_Ptr_t * vSimRoots; // the roots of cand const 1 nodes to simulate - Vec_Ptr_t * vSimClasses; // the roots of cand equiv classes to simulate - // solver cone size - int nConeThis; - int nConeMax; - // SAT calls statistics - int nSatCalls; // the number of SAT calls - int nSatProof; // the number of proofs - int nSatFailsReal; // the number of timeouts - int nSatCallsUnsat; // the number of unsat SAT calls - int nSatCallsSat; // the number of sat SAT calls - // choice node statistics - int nLits; // the number of lits in the cand equiv classes - int nReprs; // the number of proved equivalent pairs - int nEquivs; // the number of final equivalences - int nChoices; // the number of final choice nodes - // runtime stats - int timeSimInit; // simulation and class computation - int timeSimSat; // simulation of the counter-examples - int timeSat; // solving SAT - int timeSatSat; // sat - int timeSatUnsat; // unsat - int timeSatUndec; // undecided - int timeChoice; // choice computation - int timeOther; // other runtime - int timeTotal; // total runtime -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline int Dch_ObjSatNum( Dch_Man_t * p, Aig_Obj_t * pObj ) { return p->pSatVars[pObj->Id]; } -static inline void Dch_ObjSetSatNum( Dch_Man_t * p, Aig_Obj_t * pObj, int Num ) { p->pSatVars[pObj->Id] = Num; } - -static inline Aig_Obj_t * Dch_ObjFraig( Aig_Obj_t * pObj ) { return (Aig_Obj_t *)pObj->pData; } -static inline void Dch_ObjSetFraig( Aig_Obj_t * pObj, Aig_Obj_t * pNode ) { pObj->pData = pNode; } - -static inline int Dch_ObjIsConst1Cand( Aig_Man_t * pAig, Aig_Obj_t * pObj ) -{ - return Aig_ObjRepr(pAig, pObj) == Aig_ManConst1(pAig); -} -static inline void Dch_ObjSetConst1Cand( Aig_Man_t * pAig, Aig_Obj_t * pObj ) -{ - assert( !Dch_ObjIsConst1Cand( pAig, pObj ) ); - Aig_ObjSetRepr( pAig, pObj, Aig_ManConst1(pAig) ); -} - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== dchAig.c ===================================================*/ -/*=== dchChoice.c ===================================================*/ -extern int Dch_DeriveChoiceCountReprs( Aig_Man_t * pAig ); -extern int Dch_DeriveChoiceCountEquivs( Aig_Man_t * pAig ); -extern Aig_Man_t * Dch_DeriveChoiceAig( Aig_Man_t * pAig ); -/*=== dchClass.c =================================================*/ -extern Dch_Cla_t * Dch_ClassesStart( Aig_Man_t * pAig ); -extern void Dch_ClassesSetData( Dch_Cla_t * p, void * pManData, - unsigned (*pFuncNodeHash)(void *,Aig_Obj_t *), - int (*pFuncNodeIsConst)(void *,Aig_Obj_t *), - int (*pFuncNodesAreEqual)(void *,Aig_Obj_t *, Aig_Obj_t *) ); -extern void Dch_ClassesStop( Dch_Cla_t * p ); -extern int Dch_ClassesLitNum( Dch_Cla_t * p ); -extern Aig_Obj_t ** Dch_ClassesReadClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, int * pnSize ); -extern void Dch_ClassesPrint( Dch_Cla_t * p, int fVeryVerbose ); -extern void Dch_ClassesPrepare( Dch_Cla_t * p, int fLatchCorr, int nMaxLevs ); -extern int Dch_ClassesRefine( Dch_Cla_t * p ); -extern int Dch_ClassesRefineOneClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, int fRecursive ); -extern void Dch_ClassesCollectOneClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, Vec_Ptr_t * vRoots ); -extern void Dch_ClassesCollectConst1Group( Dch_Cla_t * p, Aig_Obj_t * pObj, int nNodes, Vec_Ptr_t * vRoots ); -extern int Dch_ClassesRefineConst1Group( Dch_Cla_t * p, Vec_Ptr_t * vRoots, int fRecursive ); -/*=== dchCnf.c ===================================================*/ -extern void Dch_CnfNodeAddToSolver( Dch_Man_t * p, Aig_Obj_t * pObj ); -/*=== dchMan.c ===================================================*/ -extern Dch_Man_t * Dch_ManCreate( Aig_Man_t * pAig, Dch_Pars_t * pPars ); -extern void Dch_ManStop( Dch_Man_t * p ); -extern void Dch_ManSatSolverRecycle( Dch_Man_t * p ); -/*=== dchSat.c ===================================================*/ -extern int Dch_NodesAreEquiv( Dch_Man_t * p, Aig_Obj_t * pObj1, Aig_Obj_t * pObj2 ); -/*=== dchSim.c ===================================================*/ -extern Dch_Cla_t * Dch_CreateCandEquivClasses( Aig_Man_t * pAig, int nWords, int fVerbose ); -/*=== dchSimSat.c ===================================================*/ -extern void Dch_ManResimulateCex( Dch_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr ); -extern void Dch_ManResimulateCex2( Dch_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr ); -/*=== dchSweep.c ===================================================*/ -extern void Dch_ManSweep( Dch_Man_t * p ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/dch/dchMan.c b/src/aig/dch/dchMan.c deleted file mode 100644 index dc856309..00000000 --- a/src/aig/dch/dchMan.c +++ /dev/null @@ -1,191 +0,0 @@ -/**CFile**************************************************************** - - FileName [dchMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Choice computation for tech-mapping.] - - Synopsis [Calls to the SAT solver.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 29, 2008.] - - Revision [$Id: dchMan.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "dchInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dch_Man_t * Dch_ManCreate( Aig_Man_t * pAig, Dch_Pars_t * pPars ) -{ - Dch_Man_t * p; - // create interpolation manager - p = ABC_ALLOC( Dch_Man_t, 1 ); - memset( p, 0, sizeof(Dch_Man_t) ); - p->pPars = pPars; - p->pAigTotal = pAig; //Dch_DeriveTotalAig( vAigs ); - Aig_ManFanoutStart( p->pAigTotal ); - // SAT solving - p->nSatVars = 1; - p->pSatVars = ABC_CALLOC( int, Aig_ManObjNumMax(p->pAigTotal) ); - p->vUsedNodes = Vec_PtrAlloc( 1000 ); - p->vFanins = Vec_PtrAlloc( 100 ); - p->vSimRoots = Vec_PtrAlloc( 1000 ); - p->vSimClasses = Vec_PtrAlloc( 1000 ); - // equivalences proved - p->pReprsProved = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAigTotal) ); - return p; -} - -/**Function************************************************************* - - Synopsis [Prints stats of the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_ManPrintStats( Dch_Man_t * p ) -{ - int nNodeNum = Aig_ManNodeNum(p->pAigTotal) / 3; - Abc_Print( 1, "Parameters: Sim words = %d. Conf limit = %d. SAT var max = %d.\n", - p->pPars->nWords, p->pPars->nBTLimit, p->pPars->nSatVarMax ); - Abc_Print( 1, "AIG nodes : Total = %6d. Dangling = %6d. Main = %6d. (%6.2f %%)\n", - Aig_ManNodeNum(p->pAigTotal), - Aig_ManNodeNum(p->pAigTotal)-nNodeNum, - nNodeNum, - 100.0 * nNodeNum/Aig_ManNodeNum(p->pAigTotal) ); - Abc_Print( 1, "SAT solver: Vars = %d. Max cone = %d. Recycles = %d.\n", - p->nSatVars, p->nConeMax, p->nRecycles ); - Abc_Print( 1, "SAT calls : All = %6d. Unsat = %6d. Sat = %6d. Fail = %6d.\n", - p->nSatCalls, p->nSatCalls-p->nSatCallsSat-p->nSatFailsReal, - p->nSatCallsSat, p->nSatFailsReal ); - Abc_Print( 1, "Choices : Lits = %6d. Reprs = %5d. Equivs = %5d. Choices = %5d.\n", - p->nLits, p->nReprs, p->nEquivs, p->nChoices ); - Abc_Print( 1, "Choicing runtime statistics:\n" ); - p->timeOther = p->timeTotal-p->timeSimInit-p->timeSimSat-p->timeSat-p->timeChoice; - Abc_PrintTimeP( 1, "Sim init ", p->timeSimInit, p->timeTotal ); - Abc_PrintTimeP( 1, "Sim SAT ", p->timeSimSat, p->timeTotal ); - Abc_PrintTimeP( 1, "SAT solving", p->timeSat, p->timeTotal ); - Abc_PrintTimeP( 1, " sat ", p->timeSatSat, p->timeTotal ); - Abc_PrintTimeP( 1, " unsat ", p->timeSatUnsat, p->timeTotal ); - Abc_PrintTimeP( 1, " undecided", p->timeSatUndec, p->timeTotal ); - Abc_PrintTimeP( 1, "Choice ", p->timeChoice, p->timeTotal ); - Abc_PrintTimeP( 1, "Other ", p->timeOther, p->timeTotal ); - Abc_PrintTimeP( 1, "TOTAL ", p->timeTotal, p->timeTotal ); - if ( p->pPars->timeSynth ) - { - Abc_PrintTime( 1, "Synthesis ", p->pPars->timeSynth ); - } -} - -/**Function************************************************************* - - Synopsis [Frees the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_ManStop( Dch_Man_t * p ) -{ - Aig_ManFanoutStop( p->pAigTotal ); - if ( p->pPars->fVerbose ) - Dch_ManPrintStats( p ); - if ( p->pAigFraig ) - Aig_ManStop( p->pAigFraig ); - if ( p->ppClasses ) - Dch_ClassesStop( p->ppClasses ); - if ( p->pSat ) - sat_solver_delete( p->pSat ); - Vec_PtrFree( p->vUsedNodes ); - Vec_PtrFree( p->vFanins ); - Vec_PtrFree( p->vSimRoots ); - Vec_PtrFree( p->vSimClasses ); - ABC_FREE( p->pReprsProved ); - ABC_FREE( p->pSatVars ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Recycles the SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_ManSatSolverRecycle( Dch_Man_t * p ) -{ - int Lit; - if ( p->pSat ) - { - Aig_Obj_t * pObj; - int i; - Vec_PtrForEachEntry( Aig_Obj_t *, p->vUsedNodes, pObj, i ) - Dch_ObjSetSatNum( p, pObj, 0 ); - Vec_PtrClear( p->vUsedNodes ); -// memset( p->pSatVars, 0, sizeof(int) * Aig_ManObjNumMax(p->pAigTotal) ); - sat_solver_delete( p->pSat ); - } - p->pSat = sat_solver_new(); - sat_solver_setnvars( p->pSat, 1000 ); - // var 0 is not used - // var 1 is reserved for const1 node - add the clause - p->nSatVars = 1; -// p->nSatVars = 0; - Lit = toLit( p->nSatVars ); - if ( p->pPars->fPolarFlip ) - Lit = lit_neg( Lit ); - sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ); - Dch_ObjSetSatNum( p, Aig_ManConst1(p->pAigFraig), p->nSatVars++ ); - - p->nRecycles++; - p->nCallsSince = 0; -} - - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/dch/dchSat.c b/src/aig/dch/dchSat.c deleted file mode 100644 index f5e346ef..00000000 --- a/src/aig/dch/dchSat.c +++ /dev/null @@ -1,166 +0,0 @@ -/**CFile**************************************************************** - - FileName [dchSat.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Choice computation for tech-mapping.] - - Synopsis [Calls to the SAT solver.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 29, 2008.] - - Revision [$Id: dchSat.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "dchInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Runs equivalence test for the two nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dch_NodesAreEquiv( Dch_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ) -{ - int nBTLimit = p->pPars->nBTLimit; - int pLits[2], RetValue, RetValue1, status, clk; - p->nSatCalls++; - - // sanity checks - assert( !Aig_IsComplement(pNew) ); - assert( !Aig_IsComplement(pOld) ); - assert( pNew != pOld ); - - p->nCallsSince++; // experiment with this!!! - - // check if SAT solver needs recycling - if ( p->pSat == NULL || - (p->pPars->nSatVarMax && - p->nSatVars > p->pPars->nSatVarMax && - p->nCallsSince > p->pPars->nCallsRecycle) ) - Dch_ManSatSolverRecycle( p ); - - // if the nodes do not have SAT variables, allocate them - Dch_CnfNodeAddToSolver( p, pOld ); - Dch_CnfNodeAddToSolver( p, pNew ); - - // propage unit clauses - if ( p->pSat->qtail != p->pSat->qhead ) - { - status = sat_solver_simplify(p->pSat); - assert( status != 0 ); - assert( p->pSat->qtail == p->pSat->qhead ); - } - - // solve under assumptions - // A = 1; B = 0 OR A = 1; B = 1 - pLits[0] = toLitCond( Dch_ObjSatNum(p,pOld), 0 ); - pLits[1] = toLitCond( Dch_ObjSatNum(p,pNew), pOld->fPhase == pNew->fPhase ); - if ( p->pPars->fPolarFlip ) - { - if ( pOld->fPhase ) pLits[0] = lit_neg( pLits[0] ); - if ( pNew->fPhase ) pLits[1] = lit_neg( pLits[1] ); - } -//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 ); -clk = clock(); - RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, - (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); -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; - p->nSatCallsSat++; - return 0; - } - else // if ( RetValue1 == l_Undef ) - { -p->timeSatUndec += clock() - clk; - p->nSatFailsReal++; - return -1; - } - - // if the old node was constant 0, we already know the answer - if ( pOld == Aig_ManConst1(p->pAigFraig) ) - { - p->nSatProof++; - return 1; - } - - // solve under assumptions - // A = 0; B = 1 OR A = 0; B = 0 - pLits[0] = toLitCond( Dch_ObjSatNum(p,pOld), 1 ); - pLits[1] = toLitCond( Dch_ObjSatNum(p,pNew), pOld->fPhase ^ pNew->fPhase ); - if ( p->pPars->fPolarFlip ) - { - if ( pOld->fPhase ) pLits[0] = lit_neg( pLits[0] ); - if ( pNew->fPhase ) pLits[1] = lit_neg( pLits[1] ); - } -clk = clock(); - RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, - (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); -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; - p->nSatCallsSat++; - return 0; - } - else // if ( RetValue1 == l_Undef ) - { -p->timeSatUndec += clock() - clk; - p->nSatFailsReal++; - return -1; - } - // return SAT proof - p->nSatProof++; - return 1; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/dch/dchSim.c b/src/aig/dch/dchSim.c deleted file mode 100644 index b2d24761..00000000 --- a/src/aig/dch/dchSim.c +++ /dev/null @@ -1,297 +0,0 @@ -/**CFile**************************************************************** - - FileName [dchSim.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Choice computation for tech-mapping.] - - Synopsis [Performs random simulation at the beginning.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 29, 2008.] - - Revision [$Id: dchSim.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "dchInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline unsigned * Dch_ObjSim( Vec_Ptr_t * vSims, Aig_Obj_t * pObj ) -{ - return (unsigned *)Vec_PtrEntry( vSims, pObj->Id ); -} -static inline unsigned Dch_ObjRandomSim() -{ - return Aig_ManRandom(0); -} - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns 1 if the node appears to be constant 1 candidate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dch_NodeIsConstCex( void * p, Aig_Obj_t * pObj ) -{ - return pObj->fPhase == pObj->fMarkB; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the nodes appear equal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dch_NodesAreEqualCex( void * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) -{ - return (pObj0->fPhase == pObj1->fPhase) == (pObj0->fMarkB == pObj1->fMarkB); -} - -/**Function************************************************************* - - Synopsis [Computes hash value of the node using its simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Dch_NodeHash( void * p, Aig_Obj_t * pObj ) -{ - Vec_Ptr_t * vSims = (Vec_Ptr_t *)p; - 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 * pSim; - unsigned uHash; - int k, nWords; - nWords = (unsigned *)Vec_PtrEntry(vSims, 1) - (unsigned *)Vec_PtrEntry(vSims, 0); - uHash = 0; - pSim = Dch_ObjSim( vSims, pObj ); - if ( pObj->fPhase ) - { - for ( k = 0; k < nWords; k++ ) - uHash ^= ~pSim[k] * s_FPrimes[k & 0x7F]; - } - else - { - for ( k = 0; k < nWords; k++ ) - uHash ^= pSim[k] * s_FPrimes[k & 0x7F]; - } - return uHash; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if simulation info is composed of all zeros.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dch_NodeIsConst( void * p, Aig_Obj_t * pObj ) -{ - Vec_Ptr_t * vSims = (Vec_Ptr_t *)p; - unsigned * pSim; - int k, nWords; - nWords = (unsigned *)Vec_PtrEntry(vSims, 1) - (unsigned *)Vec_PtrEntry(vSims, 0); - pSim = Dch_ObjSim( vSims, pObj ); - if ( pObj->fPhase ) - { - for ( k = 0; k < nWords; k++ ) - if ( ~pSim[k] ) - return 0; - } - else - { - for ( k = 0; k < nWords; k++ ) - if ( pSim[k] ) - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if simulation infos are equal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dch_NodesAreEqual( void * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) -{ - Vec_Ptr_t * vSims = (Vec_Ptr_t *)p; - unsigned * pSim0, * pSim1; - int k, nWords; - nWords = (unsigned *)Vec_PtrEntry(vSims, 1) - (unsigned *)Vec_PtrEntry(vSims, 0); - pSim0 = Dch_ObjSim( vSims, pObj0 ); - pSim1 = Dch_ObjSim( vSims, pObj1 ); - if ( pObj0->fPhase != pObj1->fPhase ) - { - for ( k = 0; k < nWords; k++ ) - if ( pSim0[k] != ~pSim1[k] ) - return 0; - } - else - { - for ( k = 0; k < nWords; k++ ) - if ( pSim0[k] != pSim1[k] ) - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Perform random simulation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_PerformRandomSimulation( Aig_Man_t * pAig, Vec_Ptr_t * vSims ) -{ - unsigned * pSim, * pSim0, * pSim1; - Aig_Obj_t * pObj; - int i, k, nWords; - nWords = (unsigned *)Vec_PtrEntry(vSims, 1) - (unsigned *)Vec_PtrEntry(vSims, 0); - - // assign const 1 sim info - pObj = Aig_ManConst1(pAig); - pSim = Dch_ObjSim( vSims, pObj ); - memset( pSim, 0xff, sizeof(unsigned) * nWords ); - - // assign primary input random sim info - Aig_ManForEachPi( pAig, pObj, i ) - { - pSim = Dch_ObjSim( vSims, pObj ); - for ( k = 0; k < nWords; k++ ) - pSim[k] = Dch_ObjRandomSim(); - pSim[0] <<= 1; - } - - // simulate AIG in the topological order - Aig_ManForEachNode( pAig, pObj, i ) - { - pSim0 = Dch_ObjSim( vSims, Aig_ObjFanin0(pObj) ); - pSim1 = Dch_ObjSim( vSims, Aig_ObjFanin1(pObj) ); - pSim = Dch_ObjSim( vSims, pObj ); - - if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) // both are compls - { - for ( k = 0; k < nWords; k++ ) - pSim[k] = ~pSim0[k] & ~pSim1[k]; - } - else if ( Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) ) // first one is compl - { - for ( k = 0; k < nWords; k++ ) - pSim[k] = ~pSim0[k] & pSim1[k]; - } - else if ( !Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) // second one is compl - { - for ( k = 0; k < nWords; k++ ) - pSim[k] = pSim0[k] & ~pSim1[k]; - } - else // if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) // none is compl - { - for ( k = 0; k < nWords; k++ ) - pSim[k] = pSim0[k] & pSim1[k]; - } - } - // get simulation information for primary outputs -} - -/**Function************************************************************* - - Synopsis [Derives candidate equivalence classes of AIG nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dch_Cla_t * Dch_CreateCandEquivClasses( Aig_Man_t * pAig, int nWords, int fVerbose ) -{ - Dch_Cla_t * pClasses; - Vec_Ptr_t * vSims; - int i; - // allocate simulation information - vSims = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(pAig), nWords ); - // run random simulation from the primary inputs - Dch_PerformRandomSimulation( pAig, vSims ); - // start storage for equivalence classes - pClasses = Dch_ClassesStart( pAig ); - Dch_ClassesSetData( pClasses, vSims, Dch_NodeHash, Dch_NodeIsConst, Dch_NodesAreEqual ); - // hash nodes by sim info - Dch_ClassesPrepare( pClasses, 0, 0 ); - // iterate random simulation - for ( i = 0; i < 7; i++ ) - { - Dch_PerformRandomSimulation( pAig, vSims ); - Dch_ClassesRefine( pClasses ); - } - // clean up and return - Vec_PtrFree( vSims ); - // prepare class refinement procedures - Dch_ClassesSetData( pClasses, NULL, NULL, Dch_NodeIsConstCex, Dch_NodesAreEqualCex ); - return pClasses; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/dch/dchSimSat.c b/src/aig/dch/dchSimSat.c deleted file mode 100644 index 325543d1..00000000 --- a/src/aig/dch/dchSimSat.c +++ /dev/null @@ -1,258 +0,0 @@ -/**CFile**************************************************************** - - FileName [dchSimSat.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Choice computation for tech-mapping.] - - Synopsis [Performs resimulation using counter-examples.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 29, 2008.] - - Revision [$Id: dchSimSat.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "dchInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Collects internal nodes in the reverse DFS order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_ManCollectTfoCands_rec( Dch_Man_t * p, Aig_Obj_t * pObj ) -{ - Aig_Obj_t * pFanout, * pRepr; - int iFanout = -1, i; - assert( !Aig_IsComplement(pObj) ); - if ( Aig_ObjIsTravIdCurrent(p->pAigTotal, pObj) ) - return; - Aig_ObjSetTravIdCurrent(p->pAigTotal, pObj); - // traverse the fanouts - Aig_ObjForEachFanout( p->pAigTotal, pObj, pFanout, iFanout, i ) - Dch_ManCollectTfoCands_rec( p, pFanout ); - // check if the given node has a representative - pRepr = Aig_ObjRepr( p->pAigTotal, pObj ); - if ( pRepr == NULL ) - return; - // pRepr is the constant 1 node - if ( pRepr == Aig_ManConst1(p->pAigTotal) ) - { - Vec_PtrPush( p->vSimRoots, pObj ); - return; - } - // pRepr is the representative of an equivalence class - if ( pRepr->fMarkA ) - return; - pRepr->fMarkA = 1; - Vec_PtrPush( p->vSimClasses, pRepr ); -} - -/**Function************************************************************* - - Synopsis [Collect equivalence classes and const1 cands in the TFO.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_ManCollectTfoCands( Dch_Man_t * p, Aig_Obj_t * pObj1, Aig_Obj_t * pObj2 ) -{ - Aig_Obj_t * pObj; - int i; - Vec_PtrClear( p->vSimRoots ); - Vec_PtrClear( p->vSimClasses ); - Aig_ManIncrementTravId( p->pAigTotal ); - Aig_ObjSetTravIdCurrent( p->pAigTotal, Aig_ManConst1(p->pAigTotal) ); - Dch_ManCollectTfoCands_rec( p, pObj1 ); - Dch_ManCollectTfoCands_rec( p, pObj2 ); - Vec_PtrSort( p->vSimRoots, (int (*)(void))Aig_ObjCompareIdIncrease ); - Vec_PtrSort( p->vSimClasses, (int (*)(void))Aig_ObjCompareIdIncrease ); - Vec_PtrForEachEntry( Aig_Obj_t *, p->vSimClasses, pObj, i ) - pObj->fMarkA = 0; -} - -/**Function************************************************************* - - Synopsis [Resimulates the cone of influence of the solved nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_ManResimulateSolved_rec( Dch_Man_t * p, Aig_Obj_t * pObj ) -{ - if ( Aig_ObjIsTravIdCurrent(p->pAigTotal, pObj) ) - return; - Aig_ObjSetTravIdCurrent(p->pAigTotal, pObj); - if ( Aig_ObjIsPi(pObj) ) - { - Aig_Obj_t * pObjFraig; - int nVarNum; - pObjFraig = Dch_ObjFraig( pObj ); - assert( !Aig_IsComplement(pObjFraig) ); - nVarNum = Dch_ObjSatNum( p, pObjFraig ); - // get the value from the SAT solver - // (account for the fact that some vars may be minimized away) - pObj->fMarkB = !nVarNum? 0 : sat_solver_var_value( p->pSat, nVarNum ); -// pObj->fMarkB = !nVarNum? Aig_ManRandom(0) & 1 : sat_solver_var_value( p->pSat, nVarNum ); - return; - } - Dch_ManResimulateSolved_rec( p, Aig_ObjFanin0(pObj) ); - Dch_ManResimulateSolved_rec( p, Aig_ObjFanin1(pObj) ); - pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ) - & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) ); - // count the cone size - if ( Dch_ObjSatNum( p, Aig_Regular(Dch_ObjFraig(pObj)) ) > 0 ) - p->nConeThis++; -} - -/**Function************************************************************* - - Synopsis [Resimulates the cone of influence of the other nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_ManResimulateOther_rec( Dch_Man_t * p, Aig_Obj_t * pObj ) -{ - if ( Aig_ObjIsTravIdCurrent(p->pAigTotal, pObj) ) - return; - Aig_ObjSetTravIdCurrent(p->pAigTotal, pObj); - if ( Aig_ObjIsPi(pObj) ) - { - // set random value - pObj->fMarkB = Aig_ManRandom(0) & 1; - return; - } - Dch_ManResimulateOther_rec( p, Aig_ObjFanin0(pObj) ); - Dch_ManResimulateOther_rec( p, Aig_ObjFanin1(pObj) ); - pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ) - & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Handle the counter-example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_ManResimulateCex( Dch_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr ) -{ - Aig_Obj_t * pRoot, ** ppClass; - int i, k, nSize, RetValue1, RetValue2, clk = clock(); - // get the equivalence classes - Dch_ManCollectTfoCands( p, pObj, pRepr ); - // resimulate the cone of influence of the solved nodes - p->nConeThis = 0; - Aig_ManIncrementTravId( p->pAigTotal ); - Aig_ObjSetTravIdCurrent( p->pAigTotal, Aig_ManConst1(p->pAigTotal) ); - Dch_ManResimulateSolved_rec( p, pObj ); - Dch_ManResimulateSolved_rec( p, pRepr ); - p->nConeMax = ABC_MAX( p->nConeMax, p->nConeThis ); - // resimulate the cone of influence of the other nodes - Vec_PtrForEachEntry( Aig_Obj_t *, p->vSimRoots, pRoot, i ) - Dch_ManResimulateOther_rec( p, pRoot ); - // refine these nodes - RetValue1 = Dch_ClassesRefineConst1Group( p->ppClasses, p->vSimRoots, 0 ); - // resimulate the cone of influence of the cand classes - RetValue2 = 0; - Vec_PtrForEachEntry( Aig_Obj_t *, p->vSimClasses, pRoot, i ) - { - ppClass = Dch_ClassesReadClass( p->ppClasses, pRoot, &nSize ); - for ( k = 0; k < nSize; k++ ) - Dch_ManResimulateOther_rec( p, ppClass[k] ); - // refine this class - RetValue2 += Dch_ClassesRefineOneClass( p->ppClasses, pRoot, 0 ); - } - // make sure refinement happened - if ( Aig_ObjIsConst1(pRepr) ) - assert( RetValue1 ); - else - assert( RetValue2 ); -p->timeSimSat += clock() - clk; -} - -/**Function************************************************************* - - Synopsis [Handle the counter-example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_ManResimulateCex2( Dch_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr ) -{ - Aig_Obj_t * pRoot; - int i, RetValue, clk = clock(); - // get the equivalence class - if ( Dch_ObjIsConst1Cand(p->pAigTotal, pObj) ) - Dch_ClassesCollectConst1Group( p->ppClasses, pObj, 500, p->vSimRoots ); - else - Dch_ClassesCollectOneClass( p->ppClasses, pRepr, p->vSimRoots ); - // resimulate the cone of influence of the solved nodes - p->nConeThis = 0; - Aig_ManIncrementTravId( p->pAigTotal ); - Aig_ObjSetTravIdCurrent( p->pAigTotal, Aig_ManConst1(p->pAigTotal) ); - Dch_ManResimulateSolved_rec( p, pObj ); - Dch_ManResimulateSolved_rec( p, pRepr ); - p->nConeMax = ABC_MAX( p->nConeMax, p->nConeThis ); - // resimulate the cone of influence of the other nodes - Vec_PtrForEachEntry( Aig_Obj_t *, p->vSimRoots, pRoot, i ) - Dch_ManResimulateOther_rec( p, pRoot ); - // refine this class - if ( Dch_ObjIsConst1Cand(p->pAigTotal, pObj) ) - RetValue = Dch_ClassesRefineConst1Group( p->ppClasses, p->vSimRoots, 0 ); - else - RetValue = Dch_ClassesRefineOneClass( p->ppClasses, pRepr, 0 ); - assert( RetValue ); -p->timeSimSat += clock() - clk; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/dch/dchSweep.c b/src/aig/dch/dchSweep.c deleted file mode 100644 index 4b054be2..00000000 --- a/src/aig/dch/dchSweep.c +++ /dev/null @@ -1,146 +0,0 @@ -/**CFile**************************************************************** - - FileName [dchSweep.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Choice computation for tech-mapping.] - - Synopsis [One round of SAT sweeping.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 29, 2008.] - - Revision [$Id: dchSweep.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "dchInt.h" -#include "bar.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline Aig_Obj_t * Dch_ObjChild0Fra( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Dch_ObjFraig(Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj)) : NULL; } -static inline Aig_Obj_t * Dch_ObjChild1Fra( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Dch_ObjFraig(Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj)) : NULL; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs fraiging for one node.] - - Description [Returns the fraiged node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_ManSweepNode( Dch_Man_t * p, Aig_Obj_t * pObj ) -{ - Aig_Obj_t * pObjRepr, * pObjFraig, * pObjFraig2, * pObjReprFraig; - int RetValue; - // get representative of this class - pObjRepr = Aig_ObjRepr( p->pAigTotal, pObj ); - if ( pObjRepr == NULL ) - return; - // get the fraiged node - pObjFraig = Dch_ObjFraig( pObj ); - if ( pObjFraig == NULL ) - return; - // get the fraiged representative - pObjReprFraig = Dch_ObjFraig( pObjRepr ); - if ( pObjReprFraig == NULL ) - return; - // if the fraiged nodes are the same, return - if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) ) - { - // remember the proved equivalence - p->pReprsProved[ pObj->Id ] = pObjRepr; - return; - } - assert( Aig_Regular(pObjFraig) != Aig_ManConst1(p->pAigFraig) ); - RetValue = Dch_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) ); - if ( RetValue == -1 ) // timed out - { - Dch_ObjSetFraig( pObj, NULL ); - return; - } - if ( RetValue == 1 ) // proved equivalent - { - pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase ); - Dch_ObjSetFraig( pObj, pObjFraig2 ); - // remember the proved equivalence - p->pReprsProved[ pObj->Id ] = pObjRepr; - return; - } - // disproved the equivalence - if ( p->pPars->fSimulateTfo ) - Dch_ManResimulateCex( p, pObj, pObjRepr ); - else - Dch_ManResimulateCex2( p, pObj, pObjRepr ); - assert( Aig_ObjRepr( p->pAigTotal, pObj ) != pObjRepr ); -} - -/**Function************************************************************* - - Synopsis [Performs fraiging for the internal nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dch_ManSweep( Dch_Man_t * p ) -{ - Bar_Progress_t * pProgress = NULL; - Aig_Obj_t * pObj, * pObjNew; - int i; - // map constants and PIs - p->pAigFraig = Aig_ManStart( Aig_ManObjNumMax(p->pAigTotal) ); - Aig_ManCleanData( p->pAigTotal ); - Aig_ManConst1(p->pAigTotal)->pData = Aig_ManConst1(p->pAigFraig); - Aig_ManForEachPi( p->pAigTotal, pObj, i ) - pObj->pData = Aig_ObjCreatePi( p->pAigFraig ); - // sweep internal nodes - pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAigTotal) ); - Aig_ManForEachNode( p->pAigTotal, pObj, i ) - { - Bar_ProgressUpdate( pProgress, i, NULL ); - if ( Dch_ObjFraig(Aig_ObjFanin0(pObj)) == NULL || - Dch_ObjFraig(Aig_ObjFanin1(pObj)) == NULL ) - continue; - pObjNew = Aig_And( p->pAigFraig, Dch_ObjChild0Fra(pObj), Dch_ObjChild1Fra(pObj) ); - if ( pObjNew == NULL ) - continue; - Dch_ObjSetFraig( pObj, pObjNew ); - Dch_ManSweepNode( p, pObj ); - } - Bar_ProgressStop( pProgress ); - // update the representatives of the nodes (makes classes invalid) - ABC_FREE( p->pAigTotal->pReprs ); - p->pAigTotal->pReprs = p->pReprsProved; - p->pReprsProved = NULL; - // clean the mark - Aig_ManCleanMarkB( p->pAigTotal ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/dch/module.make b/src/aig/dch/module.make deleted file mode 100644 index 5709f87a..00000000 --- a/src/aig/dch/module.make +++ /dev/null @@ -1,10 +0,0 @@ -SRC += src/aig/dch/dchAig.c \ - src/aig/dch/dchChoice.c \ - src/aig/dch/dchClass.c \ - src/aig/dch/dchCnf.c \ - src/aig/dch/dchCore.c \ - src/aig/dch/dchMan.c \ - src/aig/dch/dchSat.c \ - src/aig/dch/dchSim.c \ - src/aig/dch/dchSimSat.c \ - src/aig/dch/dchSweep.c diff --git a/src/aig/deco/deco.h b/src/aig/deco/deco.h deleted file mode 100644 index 84f2e25e..00000000 --- a/src/aig/deco/deco.h +++ /dev/null @@ -1,714 +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__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 - union { int iFunc; // the literal of the node (AIG) - 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 m ) { union { Dec_Edge_t x; unsigned y; } v; v.x = m; return v.y; } -/* -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 m ) { union { Dec_Edge_t x; unsigned y; } v; v.y = m; return v.x; } -/* -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 = ABC_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 = ABC_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 = ABC_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 = ABC_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 ) -{ - ABC_FREE( pGraph->pNodes ); - ABC_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 = ABC_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; -} - - - -ABC_NAMESPACE_HEADER_END - - - -#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 ea362bdf..00000000 --- a/src/aig/fra/fra.h +++ /dev/null @@ -1,389 +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__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include - -#include "vec.h" -#include "aig.h" -#include "dar.h" -#include "satSolver.h" -#include "ioa.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Fra_Par_t_ Fra_Par_t; -typedef struct Fra_Ssw_t_ Fra_Ssw_t; -typedef struct Fra_Sec_t_ Fra_Sec_t; -typedef struct Fra_Man_t_ Fra_Man_t; -typedef struct Fra_Cla_t_ Fra_Cla_t; -typedef struct Fra_Sml_t_ Fra_Sml_t; -typedef struct Fra_Bmc_t_ Fra_Bmc_t; - -// FRAIG parameters -struct Fra_Par_t_ -{ - int nSimWords; // the number of words in the simulation info - double dSimSatur; // the ratio of refined classes when saturation is reached - int fPatScores; // enables simulation pattern scoring - int MaxScore; // max score after which resimulation is used - double dActConeRatio; // the ratio of cone to be bumped - double dActConeBumpMax; // the largest bump in activity - int fChoicing; // enables choicing - int fSpeculate; // use speculative reduction - int fProve; // prove the miter outputs - int fVerbose; // verbose output - int fDoSparse; // skip sparse functions - int fConeBias; // bias variables in the cone (good for unsat runs) - int nBTLimitNode; // conflict limit at a node - int nBTLimitMiter; // conflict limit at an output - int nLevelMax; // the max level to consider seriously - 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 fUse1Hot; // use one-hotness conditions - int fWriteImps; // record implications - int fDontShowBar; // does not show progressbar during fraiging -}; - -// seq SAT sweeping parameters -struct Fra_Ssw_t_ -{ - int nPartSize; // size of the partition - int nOverSize; // size of the overlap between partitions - int nFramesP; // number of frames in the prefix - int nFramesK; // number of frames for induction (1=simple) - int nMaxImps; // max implications to consider - int nMaxLevs; // max levels to consider - int nMinDomSize; // min clock domain considered for optimization - int fUseImps; // use implications - int fRewrite; // enable rewriting of the specualatively reduced model - int fFraiging; // enable comb SAT sweeping as preprocessing - int fLatchCorr; // perform register correspondence - int fWriteImps; // write implications into a file - int fUse1Hot; // use one-hotness constraints - int fVerbose; // enable verbose output - int fSilent; // disable any output - int nIters; // the number of iterations performed - float TimeLimit; // the runtime budget for this call -}; - -// SEC parametesr -struct Fra_Sec_t_ -{ - int fTryComb; // try CEC call as a preprocessing step - int fTryBmc; // try BMC call as a preprocessing step - int nFramesMax; // the max number of frames used for induction - int nBTLimit; // the conflict limit at a node - int nBTLimitGlobal; // the global conflict limit - int nBTLimitInter; // the conflict limit for interpolation - int nBddVarsMax; // the state space limit for BDD reachability - int nBddMax; // the max number of BDD nodes - int nBddIterMax; // the limit on the number of BDD iterations - int nPdrTimeout; // the timeout for PDR in the end - int fPhaseAbstract; // enables phase abstraction - int fRetimeFirst; // enables most-forward retiming at the beginning - int fRetimeRegs; // enables min-register retiming at the beginning - int fFraiging; // enables fraiging at the beginning - int fInduction; // enable the use of induction - int fInterpolation; // enables interpolation - int fInterSeparate; // enables interpolation for each outputs separately - int fReachability; // enables BDD based reachability - int fReorderImage; // enables BDD reordering during image computation - int fStopOnFirstFail; // enables stopping after first output of a miter has failed to prove - int fUseNewProver; // the new prover - int fUsePdr; // the PDR - int fSilent; // disables all output - int fVerbose; // enables verbose reporting of statistics - int fVeryVerbose; // enables very verbose reporting - int TimeLimit; // enables the timeout - int fReadUnsolved; // inserts the unsolved model back - int nSMnumber; // the number of model written - // internal parameters - int fRecursive; // set to 1 when SEC is called recursively - int fReportSolution; // enables report solution in a special form -}; - -// FRAIG equivalence classes -struct Fra_Cla_t_ -{ - Aig_Man_t * pAig; // the original AIG manager - Aig_Obj_t ** pMemRepr; // pointers to representatives of each node - Vec_Ptr_t * vClasses; // equivalence classes - Vec_Ptr_t * vClasses1; // equivalence class of Const1 node - Vec_Ptr_t * vClassesTemp; // temporary storage for new classes - Aig_Obj_t ** pMemClasses; // memory allocated for equivalence classes - Aig_Obj_t ** pMemClassesFree; // memory allocated for equivalence classes to be used - Vec_Ptr_t * vClassOld; // old equivalence class after splitting - Vec_Ptr_t * vClassNew; // new equivalence class(es) after splitting - int nPairs; // the number of pairs of nodes - int fRefinement; // set to 1 when refinement has happened - Vec_Int_t * vImps; // implications - // procedures used for class refinement - int (*pFuncNodeHash) (Aig_Obj_t *, int); // returns has key of the node - int (*pFuncNodeIsConst) (Aig_Obj_t *); // returns 1 if the node is a constant - int (*pFuncNodesAreEqual)(Aig_Obj_t *, Aig_Obj_t *); // returns 1 if nodes are equal up to a complement -}; - -// simulation manager -struct Fra_Sml_t_ -{ - Aig_Man_t * pAig; // the original AIG manager - int nPref; // the number of times frames in the prefix - int nFrames; // the number of times frames - int nWordsFrame; // the number of words in each time frame - int nWordsTotal; // the total number of words at a node - int nWordsPref; // the number of word in the prefix - int fNonConstOut; // have seen a non-const-0 output during simulation - int nSimRounds; // statistics - int timeSim; // statistics - unsigned pData[0]; // simulation data for the nodes -}; - -// FRAIG manager -struct Fra_Man_t_ -{ - // high-level data - Fra_Par_t * pPars; // parameters governing fraiging - // AIG managers - Aig_Man_t * pManAig; // the starting AIG manager - Aig_Man_t * pManFraig; // the final AIG manager - // mapping AIG into FRAIG - int nFramesAll; // the number of timeframes used - Aig_Obj_t ** pMemFraig; // memory allocated for points to the fraig nodes - int nSizeAlloc; // allocated size of the arrays for timeframe nodes - // equivalence classes - Fra_Cla_t * pCla; // representation of (candidate) equivalent nodes - // simulation info - Fra_Sml_t * pSml; // simulation manager - // bounded model checking manager - Fra_Bmc_t * pBmc; - // counter example storage - int nPatWords; // the number of words in the counter example - unsigned * pPatWords; // the counter example - Vec_Int_t * vCex; - // one-hotness conditions - Vec_Int_t * vOneHots; - // 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 - ABC_INT64_T nBTLimitGlobal; // resource limit - ABC_INT64_T 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 Aig_ManRandom(0); } - -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, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int fFlipBits, int fAndOuts, int fNewSolver, int fVerbose ); -extern int Fra_FraigCec( Aig_Man_t ** ppAig, int nConfLimit, int fVerbose ); -extern int Fra_FraigCecPartitioned( Aig_Man_t * pMan1, Aig_Man_t * pMan2, int nConfLimit, int nPartSize, int fSmart, 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, int nLevelMax ); -extern Aig_Man_t * Fra_FraigEquivence( Aig_Man_t * pManAig, int nConfMax, int fProve ); -/*=== fraHot.c ========================================================*/ -extern Vec_Int_t * Fra_OneHotCompute( Fra_Man_t * p, Fra_Sml_t * pSim ); -extern void Fra_OneHotAssume( Fra_Man_t * p, Vec_Int_t * vOneHots ); -extern void Fra_OneHotCheck( Fra_Man_t * p, Vec_Int_t * vOneHots ); -extern int Fra_OneHotRefineUsingCex( Fra_Man_t * p, Vec_Int_t * vOneHots ); -extern int Fra_OneHotCount( Fra_Man_t * p, Vec_Int_t * vOneHots ); -extern void Fra_OneHotEstimateCoverage( Fra_Man_t * p, Vec_Int_t * vOneHots ); -extern Aig_Man_t * Fra_OneHotCreateExdc( Fra_Man_t * p, Vec_Int_t * vOneHots ); -extern void Fra_OneHotAddKnownConstraint( Fra_Man_t * p, Vec_Ptr_t * vOnehots ); -/*=== 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, Fra_Ssw_t * pPars ); -/*=== fraIndVer.c =====================================================*/ -extern int Fra_InvariantVerify( Aig_Man_t * p, int nFrames, Vec_Int_t * vClauses, Vec_Int_t * vLits ); -/*=== fraLcr.c ========================================================*/ -extern Aig_Man_t * Fra_FraigLatchCorrespondence( Aig_Man_t * pAig, int nFramesP, int nConfMax, int fProve, int fVerbose, int * pnIter, float TimeLimit ); -/*=== 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_NodesAreClause( 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 void Fra_SecSetDefaultParams( Fra_Sec_t * p ); -extern int Fra_FraigSec( Aig_Man_t * p, Fra_Sec_t * pParSec, Aig_Man_t ** ppResult ); -/*=== 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_SmlNodeCountOnes( Fra_Sml_t * p, Aig_Obj_t * pObj ); -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, int fCheckMiter ); -extern Fra_Sml_t * Fra_SmlSimulateComb( Aig_Man_t * pAig, int nWords ); -extern Abc_Cex_t * Fra_SmlGetCounterExample( Fra_Sml_t * p ); -extern Abc_Cex_t * Fra_SmlCopyCounterExample( Aig_Man_t * pAig, Aig_Man_t * pFrames, int * pModel ); - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/fra/fraBmc.c b/src/aig/fra/fraBmc.c deleted file mode 100644 index 3907fcdd..00000000 --- a/src/aig/fra/fraBmc.c +++ /dev/null @@ -1,451 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 = (Fra_Man_t *)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 = (Fra_Man_t *)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 = ABC_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 = ABC_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 ); - ABC_FREE( p->pObjToFrames ); - ABC_FREE( p->pObjToFraig ); - ABC_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 ); - pAigFrames->pSpec = Aig_UtilStrsav( p->pAig->pSpec ); - // 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 = ABC_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) ); - } - ABC_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) ); - ABC_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 clk, iOutput; - // derive and fraig the frames - clk = clock(); - pBmc = Fra_BmcStart( pAig, 0, nFrames ); - pTemp = Fra_LcrAigPrepare( pAig ); - pTemp->pBmc = pBmc; - pBmc->pAigFrames = Fra_BmcFrames( pBmc, 1 ); - if ( fVerbose ) - { - printf( "AIG: PI/PO/Reg = %d/%d/%d. Node = %6d. Lev = %5d.\n", - Aig_ManPiNum(pAig)-Aig_ManRegNum(pAig), Aig_ManPoNum(pAig)-Aig_ManRegNum(pAig), Aig_ManRegNum(pAig), - Aig_ManNodeNum(pAig), Aig_ManLevelNum(pAig) ); - printf( "Time-frames (%d): PI/PO = %d/%d. Node = %6d. Lev = %5d. ", - nFrames, Aig_ManPiNum(pBmc->pAigFrames), Aig_ManPoNum(pBmc->pAigFrames), - Aig_ManNodeNum(pBmc->pAigFrames), Aig_ManLevelNum(pBmc->pAigFrames) ); - ABC_PRT( "Time", clock() - clk ); - } - if ( fRewrite ) - { - clk = clock(); - pBmc->pAigFrames = Dar_ManRwsat( pAigTemp = pBmc->pAigFrames, 1, 0 ); - Aig_ManStop( pAigTemp ); - if ( fVerbose ) - { - printf( "Time-frames after rewriting: Node = %6d. Lev = %5d. ", - Aig_ManNodeNum(pBmc->pAigFrames), Aig_ManLevelNum(pBmc->pAigFrames) ); - ABC_PRT( "Time", clock() - clk ); - } - } - clk = clock(); - iOutput = Fra_FraigMiterAssertedOutput( pBmc->pAigFrames ); - if ( iOutput >= 0 ) - pAig->pSeqModel = Abc_CexMakeTriv( Aig_ManRegNum(pAig), Aig_ManPiNum(pAig)-Aig_ManRegNum(pAig), Aig_ManPoNum(pAig)-Aig_ManRegNum(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, (int *)pBmc->pAigFraig->pData ); - ABC_FREE( pBmc->pAigFraig->pData ); - } - else if ( iOutput >= 0 ) - pAig->pSeqModel = Abc_CexMakeTriv( Aig_ManRegNum(pAig), Aig_ManPiNum(pAig)-Aig_ManRegNum(pAig), Aig_ManPoNum(pAig)-Aig_ManRegNum(pAig), iOutput ); - } - if ( fVerbose ) - { - printf( "Fraiged init frames: Node = %6d. Lev = %5d. ", - pBmc->pAigFraig? Aig_ManNodeNum(pBmc->pAigFraig) : -1, - pBmc->pAigFraig? Aig_ManLevelNum(pBmc->pAigFraig) : -1 ); - ABC_PRT( "Time", clock() - clk ); - } - Fra_BmcStop( pBmc ); - ABC_FREE( pTemp ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/fra/fraCec.c b/src/aig/fra/fraCec.c deleted file mode 100644 index c52f4308..00000000 --- a/src/aig/fra/fraCec.c +++ /dev/null @@ -1,516 +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" -#include "satSolver2.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_FraigSat( Aig_Man_t * pMan, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int fFlipBits, int fAndOuts, int fNewSolver, int fVerbose ) -{ - if ( fNewSolver ) - { - extern void * Cnf_DataWriteIntoSolver2( Cnf_Dat_t * p, int nFrames, int fInit ); - extern int Cnf_DataWriteOrClause2( void * pSat, Cnf_Dat_t * pCnf ); - - sat_solver2 * pSat; - Cnf_Dat_t * pCnf; - int status, RetValue, clk = clock(); - Vec_Int_t * vCiIds; - - assert( Aig_ManRegNum(pMan) == 0 ); - pMan->pData = NULL; - - // derive CNF - pCnf = Cnf_Derive( pMan, Aig_ManPoNum(pMan) ); - // pCnf = Cnf_DeriveSimple( pMan, Aig_ManPoNum(pMan) ); - - if ( fFlipBits ) - Cnf_DataTranformPolarity( pCnf, 0 ); - - // convert into SAT solver - pSat = (sat_solver2 *)Cnf_DataWriteIntoSolver2( pCnf, 1, 0 ); - if ( pSat == NULL ) - { - Cnf_DataFree( pCnf ); - return 1; - } - - - if ( fAndOuts ) - { - // assert each output independently - if ( !Cnf_DataWriteAndClauses( pSat, pCnf ) ) - { - sat_solver2_delete( pSat ); - Cnf_DataFree( pCnf ); - return 1; - } - } - else - { - // add the OR clause for the outputs - if ( !Cnf_DataWriteOrClause2( pSat, pCnf ) ) - { - sat_solver2_delete( pSat ); - Cnf_DataFree( pCnf ); - return 1; - } - } - vCiIds = Cnf_DataCollectPiSatNums( pCnf, pMan ); - Cnf_DataFree( pCnf ); - - - printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver2_nvars(pSat), sat_solver2_nclauses(pSat) ); - ABC_PRT( "Time", clock() - clk ); - - // simplify the problem - clk = clock(); - status = sat_solver2_simplify(pSat); -// printf( "Simplified the problem to %d variables and %d clauses. ", sat_solver2_nvars(pSat), sat_solver2_nclauses(pSat) ); -// ABC_PRT( "Time", clock() - clk ); - if ( status == 0 ) - { - Vec_IntFree( vCiIds ); - sat_solver2_delete( pSat ); - // printf( "The problem is UNSATISFIABLE after simplification.\n" ); - return 1; - } - - // solve the miter - clk = clock(); - if ( fVerbose ) - pSat->verbosity = 1; - status = sat_solver2_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, (ABC_INT64_T)0, (ABC_INT64_T)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 ); - - // Abc_Print( 1, "The number of conflicts = %6d. ", (int)pSat->stats.conflicts ); - // Abc_PrintTime( 1, "Solving time", clock() - clk ); - - // if the problem is SAT, get the counterexample - if ( status == l_True ) - { - pMan->pData = Sat_Solver2GetModel( pSat, vCiIds->pArray, vCiIds->nSize ); - } - // free the sat_solver2 - if ( fVerbose ) - Sat_Solver2PrintStats( stdout, pSat ); - //sat_solver2_store_write( pSat, "trace.cnf" ); - //sat_solver2_store_free( pSat ); - sat_solver2_delete( pSat ); - Vec_IntFree( vCiIds ); - return RetValue; - } - else - { - sat_solver * pSat; - Cnf_Dat_t * pCnf; - int status, RetValue, clk = clock(); - Vec_Int_t * vCiIds; - - assert( Aig_ManRegNum(pMan) == 0 ); - pMan->pData = NULL; - - // derive CNF - pCnf = Cnf_Derive( pMan, Aig_ManPoNum(pMan) ); - // pCnf = Cnf_DeriveSimple( pMan, Aig_ManPoNum(pMan) ); - - if ( fFlipBits ) - Cnf_DataTranformPolarity( pCnf, 0 ); - - // convert into SAT solver - pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); - if ( pSat == NULL ) - { - Cnf_DataFree( pCnf ); - return 1; - } - - - if ( fAndOuts ) - { - // assert each output independently - if ( !Cnf_DataWriteAndClauses( pSat, pCnf ) ) - { - sat_solver_delete( pSat ); - Cnf_DataFree( pCnf ); - return 1; - } - } - else - { - // add the OR clause for the outputs - if ( !Cnf_DataWriteOrClause( pSat, pCnf ) ) - { - sat_solver_delete( pSat ); - Cnf_DataFree( pCnf ); - return 1; - } - } - vCiIds = Cnf_DataCollectPiSatNums( pCnf, pMan ); - Cnf_DataFree( pCnf ); - - - // printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) ); - // ABC_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) ); - // ABC_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, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, (ABC_INT64_T)0, (ABC_INT64_T)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 ); - - // Abc_Print( 1, "The number of conflicts = %6d. ", (int)pSat->stats.conflicts ); - // Abc_PrintTime( 1, "Solving time", clock() - clk ); - - // 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 nConfLimit, int fVerbose ) -{ - int nBTLimitStart = 300; // starting SAT run - int nBTLimitFirst = 2; // first fraiging iteration - int nBTLimitLast = nConfLimit; // 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 ) - { - pAig->pData = ABC_ALLOC( int, Aig_ManPiNum(pAig) ); - memset( pAig->pData, 0, sizeof(int) * Aig_ManPiNum(pAig) ); - return RetValue; - } - - // if SAT only, solve without iteration -clk = clock(); - RetValue = Fra_FraigSat( pAig, (ABC_INT64_T)2*nBTLimitStart, (ABC_INT64_T)0, 1, 0, 0, 0 ); - if ( fVerbose ) - { - printf( "Initial SAT: Nodes = %6d. ", Aig_ManNodeNum(pAig) ); -ABC_PRT( "Time", clock() - clk ); - } - if ( RetValue >= 0 ) - return RetValue; - - // duplicate the AIG -clk = clock(); - pAig = Dar_ManRwsat( pTemp = pAig, 1, 0 ); - Aig_ManStop( pTemp ); - if ( fVerbose ) - { - printf( "Rewriting: Nodes = %6d. ", Aig_ManNodeNum(pAig) ); -ABC_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) ); -ABC_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) ); -ABC_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, (ABC_INT64_T)nBTLimitLast, (ABC_INT64_T)0, 1, 0, 0, 0 ); - if ( fVerbose ) - { - printf( "Final SAT: Nodes = %6d. ", Aig_ManNodeNum(pAig) ); -ABC_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 nConfLimit, int nPartSize, int fSmart, int fVerbose ) -{ - Aig_Man_t * pAig; - Vec_Ptr_t * vParts; - int i, RetValue = 1, nOutputs; - // create partitions - vParts = Aig_ManMiterPartitioned( pMan1, pMan2, nPartSize, fSmart ); - // solve the partitions - nOutputs = -1; - Vec_PtrForEachEntry( Aig_Man_t *, 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) ); - fflush( stdout ); - } - RetValue = Fra_FraigMiterStatus( pAig ); - if ( RetValue == 1 ) - continue; - if ( RetValue == 0 ) - break; - RetValue = Fra_FraigCec( &pAig, nConfLimit, 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( Aig_Man_t *, vParts, pAig, i ) - Aig_ManStop( pAig ); - Vec_PtrFree( vParts ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_FraigCecTop( Aig_Man_t * pMan1, Aig_Man_t * pMan2, int nConfLimit, int nPartSize, int fSmart, int fVerbose ) -{ - Aig_Man_t * pTemp; - //Abc_NtkDarCec( pNtk1, pNtk2, fPartition, fVerbose ); - int RetValue, clkTotal = clock(); - - if ( Aig_ManPiNum(pMan1) != Aig_ManPiNum(pMan1) ) - { - printf( "Abc_CommandAbc8Cec(): Miters have different number of PIs.\n" ); - return 0; - } - if ( Aig_ManPoNum(pMan1) != Aig_ManPoNum(pMan1) ) - { - printf( "Abc_CommandAbc8Cec(): Miters have different number of POs.\n" ); - return 0; - } - assert( Aig_ManPiNum(pMan1) == Aig_ManPiNum(pMan1) ); - assert( Aig_ManPoNum(pMan1) == Aig_ManPoNum(pMan1) ); - - // make sure that the first miter has more nodes - if ( Aig_ManNodeNum(pMan1) < Aig_ManNodeNum(pMan2) ) - { - pTemp = pMan1; - pMan1 = pMan2; - pMan2 = pTemp; - } - assert( Aig_ManNodeNum(pMan1) >= Aig_ManNodeNum(pMan2) ); - - if ( nPartSize ) - RetValue = Fra_FraigCecPartitioned( pMan1, pMan2, nConfLimit, nPartSize, fSmart, fVerbose ); - else // no partitioning - RetValue = Fra_FraigCecPartitioned( pMan1, pMan2, nConfLimit, Aig_ManPoNum(pMan1), 0, fVerbose ); - - // report the miter - if ( RetValue == 1 ) - { - printf( "Networks are equivalent. " ); -ABC_PRT( "Time", clock() - clkTotal ); - } - else if ( RetValue == 0 ) - { - printf( "Networks are NOT EQUIVALENT. " ); -ABC_PRT( "Time", clock() - clkTotal ); - } - else - { - printf( "Networks are UNDECIDED. " ); -ABC_PRT( "Time", clock() - clkTotal ); - } - fflush( stdout ); - return RetValue; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/fra/fraClass.c b/src/aig/fra/fraClass.c deleted file mode 100644 index 8cf2a54d..00000000 --- a/src/aig/fra/fraClass.c +++ /dev/null @@ -1,862 +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" - -ABC_NAMESPACE_IMPL_START - - -/* - 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 = ABC_ALLOC( Fra_Cla_t, 1 ); - memset( p, 0, sizeof(Fra_Cla_t) ); - p->pAig = pAig; - p->pMemRepr = ABC_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 ) -{ - ABC_FREE( p->pMemClasses ); - ABC_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 ); - ABC_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( Aig_Obj_t *, 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( Aig_Obj_t **, 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( Aig_Obj_t **, 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( Fra_Cla_t * p, 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,%d) ", pTemp->Id, pTemp->Level, Aig_SupportSize(p->pAig,pTemp) ); - 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( Aig_Obj_t *, p->vClasses1, pObj, i ) - assert( Fra_ClassObjRepr(pObj) == Aig_ManConst1(p->pAig) ); - printf( "Constants { " ); - Vec_PtrForEachEntry( Aig_Obj_t *, p->vClasses1, pObj, i ) - printf( "%d(%d,%d) ", pObj->Id, pObj->Level, Aig_SupportSize(p->pAig,pObj) ); - printf( "}\n" ); - Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, pClass, i ) - { - printf( "%3d (%3d) : ", i, Fra_ClassCount(pClass) ); - Fra_PrintClass( p, 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 = ABC_FALLOC( Aig_Obj_t *, nTableSize ); - ppNexts = ABC_FALLOC( 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 = ABC_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; - } - ABC_FREE( ppTable ); - ABC_FREE( ppNexts ); - // now it is time to refine the classes - Fra_ClassesRefine( p ); -// Fra_ClassesPrint( p, 0 ); -} - -/**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( Aig_Obj_t *, p->vClassOld, pObj, i ) - printf( "%d,", pObj->Id ); - printf( ") + (" ); - Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i ) - printf( "%d,", pObj->Id ); - printf( ")\n" ); -*/ - // put the nodes back into the class memory - Vec_PtrForEachEntry( Aig_Obj_t *, 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( Aig_Obj_t *, 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 = (Aig_Obj_t **)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( Aig_Obj_t **, 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( Aig_Obj_t *, 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( Aig_Obj_t *, p->vClassNew, pObj, i ) - printf( " %d", pObj->Id ); - printf( " }\n" ); -*/ - if ( Vec_PtrSize(p->vClassNew) == 1 ) - { - Fra_ClassObjSetRepr( (Aig_Obj_t *)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( Aig_Obj_t *, 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 = ABC_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 = ABC_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 = ABC_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 = ABC_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( Aig_Obj_t *, 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( Aig_Obj_t **, 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( Aig_Obj_t **, 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) ); - ABC_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( Aig_Obj_t **, p->vClasses, pClass, i ) - { - // collect support sizes and find the min-support node - cMinSupp = -1; - pNodeMin = NULL; - nSuppSizeMin = ABC_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 ); - pManFraig->pSpec = Aig_UtilStrsav( p->pAig->pSpec ); - // allocate place for the node mapping - ppEquivs = ABC_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 = ABC_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++] ); - } - ABC_FREE( pLatches ); - ABC_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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/fra/fraClau.c b/src/aig/fra/fraClau.c deleted file mode 100644 index 490c73ff..00000000 --- a/src/aig/fra/fraClau.c +++ /dev/null @@ -1,763 +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" - -ABC_NAMESPACE_IMPL_START - - -/* - 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 = ABC_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 ) -{ - ABC_FREE( p->pMapCsMainToCsTest ); - ABC_FREE( p->pMapCsTestToCsMain ); - ABC_FREE( p->pMapCsTestToNsTest ); - ABC_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 ); - ABC_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 = ABC_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 = (sat_solver *)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 = (sat_solver *)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 = (sat_solver *)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, (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)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), - (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)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; - // 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), - (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/fra/fraClaus.c b/src/aig/fra/fraClaus.c deleted file mode 100644 index 9548c166..00000000 --- a/src/aig/fra/fraClaus.c +++ /dev/null @@ -1,1875 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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; - // 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, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)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 = ABC_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, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); - ABC_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, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)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 = ABC_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 ); - } - ABC_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; -/* - // add the property - { - Aig_Obj_t * pObj; - int Lits[1]; - pObj = Aig_ManPo( p->pAig, 0 ); - Lits[0] = toLitCond( p->pCnf->pVarNums[pObj->Id], 1 ); - Vec_IntPush( p->vLits, Lits[0] ); - Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) ); - Vec_IntPush( p->vCosts, CostMax ); - nCountConst++; -// printf( "Added the target property to the set of clauses to be inductively checked.\n" ); - } -*/ - - 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 ); - Aig_ManRandom(1); - pSeq = Fra_SmlSimulateSeq( p->pAig, 0, p->nPref + p->nSimFrames, p->nSimWords/p->nSimFrames, 1 ); - if ( p->fTarget && pSeq->fNonConstOut ) - { - printf( "Property failed after sequential simulation!\n" ); - Fra_SmlStop( pSeq ); - return 0; - } -if ( p->fVerbose ) -{ -ABC_PRT( "Sim-seq", clock() - clk ); -} - - -clk = clock(); - if ( fRefs ) - { - Fra_ClausCollectLatchClauses( p, pSeq ); -if ( p->fVerbose ) -{ -ABC_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 ) -{ -ABC_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 ) -{ -ABC_PRT( "Infoseq", clock() - clk ); -} - Fra_SmlStop( pSeq ); - - // perform combinational simulation -clk = clock(); -// srand( 0xAABBAABB ); - Aig_ManRandom(1); - pComb = Fra_SmlSimulateComb( p->pAig, p->nSimWords + p->nSimWordsPref ); -if ( p->fVerbose ) -{ -ABC_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 ) -{ -ABC_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 ); - Aig_ManRandom(1); - pSeq = Fra_SmlSimulateSeq( p->pAig, 0, p->nPref + p->nSimFrames, p->nSimWords/p->nSimFrames, 1 ); - if ( p->fTarget && pSeq->fNonConstOut ) - { - printf( "Property failed after sequential simulation!\n" ); - Fra_SmlStop( pSeq ); - return 0; - } -if ( p->fVerbose ) -{ -//ABC_PRT( "Sim-seq", clock() - clk ); -} - - // perform combinational simulation -clk = clock(); -// srand( 0xAABBAABB ); - Aig_ManRandom(1); - pComb = Fra_SmlSimulateComb( p->pAig, p->nSimWords + p->nSimWordsPref ); -if ( p->fVerbose ) -{ -//ABC_PRT( "Sim-cmb", clock() - clk ); -} - - -clk = clock(); - if ( fRefs ) - { - Fra_ClausCollectLatchClauses( p, pSeq ); -if ( p->fVerbose ) -{ -//ABC_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 ) -{ -//ABC_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 ); - ABC_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; - int End = -1; // Suppress "might be used uninitialized" - int * pStart; - // reset the solver - if ( p->pSatMain ) sat_solver_delete( p->pSatMain ); - p->pSatMain = (sat_solver *)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, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)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, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)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( (unsigned *)Vec_PtrEntry(p->vCexes, i), p->nCexes ) == 0 ); - Aig_InfoSetBit( (unsigned *)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] = (unsigned *)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 = (sat_solver *)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, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)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 ); - Fra_ClausSimInfoRecord( p, (int*)p->pSatMain->model + 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 = ABC_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 ); - ABC_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 [Writes the clauses into an AIGER file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Fra_ClausGetLiteral( Clu_Man_t * p, int * pVar2Id, int Lit ) -{ - Aig_Obj_t * pLiteral; - int NodeId = pVar2Id[ lit_var(Lit) ]; - assert( NodeId >= 0 ); - pLiteral = (Aig_Obj_t *)Aig_ManObj( p->pAig, NodeId )->pData; - return Aig_NotCond( pLiteral, lit_sign(Lit) ); -} - -/**Function************************************************************* - - Synopsis [Writes the clauses into an AIGER file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ClausWriteIndClauses( Clu_Man_t * p ) -{ - extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact ); - Aig_Man_t * pNew; - Aig_Obj_t * pClause, * pLiteral; - char * pName; - int * pStart, * pVar2Id; - int Beg, End, i, k; - // create mapping from SAT vars to node IDs - pVar2Id = ABC_ALLOC( int, p->pCnf->nVars ); - memset( pVar2Id, 0xFF, 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; - } - // start the manager - pNew = Aig_ManDupWithoutPos( p->pAig ); - // add the clauses - Beg = 0; - pStart = Vec_IntArray( p->vLitsProven ); - Vec_IntForEachEntry( p->vClausesProven, End, i ) - { - pClause = Fra_ClausGetLiteral( p, pVar2Id, pStart[Beg] ); - for ( k = Beg + 1; k < End; k++ ) - { - pLiteral = Fra_ClausGetLiteral( p, pVar2Id, pStart[k] ); - pClause = Aig_Or( pNew, pClause, pLiteral ); - } - Aig_ObjCreatePo( pNew, pClause ); - Beg = End; - } - ABC_FREE( pVar2Id ); - Aig_ManCleanup( pNew ); - pName = Ioa_FileNameGenericAppend( p->pAig->pName, "_care.aig" ); - printf( "Care one-hotness clauses will be written into file \"%s\".\n", pName ); - Ioa_WriteAiger( pNew, pName, 0, 1 ); - Aig_ManStop( pNew ); -} - -/**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 ); - Aig_ManRandom(1); - pComb = Fra_SmlSimulateComb( p->pAig, nCombSimWords ); - // create mapping from SAT vars to node IDs - pVar2Id = ABC_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 ); - ABC_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 ); - ABC_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" ); -//ABC_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 ) -{ -//ABC_PRT( "CNF ", clock() - clk ); -} - - // check BMC -clk = clock(); - p->pSatBmc = (sat_solver *)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 ) -{ -//ABC_PRT( "SAT-bmc", clock() - clk ); -} - - // start the SAT solver -clk = clock(); - p->pSatMain = (sat_solver *)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 ) - { -// ABC_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; - - //ABC_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 ); - ABC_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" ); - ABC_PRT( "Time", clock() - clk ); - } - clk = clock(); - } - // add proved clauses to storage - Fra_ClausAddToStorage( p ); - // report the results - 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. " ); - ABC_PRT( "Time ", clock() - clkTotal ); - if ( !p->fFail ) - break; - } - else - { - printf( "Finished proving inductive clauses. " ); - ABC_PRT( "Time ", clock() - clkTotal ); - } - } - - // verify the computed interpolant - Fra_InvariantVerify( pAig, nFrames, p->vClausesProven, p->vLitsProven ); -// printf( "THIS COMMAND IS KNOWN TO HAVE A BUG!\n" ); - -// if ( !p->fTarget && p->fVerbose ) - if ( p->fVerbose ) - { - Fra_ClausPrintIndClauses( p ); - Fra_ClausEstimateCoverage( p ); - } - - if ( !p->fTarget ) - { - Fra_ClausWriteIndClauses( 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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/fra/fraCnf.c b/src/aig/fra/fraCnf.c deleted file mode 100644 index 5021e750..00000000 --- a/src/aig/fra/fraCnf.c +++ /dev/null @@ -1,289 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 = ABC_ALLOC( int, nLits ); - // suppose AND-gate is A & B = C - // add !A => !C or A + !C - Vec_PtrForEachEntry( Aig_Obj_t *, 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( Aig_Obj_t *, 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 ); - ABC_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( Aig_Obj_t *, 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( Aig_Obj_t *, vFanins, pFanin, k ) - Fra_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier ); - Fra_AddClausesMux( p, pNode ); - } - else - { - vFanins = Fra_CollectSuper( pNode, fUseMuxes ); - Vec_PtrForEachEntry( Aig_Obj_t *, 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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/fra/fraCore.c b/src/aig/fra/fraCore.c deleted file mode 100644 index d3b60ab7..00000000 --- a/src/aig/fra/fraCore.c +++ /dev/null @@ -1,490 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 refinement 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 is a primary input - if ( Aig_ObjIsPi(Aig_Regular(pChild)) && Aig_ObjPioNum(Aig_Regular(pChild)) < p->nTruePis ) - { - 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, NULL, NULL ); - 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( Aig_Obj_t *, p->pCla->vClasses1, pObj, i ) - { - if ( pObj->fPhase != pObj->fMarkB ) - printf( "The node %d is not constant under cex!\n", pObj->Id ); - } - Vec_PtrForEachEntry( Aig_Obj_t **, 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; - int nBTracksOld; - // 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) ); - nBTracksOld = p->pPars->nBTLimitNode; - 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; -// if ( Aig_SupportSize(p->pManAig,pObj) > 16 ) -// continue; - // perform fraiging - if ( p->pPars->nLevelMax && (int)pObj->Level > p->pPars->nLevelMax ) - p->pPars->nBTLimitNode = 5; - Fra_FraigNode( p, pObj ); - if ( p->pPars->nLevelMax && (int)pObj->Level > p->pPars->nLevelMax ) - p->pPars->nBTLimitNode = nBTracksOld; - // check implications - 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_ManDupOrdered(pManAig); -clk = clock(); - 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 -if ( p->pPars->fVerbose ) -Fra_ClassesPrint( p->pCla, 1 ); - Fra_FraigSweep( p ); - // call back the procedure to check implications - if ( pManAig->pImpFunc ) - pManAig->pImpFunc( p, pManAig->pImpData ); - // no need to filter one-hot clauses because they satisfy base case by construction - // 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 - { - Fra_ClassesCopyReprs( p->pCla, p->vTimeouts ); - 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, int nLevelMax ) -{ - 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; - pPars->nLevelMax = nLevelMax; - 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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/fra/fraHot.c b/src/aig/fra/fraHot.c deleted file mode 100644 index 29c9c33d..00000000 --- a/src/aig/fra/fraHot.c +++ /dev/null @@ -1,476 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraHot.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [New FRAIG package.] - - Synopsis [Computing and using one-hotness conditions.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 30, 2007.] - - Revision [$Id: fraHot.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fra.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline int Fra_RegToLit( int n, int c ) { return c? -n-1 : n+1; } -static inline int Fra_LitReg( int n ) { return (n>0)? n-1 : -n-1; } -static inline int Fra_LitSign( int n ) { return (n<0); } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns 1 if simulation info is composed of all zeros.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_OneHotNodeIsConst( 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 simulation infos are equal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_OneHotNodesAreEqual( Fra_Sml_t * pSeq, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) -{ - unsigned * pSims0, * pSims1; - int i; - pSims0 = Fra_ObjSim(pSeq, pObj0->Id); - pSims1 = Fra_ObjSim(pSeq, pObj1->Id); - for ( i = pSeq->nWordsPref; i < pSeq->nWordsTotal; i++ ) - if ( pSims0[i] != pSims1[i] ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if implications holds.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_OneHotNodesAreClause( Fra_Sml_t * pSeq, Aig_Obj_t * pObj1, Aig_Obj_t * pObj2, int fCompl1, int fCompl2 ) -{ - unsigned * pSim1, * pSim2; - int k; - pSim1 = Fra_ObjSim(pSeq, pObj1->Id); - pSim2 = Fra_ObjSim(pSeq, pObj2->Id); - if ( fCompl1 && fCompl2 ) - { - for ( k = pSeq->nWordsPref; k < pSeq->nWordsTotal; k++ ) - if ( pSim1[k] & pSim2[k] ) - return 0; - } - else if ( fCompl1 ) - { - for ( k = pSeq->nWordsPref; k < pSeq->nWordsTotal; k++ ) - if ( pSim1[k] & ~pSim2[k] ) - return 0; - } - else if ( fCompl2 ) - { - for ( k = pSeq->nWordsPref; k < pSeq->nWordsTotal; k++ ) - if ( ~pSim1[k] & pSim2[k] ) - return 0; - } - else - assert( 0 ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Computes one-hot implications.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Fra_OneHotCompute( Fra_Man_t * p, Fra_Sml_t * pSim ) -{ - int fSkipConstEqu = 1; - Vec_Int_t * vOneHots; - Aig_Obj_t * pObj1, * pObj2; - int i, k; - int nTruePis = Aig_ManPiNum(pSim->pAig) - Aig_ManRegNum(pSim->pAig); - assert( pSim->pAig == p->pManAig ); - vOneHots = Vec_IntAlloc( 100 ); - Aig_ManForEachLoSeq( pSim->pAig, pObj1, i ) - { - if ( fSkipConstEqu && Fra_OneHotNodeIsConst(pSim, pObj1) ) - continue; - assert( i-nTruePis >= 0 ); -// Aig_ManForEachLoSeq( pSim->pAig, pObj2, k ) -// Vec_PtrForEachEntryStart( Aig_Obj_t *, pSim->pAig->vPis, pObj2, k, Aig_ManPiNum(p)-Aig_ManRegNum(p) ) - Vec_PtrForEachEntryStart( Aig_Obj_t *, pSim->pAig->vPis, pObj2, k, i+1 ) - { - if ( fSkipConstEqu && Fra_OneHotNodeIsConst(pSim, pObj2) ) - continue; - if ( fSkipConstEqu && Fra_OneHotNodesAreEqual( pSim, pObj1, pObj2 ) ) - continue; - assert( k-nTruePis >= 0 ); - if ( Fra_OneHotNodesAreClause( pSim, pObj1, pObj2, 1, 1 ) ) - { - Vec_IntPush( vOneHots, Fra_RegToLit(i-nTruePis, 1) ); - Vec_IntPush( vOneHots, Fra_RegToLit(k-nTruePis, 1) ); - continue; - } - if ( Fra_OneHotNodesAreClause( pSim, pObj1, pObj2, 0, 1 ) ) - { - Vec_IntPush( vOneHots, Fra_RegToLit(i-nTruePis, 0) ); - Vec_IntPush( vOneHots, Fra_RegToLit(k-nTruePis, 1) ); - continue; - } - if ( Fra_OneHotNodesAreClause( pSim, pObj1, pObj2, 1, 0 ) ) - { - Vec_IntPush( vOneHots, Fra_RegToLit(i-nTruePis, 1) ); - Vec_IntPush( vOneHots, Fra_RegToLit(k-nTruePis, 0) ); - continue; - } - } - } - return vOneHots; -} - -/**Function************************************************************* - - Synopsis [Assumes one-hot implications in the SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -**********************************************************************/ -void Fra_OneHotAssume( Fra_Man_t * p, Vec_Int_t * vOneHots ) -{ - Aig_Obj_t * pObj1, * pObj2; - int i, Out1, Out2, pLits[2]; - int nPiNum = Aig_ManPiNum(p->pManFraig) - Aig_ManRegNum(p->pManFraig); - assert( p->pPars->nFramesK == 1 ); // add to only one frame - for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 ) - { - Out1 = Vec_IntEntry( vOneHots, i ); - Out2 = Vec_IntEntry( vOneHots, i+1 ); - if ( Out1 == 0 && Out2 == 0 ) - continue; - pObj1 = Aig_ManPi( p->pManFraig, nPiNum + Fra_LitReg(Out1) ); - pObj2 = Aig_ManPi( p->pManFraig, nPiNum + Fra_LitReg(Out2) ); - pLits[0] = toLitCond( Fra_ObjSatNum(pObj1), Fra_LitSign(Out1) ); - pLits[1] = toLitCond( Fra_ObjSatNum(pObj2), Fra_LitSign(Out2) ); - // add constraint to solver - if ( !sat_solver_addclause( p->pSat, pLits, pLits + 2 ) ) - { - printf( "Fra_OneHotAssume(): Adding clause makes SAT solver unsat.\n" ); - sat_solver_delete( p->pSat ); - p->pSat = NULL; - return; - } - } -} - -/**Function************************************************************* - - Synopsis [Checks one-hot implications.] - - Description [] - - SideEffects [] - - SeeAlso [] - -**********************************************************************/ -void Fra_OneHotCheck( Fra_Man_t * p, Vec_Int_t * vOneHots ) -{ - Aig_Obj_t * pObj1, * pObj2; - int RetValue, i, Out1, Out2; - int nTruePos = Aig_ManPoNum(p->pManFraig) - Aig_ManRegNum(p->pManFraig); - for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 ) - { - Out1 = Vec_IntEntry( vOneHots, i ); - Out2 = Vec_IntEntry( vOneHots, i+1 ); - if ( Out1 == 0 && Out2 == 0 ) - continue; - pObj1 = Aig_ManPo( p->pManFraig, nTruePos + Fra_LitReg(Out1) ); - pObj2 = Aig_ManPo( p->pManFraig, nTruePos + Fra_LitReg(Out2) ); - RetValue = Fra_NodesAreClause( p, pObj1, pObj2, Fra_LitSign(Out1), Fra_LitSign(Out2) ); - if ( RetValue != 1 ) - { - p->pCla->fRefinement = 1; - if ( RetValue == 0 ) - Fra_SmlResimulate( p ); - if ( Vec_IntEntry(vOneHots, i) != 0 ) - printf( "Fra_OneHotCheck(): Clause is not refined!\n" ); - assert( Vec_IntEntry(vOneHots, i) == 0 ); - } - } -} - -/**Function************************************************************* - - Synopsis [Removes those implications that no longer hold.] - - Description [Returns 1 if refinement has happened.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_OneHotRefineUsingCex( Fra_Man_t * p, Vec_Int_t * vOneHots ) -{ - Aig_Obj_t * pObj1, * pObj2; - int i, Out1, Out2, RetValue = 0; - int nPiNum = Aig_ManPiNum(p->pManAig) - Aig_ManRegNum(p->pManAig); - assert( p->pSml->pAig == p->pManAig ); - for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 ) - { - Out1 = Vec_IntEntry( vOneHots, i ); - Out2 = Vec_IntEntry( vOneHots, i+1 ); - if ( Out1 == 0 && Out2 == 0 ) - continue; - // get the corresponding nodes - pObj1 = Aig_ManPi( p->pManAig, nPiNum + Fra_LitReg(Out1) ); - pObj2 = Aig_ManPi( p->pManAig, nPiNum + Fra_LitReg(Out2) ); - // check if implication holds using this simulation info - if ( !Fra_OneHotNodesAreClause( p->pSml, pObj1, pObj2, Fra_LitSign(Out1), Fra_LitSign(Out2) ) ) - { - Vec_IntWriteEntry( vOneHots, i, 0 ); - Vec_IntWriteEntry( vOneHots, i+1, 0 ); - RetValue = 1; - } - } - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Removes those implications that no longer hold.] - - Description [Returns 1 if refinement has happened.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_OneHotCount( Fra_Man_t * p, Vec_Int_t * vOneHots ) -{ - int i, Out1, Out2, Counter = 0; - for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 ) - { - Out1 = Vec_IntEntry( vOneHots, i ); - Out2 = Vec_IntEntry( vOneHots, i+1 ); - if ( Out1 == 0 && Out2 == 0 ) - continue; - Counter++; - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Estimates the coverage of state space by clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_OneHotEstimateCoverage( Fra_Man_t * p, Vec_Int_t * vOneHots ) -{ - int nSimWords = (1<<14); - int nRegs = Aig_ManRegNum(p->pManAig); - Vec_Ptr_t * vSimInfo; - unsigned * pSim1, * pSim2, * pSimTot; - int i, w, Out1, Out2, nCovered, Counter = 0; - int clk = clock(); - - // generate random sim-info at register outputs - vSimInfo = Vec_PtrAllocSimInfo( nRegs + 1, nSimWords ); -// srand( 0xAABBAABB ); - Aig_ManRandom(1); - for ( i = 0; i < nRegs; i++ ) - { - pSim1 = (unsigned *)Vec_PtrEntry( vSimInfo, i ); - for ( w = 0; w < nSimWords; w++ ) - pSim1[w] = Fra_ObjRandomSim(); - } - pSimTot = (unsigned *)Vec_PtrEntry( vSimInfo, nRegs ); - - // collect simulation info - memset( pSimTot, 0, sizeof(unsigned) * nSimWords ); - for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 ) - { - Out1 = Vec_IntEntry( vOneHots, i ); - Out2 = Vec_IntEntry( vOneHots, i+1 ); - if ( Out1 == 0 && Out2 == 0 ) - continue; -//printf( "(%c%d,%c%d) ", -//Fra_LitSign(Out1)? '-': '+', Fra_LitReg(Out1), -//Fra_LitSign(Out2)? '-': '+', Fra_LitReg(Out2) ); - Counter++; - pSim1 = (unsigned *)Vec_PtrEntry( vSimInfo, Fra_LitReg(Out1) ); - pSim2 = (unsigned *)Vec_PtrEntry( vSimInfo, Fra_LitReg(Out2) ); - if ( Fra_LitSign(Out1) && Fra_LitSign(Out2) ) - for ( w = 0; w < nSimWords; w++ ) - pSimTot[w] |= pSim1[w] & pSim2[w]; - else if ( Fra_LitSign(Out1) ) - for ( w = 0; w < nSimWords; w++ ) - pSimTot[w] |= pSim1[w] & ~pSim2[w]; - else if ( Fra_LitSign(Out2) ) - for ( w = 0; w < nSimWords; w++ ) - pSimTot[w] |= ~pSim1[w] & pSim2[w]; - else - assert( 0 ); - } -//printf( "\n" ); - // count the total number of patterns contained in the don't-care - nCovered = 0; - for ( w = 0; w < nSimWords; w++ ) - nCovered += Aig_WordCountOnes( pSimTot[w] ); - Vec_PtrFree( vSimInfo ); - // print the result - printf( "Care states ratio = %f. ", 1.0 * (nSimWords * 32 - nCovered) / (nSimWords * 32) ); - printf( "(%d out of %d patterns) ", nSimWords * 32 - nCovered, nSimWords * 32 ); - ABC_PRT( "Time", clock() - clk ); -} - -/**Function************************************************************* - - Synopsis [Creates one-hotness EXDC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Fra_OneHotCreateExdc( Fra_Man_t * p, Vec_Int_t * vOneHots ) -{ - Aig_Man_t * pNew; - Aig_Obj_t * pObj1, * pObj2, * pObj; - int i, Out1, Out2, nTruePis; - pNew = Aig_ManStart( Vec_IntSize(vOneHots)/2 ); -// for ( i = 0; i < Aig_ManRegNum(p->pManAig); i++ ) -// Aig_ObjCreatePi(pNew); - Aig_ManForEachPi( p->pManAig, pObj, i ) - Aig_ObjCreatePi(pNew); - nTruePis = Aig_ManPiNum(p->pManAig) - Aig_ManRegNum(p->pManAig); - for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 ) - { - Out1 = Vec_IntEntry( vOneHots, i ); - Out2 = Vec_IntEntry( vOneHots, i+1 ); - if ( Out1 == 0 && Out2 == 0 ) - continue; - pObj1 = Aig_ManPi( pNew, nTruePis + Fra_LitReg(Out1) ); - pObj2 = Aig_ManPi( pNew, nTruePis + Fra_LitReg(Out2) ); - pObj1 = Aig_NotCond( pObj1, Fra_LitSign(Out1) ); - pObj2 = Aig_NotCond( pObj2, Fra_LitSign(Out2) ); - pObj = Aig_Or( pNew, pObj1, pObj2 ); - Aig_ObjCreatePo( pNew, pObj ); - } - Aig_ManCleanup(pNew); -// printf( "Created AIG with %d nodes and %d outputs.\n", Aig_ManNodeNum(pNew), Aig_ManPoNum(pNew) ); - return pNew; -} - - -/**Function************************************************************* - - Synopsis [Assumes one-hot implications in the SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -**********************************************************************/ -void Fra_OneHotAddKnownConstraint( Fra_Man_t * p, Vec_Ptr_t * vOnehots ) -{ - Vec_Int_t * vGroup; - Aig_Obj_t * pObj1, * pObj2; - int k, i, j, Out1, Out2, pLits[2]; - // - // these constrants should be added to different timeframes! - // (also note that PIs follow first - then registers) - // - Vec_PtrForEachEntry( Vec_Int_t *, vOnehots, vGroup, k ) - { - Vec_IntForEachEntry( vGroup, Out1, i ) - Vec_IntForEachEntryStart( vGroup, Out2, j, i+1 ) - { - pObj1 = Aig_ManPi( p->pManFraig, Out1 ); - pObj2 = Aig_ManPi( p->pManFraig, Out2 ); - pLits[0] = toLitCond( Fra_ObjSatNum(pObj1), 1 ); - pLits[1] = toLitCond( Fra_ObjSatNum(pObj2), 1 ); - // add constraint to solver - if ( !sat_solver_addclause( p->pSat, pLits, pLits + 2 ) ) - { - printf( "Fra_OneHotAddKnownConstraint(): Adding clause makes SAT solver unsat.\n" ); - sat_solver_delete( p->pSat ); - p->pSat = NULL; - return; - } - } - } -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/fra/fraImp.c b/src/aig/fra/fraImp.c deleted file mode 100644 index 34fa87e5..00000000 --- a/src/aig/fra/fraImp.c +++ /dev/null @@ -1,731 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 = ABC_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 = ABC_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 = ABC_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 = (int *)Vec_PtrEntry( vNodes, pnBits[i] ); - pMemory[ pnNodes[pnBits[i]]++ ] = i; - } - // add 0s in the end - nTotal = 0; - Vec_PtrForEachEntry( int *, vNodes, pMemory, i ) - { - pMemory[ pnNodes[i]++ ] = 0; - nTotal += pnNodes[i]; - } - assert( nTotal == nNodes + nBits + 1 ); - ABC_FREE( pnNodes ); - ABC_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 = ABC_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; - } - ABC_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 = ABC_MAX( pImp1[0], pImp1[1] ); - int Max2 = ABC_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 = ABC_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, 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 = (int *)Vec_PtrEntry( vNodes, i ); *pNodesI; pNodesI++ ) - for ( pNodesK = (int *)Vec_PtrEntry( vNodes, k ); *pNodesK; pNodesK++ ) - nImpsTotal++; - - // compute implications and their costs - pImpCosts = ABC_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 = (int *)Vec_PtrEntry( vNodes, i ); *pNodesI; pNodesI++ ) - for ( pNodesK = (int *)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 = ABC_MIN( CostMin, pImpCosts[ Vec_IntSize(vImps) ] ); - CostMax = ABC_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 - ABC_FREE( pImpCosts ); - { - void * pTemp = Vec_PtrEntry(vNodes, 0); - ABC_FREE( pTemp ); - } - 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 ); -ABC_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 constraint 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 = ABC_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, 1 ); - // go through the implications and check how many of them do not hold - pfFails = ABC_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]; - ABC_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((Aig_Obj_t *)pLeft->pData, !pLeft->fPhase), - Aig_NotCond((Aig_Obj_t *)pRight->pData, pRight->fPhase) ); - Aig_ObjCreatePo( pNew, pMiter ); - } - pNew->nAsserts = Aig_ManPoNum(pNew) - nPosOld; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/fra/fraInd.c b/src/aig/fra/fraInd.c deleted file mode 100644 index 2f2d8f2d..00000000 --- a/src/aig/fra/fraInd.c +++ /dev/null @@ -1,709 +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" -#include "saig.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs AIG rewriting on the constraint 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", NULL, NULL ); -//Aig_ManDumpBlif( pTemp, "2.blif", NULL, NULL ); -// 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, pObjNew, pObjReprNew ); - pMiter = Aig_NotCond( pMiter, !Aig_ObjPhaseReal(pMiter) ); - assert( Aig_ObjPhaseReal(pMiter) == 1 ); - 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->pSpec = Aig_UtilStrsav( p->pManAig->pSpec ); - 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 = ABC_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; - } - } - ABC_FREE( pLatches ); -} - - -/**Function************************************************************* - - Synopsis [Performs partitioned sequential SAT sweepingG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Fra_FraigInductionPart( Aig_Man_t * pAig, Fra_Ssw_t * pPars ) -{ - int fPrintParts = 0; - char Buffer[100]; - Aig_Man_t * pTemp, * pNew; - Vec_Ptr_t * vResult; - Vec_Int_t * vPart; - int * pMapBack; - int i, nCountPis, nCountRegs; - int nClasses, nPartSize, fVerbose; - int clk = clock(); - - // save parameters - nPartSize = pPars->nPartSize; pPars->nPartSize = 0; - fVerbose = pPars->fVerbose; pPars->fVerbose = 0; - // generate partitions - if ( pAig->vClockDoms ) - { - // divide large clock domains into separate partitions - vResult = Vec_PtrAlloc( 100 ); - Vec_PtrForEachEntry( Vec_Int_t *, (Vec_Ptr_t *)pAig->vClockDoms, vPart, i ) - { - if ( nPartSize && Vec_IntSize(vPart) > nPartSize ) - Aig_ManPartDivide( vResult, vPart, nPartSize, pPars->nOverSize ); - else - Vec_PtrPush( vResult, Vec_IntDup(vPart) ); - } - } - else - vResult = Aig_ManRegPartitionSimple( pAig, nPartSize, pPars->nOverSize ); -// vResult = Aig_ManPartitionSmartRegisters( pAig, nPartSize, 0 ); -// vResult = Aig_ManRegPartitionSmart( pAig, nPartSize ); - if ( fPrintParts ) - { - // print partitions - printf( "Simple partitioning. %d partitions are saved:\n", Vec_PtrSize(vResult) ); - Vec_PtrForEachEntry( Vec_Int_t *, vResult, vPart, i ) - { - sprintf( Buffer, "part%03d.aig", i ); - pTemp = Aig_ManRegCreatePart( pAig, vPart, &nCountPis, &nCountRegs, NULL ); - Ioa_WriteAiger( pTemp, Buffer, 0, 0 ); - printf( "part%03d.aig : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d.\n", - i, Vec_IntSize(vPart), Aig_ManPiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Aig_ManNodeNum(pTemp) ); - Aig_ManStop( pTemp ); - } - } - - // perform SSW with partitions - Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) ); - Vec_PtrForEachEntry( Vec_Int_t *, vResult, vPart, i ) - { - pTemp = Aig_ManRegCreatePart( pAig, vPart, &nCountPis, &nCountRegs, &pMapBack ); - // create the projection of 1-hot registers - if ( pAig->vOnehots ) - pTemp->vOnehots = Aig_ManRegProjectOnehots( pAig, pTemp, pAig->vOnehots, fVerbose ); - // run SSW - pNew = Fra_FraigInduction( pTemp, pPars ); - nClasses = Aig_TransferMappedClasses( pAig, pTemp, pMapBack ); - if ( fVerbose ) - printf( "%3d : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d. It = %3d. Cl = %5d.\n", - i, Vec_IntSize(vPart), Aig_ManPiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Aig_ManNodeNum(pTemp), pPars->nIters, nClasses ); - Aig_ManStop( pNew ); - Aig_ManStop( pTemp ); - ABC_FREE( pMapBack ); - } - // remap the AIG - pNew = Aig_ManDupRepr( pAig, 0 ); - Aig_ManSeqCleanup( pNew ); -// Aig_ManPrintStats( pAig ); -// Aig_ManPrintStats( pNew ); - Vec_VecFree( (Vec_Vec_t *)vResult ); - pPars->nPartSize = nPartSize; - pPars->fVerbose = fVerbose; - if ( fVerbose ) - { - ABC_PRT( "Total time", clock() - clk ); - } - return pNew; -} - -/**Function************************************************************* - - Synopsis [Performs sequential SAT sweeping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Fra_FraigInduction( Aig_Man_t * pManAig, Fra_Ssw_t * pParams ) -{ - 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 = NULL; - int nNodesBeg, nRegsBeg; - int nIter = -1; // Suppress "might be used uninitialized" - int i, clk = clock(), clk2; - int TimeToStop = (pParams->TimeLimit == 0.0)? 0 : clock() + (int)(pParams->TimeLimit * CLOCKS_PER_SEC); - - if ( Aig_ManNodeNum(pManAig) == 0 ) - { - pParams->nIters = 0; - // Ntl_ManFinalize() needs the following to satisfy an assertion - Aig_ManReprStart(pManAig,Aig_ManObjNumMax(pManAig)); - return Aig_ManDupOrdered(pManAig); - } - assert( Aig_ManRegNum(pManAig) > 0 ); - assert( pParams->nFramesK > 0 ); -//Aig_ManShow( pManAig, 0, NULL ); - - if ( pParams->fWriteImps && pParams->nPartSize > 0 ) - { - pParams->nPartSize = 0; - printf( "Partitioning was disabled to allow implication writing.\n" ); - } - // perform partitioning - if ( (pParams->nPartSize > 0 && pParams->nPartSize < Aig_ManRegNum(pManAig)) - || (pManAig->vClockDoms && Vec_VecSize(pManAig->vClockDoms) > 0) ) - return Fra_FraigInductionPart( pManAig, pParams ); - - 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 = pParams->nFramesP; - pPars->nFramesK = pParams->nFramesK; - pPars->nMaxImps = pParams->nMaxImps; - pPars->nMaxLevs = pParams->nMaxLevs; - pPars->fVerbose = pParams->fVerbose; - pPars->fRewrite = pParams->fRewrite; - pPars->fLatchCorr = pParams->fLatchCorr; - pPars->fUseImps = pParams->fUseImps; - pPars->fWriteImps = pParams->fWriteImps; - pPars->fUse1Hot = pParams->fUse1Hot; - - assert( !(pPars->nFramesP > 0 && pPars->fUse1Hot) ); - assert( !(pPars->nFramesK > 1 && pPars->fUse1Hot) ); - - // start the fraig manager for this run - p = Fra_ManStart( pManAig, pPars ); - p->pPars->nBTLimitNode = 0; - // 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 ( pPars->fVerbose ) -printf( "Simulating %d AIG nodes for %d cycles ... ", Aig_ManNodeNum(pManAig), pPars->nFramesP + 32 ); - p->pSml = Fra_SmlSimulateSeq( pManAig, pPars->nFramesP, 32, 1, 1 ); //pPars->nFramesK + 1, 1 ); -if ( pPars->fVerbose ) -{ -ABC_PRT( "Time", clock() - clk ); -} - Fra_ClassesPrepare( p->pCla, p->pPars->fLatchCorr, p->pPars->nMaxLevs ); -// Fra_ClassesPostprocess( p->pCla ); - // compute one-hotness conditions - if ( p->pPars->fUse1Hot ) - p->vOneHots = Fra_OneHotCompute( p, p->pSml ); - // 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 ); - - if ( pParams->TimeLimit != 0.0 && clock() > TimeToStop ) - { - if ( !pParams->fSilent ) - printf( "Fra_FraigInduction(): Runtime limit exceeded.\n" ); - goto finish; - } - - // 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", NULL, NULL ); -// 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; - int nHotsOld = p->vOneHots? Fra_OneHotCount(p, p->vOneHots) : 0; - int clk3 = clock(); - - if ( pParams->TimeLimit != 0.0 && clock() > TimeToStop ) - { - if ( !pParams->fSilent ) - printf( "Fra_FraigInduction(): Runtime limit exceeded.\n" ); - goto finish; - } - - // 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", NULL, NULL ); - - // 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_DataTranformPolarity( pCnf, 0 ); -//Cnf_DataWriteIntoFile( pCnf, "temp.cnf", 1 ); - - p->pSat = (sat_solver *)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, (Vec_Ptr_t *)1 ); - } - Cnf_DataFree( pCnf ); - - // add one-hotness clauses - if ( p->pPars->fUse1Hot ) - Fra_OneHotAssume( p, p->vOneHots ); -// if ( p->pManAig->vOnehots ) -// Fra_OneHotAddKnownConstraint( p, p->pManAig->vOnehots ); - - // report the intermediate results - if ( pPars->fVerbose ) - { - printf( "%3d : C = %6d. Cl = %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) ); - if ( p->pPars->fUse1Hot ) - printf( "1h = %6d. ", Fra_OneHotCount(p, p->vOneHots) ); - printf( "NR = %6d. ", Aig_ManNodeNum(p->pManFraig) ); -// printf( "\n" ); - } - - // perform sweeping - p->nSatCallsRecent = 0; - p->nSatCallsSkipped = 0; -clk2 = clock(); - if ( p->pPars->fUse1Hot ) - Fra_OneHotCheck( p, p->vOneHots ); - Fra_FraigSweep( p ); - if ( pPars->fVerbose ) - { - ABC_PRT( "T", clock() - clk3 ); - } - -// Sat_SolverPrintStats( stdout, p->pSat ); - // remove FRAIG and SAT solver - Aig_ManStop( p->pManFraig ); p->pManFraig = NULL; -// printf( "Vars = %d. Clauses = %d. Learnts = %d.\n", p->pSat->size, p->pSat->clauses.size, p->pSat->learnts.size ); - 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) && - nHotsOld == (p->vOneHots? Fra_OneHotCount(p, p->vOneHots) : 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) ); - ABC_PRT( "Time", clock() - clk ); - } -*/ - - // move the classes into representatives and reduce AIG -clk2 = clock(); - if ( p->pPars->fWriteImps && p->vOneHots && Fra_OneHotCount(p, p->vOneHots) ) - { - extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact ); - Aig_Man_t * pNew; - char * pFileName = Ioa_FileNameGenericAppend( p->pManAig->pName, "_care.aig" ); - printf( "Care one-hotness clauses will be written into file \"%s\".\n", pFileName ); - pManAigNew = Aig_ManDupOrdered( pManAig ); - pNew = Fra_OneHotCreateExdc( p, p->vOneHots ); - Ioa_WriteAiger( pNew, pFileName, 0, 1 ); - Aig_ManStop( pNew ); - } - else - { - // 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 ); - // remove pointers to the dead nodes -// Aig_ManForEachObj( pManAig, pObj, i ) -// if ( pObj->pData && Aig_ObjIsNone(pObj->pData) ) -// pObj->pData = NULL; -// 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 -finish: - 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" ); - pParams->nIters = nIter; - return pManAigNew; -} - -/**Function************************************************************* - - Synopsis [Outputs a set of pairs of equivalent nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_FraigInductionTest( char * pFileName, Fra_Ssw_t * pParams ) -{ - FILE * pFile; - char * pFilePairs; - Aig_Man_t * pMan, * pNew; - Aig_Obj_t * pObj, * pRepr; - int * pNum2Id; - int i, Counter = 0; - pMan = Saig_ManReadBlif( pFileName ); - if ( pMan == NULL ) - return 0; - // perform seq SAT sweeping - pNew = Fra_FraigInduction( pMan, pParams ); - if ( pNew == NULL ) - { - Aig_ManStop( pMan ); - return 0; - } - if ( pParams->fVerbose ) - { - printf( "Original AIG: " ); - Aig_ManPrintStats( pMan ); - printf( "Reduced AIG: " ); - Aig_ManPrintStats( pNew ); - } - Aig_ManStop( pNew ); - pNum2Id = (int *)pMan->pData; - // write the output file - pFilePairs = Aig_FileNameGenericAppend( pFileName, ".pairs" ); - pFile = fopen( pFilePairs, "w" ); - Aig_ManForEachObj( pMan, pObj, i ) - if ( (pRepr = pMan->pReprs[pObj->Id]) ) - { - fprintf( pFile, "%d %d %c\n", pNum2Id[pObj->Id], pNum2Id[pRepr->Id], (Aig_ObjPhase(pObj) ^ Aig_ObjPhase(pRepr))? '-' : '+' ); - Counter++; - } - fclose( pFile ); - if ( pParams->fVerbose ) - { - printf( "Result: %d pairs of seq equiv nodes are written into file \"%s\".\n", Counter, pFilePairs ); - } - Aig_ManStop( pMan ); - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/fra/fraIndVer.c b/src/aig/fra/fraIndVer.c deleted file mode 100644 index 32069cfb..00000000 --- a/src/aig/fra/fraIndVer.c +++ /dev/null @@ -1,166 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraIndVer.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [New FRAIG package.] - - Synopsis [Verification of the inductive invariant.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 30, 2007.] - - Revision [$Id: fraIndVer.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fra.h" -#include "cnf.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Verifies the inductive invariant.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_InvariantVerify( Aig_Man_t * pAig, int nFrames, Vec_Int_t * vClauses, Vec_Int_t * vLits ) -{ - Cnf_Dat_t * pCnf; - sat_solver * pSat; - int * pStart; - int RetValue, Beg, End, i, k; - int CounterBase = 0, CounterInd = 0; - int clk = clock(); - - if ( nFrames != 1 ) - { - printf( "Invariant verification: Can only verify for K = 1\n" ); - return 1; - } - - // derive CNF - pCnf = Cnf_DeriveSimple( pAig, Aig_ManPoNum(pAig) ); -/* - // add the property - { - Aig_Obj_t * pObj; - int Lits[1]; - - pObj = Aig_ManPo( pAig, 0 ); - Lits[0] = toLitCond( pCnf->pVarNums[pObj->Id], 1 ); - - Vec_IntPush( vLits, Lits[0] ); - Vec_IntPush( vClauses, Vec_IntSize(vLits) ); - printf( "Added the target property to the set of clauses to be inductively checked.\n" ); - } -*/ - // derive initialized frames for the base case - pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, nFrames, 1 ); - // check clauses in the base case - Beg = 0; - pStart = Vec_IntArray( vLits ); - Vec_IntForEachEntry( vClauses, End, i ) - { - // complement the literals - for ( k = Beg; k < End; k++ ) - pStart[k] = lit_neg(pStart[k]); - RetValue = sat_solver_solve( pSat, pStart + Beg, pStart + End, 0, 0, 0, 0 ); - for ( k = Beg; k < End; k++ ) - pStart[k] = lit_neg(pStart[k]); - Beg = End; - if ( RetValue == l_False ) - continue; -// printf( "Clause %d failed the base case.\n", i ); - CounterBase++; - } - sat_solver_delete( pSat ); - - // derive initialized frames for the base case - pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, nFrames + 1, 0 ); - assert( pSat->size == 2 * pCnf->nVars ); - // add clauses to the first frame - Beg = 0; - pStart = Vec_IntArray( vLits ); - Vec_IntForEachEntry( vClauses, End, i ) - { - RetValue = sat_solver_addclause( pSat, pStart + Beg, pStart + End ); - Beg = End; - if ( RetValue == 0 ) - { - Cnf_DataFree( pCnf ); - sat_solver_delete( pSat ); - printf( "Invariant verification: SAT solver is unsat after adding a clause.\n" ); - return 0; - } - } - // simplify the solver - if ( pSat->qtail != pSat->qhead ) - { - RetValue = sat_solver_simplify(pSat); - assert( RetValue != 0 ); - assert( pSat->qtail == pSat->qhead ); - } - - // check clauses in the base case - Beg = 0; - pStart = Vec_IntArray( vLits ); - Vec_IntForEachEntry( vClauses, End, i ) - { - // complement the literals - for ( k = Beg; k < End; k++ ) - { - pStart[k] += 2 * pCnf->nVars; - pStart[k] = lit_neg(pStart[k]); - } - RetValue = sat_solver_solve( pSat, pStart + Beg, pStart + End, 0, 0, 0, 0 ); - for ( k = Beg; k < End; k++ ) - { - pStart[k] = lit_neg(pStart[k]); - pStart[k] -= 2 * pCnf->nVars; - } - Beg = End; - if ( RetValue == l_False ) - continue; -// printf( "Clause %d failed the inductive case.\n", i ); - CounterInd++; - } - sat_solver_delete( pSat ); - Cnf_DataFree( pCnf ); - if ( CounterBase ) - printf( "Invariant verification: %d clauses (out of %d) FAILED the base case.\n", CounterBase, Vec_IntSize(vClauses) ); - if ( CounterInd ) - printf( "Invariant verification: %d clauses (out of %d) FAILED the inductive case.\n", CounterInd, Vec_IntSize(vClauses) ); - if ( CounterBase || CounterInd ) - return 0; - printf( "Invariant verification: %d clauses verified correctly. ", Vec_IntSize(vClauses) ); - ABC_PRT( "Time", clock() - clk ); - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/fra/fraLcr.c b/src/aig/fra/fraLcr.c deleted file mode 100644 index b18a8fcd..00000000 --- a/src/aig/fra/fraLcr.c +++ /dev/null @@ -1,709 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 = ABC_ALLOC( Fra_Lcr_t, 1 ); - memset( p, 0, sizeof(Fra_Lcr_t) ); - p->pAig = pAig; - p->pInToOutPart = ABC_ALLOC( int, Aig_ManPiNum(pAig) ); - memset( p->pInToOutPart, 0, sizeof(int) * Aig_ManPiNum(pAig) ); - p->pInToOutNum = ABC_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 ); - ABC_PRT( "AIG simulation ", p->timeSim ); - ABC_PRT( "AIG partitioning", p->timePart ); - ABC_PRT( "AIG rebuiding ", p->timeTrav ); - ABC_PRT( "FRAIGing ", p->timeFraig ); - ABC_PRT( "AIG updating ", p->timeUpdate ); - ABC_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 ); - ABC_FREE( p->pInToOutPart ); - ABC_FREE( p->pInToOutNum ); - ABC_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 = ABC_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 = (Fra_Man_t *)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 = (Aig_Man_t *)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 = (Fra_Man_t *)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 = (Aig_Man_t *)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 [Duplicates the AIG manager recursively.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Fra_LcrManDup_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - Aig_Obj_t * pObjNew; - if ( pObj->pData ) - return (Aig_Obj_t *)pObj->pData; - Fra_LcrManDup_rec( pNew, p, Aig_ObjFanin0(pObj) ); - if ( Aig_ObjIsBuf(pObj) ) - return (Aig_Obj_t *)(pObj->pData = Aig_ObjChild0Copy(pObj)); - Fra_LcrManDup_rec( pNew, p, Aig_ObjFanin1(pObj) ); - pObjNew = Aig_Oper( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj), Aig_ObjType(pObj) ); - Aig_Regular(pObjNew)->pHaig = pObj->pHaig; - return (Aig_Obj_t *)(pObj->pData = pObjNew); -} - -/**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( Aig_Obj_t **, 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 = Fra_LcrManDup_rec( pNew, pLcr->pAig, Aig_ObjFanin0(pObjPo) ); - pMiter = Aig_Exor( pNew, pMiter, pObjNew ); - } - Aig_ObjCreatePo( pNew, pMiter ); - } - // go over the constant candidates - Vec_PtrForEachEntry( Aig_Obj_t *, pLcr->pCla->vClasses1, pObj, i ) - { - assert( Aig_ObjIsPi(pObj) ); - pObjPo = Aig_ManPo( pLcr->pAig, Offset+(long)pObj->pNext ); - pMiter = Fra_LcrManDup_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( Vec_Int_t *, vParts, vOne, i ) - { - vOneNew = Vec_IntAlloc( Vec_IntSize(vOne) ); - Vec_IntForEachEntry( vOne, Out, k ) - { - if ( Out < Vec_PtrSize(pCla->vClasses) ) - { - ppClass = (Aig_Obj_t **)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 = (Aig_Obj_t *)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 (Aig_Obj_t *)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( (Aig_Obj_t *)pObj->pData, pRepr->fPhase ^ pObj->fPhase ); - } - return (Aig_Obj_t *)pObj->pData; - } - Fra_LcrCreatePart_rec( pCla, pNew, p, Aig_ObjFanin0(pObj) ); - Fra_LcrCreatePart_rec( pCla, pNew, p, Aig_ObjFanin1(pObj) ); - return (Aig_Obj_t *)(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( Aig_Obj_t *, p->pCla->vClasses1, pObj, i ) - { - pObj = Aig_ManPo( p->pCla->pAig, Offset+(long)pObj->pNext ); - pObj->fMarkA = 1; - } - Vec_PtrForEachEntry( Aig_Obj_t **, 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( Aig_Obj_t *, p->pCla->vClasses1, pObj, i ) - { - pObj = Aig_ManPo( p->pCla->pAig, Offset+(long)pObj->pNext ); - pObj->fMarkA = 0; - } - Vec_PtrForEachEntry( Aig_Obj_t **, 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, float TimeLimit ) -{ - int nPartSize = 200; - int fReprSelect = 0; - Fra_Lcr_t * p; - Fra_Sml_t * pSml; - Fra_Man_t * pTemp; - Aig_Man_t * pAigPart, * pAigTemp, * pAigNew = NULL; - Vec_Int_t * vPart; - int i, nIter, timeSim, clk = clock(), clk2, clk3; - int TimeToStop = (TimeLimit == 0.0)? 0 : clock() + (int)(TimeLimit * CLOCKS_PER_SEC); - if ( Aig_ManNodeNum(pAig) == 0 ) - { - if ( pnIter ) *pnIter = 0; - // Ntl_ManFinalize() requires the following to satisfy an assertion. - Aig_ManReprStart(pAig,Aig_ManObjNumMax(pAig)); - return Aig_ManDupOrdered(pAig); - } - 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, 1 ); -if ( fVerbose ) -{ -ABC_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 ) -{ -ABC_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( Vec_Int_t *, p->vParts, vPart, i ) - { - int clk3 = clock(); - if ( TimeLimit != 0.0 && clock() > TimeToStop ) - { - Vec_PtrForEachEntry( Aig_Man_t *, p->vFraigs, pAigPart, i ) - Aig_ManStop( pAigPart ); - Aig_ManCleanMarkA( pAig ); - Aig_ManCleanMarkB( pAig ); - printf( "Fra_FraigLatchCorrespondence(): Runtime limit exceeded.\n" ); - goto finish; - } -clk2 = clock(); - pAigPart = Fra_LcrCreatePart( p, vPart ); -p->timeTrav += clock() - clk2; -clk2 = clock(); - pAigTemp = Fra_FraigEquivence( pAigPart, nConfMax, 0 ); -p->timeFraig += clock() - clk2; - Vec_PtrPush( p->vFraigs, pAigTemp ); -/* - { - char Name[1000]; - sprintf( Name, "part%04d.blif", i ); - Aig_ManDumpBlif( pAigPart, Name, NULL, NULL ); - } -printf( "Finished part %4d (out of %4d). ", i, Vec_PtrSize(p->vParts) ); -ABC_PRT( "Time", clock() - clk3 ); -*/ - - 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) ); - ABC_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( Aig_Man_t *, 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; - } - } - 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); -finish: - ABC_FREE( pTemp ); - Lcr_ManFree( p ); - if ( pnIter ) *pnIter = nIter; - return pAigNew; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/fra/fraMan.c b/src/aig/fra/fraMan.c deleted file mode 100644 index 7e427e72..00000000 --- a/src/aig/fra/fraMan.c +++ /dev/null @@ -1,314 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 = ABC_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 = ABC_ALLOC( unsigned, p->nPatWords ); - p->vPiVars = Vec_PtrAlloc( 100 ); - // equivalence classes - p->pCla = Fra_ClassesStart( pManAig ); - // allocate other members - p->pMemFraig = ABC_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 ); - Aig_ManRandom(1); - // 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 = ABC_REALLOC( Vec_Ptr_t *, p->pMemFanins, nMemAllocNew ); - p->pMemSatNums = ABC_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->pSpec = Aig_UtilStrsav( p->pManAig->pSpec ); - 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 = ABC_ALLOC( Vec_Ptr_t *, p->nMemAlloc ); - memset( p->pMemFanins, 0, sizeof(Vec_Ptr_t *) * p->nMemAlloc ); - p->pMemSatNums = ABC_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 ) - ABC_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 ); - if ( p->vOneHots ) Vec_IntFree( p->vOneHots ); - ABC_FREE( p->pMemFraig ); - ABC_FREE( p->pMemFanins ); - ABC_FREE( p->pMemSatNums ); - ABC_FREE( p->pPatWords ); - ABC_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 ); - if ( p->pPars->fUse1Hot ) Fra_OneHotEstimateCoverage( p, p->vOneHots ); - ABC_PRT( "AIG simulation ", p->pSml->timeSim ); - ABC_PRT( "AIG traversal ", p->timeTrav ); - if ( p->timeRwr ) - { - ABC_PRT( "AIG rewriting ", p->timeRwr ); - } - ABC_PRT( "SAT solving ", p->timeSat ); - ABC_PRT( " Unsat ", p->timeSatUnsat ); - ABC_PRT( " Sat ", p->timeSatSat ); - ABC_PRT( " Fail ", p->timeSatFail ); - ABC_PRT( "Class refining ", p->timeRef ); - ABC_PRT( "TOTAL RUNTIME ", p->timeTotal ); - if ( p->time1 ) { ABC_PRT( "time1 ", p->time1 ); } - if ( p->nSpeculs ) - printf( "Speculations = %d.\n", p->nSpeculs ); - fflush( stdout ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/fra/fraPart.c b/src/aig/fra/fraPart.c deleted file mode 100644 index e9739f97..00000000 --- a/src/aig/fra/fraPart.c +++ /dev/null @@ -1,268 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 ); -ABC_PRT( "Supports", clock() - clk ); - // remove last entry - Aig_ManForEachPo( p, pObj, i ) - { - vSup = Vec_VecEntryInt( 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_VecEntryInt( vSupps, i ); - Vec_IntForEachEntry( vSup, Entry, k ) - Vec_VecPush( vSuppsIn, Entry, (void *)(ABC_PTRUINT_T)i ); - } -ABC_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_VecEntryInt( 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_VecEntryInt( 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 ); -ABC_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 ); -ABC_PRT( "Supports", clock() - clk ); - // remove last entry - Aig_ManForEachPo( p, pObj, i ) - { - vSup = Vec_VecEntryInt( 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_VecEntryInt( vSupps, i ); - Vec_IntForEachEntry( vSup, Entry, k ) - Vec_VecPush( vSuppsIn, Entry, (void *)(ABC_PTRUINT_T)i ); - } -ABC_PRT( "Inverse ", clock() - clk ); - - // create affective supports -clk = clock(); - pSupp = ABC_ALLOC( char, Aig_ManPiNum(p) ); - Aig_ManForEachPo( p, pObj, i ) - { - if ( i % 50 != 0 ) - continue; - vSup = Vec_VecEntryInt( 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_VecEntryInt( vSuppsIn, Entry ); - // go though each assert of this input - Vec_IntForEachEntry( vSup2, Entry2, m ) - { - vSup3 = Vec_VecEntryInt( 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" ); -ABC_PRT( "Extension ", clock() - clk ); - - ABC_FREE( pSupp ); - Vec_VecFree( vSupps ); - Vec_VecFree( vSuppsIn ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/fra/fraSat.c b/src/aig/fra/fraSat.c deleted file mode 100644 index 78d25c37..00000000 --- a/src/aig/fra/fraSat.c +++ /dev/null @@ -1,566 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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, - (ABC_INT64_T)nBTLimit, (ABC_INT64_T)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, - (ABC_INT64_T)nBTLimit, (ABC_INT64_T)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; - ABC_PRT( "Sat", clock() - clk2 ); - clk2 = clock(); - RetVal = Fra_NodesAreEquivBdd( pOld, pNew ); -// printf( "%d ", RetVal ); - assert( RetVal ); - ABC_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, - (ABC_INT64_T)nBTLimit, (ABC_INT64_T)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 the result of test for pObj => pNew.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_NodesAreClause( 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, - (ABC_INT64_T)nBTLimit, (ABC_INT64_T)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, - (ABC_INT64_T)p->pPars->nBTLimitMiter, (ABC_INT64_T)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 - if ( p->pSat->factors == NULL ) - p->pSat->factors = ABC_CALLOC( double, p->pSat->size ); - 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( Aig_Obj_t *, 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 = ABC_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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/fra/fraSec.c b/src/aig/fra/fraSec.c deleted file mode 100644 index 3b28936d..00000000 --- a/src/aig/fra/fraSec.c +++ /dev/null @@ -1,696 +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" -#include "int.h" -#include "ssw.h" -#include "saig.h" -#include "bbr.h" -#include "pdr.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_SecSetDefaultParams( Fra_Sec_t * p ) -{ - memset( p, 0, sizeof(Fra_Sec_t) ); - p->fTryComb = 1; // try CEC call as a preprocessing step - p->fTryBmc = 1; // try BMC call as a preprocessing step - p->nFramesMax = 4; // the max number of frames used for induction - p->nBTLimit = 1000; // conflict limit at a node during induction - p->nBTLimitGlobal = 5000000; // global conflict limit during induction - p->nBTLimitInter = 10000; // conflict limit during interpolation - p->nBddVarsMax = 150; // the limit on the number of registers in BDD reachability - p->nBddMax = 50000; // the limit on the number of BDD nodes - p->nBddIterMax = 1000000; // the limit on the number of BDD iterations - p->fPhaseAbstract = 0; // enables phase abstraction - p->fRetimeFirst = 1; // enables most-forward retiming at the beginning - p->fRetimeRegs = 1; // enables min-register retiming at the beginning - p->fFraiging = 1; // enables fraiging at the beginning - p->fInduction = 1; // enables the use of induction (signal correspondence) - p->fInterpolation = 1; // enables interpolation - p->fInterSeparate = 0; // enables interpolation for each outputs separately - p->fReachability = 1; // enables BDD based reachability - p->fReorderImage = 1; // enables variable reordering during image computation - p->fStopOnFirstFail = 1; // enables stopping after first output of a miter has failed to prove - p->fUseNewProver = 0; // enables new prover - p->fUsePdr = 1; // enables PDR - p->nPdrTimeout = 60; // enabled PDR timeout - p->fSilent = 0; // disables all output - p->fVerbose = 0; // enables verbose reporting of statistics - p->fVeryVerbose = 0; // enables very verbose reporting - p->TimeLimit = 0; // enables the timeout - // internal parameters - p->fReportSolution = 0; // enables specialized format for reporting solution -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_FraigSec( Aig_Man_t * p, Fra_Sec_t * pParSec, Aig_Man_t ** ppResult ) -{ - Ssw_Pars_t Pars2, * pPars2 = &Pars2; - Fra_Ssw_t Pars, * pPars = &Pars; - Fra_Sml_t * pSml; - Aig_Man_t * pNew, * pTemp; - int nFrames, RetValue, nIter, clk, clkTotal = clock(); - int TimeOut = 0; - int fLatchCorr = 0; - float TimeLeft = 0.0; - pParSec->nSMnumber = -1; - - // try the miter before solving - pNew = Aig_ManDupSimple( p ); - RetValue = Fra_FraigMiterStatus( pNew ); - if ( RetValue >= 0 ) - goto finish; - - // prepare parameters - memset( pPars, 0, sizeof(Fra_Ssw_t) ); - pPars->fLatchCorr = fLatchCorr; - pPars->fVerbose = pParSec->fVeryVerbose; - if ( pParSec->fVerbose ) - { - printf( "Original miter: Latches = %5d. Nodes = %6d.\n", - Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); - } -//Aig_ManDumpBlif( pNew, "after.blif", NULL, NULL ); - - // perform sequential cleanup -clk = clock(); - if ( pNew->nRegs ) - pNew = Aig_ManReduceLaches( pNew, 0 ); - if ( pNew->nRegs ) - pNew = Aig_ManConstReduce( pNew, 0, -1, -1, 0, 0 ); - if ( pParSec->fVerbose ) - { - printf( "Sequential cleanup: Latches = %5d. Nodes = %6d. ", - Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); -ABC_PRT( "Time", clock() - clk ); - } - RetValue = Fra_FraigMiterStatus( pNew ); - if ( RetValue >= 0 ) - goto finish; - - // perform phase abstraction -clk = clock(); - if ( pParSec->fPhaseAbstract ) - { - extern Aig_Man_t * Saig_ManPhaseAbstractAuto( Aig_Man_t * p, int fVerbose ); - pNew->nTruePis = Aig_ManPiNum(pNew) - Aig_ManRegNum(pNew); - pNew->nTruePos = Aig_ManPoNum(pNew) - Aig_ManRegNum(pNew); - pNew = Saig_ManPhaseAbstractAuto( pTemp = pNew, 0 ); - Aig_ManStop( pTemp ); - if ( pParSec->fVerbose ) - { - printf( "Phase abstraction: Latches = %5d. Nodes = %6d. ", - Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); -ABC_PRT( "Time", clock() - clk ); - } - } - - // perform forward retiming - if ( pParSec->fRetimeFirst && pNew->nRegs ) - { -clk = clock(); -// pNew = Rtm_ManRetime( pTemp = pNew, 1, 1000, 0 ); - pNew = Saig_ManRetimeForward( pTemp = pNew, 100, 0 ); - Aig_ManStop( pTemp ); - if ( pParSec->fVerbose ) - { - printf( "Forward retiming: Latches = %5d. Nodes = %6d. ", - Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); -ABC_PRT( "Time", clock() - clk ); - } - } - - // run latch correspondence -clk = clock(); - if ( pNew->nRegs ) - { - pNew = Aig_ManDupOrdered( pTemp = pNew ); -// pNew = Aig_ManDupDfs( pTemp = pNew ); - Aig_ManStop( pTemp ); -/* - if ( RetValue == -1 && pParSec->TimeLimit ) - { - TimeLeft = (float)pParSec->TimeLimit - ((float)(clock()-clkTotal)/(float)(CLOCKS_PER_SEC)); - TimeLeft = ABC_MAX( TimeLeft, 0.0 ); - if ( TimeLeft == 0.0 ) - { - if ( !pParSec->fSilent ) - printf( "Runtime limit exceeded.\n" ); - RetValue = -1; - TimeOut = 1; - goto finish; - } - } -*/ - -// pNew = Fra_FraigLatchCorrespondence( pTemp = pNew, 0, 1000, 1, pParSec->fVeryVerbose, &nIter, TimeLeft ); -//Aig_ManDumpBlif( pNew, "ex.blif", NULL, NULL ); - Ssw_ManSetDefaultParamsLcorr( pPars2 ); - pNew = Ssw_LatchCorrespondence( pTemp = pNew, pPars2 ); - nIter = pPars2->nIters; - - // prepare parameters for scorr - Ssw_ManSetDefaultParams( pPars2 ); - - if ( pTemp->pSeqModel ) - { - if ( !Saig_ManVerifyCex( pTemp, pTemp->pSeqModel ) ) - printf( "Fra_FraigSec(): Counter-example verification has FAILED.\n" ); - if ( Saig_ManPiNum(p) != Saig_ManPiNum(pTemp) ) - printf( "The counter-example is invalid because of phase abstraction.\n" ); - else - { - ABC_FREE( p->pSeqModel ); - p->pSeqModel = Abc_CexDup( pTemp->pSeqModel, Aig_ManRegNum(p) ); - ABC_FREE( pTemp->pSeqModel ); - } - } - if ( pNew == NULL ) - { - if ( p->pSeqModel ) - { - RetValue = 0; - if ( !pParSec->fSilent ) - { - printf( "Networks are NOT EQUIVALENT after simulation. " ); -ABC_PRT( "Time", clock() - clkTotal ); - } - if ( pParSec->fReportSolution && !pParSec->fRecursive ) - { - printf( "SOLUTION: FAIL " ); -ABC_PRT( "Time", clock() - clkTotal ); - } - Aig_ManStop( pTemp ); - return RetValue; - } - pNew = pTemp; - RetValue = -1; - TimeOut = 1; - goto finish; - } - Aig_ManStop( pTemp ); - - if ( pParSec->fVerbose ) - { - printf( "Latch-corr (I=%3d): Latches = %5d. Nodes = %6d. ", - nIter, Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); -ABC_PRT( "Time", clock() - clk ); - } - } -/* - if ( RetValue == -1 && pParSec->TimeLimit ) - { - TimeLeft = (float)pParSec->TimeLimit - ((float)(clock()-clkTotal)/(float)(CLOCKS_PER_SEC)); - TimeLeft = ABC_MAX( TimeLeft, 0.0 ); - if ( TimeLeft == 0.0 ) - { - if ( !pParSec->fSilent ) - printf( "Runtime limit exceeded.\n" ); - RetValue = -1; - TimeOut = 1; - goto finish; - } - } -*/ - // perform fraiging - if ( pParSec->fFraiging ) - { -clk = clock(); - pNew = Fra_FraigEquivence( pTemp = pNew, 100, 0 ); - Aig_ManStop( pTemp ); - if ( pParSec->fVerbose ) - { - printf( "Fraiging: Latches = %5d. Nodes = %6d. ", - Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); -ABC_PRT( "Time", clock() - clk ); - } - } - - if ( pNew->nRegs == 0 ) - RetValue = Fra_FraigCec( &pNew, 100000, 0 ); - - RetValue = Fra_FraigMiterStatus( pNew ); - if ( RetValue >= 0 ) - goto finish; -/* - if ( RetValue == -1 && pParSec->TimeLimit ) - { - TimeLeft = (float)pParSec->TimeLimit - ((float)(clock()-clkTotal)/(float)(CLOCKS_PER_SEC)); - TimeLeft = ABC_MAX( TimeLeft, 0.0 ); - if ( TimeLeft == 0.0 ) - { - if ( !pParSec->fSilent ) - printf( "Runtime limit exceeded.\n" ); - RetValue = -1; - TimeOut = 1; - goto finish; - } - } -*/ - // perform min-area retiming - if ( pParSec->fRetimeRegs && pNew->nRegs ) - { -// extern Aig_Man_t * Saig_ManRetimeMinArea( Aig_Man_t * p, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose ); -clk = clock(); - pNew->nTruePis = Aig_ManPiNum(pNew) - Aig_ManRegNum(pNew); - pNew->nTruePos = Aig_ManPoNum(pNew) - Aig_ManRegNum(pNew); -// pNew = Rtm_ManRetime( pTemp = pNew, 1, 1000, 0 ); - pNew = Saig_ManRetimeMinArea( pTemp = pNew, 1000, 0, 0, 1, 0 ); - Aig_ManStop( pTemp ); - pNew = Aig_ManDupOrdered( pTemp = pNew ); - Aig_ManStop( pTemp ); - if ( pParSec->fVerbose ) - { - printf( "Min-reg retiming: Latches = %5d. Nodes = %6d. ", - Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); -ABC_PRT( "Time", clock() - clk ); - } - } - - // perform seq sweeping while increasing the number of frames - RetValue = Fra_FraigMiterStatus( pNew ); - if ( RetValue == -1 && pParSec->fInduction ) - for ( nFrames = 1; nFrames <= pParSec->nFramesMax; nFrames *= 2 ) - { -/* - if ( RetValue == -1 && pParSec->TimeLimit ) - { - TimeLeft = (float)pParSec->TimeLimit - ((float)(clock()-clkTotal)/(float)(CLOCKS_PER_SEC)); - TimeLeft = ABC_MAX( TimeLeft, 0.0 ); - if ( TimeLeft == 0.0 ) - { - if ( !pParSec->fSilent ) - printf( "Runtime limit exceeded.\n" ); - RetValue = -1; - TimeOut = 1; - goto finish; - } - } -*/ - -clk = clock(); - pPars->nFramesK = nFrames; - pPars->TimeLimit = TimeLeft; - pPars->fSilent = pParSec->fSilent; -// pNew = Fra_FraigInduction( pTemp = pNew, pPars ); - - pPars2->nFramesK = nFrames; - pPars2->nBTLimit = pParSec->nBTLimit; - pPars2->nBTLimitGlobal = pParSec->nBTLimitGlobal; -// pPars2->nBTLimit = 1000 * nFrames; - - if ( RetValue == -1 && pPars2->nConflicts > pPars2->nBTLimitGlobal ) - { - if ( !pParSec->fSilent ) - printf( "Global conflict limit (%d) exceeded.\n", pPars2->nBTLimitGlobal ); - RetValue = -1; - TimeOut = 1; - goto finish; - } - - Aig_ManSetRegNum( pNew, pNew->nRegs ); -// pNew = Ssw_SignalCorrespondence( pTemp = pNew, pPars2 ); - if ( Aig_ManRegNum(pNew) > 0 ) - pNew = Ssw_SignalCorrespondence( pTemp = pNew, pPars2 ); - else - pNew = Aig_ManDupSimpleDfs( pTemp = pNew ); - - if ( pNew == NULL ) - { - pNew = pTemp; - RetValue = -1; - TimeOut = 1; - goto finish; - } - -// printf( "Total conflicts = %d.\n", pPars2->nConflicts ); - - Aig_ManStop( pTemp ); - RetValue = Fra_FraigMiterStatus( pNew ); - if ( pParSec->fVerbose ) - { - printf( "K-step (K=%2d,I=%3d): Latches = %5d. Nodes = %6d. ", - nFrames, pPars2->nIters, Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); -ABC_PRT( "Time", clock() - clk ); - } - if ( RetValue != -1 ) - break; - - // perform retiming -// if ( pParSec->fRetimeFirst && pNew->nRegs ) - if ( pNew->nRegs ) - { -// extern Aig_Man_t * Saig_ManRetimeMinArea( Aig_Man_t * p, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose ); -clk = clock(); - pNew->nTruePis = Aig_ManPiNum(pNew) - Aig_ManRegNum(pNew); - pNew->nTruePos = Aig_ManPoNum(pNew) - Aig_ManRegNum(pNew); -// pNew = Rtm_ManRetime( pTemp = pNew, 1, 1000, 0 ); - pNew = Saig_ManRetimeMinArea( pTemp = pNew, 1000, 0, 0, 1, 0 ); - Aig_ManStop( pTemp ); - pNew = Aig_ManDupOrdered( pTemp = pNew ); - Aig_ManStop( pTemp ); - if ( pParSec->fVerbose ) - { - printf( "Min-reg retiming: Latches = %5d. Nodes = %6d. ", - Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); -ABC_PRT( "Time", clock() - clk ); - } - } - - if ( pNew->nRegs ) - pNew = Aig_ManConstReduce( pNew, 0, -1, -1, 0, 0 ); - - // perform rewriting -clk = clock(); - pNew = Aig_ManDupOrdered( pTemp = pNew ); - Aig_ManStop( pTemp ); -// pNew = Dar_ManRewriteDefault( pTemp = pNew ); - pNew = Dar_ManCompress2( pTemp = pNew, 1, 0, 1, 0, 0 ); - Aig_ManStop( pTemp ); - if ( pParSec->fVerbose ) - { - printf( "Rewriting: Latches = %5d. Nodes = %6d. ", - Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); -ABC_PRT( "Time", clock() - clk ); - } - - // perform sequential simulation - if ( pNew->nRegs ) - { -clk = clock(); - pSml = Fra_SmlSimulateSeq( pNew, 0, 128 * nFrames, 1 + 16/(1+Aig_ManNodeNum(pNew)/1000), 1 ); - if ( pParSec->fVerbose ) - { - printf( "Seq simulation : Latches = %5d. Nodes = %6d. ", - Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); -ABC_PRT( "Time", clock() - clk ); - } - if ( pSml->fNonConstOut ) - { - pNew->pSeqModel = Fra_SmlGetCounterExample( pSml ); - // transfer to the original manager - if ( Saig_ManPiNum(p) != Saig_ManPiNum(pNew) ) - printf( "The counter-example is invalid because of phase abstraction.\n" ); - else - { - ABC_FREE( p->pSeqModel ); - p->pSeqModel = Abc_CexDup( pNew->pSeqModel, Aig_ManRegNum(p) ); - ABC_FREE( pNew->pSeqModel ); - } - - Fra_SmlStop( pSml ); - Aig_ManStop( pNew ); - RetValue = 0; - if ( !pParSec->fSilent ) - { - printf( "Networks are NOT EQUIVALENT after simulation. " ); -ABC_PRT( "Time", clock() - clkTotal ); - } - if ( pParSec->fReportSolution && !pParSec->fRecursive ) - { - printf( "SOLUTION: FAIL " ); -ABC_PRT( "Time", clock() - clkTotal ); - } - return RetValue; - } - Fra_SmlStop( pSml ); - } - } - - // get the miter status - RetValue = Fra_FraigMiterStatus( pNew ); - - // try interplation -clk = clock(); - Aig_ManSetRegNum( pNew, Aig_ManRegNum(pNew) ); - if ( pParSec->fInterpolation && RetValue == -1 && Aig_ManRegNum(pNew) > 0 ) - { - Inter_ManParams_t Pars, * pPars = &Pars; - int Depth; - ABC_FREE( pNew->pSeqModel ); - Inter_ManSetDefaultParams( pPars ); -// pPars->nBTLimit = 100; - pPars->nBTLimit = pParSec->nBTLimitInter; - pPars->fVerbose = pParSec->fVeryVerbose; - if ( Saig_ManPoNum(pNew) == 1 ) - { - RetValue = Inter_ManPerformInterpolation( pNew, pPars, &Depth ); - } - else if ( pParSec->fInterSeparate ) - { - Abc_Cex_t * pCex = NULL; - Aig_Man_t * pTemp, * pAux; - Aig_Obj_t * pObjPo; - int i, Counter = 0; - Saig_ManForEachPo( pNew, pObjPo, i ) - { - if ( Aig_ObjFanin0(pObjPo) == Aig_ManConst1(pNew) ) - continue; - if ( pPars->fVerbose ) - printf( "Solving output %2d (out of %2d):\n", i, Saig_ManPoNum(pNew) ); - pTemp = Aig_ManDupOneOutput( pNew, i, 1 ); - pTemp = Aig_ManScl( pAux = pTemp, 1, 1, 0, -1, -1, 0, 0 ); - Aig_ManStop( pAux ); - if ( Saig_ManRegNum(pTemp) > 0 ) - { - RetValue = Inter_ManPerformInterpolation( pTemp, pPars, &Depth ); - if ( pTemp->pSeqModel ) - { - pCex = p->pSeqModel = Abc_CexDup( pTemp->pSeqModel, Aig_ManRegNum(p) ); - pCex->iPo = i; - Aig_ManStop( pTemp ); - break; - } - // if solved, remove the output - if ( RetValue == 1 ) - { - Aig_ObjPatchFanin0( pNew, pObjPo, Aig_ManConst0(pNew) ); - // printf( "Output %3d : Solved ", i ); - } - else - { - Counter++; - // printf( "Output %3d : Undec ", i ); - } - } - else - Counter++; -// Aig_ManPrintStats( pTemp ); - Aig_ManStop( pTemp ); - printf( "Solving output %3d (out of %3d) using interpolation.\r", i, Saig_ManPoNum(pNew) ); - } - Aig_ManCleanup( pNew ); - if ( pCex == NULL ) - { - printf( "Interpolation left %d (out of %d) outputs unsolved \n", Counter, Saig_ManPoNum(pNew) ); - if ( Counter ) - RetValue = -1; - } - pNew = Aig_ManDupUnsolvedOutputs( pTemp = pNew, 1 ); - Aig_ManStop( pTemp ); - pNew = Aig_ManScl( pTemp = pNew, 1, 1, 0, -1, -1, 0, 0 ); - Aig_ManStop( pTemp ); - } - else - { - Aig_Man_t * pNewOrpos = Saig_ManDupOrpos( pNew ); - RetValue = Inter_ManPerformInterpolation( pNewOrpos, pPars, &Depth ); - if ( pNewOrpos->pSeqModel ) - { - Abc_Cex_t * pCex; - pCex = pNew->pSeqModel = pNewOrpos->pSeqModel; pNewOrpos->pSeqModel = NULL; - pCex->iPo = Saig_ManFindFailedPoCex( pNew, pNew->pSeqModel ); - } - Aig_ManStop( pNewOrpos ); - } - - if ( pParSec->fVerbose ) - { - if ( RetValue == 1 ) - printf( "Property proved using interpolation. " ); - else if ( RetValue == 0 ) - printf( "Property DISPROVED in frame %d using interpolation. ", Depth ); - else if ( RetValue == -1 ) - printf( "Property UNDECIDED after interpolation. " ); - else - assert( 0 ); -ABC_PRT( "Time", clock() - clk ); - } - } - - // try reachability analysis - if ( pParSec->fReachability && RetValue == -1 && Aig_ManRegNum(pNew) > 0 && Aig_ManRegNum(pNew) < pParSec->nBddVarsMax ) - { - Saig_ParBbr_t Pars, * pPars = &Pars; - Bbr_ManSetDefaultParams( pPars ); - pPars->TimeLimit = 0; - pPars->nBddMax = pParSec->nBddMax; - pPars->nIterMax = pParSec->nBddIterMax; - pPars->fPartition = 1; - pPars->fReorder = 1; - pPars->fReorderImage = 1; - pPars->fVerbose = 0; - pPars->fSilent = pParSec->fSilent; - pNew->nTruePis = Aig_ManPiNum(pNew) - Aig_ManRegNum(pNew); - pNew->nTruePos = Aig_ManPoNum(pNew) - Aig_ManRegNum(pNew); - RetValue = Aig_ManVerifyUsingBdds( pNew, pPars ); - } - - // try PDR - if ( pParSec->fUsePdr && RetValue == -1 && Aig_ManRegNum(pNew) > 0 ) - { - Abc_Cex_t * pCex = NULL; - Aig_Man_t * pNewOrpos = Saig_ManDupOrpos( pNew ); - Pdr_Par_t Pars, * pPars = &Pars; - Pdr_ManSetDefaultParams( pPars ); - pPars->nTimeOut = pParSec->nPdrTimeout; - pPars->fVerbose = pParSec->fVerbose; - if ( pParSec->fVerbose ) - printf( "Running property directed reachability...\n" ); - RetValue = Pdr_ManSolve( pNewOrpos, pPars, &pCex ); - if ( pCex ) - pCex->iPo = Saig_ManFindFailedPoCex( pNew, pCex ); - Aig_ManStop( pNewOrpos ); - pNew->pSeqModel = pCex; - } - -finish: - // report the miter - if ( RetValue == 1 ) - { - if ( !pParSec->fSilent ) - { - printf( "Networks are equivalent. " ); -ABC_PRT( "Time", clock() - clkTotal ); - } - if ( pParSec->fReportSolution && !pParSec->fRecursive ) - { - printf( "SOLUTION: PASS " ); -ABC_PRT( "Time", clock() - clkTotal ); - } - } - else if ( RetValue == 0 ) - { - if ( pNew->pSeqModel == NULL ) - { - int i; - // if the CEX is not derives, it is because tricial CEX should be assumed - pNew->pSeqModel = Abc_CexAlloc( Aig_ManRegNum(pNew), pNew->nTruePis, 1 ); - // if the CEX does not work, we need to change PIs to 1 because - // the only way it can happen is when a PO is equal to a PI... - if ( Saig_ManFindFailedPoCex( pNew, pNew->pSeqModel ) == -1 ) - for ( i = 0; i < pNew->nTruePis; i++ ) - Aig_InfoSetBit( pNew->pSeqModel->pData, i ); - } - if ( !pParSec->fSilent ) - { - printf( "Networks are NOT EQUIVALENT. " ); -ABC_PRT( "Time", clock() - clkTotal ); - } - if ( pParSec->fReportSolution && !pParSec->fRecursive ) - { - printf( "SOLUTION: FAIL " ); -ABC_PRT( "Time", clock() - clkTotal ); - } - } - else - { - /////////////////////////////////// - // save intermediate result - extern void Abc_FrameSetSave1( void * pAig ); - Abc_FrameSetSave1( Aig_ManDupSimple(pNew) ); - /////////////////////////////////// - if ( !pParSec->fSilent ) - { - printf( "Networks are UNDECIDED. " ); -ABC_PRT( "Time", clock() - clkTotal ); - } - if ( pParSec->fReportSolution && !pParSec->fRecursive ) - { - printf( "SOLUTION: UNDECIDED " ); -ABC_PRT( "Time", clock() - clkTotal ); - } - if ( !TimeOut && !pParSec->fSilent ) - { - static int Counter = 1; - char pFileName[1000]; - pParSec->nSMnumber = Counter; - sprintf( pFileName, "sm%02d.aig", Counter++ ); - Ioa_WriteAiger( pNew, pFileName, 0, 0 ); - printf( "The unsolved reduced miter is written into file \"%s\".\n", pFileName ); - } - } - if ( pNew->pSeqModel ) - { - if ( Saig_ManPiNum(p) != Saig_ManPiNum(pNew) ) - printf( "The counter-example is invalid because of phase abstraction.\n" ); - else - { - ABC_FREE( p->pSeqModel ); - p->pSeqModel = Abc_CexDup( pNew->pSeqModel, Aig_ManRegNum(p) ); - ABC_FREE( pNew->pSeqModel ); - } - } - if ( ppResult != NULL ) - *ppResult = Aig_ManDupSimpleDfs( pNew ); - if ( pNew ) - Aig_ManStop( pNew ); - return RetValue; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/fra/fraSim.c b/src/aig/fra/fraSim.c deleted file mode 100644 index 8f912915..00000000 --- a/src/aig/fra/fraSim.c +++ /dev/null @@ -1,1023 +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" -#include "saig.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 = (Fra_Man_t *)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 = (Fra_Man_t *)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 = (Fra_Man_t *)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 [Counts the number of one's in the patten of the output.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_SmlNodeCountOnes( Fra_Sml_t * p, Aig_Obj_t * pObj ) -{ - unsigned * pSims; - int i, Counter = 0; - pSims = Fra_ObjSim(p, pObj->Id); - for ( i = 0; i < p->nWordsTotal; i++ ) - Counter += Aig_WordCountOnes( pSims[i] ); - return Counter; -} - - - -/**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 ) - if ( sat_solver_var_value(p->pSat, Fra_ObjSatNum(pObj)) ) - 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 = ABC_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 = ABC_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 = ABC_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 [] - -***********************************************************************/ -int Fra_SmlNodesCompareInFrame( Fra_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1, int iFrame0, int iFrame1 ) -{ - unsigned * pSims0, * pSims1; - int i; - assert( !Aig_IsComplement(pObj0) ); - assert( !Aig_IsComplement(pObj1) ); - assert( iFrame0 == 0 || p->nWordsFrame < p->nWordsTotal ); - assert( iFrame1 == 0 || p->nWordsFrame < p->nWordsTotal ); - // get hold of the simulation information - pSims0 = Fra_ObjSim(p, pObj0->Id) + p->nWordsFrame * iFrame0; - pSims1 = Fra_ObjSim(p, pObj1->Id) + p->nWordsFrame * iFrame1; - // compare - for ( i = 0; i < p->nWordsFrame; i++ ) - if ( pSims0[i] != pSims1[i] ) - return 0; - return 1; -} - -/**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 ); - if ( p->vOneHots ) - nChanges += Fra_OneHotRefineUsingCex( p, p->vOneHots ); -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 *)ABC_ALLOC( char, 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 ) -{ - ABC_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, int fCheckMiter ) -{ - Fra_Sml_t * p; - p = Fra_SmlStart( pAig, nPref, nFrames, nWords ); - Fra_SmlInitialize( p, 1 ); - Fra_SmlSimulateOne( p ); - if ( fCheckMiter ) - p->fNonConstOut = Fra_SmlCheckNonConstOutputs( p ); - return p; -} - -/**Function************************************************************* - - Synopsis [Creates sequential counter-example from the simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Cex_t * Fra_SmlGetCounterExample( Fra_Sml_t * p ) -{ - Abc_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 = Abc_CexAlloc( 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 ( !Saig_ManVerifyCex( p->pAig, pCex ) ) - { - printf( "Fra_SmlGetCounterExample(): Counter-example is invalid.\n" ); - Abc_CexFree( pCex ); - pCex = NULL; - } - return pCex; -} - -/**Function************************************************************* - - Synopsis [Generates seq counter-example from the combinational one.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Cex_t * Fra_SmlCopyCounterExample( Aig_Man_t * pAig, Aig_Man_t * pFrames, int * pModel ) -{ - Abc_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 = Abc_CexAlloc( 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 ( !Saig_ManVerifyCex( pAig, pCex ) ) - { - printf( "Fra_SmlGetCounterExample(): Counter-example is invalid.\n" ); - Abc_CexFree( pCex ); - pCex = NULL; - } - return pCex; - -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/fra/fra_.c b/src/aig/fra/fra_.c deleted file mode 100644 index 8e5785ec..00000000 --- a/src/aig/fra/fra_.c +++ /dev/null @@ -1,53 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/fra/module.make b/src/aig/fra/module.make deleted file mode 100644 index e3a88aae..00000000 --- a/src/aig/fra/module.make +++ /dev/null @@ -1,17 +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/fraHot.c \ - src/aig/fra/fraImp.c \ - src/aig/fra/fraInd.c \ - src/aig/fra/fraIndVer.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/fsim/fsim.h b/src/aig/fsim/fsim.h deleted file mode 100644 index fabc5254..00000000 --- a/src/aig/fsim/fsim.h +++ /dev/null @@ -1,101 +0,0 @@ -/**CFile**************************************************************** - - FileName [fsim.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Fast sequential AIG simulator.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: fsim.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __FSIM_H__ -#define __FSIM_H__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Fsim_Man_t_ Fsim_Man_t; - -// simulation parameters -typedef struct Fsim_ParSim_t_ Fsim_ParSim_t; -struct Fsim_ParSim_t_ -{ - // user-controlled parameters - int nWords; // the number of machine words - int nIters; // the number of timeframes - int TimeLimit; // time limit in seconds - int fCheckMiter; // check if miter outputs are non-zero - int fVerbose; // enables verbose output - // internal parameters - int fCompressAig; // compresses internal data -}; - -// switching estimation parameters -typedef struct Fsim_ParSwitch_t_ Fsim_ParSwitch_t; -struct Fsim_ParSwitch_t_ -{ - // user-controlled parameters - int nWords; // the number of machine words - int nIters; // the number of timeframes - int nPref; // the number of first timeframes to skip - int nRandPiNum; // PI trans prob (0=1/2; 1=1/4; 2=1/8, etc) - int fProbOne; // collect probability of one - int fProbTrans; // collect probatility of switching - int fVerbose; // enables verbose output -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== fsimCore.c ==========================================================*/ -extern void Fsim_ManSetDefaultParamsSim( Fsim_ParSim_t * p ); -extern void Fsim_ManSetDefaultParamsSwitch( Fsim_ParSwitch_t * p ); -/*=== fsimSim.c ==========================================================*/ -extern int Fsim_ManSimulate( Aig_Man_t * pAig, Fsim_ParSim_t * pPars ); -/*=== fsimSwitch.c ==========================================================*/ -extern Vec_Int_t * Fsim_ManSwitchSimulate( Aig_Man_t * pAig, Fsim_ParSwitch_t * pPars ); -/*=== fsimTsim.c ==========================================================*/ -extern Vec_Ptr_t * Fsim_ManTerSimulate( Aig_Man_t * pAig, int fVerbose ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/fsim/fsimCore.c b/src/aig/fsim/fsimCore.c deleted file mode 100644 index 9516f09e..00000000 --- a/src/aig/fsim/fsimCore.c +++ /dev/null @@ -1,88 +0,0 @@ -/**CFile**************************************************************** - - FileName [fsimCore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Fast sequential AIG simulator.] - - Synopsis [Core procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: fsimCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fsimInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [This procedure sets default parameters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fsim_ManSetDefaultParamsSim( Fsim_ParSim_t * p ) -{ - memset( p, 0, sizeof(Fsim_ParSim_t) ); - // user-controlled parameters - p->nWords = 8; // the number of machine words - p->nIters = 32; // the number of timeframes - p->TimeLimit = 60; // time limit in seconds - p->fCheckMiter = 0; // check if miter outputs are non-zero - p->fVerbose = 1; // enables verbose output - // internal parameters - p->fCompressAig = 0; // compresses internal data -} - -/**Function************************************************************* - - Synopsis [This procedure sets default parameters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fsim_ManSetDefaultParamsSwitch( Fsim_ParSwitch_t * p ) -{ - memset( p, 0, sizeof(Fsim_ParSwitch_t) ); - // user-controlled parameters - p->nWords = 1; // the number of machine words - p->nIters = 48; // the number of timeframes - p->nPref = 16; // the number of first timeframes to skip - p->nRandPiNum = 0; // PI trans prob (0=1/2; 1=1/4; 2=1/8, etc) - p->fProbOne = 1; // collect probability of one - p->fProbTrans = 1; // collect probatility of switching - p->fVerbose = 1; // enables verbose output -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/fsim/fsimFront.c b/src/aig/fsim/fsimFront.c deleted file mode 100644 index 6169543c..00000000 --- a/src/aig/fsim/fsimFront.c +++ /dev/null @@ -1,369 +0,0 @@ -/**CFile**************************************************************** - - FileName [fsimFront.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Fast sequential AIG simulator.] - - Synopsis [Simulation frontier.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: fsimFront.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fsimInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Fsim_ManStoreNum( Fsim_Man_t * p, int Num ) -{ - unsigned x = (unsigned)Num; - assert( Num >= 0 ); - while ( x & ~0x7f ) - { - *p->pDataCur++ = (x & 0x7f) | 0x80; - x >>= 7; - } - *p->pDataCur++ = x; - assert( p->pDataCur - p->pDataAig < p->nDataAig ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Fsim_ManRestoreNum( Fsim_Man_t * p ) -{ - int ch, i, x = 0; - for ( i = 0; (ch = *p->pDataCur++) & 0x80; i++ ) - x |= (ch & 0x7f) << (7 * i); - assert( p->pDataCur - p->pDataAig < p->nDataAig ); - return x | (ch << (7 * i)); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Fsim_ManStoreObj( Fsim_Man_t * p, Fsim_Obj_t * pObj ) -{ - if ( p->pDataAig2 ) - { - *p->pDataCur2++ = pObj->iNode; - *p->pDataCur2++ = pObj->iFan0; - *p->pDataCur2++ = pObj->iFan1; - return; - } - if ( pObj->iFan0 && pObj->iFan1 ) // and - { - assert( pObj->iNode ); - assert( pObj->iNode >= p->iNodePrev ); - assert( (pObj->iNode << 1) > pObj->iFan0 ); - assert( pObj->iFan0 > pObj->iFan1 ); - Fsim_ManStoreNum( p, ((pObj->iNode - p->iNodePrev) << 2) | 3 ); - Fsim_ManStoreNum( p, (pObj->iNode << 1) - pObj->iFan0 ); - Fsim_ManStoreNum( p, pObj->iFan0 - pObj->iFan1 ); - p->iNodePrev = pObj->iNode; - } - else if ( !pObj->iFan0 && !pObj->iFan1 ) // ci - { - assert( pObj->iNode ); - assert( pObj->iNode >= p->iNodePrev ); - Fsim_ManStoreNum( p, ((pObj->iNode - p->iNodePrev) << 2) | 1 ); - p->iNodePrev = pObj->iNode; - } - else // if ( !pObj->iFan0 && pObj->iFan1 ) // co - { - assert( pObj->iNode == 0 ); - assert( pObj->iFan0 != 0 ); - assert( pObj->iFan1 == 0 ); - assert( ((p->iNodePrev << 1) | 1) >= pObj->iFan0 ); - Fsim_ManStoreNum( p, (((p->iNodePrev << 1) | 1) - pObj->iFan0) << 1 ); - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Fsim_ManRestoreObj( Fsim_Man_t * p, Fsim_Obj_t * pObj ) -{ - int iValue = Fsim_ManRestoreNum( p ); - if ( (iValue & 3) == 3 ) // and - { - pObj->iNode = (iValue >> 2) + p->iNodePrev; - pObj->iFan0 = (pObj->iNode << 1) - Fsim_ManRestoreNum( p ); - pObj->iFan1 = pObj->iFan0 - Fsim_ManRestoreNum( p ); - p->iNodePrev = pObj->iNode; - } - else if ( (iValue & 3) == 1 ) // ci - { - pObj->iNode = (iValue >> 2) + p->iNodePrev; - pObj->iFan0 = 0; - pObj->iFan1 = 0; - p->iNodePrev = pObj->iNode; - } - else // if ( (iValue & 1) == 0 ) // co - { - pObj->iNode = 0; - pObj->iFan0 = ((p->iNodePrev << 1) | 1) - (iValue >> 1); - pObj->iFan1 = 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Determine the frontier.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Fsim_ManFrontFindNext( Fsim_Man_t * p, char * pFront ) -{ - assert( p->iNumber < (1 << 30) - p->nFront ); - while ( 1 ) - { - if ( p->iNumber % p->nFront == 0 ) - p->iNumber++; - if ( pFront[p->iNumber % p->nFront] == 0 ) - { - pFront[p->iNumber % p->nFront] = 1; - return p->iNumber; - } - p->iNumber++; - } - return -1; -} - -/**Function************************************************************* - - Synopsis [Verifies the frontier.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fsim_ManVerifyFront( Fsim_Man_t * p ) -{ - Fsim_Obj_t * pObj; - int * pFans0, * pFans1; // representation of fanins - int * pFrontToId; // mapping of nodes into frontier variables - int i, iVar0, iVar1; - pFans0 = ABC_ALLOC( int, p->nObjs ); - pFans1 = ABC_ALLOC( int, p->nObjs ); - pFans0[0] = pFans1[0] = 0; - pFans0[1] = pFans1[1] = 0; - pFrontToId = ABC_CALLOC( int, p->nFront ); - if ( Aig_ObjRefs(Aig_ManConst1(p->pAig)) ) - pFrontToId[1] = 1; - Fsim_ManForEachObj( p, pObj, i ) - { - if ( pObj->iNode ) - pFrontToId[pObj->iNode % p->nFront] = i; - iVar0 = Fsim_Lit2Var(pObj->iFan0); - iVar1 = Fsim_Lit2Var(pObj->iFan1); - pFans0[i] = Fsim_Var2Lit(pFrontToId[iVar0 % p->nFront], Fsim_LitIsCompl(pObj->iFan0)); - pFans1[i] = Fsim_Var2Lit(pFrontToId[iVar1 % p->nFront], Fsim_LitIsCompl(pObj->iFan1)); - } - for ( i = 0; i < p->nObjs; i++ ) - { - assert( pFans0[i] == p->pFans0[i] ); - assert( pFans1[i] == p->pFans1[i] ); - } - ABC_FREE( pFrontToId ); - ABC_FREE( pFans0 ); - ABC_FREE( pFans1 ); -} - -/**Function************************************************************* - - Synopsis [Determine the frontier.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fsim_ManFront( Fsim_Man_t * p, int fCompressAig ) -{ - Fsim_Obj_t Obj, * pObj = &Obj; - char * pFront; // places used for the frontier - int * pIdToFront; // mapping of nodes into frontier places - int i, iVar0, iVar1, nCrossCut = 0, nCrossCutMax = 0; - // start the frontier - pFront = ABC_CALLOC( char, p->nFront ); - pIdToFront = ABC_ALLOC( int, p->nObjs ); - pIdToFront[0] = -1; - pIdToFront[1] = -1; - // add constant node - p->iNumber = 1; - if ( p->pRefs[1] ) - { - pIdToFront[1] = Fsim_ManFrontFindNext( p, pFront ); - nCrossCut = 1; - } - // allocate room for data - if ( fCompressAig ) - { - p->nDataAig = p->nObjs * 6; - p->pDataAig = ABC_ALLOC( unsigned char, p->nDataAig ); - p->pDataCur = p->pDataAig; - p->iNodePrev = 0; - } - else - { - p->pDataAig2 = ABC_ALLOC( int, 3 * p->nObjs ); - p->pDataCur2 = p->pDataAig2 + 6; - } - // iterate through the objects - for ( i = 2; i < p->nObjs; i++ ) - { - if ( p->pFans0[i] == 0 ) // ci - { - // store node - pIdToFront[i] = Fsim_ManFrontFindNext( p, pFront ); - pObj->iNode = pIdToFront[i]; - pObj->iFan0 = 0; - pObj->iFan1 = 0; - Fsim_ManStoreObj( p, pObj ); - // handle CIs without fanout - if ( p->pRefs[i] == 0 ) - { - pFront[pIdToFront[i] % p->nFront] = 0; - pIdToFront[i] = -1; - } - } - else if ( p->pFans1[i] == 0 ) // co - { - assert( p->pRefs[i] == 0 ); - // get the fanin - iVar0 = Fsim_Lit2Var(p->pFans0[i]); - assert( pIdToFront[iVar0] > 0 ); - // store node - pObj->iNode = 0; - pObj->iFan0 = Fsim_Var2Lit(pIdToFront[iVar0], Fsim_LitIsCompl(p->pFans0[i])); - pObj->iFan1 = 0; - Fsim_ManStoreObj( p, pObj ); - // deref the fanin - if ( --p->pRefs[iVar0] == 0 ) - { - pFront[pIdToFront[iVar0] % p->nFront] = 0; - pIdToFront[iVar0] = -1; - nCrossCut--; - } - } - else - { - // get the fanins - iVar0 = Fsim_Lit2Var(p->pFans0[i]); - assert( pIdToFront[iVar0] > 0 ); - iVar1 = Fsim_Lit2Var(p->pFans1[i]); - assert( pIdToFront[iVar1] > 0 ); - // store node - pIdToFront[i] = Fsim_ManFrontFindNext( p, pFront ); - pObj->iNode = pIdToFront[i]; - pObj->iFan0 = Fsim_Var2Lit(pIdToFront[iVar0], Fsim_LitIsCompl(p->pFans0[i])); - pObj->iFan1 = Fsim_Var2Lit(pIdToFront[iVar1], Fsim_LitIsCompl(p->pFans1[i])); - Fsim_ManStoreObj( p, pObj ); - // deref the fanins - if ( --p->pRefs[iVar0] == 0 ) - { - pFront[pIdToFront[iVar0] % p->nFront] = 0; - pIdToFront[iVar0] = -1; - nCrossCut--; - } - if ( --p->pRefs[iVar1] == 0 ) - { - pFront[pIdToFront[iVar1] % p->nFront] = 0; - pIdToFront[iVar1] = -1; - nCrossCut--; - } - // handle nodes without fanout (choice nodes) - if ( p->pRefs[i] == 0 ) - { - pFront[pIdToFront[i] % p->nFront] = 0; - pIdToFront[i] = -1; - } - } - if ( p->pRefs[i] ) - if ( nCrossCutMax < ++nCrossCut ) - nCrossCutMax = nCrossCut; - } - assert( p->pDataAig2 == NULL || p->pDataCur2 - p->pDataAig2 == (3 * p->nObjs) ); - assert( nCrossCut == 0 ); - assert( nCrossCutMax == p->nCrossCutMax ); - for ( i = 0; i < p->nFront; i++ ) - assert( pFront[i] == 0 ); - ABC_FREE( pFront ); - ABC_FREE( pIdToFront ); -// Fsim_ManVerifyFront( p ); - ABC_FREE( p->pFans0 ); - ABC_FREE( p->pFans1 ); - ABC_FREE( p->pRefs ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/fsim/fsimInt.h b/src/aig/fsim/fsimInt.h deleted file mode 100644 index f5dee298..00000000 --- a/src/aig/fsim/fsimInt.h +++ /dev/null @@ -1,138 +0,0 @@ -/**CFile**************************************************************** - - FileName [fsimInt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Fast sequential AIG simulator.] - - Synopsis [Internal declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: fsimInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __FSIM_INT_H__ -#define __FSIM_INT_H__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "saig.h" -#include "fsim.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -// simulation object -typedef struct Fsim_Obj_t_ Fsim_Obj_t; -struct Fsim_Obj_t_ -{ - int iNode; // the node ID - int iFan0; // the first fanin - int iFan1; // the second fanin -}; - -// fast sequential simulation manager -struct Fsim_Man_t_ -{ - // parameters - Aig_Man_t * pAig; // the AIG to be used for simulation - int nWords; // the number of simulation words - // AIG representation - int nPis; // the number of primary inputs - int nPos; // the number of primary outputs - int nCis; // the number of combinational inputs - int nCos; // the number of combinational outputs - int nNodes; // the number of internal nodes - int nObjs; // nCis + nNodes + nCos + 2 - int * pFans0; // fanin0 for all objects - int * pFans1; // fanin1 for all objects - int * pRefs; // reference counter for each node - int * pRefsCopy; // reference counter for each node - Vec_Int_t * vCis2Ids; // mapping of CIs into their PI ids - Vec_Int_t * vLos; // register outputs - Vec_Int_t * vLis; // register inputs - // cross-cut representation - int nCrossCut; // temporary cross-cut variable - int nCrossCutMax; // maximum cross-cut variable - int nFront; // the size of frontier - // derived AIG representation - int nDataAig; // the length of allocated data - unsigned char * pDataAig; // AIG representation - unsigned char * pDataCur; // AIG representation (current position) - int iNodePrev; // previous extracted value - int iNumber; // the number of the last object - Fsim_Obj_t Obj; // current object - // temporary AIG representation - int * pDataAig2; // temporary representation - int * pDataCur2; // AIG representation (current position) - // simulation information - unsigned * pDataSim; // simulation data - unsigned * pDataSimCis; // simulation data for CIs - unsigned * pDataSimCos; // simulation data for COs - // other information - int * pData1; - int * pData2; -}; - -static inline unsigned * Fsim_SimData( Fsim_Man_t * p, int i ) { return p->pDataSim + i * p->nWords; } -static inline unsigned * Fsim_SimDataCi( Fsim_Man_t * p, int i ) { return p->pDataSimCis + i * p->nWords; } -static inline unsigned * Fsim_SimDataCo( Fsim_Man_t * p, int i ) { return p->pDataSimCos + i * p->nWords; } - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline int Fsim_Var2Lit( int Var, int fCompl ) { return Var + Var + fCompl; } -static inline int Fsim_Lit2Var( int Lit ) { return Lit >> 1; } -static inline int Fsim_LitIsCompl( int Lit ) { return Lit & 1; } -static inline int Fsim_LitNot( int Lit ) { return Lit ^ 1; } -static inline int Fsim_LitNotCond( int Lit, int c ) { return Lit ^ (int)(c > 0); } -static inline int Fsim_LitRegular( int Lit ) { return Lit & ~01; } - -#define Fsim_ManForEachObj( p, pObj, i )\ - for ( i = 2, p->pDataCur = p->pDataAig, p->iNodePrev = 0, pObj = &p->Obj;\ - i < p->nObjs && Fsim_ManRestoreObj( p, pObj ); i++ ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== fsimFront.c ========================================================*/ -extern void Fsim_ManFront( Fsim_Man_t * p, int fCompressAig ); -/*=== fsimMan.c ==========================================================*/ -extern Fsim_Man_t * Fsim_ManCreate( Aig_Man_t * pAig ); -extern void Fsim_ManDelete( Fsim_Man_t * p ); -extern void Fsim_ManTest( Aig_Man_t * pAig ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/fsim/fsimMan.c b/src/aig/fsim/fsimMan.c deleted file mode 100644 index ea0cab43..00000000 --- a/src/aig/fsim/fsimMan.c +++ /dev/null @@ -1,212 +0,0 @@ -/**CFile**************************************************************** - - FileName [fsimMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Fast sequential AIG simulator.] - - Synopsis [Simulation manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: fsimMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fsimInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates fast simulation manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fsim_ManCreate_rec( Fsim_Man_t * p, Aig_Obj_t * pObj ) -{ - int iFan0, iFan1, iTemp; - assert( !Aig_IsComplement(pObj) ); - if ( pObj->iData ) - return pObj->iData; - assert( !Aig_ObjIsConst1(pObj) ); - if ( Aig_ObjIsNode(pObj) ) - { - iFan0 = Fsim_ManCreate_rec( p, Aig_ObjFanin0(pObj) ); - iFan1 = Fsim_ManCreate_rec( p, Aig_ObjFanin1(pObj) ); - assert( iFan0 != iFan1 ); - if ( --p->pRefs[iFan0] == 0 ) - p->nCrossCut--; - iFan0 = Fsim_Var2Lit( iFan0, Aig_ObjFaninC0(pObj) ); - if ( --p->pRefs[iFan1] == 0 ) - p->nCrossCut--; - iFan1 = Fsim_Var2Lit( iFan1, Aig_ObjFaninC1(pObj) ); - if ( p->pAig->pEquivs ) - Fsim_ManCreate_rec( p, Aig_ObjEquiv(p->pAig, pObj) ); - } - else if ( Aig_ObjIsPo(pObj) ) - { - assert( Aig_ObjRefs(pObj) == 0 ); - iFan0 = Fsim_ManCreate_rec( p, Aig_ObjFanin0(pObj) ); - if ( --p->pRefs[iFan0] == 0 ) - p->nCrossCut--; - iFan0 = Fsim_Var2Lit( iFan0, Aig_ObjFaninC0(pObj) ); - iFan1 = 0; - } - else - { - iFan0 = iFan1 = 0; - Vec_IntPush( p->vCis2Ids, Aig_ObjPioNum(pObj) ); - } - if ( iFan0 < iFan1 ) - iTemp = iFan0, iFan0 = iFan1, iFan1 = iTemp; - p->pFans0[p->nObjs] = iFan0; - p->pFans1[p->nObjs] = iFan1; - p->pRefs[p->nObjs] = Aig_ObjRefs(pObj); - if ( p->pRefs[p->nObjs] ) - if ( p->nCrossCutMax < ++p->nCrossCut ) - p->nCrossCutMax = p->nCrossCut; - return pObj->iData = p->nObjs++; -} - -/**Function************************************************************* - - Synopsis [Creates fast simulation manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fsim_Man_t * Fsim_ManCreate( Aig_Man_t * pAig ) -{ - Fsim_Man_t * p; - Aig_Obj_t * pObj; - int i, nObjs; - Aig_ManCleanData( pAig ); - p = (Fsim_Man_t *)ABC_ALLOC( Fsim_Man_t, 1 ); - memset( p, 0, sizeof(Fsim_Man_t) ); - p->pAig = pAig; - p->nPis = Saig_ManPiNum(pAig); - p->nPos = Saig_ManPoNum(pAig); - p->nCis = Aig_ManPiNum(pAig); - p->nCos = Aig_ManPoNum(pAig); - p->nNodes = Aig_ManNodeNum(pAig); - nObjs = p->nCis + p->nCos + p->nNodes + 2; - p->pFans0 = ABC_ALLOC( int, nObjs ); - p->pFans1 = ABC_ALLOC( int, nObjs ); - p->pRefs = ABC_ALLOC( int, nObjs ); - p->vCis2Ids = Vec_IntAlloc( Aig_ManPiNum(pAig) ); - // add objects (0=unused; 1=const1) - p->pFans0[0] = p->pFans1[0] = 0; - p->pFans0[1] = p->pFans1[1] = 0; - p->pRefs[0] = 0; - p->nObjs = 2; - pObj = Aig_ManConst1( pAig ); - pObj->iData = 1; - p->pRefs[1] = Aig_ObjRefs(pObj); - if ( p->pRefs[1] ) - p->nCrossCut = 1; - Aig_ManForEachPi( pAig, pObj, i ) - if ( Aig_ObjRefs(pObj) == 0 ) - Fsim_ManCreate_rec( p, pObj ); - Aig_ManForEachPo( pAig, pObj, i ) - Fsim_ManCreate_rec( p, pObj ); - assert( Vec_IntSize(p->vCis2Ids) == Aig_ManPiNum(pAig) ); - assert( p->nObjs == nObjs ); - // check references - assert( p->nCrossCut == 0 ); - Aig_ManForEachObj( pAig, pObj, i ) - { - assert( p->pRefs[pObj->iData] == 0 ); - p->pRefs[pObj->iData] = Aig_ObjRefs(pObj); - } - // collect flop outputs - p->vLos = Vec_IntAlloc( Aig_ManRegNum(pAig) ); - Saig_ManForEachLo( pAig, pObj, i ) - Vec_IntPush( p->vLos, pObj->iData ); - // collect flop inputs - p->vLis = Vec_IntAlloc( Aig_ManRegNum(pAig) ); - Saig_ManForEachLi( pAig, pObj, i ) - Vec_IntPush( p->vLis, pObj->iData ); - // determine the frontier size - p->nFront = 1 + (int)(1.1 * p->nCrossCutMax); - return p; -} - -/**Function************************************************************* - - Synopsis [Deletes fast simulation manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fsim_ManDelete( Fsim_Man_t * p ) -{ - Vec_IntFree( p->vCis2Ids ); - Vec_IntFree( p->vLos ); - Vec_IntFree( p->vLis ); - ABC_FREE( p->pDataAig2 ); - ABC_FREE( p->pDataAig ); - ABC_FREE( p->pFans0 ); - ABC_FREE( p->pFans1 ); - ABC_FREE( p->pRefs ); - ABC_FREE( p->pDataSim ); - ABC_FREE( p->pDataSimCis ); - ABC_FREE( p->pDataSimCos ); - ABC_FREE( p->pData1 ); - ABC_FREE( p->pData2 ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Testing procedure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fsim_ManTest( Aig_Man_t * pAig ) -{ - Fsim_Man_t * p; - p = Fsim_ManCreate( pAig ); - Fsim_ManFront( p, 0 ); - Fsim_ManDelete( p ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/fsim/fsimSim.c b/src/aig/fsim/fsimSim.c deleted file mode 100644 index 56aeab2f..00000000 --- a/src/aig/fsim/fsimSim.c +++ /dev/null @@ -1,567 +0,0 @@ -/**CFile**************************************************************** - - FileName [fsimSim.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Fast sequential AIG simulator.] - - Synopsis [Simulation procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: fsimSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fsimInt.h" -#include "ssw.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Fsim_ManSimInfoRandom( Fsim_Man_t * p, unsigned * pInfo ) -{ - int w; - for ( w = p->nWords-1; w >= 0; w-- ) - pInfo[w] = Aig_ManRandom( 0 ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Fsim_ManSimInfoZero( Fsim_Man_t * p, unsigned * pInfo ) -{ - int w; - for ( w = p->nWords-1; w >= 0; w-- ) - pInfo[w] = 0; -} - -/**Function************************************************************* - - Synopsis [Returns index of the first pattern that failed.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Fsim_ManSimInfoIsZero( Fsim_Man_t * p, unsigned * pInfo ) -{ - int w; - for ( w = p->nWords-1; w >= 0; w-- ) - if ( pInfo[w] ) - return 32*(w-1) + Aig_WordFindFirstBit( pInfo[w] ); - return -1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Fsim_ManSimInfoOne( Fsim_Man_t * p, unsigned * pInfo ) -{ - int w; - for ( w = p->nWords-1; w >= 0; w-- ) - pInfo[w] = ~0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Fsim_ManSimInfoCopy( Fsim_Man_t * p, unsigned * pInfo, unsigned * pInfo0 ) -{ - int w; - for ( w = p->nWords-1; w >= 0; w-- ) - pInfo[w] = pInfo0[w]; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Fsim_ManSimulateCi( Fsim_Man_t * p, int iNode, int iCi ) -{ - unsigned * pInfo = Fsim_SimData( p, iNode % p->nFront ); - unsigned * pInfo0 = Fsim_SimDataCi( p, iCi ); - int w; - for ( w = p->nWords-1; w >= 0; w-- ) - pInfo[w] = pInfo0[w]; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Fsim_ManSimulateCo( Fsim_Man_t * p, int iCo, int iFan0 ) -{ - unsigned * pInfo = Fsim_SimDataCo( p, iCo ); - unsigned * pInfo0 = Fsim_SimData( p, Fsim_Lit2Var(iFan0) % p->nFront ); - int w; - if ( Fsim_LitIsCompl(iFan0) ) - for ( w = p->nWords-1; w >= 0; w-- ) - pInfo[w] = ~pInfo0[w]; - else //if ( !Fsim_LitIsCompl(iFan0) ) - for ( w = p->nWords-1; w >= 0; w-- ) - pInfo[w] = pInfo0[w]; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Fsim_ManSimulateNode( Fsim_Man_t * p, int iNode, int iFan0, int iFan1 ) -{ - unsigned * pInfo = Fsim_SimData( p, iNode % p->nFront ); - unsigned * pInfo0 = Fsim_SimData( p, Fsim_Lit2Var(iFan0) % p->nFront ); - unsigned * pInfo1 = Fsim_SimData( p, Fsim_Lit2Var(iFan1) % p->nFront ); - int w; - if ( Fsim_LitIsCompl(iFan0) && Fsim_LitIsCompl(iFan1) ) - for ( w = p->nWords-1; w >= 0; w-- ) - pInfo[w] = ~(pInfo0[w] | pInfo1[w]); - else if ( Fsim_LitIsCompl(iFan0) && !Fsim_LitIsCompl(iFan1) ) - for ( w = p->nWords-1; w >= 0; w-- ) - pInfo[w] = ~pInfo0[w] & pInfo1[w]; - else if ( !Fsim_LitIsCompl(iFan0) && Fsim_LitIsCompl(iFan1) ) - for ( w = p->nWords-1; w >= 0; w-- ) - pInfo[w] = pInfo0[w] & ~pInfo1[w]; - else //if ( !Fsim_LitIsCompl(iFan0) && !Fsim_LitIsCompl(iFan1) ) - for ( w = p->nWords-1; w >= 0; w-- ) - pInfo[w] = pInfo0[w] & pInfo1[w]; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Fsim_ManSimInfoInit( Fsim_Man_t * p ) -{ - int iPioNum, i; - Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i ) - { - if ( iPioNum < p->nPis ) - Fsim_ManSimInfoRandom( p, Fsim_SimDataCi(p, i) ); - else - Fsim_ManSimInfoZero( p, Fsim_SimDataCi(p, i) ); - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Fsim_ManSimInfoTransfer( Fsim_Man_t * p ) -{ - int iPioNum, i; - Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i ) - { - if ( iPioNum < p->nPis ) - Fsim_ManSimInfoRandom( p, Fsim_SimDataCi(p, i) ); - else - Fsim_ManSimInfoCopy( p, Fsim_SimDataCi(p, i), Fsim_SimDataCo(p, p->nPos+iPioNum-p->nPis) ); - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Fsim_ManRestoreNum( Fsim_Man_t * p ) -{ - int ch, i, x = 0; - for ( i = 0; (ch = *p->pDataCur++) & 0x80; i++ ) - x |= (ch & 0x7f) << (7 * i); - assert( p->pDataCur - p->pDataAig < p->nDataAig ); - return x | (ch << (7 * i)); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Fsim_ManRestoreObj( Fsim_Man_t * p, Fsim_Obj_t * pObj ) -{ - int iValue = Fsim_ManRestoreNum( p ); - if ( (iValue & 3) == 3 ) // and - { - pObj->iNode = (iValue >> 2) + p->iNodePrev; - pObj->iFan0 = (pObj->iNode << 1) - Fsim_ManRestoreNum( p ); - pObj->iFan1 = pObj->iFan0 - Fsim_ManRestoreNum( p ); - p->iNodePrev = pObj->iNode; - } - else if ( (iValue & 3) == 1 ) // ci - { - pObj->iNode = (iValue >> 2) + p->iNodePrev; - pObj->iFan0 = 0; - pObj->iFan1 = 0; - p->iNodePrev = pObj->iNode; - } - else // if ( (iValue & 1) == 0 ) // co - { - pObj->iNode = 0; - pObj->iFan0 = ((p->iNodePrev << 1) | 1) - (iValue >> 1); - pObj->iFan1 = 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Fsim_ManSimulateRound2( Fsim_Man_t * p ) -{ - Fsim_Obj_t * pObj; - int i, iCis = 0, iCos = 0; - if ( Aig_ObjRefs(Aig_ManConst1(p->pAig)) ) - Fsim_ManSimInfoOne( p, Fsim_SimData(p, 1) ); - Fsim_ManForEachObj( p, pObj, i ) - { - if ( pObj->iFan0 == 0 ) - Fsim_ManSimulateCi( p, pObj->iNode, iCis++ ); - else if ( pObj->iFan1 == 0 ) - Fsim_ManSimulateCo( p, iCos++, pObj->iFan0 ); - else - Fsim_ManSimulateNode( p, pObj->iNode, pObj->iFan0, pObj->iFan1 ); - } - assert( iCis == p->nCis ); - assert( iCos == p->nCos ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Fsim_ManSimulateRound( Fsim_Man_t * p ) -{ - int * pCur, * pEnd; - int iCis = 0, iCos = 0; - if ( p->pDataAig2 == NULL ) - { - Fsim_ManSimulateRound2( p ); - return; - } - if ( Aig_ObjRefs(Aig_ManConst1(p->pAig)) ) - Fsim_ManSimInfoOne( p, Fsim_SimData(p, 1) ); - pCur = p->pDataAig2 + 6; - pEnd = p->pDataAig2 + 3 * p->nObjs; - while ( pCur < pEnd ) - { - if ( pCur[1] == 0 ) - Fsim_ManSimulateCi( p, pCur[0], iCis++ ); - else if ( pCur[2] == 0 ) - Fsim_ManSimulateCo( p, iCos++, pCur[1] ); - else - Fsim_ManSimulateNode( p, pCur[0], pCur[1], pCur[2] ); - pCur += 3; - } - assert( iCis == p->nCis ); - assert( iCos == p->nCos ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fsim_ManSimulateRoundTest( Fsim_Man_t * p ) -{ - Fsim_Obj_t * pObj; - int i, clk = clock(); - Fsim_ManForEachObj( p, pObj, i ) - { - } -// ABC_PRT( "Unpacking time", p->pPars->nIters * (clock() - clk) ); -} - -/**Function************************************************************* - - Synopsis [Returns index of the PO and pattern that failed it.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Fsim_ManCheckPos( Fsim_Man_t * p, int * piPo, int * piPat ) -{ - int i, iPat; - for ( i = 0; i < p->nPos; i++ ) - { - iPat = Fsim_ManSimInfoIsZero( p, Fsim_SimDataCo(p, i) ); - if ( iPat >= 0 ) - { - *piPo = i; - *piPat = iPat; - return 1; - } - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Returns the counter-example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Cex_t * Fsim_ManGenerateCounter( Aig_Man_t * pAig, int iFrame, int iOut, int nWords, int iPat, Vec_Int_t * vCis2Ids ) -{ - Abc_Cex_t * p; - unsigned * pData; - int f, i, w, iPioId, Counter; - p = Abc_CexAlloc( Aig_ManRegNum(pAig), Saig_ManPiNum(pAig), iFrame+1 ); - p->iFrame = iFrame; - p->iPo = iOut; - // fill in the binary data - Aig_ManRandom( 1 ); - Counter = p->nRegs; - pData = ABC_ALLOC( unsigned, nWords ); - for ( f = 0; f <= iFrame; f++, Counter += p->nPis ) - for ( i = 0; i < Aig_ManPiNum(pAig); i++ ) - { - iPioId = Vec_IntEntry( vCis2Ids, i ); - if ( iPioId >= p->nPis ) - continue; - for ( w = nWords-1; w >= 0; w-- ) - pData[w] = Aig_ManRandom( 0 ); - if ( Aig_InfoHasBit( pData, iPat ) ) - Aig_InfoSetBit( p->pData, Counter + iPioId ); - } - ABC_FREE( pData ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fsim_ManSimulate( Aig_Man_t * pAig, Fsim_ParSim_t * pPars ) -{ - Fsim_Man_t * p; - Sec_MtrStatus_t Status; - int i, iOut, iPat, clk, clkTotal = clock(), clk2, clk2Total = 0; - assert( Aig_ManRegNum(pAig) > 0 ); - if ( pPars->fCheckMiter ) - { - Status = Sec_MiterStatus( pAig ); - if ( Status.nSat > 0 ) - { - printf( "Miter is trivially satisfiable (output %d).\n", Status.iOut ); - return 1; - } - if ( Status.nUndec == 0 ) - { - printf( "Miter is trivially unsatisfiable.\n" ); - return 0; - } - } - // create manager - clk = clock(); - p = Fsim_ManCreate( pAig ); - p->nWords = pPars->nWords; - if ( pPars->fVerbose ) - { - printf( "Obj = %8d (%8d). Cut = %6d. Front = %6d. FrtMem = %7.2f Mb. ", - p->nObjs, p->nCis + p->nNodes, p->nCrossCutMax, p->nFront, - 4.0*p->nWords*(p->nFront)/(1<<20) ); - ABC_PRT( "Time", clock() - clk ); - } - // create simulation frontier - clk = clock(); - Fsim_ManFront( p, pPars->fCompressAig ); - if ( pPars->fVerbose ) - { - printf( "Max ID = %8d. Log max ID = %2d. AigMem = %7.2f Mb (%5.2f byte/obj). ", - p->iNumber, Aig_Base2Log(p->iNumber), - 1.0*(p->pDataCur-p->pDataAig)/(1<<20), - 1.0*(p->pDataCur-p->pDataAig)/p->nObjs ); - ABC_PRT( "Time", clock() - clk ); - } - // perform simulation - Aig_ManRandom( 1 ); - assert( p->pDataSim == NULL ); - p->pDataSim = ABC_ALLOC( unsigned, p->nWords * p->nFront ); - p->pDataSimCis = ABC_ALLOC( unsigned, p->nWords * p->nCis ); - p->pDataSimCos = ABC_ALLOC( unsigned, p->nWords * p->nCos ); - Fsim_ManSimInfoInit( p ); - for ( i = 0; i < pPars->nIters; i++ ) - { - Fsim_ManSimulateRound( p ); - if ( pPars->fVerbose ) - { - printf( "Frame %4d out of %4d and timeout %3d sec. ", i+1, pPars->nIters, pPars->TimeLimit ); - printf( "Time = %7.2f sec\r", (1.0*clock()-clkTotal)/CLOCKS_PER_SEC ); - } - if ( pPars->fCheckMiter && Fsim_ManCheckPos( p, &iOut, &iPat ) ) - { - assert( pAig->pSeqModel == NULL ); - pAig->pSeqModel = Fsim_ManGenerateCounter( pAig, i, iOut, p->nWords, iPat, p->vCis2Ids ); - if ( pPars->fVerbose ) - printf( "Miter is satisfiable after simulation (output %d).\n", iOut ); - break; - } - if ( (clock() - clkTotal)/CLOCKS_PER_SEC >= pPars->TimeLimit ) - break; - clk2 = clock(); - if ( i < pPars->nIters - 1 ) - Fsim_ManSimInfoTransfer( p ); - clk2Total += clock() - clk2; - } - if ( pAig->pSeqModel == NULL ) - printf( "No bug detected after %d frames with time limit %d seconds.\n", i+1, pPars->TimeLimit ); - if ( pPars->fVerbose ) - { - printf( "Maxcut = %8d. AigMem = %7.2f Mb. SimMem = %7.2f Mb. ", - p->nCrossCutMax, - p->pDataAig2? 12.0*p->nObjs/(1<<20) : 1.0*(p->pDataCur-p->pDataAig)/(1<<20), - 4.0*p->nWords*(p->nFront+p->nCis+p->nCos)/(1<<20) ); - ABC_PRT( "Sim time", clock() - clkTotal ); - -// ABC_PRT( "Additional time", clk2Total ); -// Fsim_ManSimulateRoundTest( p ); -// Fsim_ManSimulateRoundTest2( p ); - } - Fsim_ManDelete( p ); - return pAig->pSeqModel != NULL; - -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/fsim/fsimSwitch.c b/src/aig/fsim/fsimSwitch.c deleted file mode 100644 index 3eef2d4c..00000000 --- a/src/aig/fsim/fsimSwitch.c +++ /dev/null @@ -1,40 +0,0 @@ -/**CFile**************************************************************** - - FileName [fsimSwitch.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Fast sequential AIG simulator.] - - Synopsis [Computing switching activity.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: fsimSwitch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fsimInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/fsim/fsimTsim.c b/src/aig/fsim/fsimTsim.c deleted file mode 100644 index e05e6409..00000000 --- a/src/aig/fsim/fsimTsim.c +++ /dev/null @@ -1,415 +0,0 @@ -/**CFile**************************************************************** - - FileName [fsimTsim.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Fast sequential AIG simulator.] - - Synopsis [Varius utilities.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: fsimTsim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fsimInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define FSIM_ZER 1 -#define FSIM_ONE 2 -#define FSIM_UND 3 - -static inline int Aig_XsimNotCond( int Value, int fCompl ) -{ - if ( Value == FSIM_UND ) - return FSIM_UND; - if ( Value == FSIM_ZER + fCompl ) - return FSIM_ZER; - return FSIM_ONE; -} -static inline int Aig_XsimAndCond( int Value0, int fCompl0, int Value1, int fCompl1 ) -{ - if ( Value0 == FSIM_UND || Value1 == FSIM_UND ) - return FSIM_UND; - if ( Value0 == FSIM_ZER + fCompl0 || Value1 == FSIM_ZER + fCompl1 ) - return FSIM_ZER; - return FSIM_ONE; -} - -static inline int Fsim_ManTerSimInfoGet( unsigned * pInfo, int i ) -{ - return 3 & (pInfo[i >> 4] >> ((i & 15) << 1)); -} -static inline void Fsim_ManTerSimInfoSet( unsigned * pInfo, int i, int Value ) -{ - assert( Value >= FSIM_ZER && Value <= FSIM_UND ); - Value ^= Fsim_ManTerSimInfoGet( pInfo, i ); - pInfo[i >> 4] ^= (Value << ((i & 15) << 1)); -} - -static inline unsigned * Fsim_ManTerStateNext( unsigned * pState, int nWords ) { return *((unsigned **)(pState + nWords)); } -static inline void Fsim_ManTerStateSetNext( unsigned * pState, int nWords, unsigned * pNext ) { *((unsigned **)(pState + nWords)) = pNext; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Fsim_ManTerSimulateCi( Fsim_Man_t * p, int iNode, int iCi ) -{ - Fsim_ManTerSimInfoSet( p->pDataSim, iNode, Fsim_ManTerSimInfoGet(p->pDataSimCis, iCi) ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Fsim_ManTerSimulateCo( Fsim_Man_t * p, int iCo, int iFan0 ) -{ - int Value = Fsim_ManTerSimInfoGet( p->pDataSim, Fsim_Lit2Var(iFan0) ); - Fsim_ManTerSimInfoSet( p->pDataSimCos, iCo, Aig_XsimNotCond( Value, Fsim_LitIsCompl(iFan0) ) ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Fsim_ManTerSimulateNode( Fsim_Man_t * p, int iNode, int iFan0, int iFan1 ) -{ - int Value0 = Fsim_ManTerSimInfoGet( p->pDataSim, Fsim_Lit2Var(iFan0) ); - int Value1 = Fsim_ManTerSimInfoGet( p->pDataSim, Fsim_Lit2Var(iFan1) ); - Fsim_ManTerSimInfoSet( p->pDataSim, iNode, Aig_XsimAndCond( Value0, Fsim_LitIsCompl(iFan0), Value1, Fsim_LitIsCompl(iFan1) ) ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Fsim_ManTerSimInfoInit( Fsim_Man_t * p ) -{ - int iPioNum, i; - Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i ) - { - if ( iPioNum < p->nPis ) - Fsim_ManTerSimInfoSet( p->pDataSimCis, i, FSIM_UND ); - else - Fsim_ManTerSimInfoSet( p->pDataSimCis, i, FSIM_ZER ); - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Fsim_ManTerSimInfoTransfer( Fsim_Man_t * p ) -{ - int iPioNum, i; - Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i ) - { - if ( iPioNum < p->nPis ) - Fsim_ManTerSimInfoSet( p->pDataSimCis, i, FSIM_UND ); - else - Fsim_ManTerSimInfoSet( p->pDataSimCis, i, Fsim_ManTerSimInfoGet( p->pDataSimCos, p->nPos+iPioNum-p->nPis ) ); - } -} - - -/**Function************************************************************* - - Synopsis [Computes hash value of the node using its simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fsim_ManTerStateHash( 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 Fsim_ManTerStateLookup( unsigned * pState, int nWords, unsigned ** pBins, int nBins ) -{ - unsigned * pEntry; - int Hash; - Hash = Fsim_ManTerStateHash( pState, nWords, nBins ); - for ( pEntry = pBins[Hash]; pEntry; pEntry = Fsim_ManTerStateNext(pEntry, nWords) ) - if ( !memcmp( pEntry, pState, sizeof(unsigned) * nWords ) ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Inserts value into the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fsim_ManTerStateInsert( unsigned * pState, int nWords, unsigned ** pBins, int nBins ) -{ - int Hash = Fsim_ManTerStateHash( pState, nWords, nBins ); - assert( !Fsim_ManTerStateLookup( pState, nWords, pBins, nBins ) ); - Fsim_ManTerStateSetNext( pState, nWords, pBins[Hash] ); - pBins[Hash] = pState; -} - -/**Function************************************************************* - - Synopsis [Inserts value into the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Fsim_ManTerStateCreate( unsigned * pInfo, int nPis, int nCis, int nWords ) -{ - unsigned * pRes; - int i; - pRes = (unsigned *)ABC_CALLOC( char, sizeof(unsigned) * nWords + sizeof(unsigned *) ); - for ( i = nPis; i < nCis; i++ ) - Fsim_ManTerSimInfoSet( pRes, i-nPis, Fsim_ManTerSimInfoGet(pInfo, i) ); - return pRes; -} - -/**Function************************************************************* - - Synopsis [Inserts value into the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fsim_ManTerStatePrint( unsigned * pState, int nRegs ) -{ - int i, Value, nZeros = 0, nOnes = 0, nDcs = 0; - for ( i = 0; i < nRegs; 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 [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Fsim_ManTerSimulateRound( Fsim_Man_t * p ) -{ - int * pCur, * pEnd; - int iCis = 0, iCos = 0; - if ( Aig_ObjRefs(Aig_ManConst1(p->pAig)) ) - Fsim_ManTerSimInfoSet( p->pDataSimCis, 1, FSIM_ONE ); - pCur = p->pDataAig2 + 6; - pEnd = p->pDataAig2 + 3 * p->nObjs; - while ( pCur < pEnd ) - { - if ( pCur[1] == 0 ) - Fsim_ManTerSimulateCi( p, pCur[0], iCis++ ); - else if ( pCur[2] == 0 ) - Fsim_ManTerSimulateCo( p, iCos++, pCur[1] ); - else - Fsim_ManTerSimulateNode( p, pCur[0], pCur[1], pCur[2] ); - pCur += 3; - } - assert( iCis == p->nCis ); - assert( iCos == p->nCos ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Fsim_ManTerSimulate( Aig_Man_t * pAig, int fVerbose ) -{ - Fsim_Man_t * p; - Vec_Ptr_t * vStates; - unsigned ** pBins, * pState; - int i, nWords, nBins, clk, clkTotal = clock(); - assert( Aig_ManRegNum(pAig) > 0 ); - // create manager - clk = clock(); - p = Fsim_ManCreate( pAig ); - if ( fVerbose ) - { - printf( "Obj = %8d (%8d). Cut = %6d. Front = %6d. FrtMem = %7.2f Mb. ", - p->nObjs, p->nCis + p->nNodes, p->nCrossCutMax, p->nFront, - 4.0*Aig_BitWordNum(2 * p->nFront)/(1<<20) ); - ABC_PRT( "Time", clock() - clk ); - } - // create simulation frontier - clk = clock(); - Fsim_ManFront( p, 0 ); - if ( fVerbose ) - { - printf( "Max ID = %8d. Log max ID = %2d. AigMem = %7.2f Mb (%5.2f byte/obj). ", - p->iNumber, Aig_Base2Log(p->iNumber), - 1.0*(p->pDataCur-p->pDataAig)/(1<<20), - 1.0*(p->pDataCur-p->pDataAig)/p->nObjs ); - ABC_PRT( "Time", clock() - clk ); - } - // allocate storage for terminary states - nWords = Aig_BitWordNum( 2*Aig_ManRegNum(pAig) ); - vStates = Vec_PtrAlloc( 1000 ); - nBins = Aig_PrimeCudd( 500 ); - pBins = ABC_ALLOC( unsigned *, nBins ); - memset( pBins, 0, sizeof(unsigned *) * nBins ); - // perform simulation - assert( p->pDataSim == NULL ); - p->pDataSim = ABC_ALLOC( unsigned, Aig_BitWordNum(2 * p->nFront) * sizeof(unsigned) ); - p->pDataSimCis = ABC_ALLOC( unsigned, Aig_BitWordNum(2 * p->nCis) * sizeof(unsigned) ); - p->pDataSimCos = ABC_ALLOC( unsigned, Aig_BitWordNum(2 * p->nCos) * sizeof(unsigned) ); - Fsim_ManTerSimInfoInit( p ); - // hash the first state - pState = Fsim_ManTerStateCreate( p->pDataSimCis, p->nPis, p->nCis, nWords ); - Vec_PtrPush( vStates, pState ); - Fsim_ManTerStateInsert( pState, nWords, pBins, nBins ); - // perform simuluation till convergence - for ( i = 0; ; i++ ) - { - Fsim_ManTerSimulateRound( p ); - Fsim_ManTerSimInfoTransfer( p ); - // hash the first state - pState = Fsim_ManTerStateCreate( p->pDataSimCis, p->nPis, p->nCis, nWords ); - Vec_PtrPush( vStates, pState ); - if ( Fsim_ManTerStateLookup(pState, nWords, pBins, nBins) ) - break; - Fsim_ManTerStateInsert( pState, nWords, pBins, nBins ); - } - if ( fVerbose ) - { - printf( "Maxcut = %8d. AigMem = %7.2f Mb. SimMem = %7.2f Mb. ", - p->nCrossCutMax, - p->pDataAig2? 12.0*p->nObjs/(1<<20) : 1.0*(p->pDataCur-p->pDataAig)/(1<<20), - 4.0*(Aig_BitWordNum(2 * p->nFront)+Aig_BitWordNum(2 * p->nCis)+Aig_BitWordNum(2 * p->nCos))/(1<<20) ); - ABC_PRT( "Sim time", clock() - clkTotal ); - } - ABC_FREE( pBins ); - Fsim_ManDelete( p ); - return vStates; - -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/fsim/module.make b/src/aig/fsim/module.make deleted file mode 100644 index 91c733c3..00000000 --- a/src/aig/fsim/module.make +++ /dev/null @@ -1,6 +0,0 @@ -SRC += src/aig/fsim/fsimCore.c \ - src/aig/fsim/fsimFront.c \ - src/aig/fsim/fsimMan.c \ - src/aig/fsim/fsimSim.c \ - src/aig/fsim/fsimSwitch.c \ - src/aig/fsim/fsimTsim.c diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index 14fd4d6e..a784ab92 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __GIA_H__ -#define __GIA_H__ +#ifndef ABC__aig__gia__gia_h +#define ABC__aig__gia__gia_h //////////////////////////////////////////////////////////////////////// @@ -32,8 +32,8 @@ #include #include -#include "vec.h" -#include "utilCex.h" +#include "src/misc/vec/vec.h" +#include "src/misc/util/utilCex.h" #include "giaAbs.h" //////////////////////////////////////////////////////////////////////// @@ -210,19 +210,6 @@ struct Gia_ParVta_t_ int iFrame; // the number of frames covered }; -static inline int Gia_IntAbs( int n ) { return (n < 0)? -n : n; } -static inline int Gia_Float2Int( float Val ) { union { int x; float y; } v; v.y = Val; return v.x; } -static inline float Gia_Int2Float( int Num ) { union { int x; float y; } v; v.x = Num; return v.y; } -static inline int Gia_Base2Log( unsigned n ) { int r; if ( n < 2 ) return n; for ( r = 0, n--; n; n >>= 1, r++ ); return r; } -static inline int Gia_Base10Log( unsigned n ) { int r; if ( n < 2 ) return n; for ( r = 0, n--; n; n /= 10, r++ ); return r; } -static inline int Gia_Base16Log( unsigned n ) { int r; if ( n < 2 ) return n; for ( r = 0, n--; n; n /= 16, r++ ); return r; } -static inline char * Gia_UtilStrsav( char * s ) { return s ? strcpy(ABC_ALLOC(char, strlen(s)+1), s) : NULL; } -static inline int Gia_BitWordNum( int nBits ) { return (nBits>>5) + ((nBits&31) > 0); } -static inline int Gia_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } -static inline int Gia_InfoHasBit( unsigned * p, int i ) { return (p[(i)>>5] & (1<<((i) & 31))) > 0; } -static inline void Gia_InfoSetBit( unsigned * p, int i ) { p[(i)>>5] |= (1<<((i) & 31)); } -static inline void Gia_InfoXorBit( unsigned * p, int i ) { p[(i)>>5] ^= (1<<((i) & 31)); } -static inline unsigned Gia_InfoMask( int nVar ) { return (~(unsigned)0) >> (32-nVar); } static inline unsigned Gia_ObjCutSign( unsigned ObjId ) { return (1 << (ObjId & 31)); } static inline int Gia_WordHasOneBit( unsigned uWord ) { return (uWord & (uWord-1)) == 0; } static inline int Gia_WordHasOnePair( unsigned uWord ) { return Gia_WordHasOneBit(uWord & (uWord>>1) & 0x55555555); } @@ -246,7 +233,7 @@ static inline int Gia_WordFindFirstBit( unsigned uWord ) static inline int Gia_ManTruthIsConst0( unsigned * pIn, int nVars ) { int w; - for ( w = Gia_TruthWordNum(nVars)-1; w >= 0; w-- ) + for ( w = Abc_TruthWordNum(nVars)-1; w >= 0; w-- ) if ( pIn[w] ) return 0; return 1; @@ -254,7 +241,7 @@ static inline int Gia_ManTruthIsConst0( unsigned * pIn, int nVars ) static inline int Gia_ManTruthIsConst1( unsigned * pIn, int nVars ) { int w; - for ( w = Gia_TruthWordNum(nVars)-1; w >= 0; w-- ) + for ( w = Abc_TruthWordNum(nVars)-1; w >= 0; w-- ) if ( pIn[w] != ~(unsigned)0 ) return 0; return 1; @@ -262,35 +249,28 @@ static inline int Gia_ManTruthIsConst1( unsigned * pIn, int nVars ) static inline void Gia_ManTruthCopy( unsigned * pOut, unsigned * pIn, int nVars ) { int w; - for ( w = Gia_TruthWordNum(nVars)-1; w >= 0; w-- ) + for ( w = Abc_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = pIn[w]; } static inline void Gia_ManTruthClear( unsigned * pOut, int nVars ) { int w; - for ( w = Gia_TruthWordNum(nVars)-1; w >= 0; w-- ) + for ( w = Abc_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = 0; } static inline void Gia_ManTruthFill( unsigned * pOut, int nVars ) { int w; - for ( w = Gia_TruthWordNum(nVars)-1; w >= 0; w-- ) + for ( w = Abc_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = ~(unsigned)0; } static inline void Gia_ManTruthNot( unsigned * pOut, unsigned * pIn, int nVars ) { int w; - for ( w = Gia_TruthWordNum(nVars)-1; w >= 0; w-- ) + for ( w = Abc_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = ~pIn[w]; } -static inline int Gia_Var2Lit( int Var, int fCompl ) { return Var + Var + fCompl; } -static inline int Gia_Lit2Var( int Lit ) { return Lit >> 1; } -static inline int Gia_LitIsCompl( int Lit ) { return Lit & 1; } -static inline int Gia_LitNot( int Lit ) { return Lit ^ 1; } -static inline int Gia_LitNotCond( int Lit, int c ) { return Lit ^ (int)(c > 0); } -static inline int Gia_LitRegular( int Lit ) { return Lit & ~01; } - static inline Gia_Obj_t * Gia_Regular( Gia_Obj_t * p ) { return (Gia_Obj_t *)((ABC_PTRUINT_T)(p) & ~01); } static inline Gia_Obj_t * Gia_Not( Gia_Obj_t * p ) { return (Gia_Obj_t *)((ABC_PTRUINT_T)(p) ^ 01); } static inline Gia_Obj_t * Gia_NotCond( Gia_Obj_t * p, int c ) { return (Gia_Obj_t *)((ABC_PTRUINT_T)(p) ^ (c)); } @@ -358,33 +338,33 @@ static inline int Gia_ObjFaninId0( Gia_Obj_t * pObj, int ObjId ) { static inline int Gia_ObjFaninId1( Gia_Obj_t * pObj, int ObjId ) { return ObjId - pObj->iDiff1; } static inline int Gia_ObjFaninId0p( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjFaninId0( pObj, Gia_ObjId(p, pObj) ); } static inline int Gia_ObjFaninId1p( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjFaninId1( pObj, Gia_ObjId(p, pObj) ); } -static inline int Gia_ObjFaninLit0( Gia_Obj_t * pObj, int ObjId ) { return Gia_Var2Lit( Gia_ObjFaninId0(pObj, ObjId), Gia_ObjFaninC0(pObj) ); } -static inline int Gia_ObjFaninLit1( Gia_Obj_t * pObj, int ObjId ) { return Gia_Var2Lit( Gia_ObjFaninId1(pObj, ObjId), Gia_ObjFaninC1(pObj) ); } -static inline int Gia_ObjFaninLit0p( Gia_Man_t * p, Gia_Obj_t * pObj) { return Gia_Var2Lit( Gia_ObjFaninId0p(p, pObj), Gia_ObjFaninC0(pObj) ); } -static inline int Gia_ObjFaninLit1p( Gia_Man_t * p, Gia_Obj_t * pObj) { return Gia_Var2Lit( Gia_ObjFaninId1p(p, pObj), Gia_ObjFaninC1(pObj) ); } +static inline int Gia_ObjFaninLit0( Gia_Obj_t * pObj, int ObjId ) { return Abc_Var2Lit( Gia_ObjFaninId0(pObj, ObjId), Gia_ObjFaninC0(pObj) ); } +static inline int Gia_ObjFaninLit1( Gia_Obj_t * pObj, int ObjId ) { return Abc_Var2Lit( Gia_ObjFaninId1(pObj, ObjId), Gia_ObjFaninC1(pObj) ); } +static inline int Gia_ObjFaninLit0p( Gia_Man_t * p, Gia_Obj_t * pObj) { return Abc_Var2Lit( Gia_ObjFaninId0p(p, pObj), Gia_ObjFaninC0(pObj) ); } +static inline int Gia_ObjFaninLit1p( Gia_Man_t * p, Gia_Obj_t * pObj) { return Abc_Var2Lit( Gia_ObjFaninId1p(p, pObj), Gia_ObjFaninC1(pObj) ); } static inline void Gia_ObjFlipFaninC0( Gia_Obj_t * pObj ) { assert( Gia_ObjIsCo(pObj) ); pObj->fCompl0 ^= 1; } static inline int Gia_ObjWhatFanin( Gia_Obj_t * pObj, Gia_Obj_t * pFanin ) { return Gia_ObjFanin0(pObj) == pFanin ? 0 : (Gia_ObjFanin1(pObj) == pFanin ? 1 : -1); } -static inline Gia_Obj_t * Gia_ObjCopy( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ManObj( p, Gia_Lit2Var(pObj->Value) ); } +static inline Gia_Obj_t * Gia_ObjCopy( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ManObj( p, Abc_Lit2Var(pObj->Value) ); } -static inline int Gia_ObjFanin0Copy( Gia_Obj_t * pObj ) { return Gia_LitNotCond( Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj) ); } -static inline int Gia_ObjFanin1Copy( Gia_Obj_t * pObj ) { return Gia_LitNotCond( Gia_ObjFanin1(pObj)->Value, Gia_ObjFaninC1(pObj) ); } +static inline int Gia_ObjFanin0Copy( Gia_Obj_t * pObj ) { return Abc_LitNotCond( Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj) ); } +static inline int Gia_ObjFanin1Copy( Gia_Obj_t * pObj ) { return Abc_LitNotCond( Gia_ObjFanin1(pObj)->Value, Gia_ObjFaninC1(pObj) ); } static inline int Gia_ObjCopyF( Gia_Man_t * p, int f, Gia_Obj_t * pObj ) { return p->pCopies[Gia_ManObjNum(p) * f + Gia_ObjId(p,pObj)]; } static inline void Gia_ObjSetCopyF( Gia_Man_t * p, int f, Gia_Obj_t * pObj, int iLit ) { p->pCopies[Gia_ManObjNum(p) * f + Gia_ObjId(p,pObj)] = iLit; } -static inline int Gia_ObjFanin0CopyF( Gia_Man_t * p, int f, Gia_Obj_t * pObj ) { return Gia_LitNotCond(Gia_ObjCopyF(p, f, Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj)); } -static inline int Gia_ObjFanin1CopyF( Gia_Man_t * p, int f, Gia_Obj_t * pObj ) { return Gia_LitNotCond(Gia_ObjCopyF(p, f, Gia_ObjFanin1(pObj)), Gia_ObjFaninC1(pObj)); } +static inline int Gia_ObjFanin0CopyF( Gia_Man_t * p, int f, Gia_Obj_t * pObj ) { return Abc_LitNotCond(Gia_ObjCopyF(p, f, Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj)); } +static inline int Gia_ObjFanin1CopyF( Gia_Man_t * p, int f, Gia_Obj_t * pObj ) { return Abc_LitNotCond(Gia_ObjCopyF(p, f, Gia_ObjFanin1(pObj)), Gia_ObjFaninC1(pObj)); } -static inline Gia_Obj_t * Gia_ObjFromLit( Gia_Man_t * p, int iLit ) { return Gia_NotCond( Gia_ManObj(p, Gia_Lit2Var(iLit)), Gia_LitIsCompl(iLit) ); } -static inline int Gia_ObjToLit( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_Var2Lit( Gia_ObjId(p, Gia_Regular(pObj)), Gia_IsComplement(pObj) ); } +static inline Gia_Obj_t * Gia_ObjFromLit( Gia_Man_t * p, int iLit ) { return Gia_NotCond( Gia_ManObj(p, Abc_Lit2Var(iLit)), Abc_LitIsCompl(iLit) ); } +static inline int Gia_ObjToLit( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Abc_Var2Lit( Gia_ObjId(p, Gia_Regular(pObj)), Gia_IsComplement(pObj) ); } static inline int Gia_ObjPhaseRealLit( Gia_Man_t * p, int iLit ) { return Gia_ObjPhaseReal( Gia_ObjFromLit(p, iLit) ); } static inline int Gia_ObjLevel( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Vec_IntGetEntry(p->vLevels, Gia_ObjId(p,pObj)); } static inline int Gia_ObjLevelId( Gia_Man_t * p, int Id ) { return Vec_IntGetEntry(p->vLevels, Id); } static inline void Gia_ObjSetLevel( Gia_Man_t * p, Gia_Obj_t * pObj, int l ) { Vec_IntSetEntry(p->vLevels, Gia_ObjId(p,pObj), l); } static inline void Gia_ObjSetCoLevel( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjIsCo(pObj) ); Gia_ObjSetLevel( p, pObj, Gia_ObjLevel(p,Gia_ObjFanin0(pObj)) ); } -static inline void Gia_ObjSetAndLevel( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjIsAnd(pObj) ); Gia_ObjSetLevel( p, pObj, 1+ABC_MAX(Gia_ObjLevel(p,Gia_ObjFanin0(pObj)),Gia_ObjLevel(p,Gia_ObjFanin1(pObj))) ); } +static inline void Gia_ObjSetAndLevel( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjIsAnd(pObj) ); Gia_ObjSetLevel( p, pObj, 1+Abc_MaxInt(Gia_ObjLevel(p,Gia_ObjFanin0(pObj)),Gia_ObjLevel(p,Gia_ObjFanin1(pObj))) ); } static inline int Gia_ObjRefs( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( p->pRefs); return p->pRefs[Gia_ObjId(p, pObj)]; } static inline int Gia_ObjRefsId( Gia_Man_t * p, int Id ) { assert( p->pRefs); return p->pRefs[Id]; } @@ -457,17 +437,17 @@ static inline int Gia_ManAppendAnd( Gia_Man_t * p, int iLit0, int iLit1 ) assert( iLit0 != iLit1 ); if ( iLit0 < iLit1 ) { - pObj->iDiff0 = Gia_ObjId(p, pObj) - Gia_Lit2Var(iLit0); - pObj->fCompl0 = Gia_LitIsCompl(iLit0); - pObj->iDiff1 = Gia_ObjId(p, pObj) - Gia_Lit2Var(iLit1); - pObj->fCompl1 = Gia_LitIsCompl(iLit1); + pObj->iDiff0 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0); + pObj->fCompl0 = Abc_LitIsCompl(iLit0); + pObj->iDiff1 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1); + pObj->fCompl1 = Abc_LitIsCompl(iLit1); } else { - pObj->iDiff1 = Gia_ObjId(p, pObj) - Gia_Lit2Var(iLit0); - pObj->fCompl1 = Gia_LitIsCompl(iLit0); - pObj->iDiff0 = Gia_ObjId(p, pObj) - Gia_Lit2Var(iLit1); - pObj->fCompl0 = Gia_LitIsCompl(iLit1); + pObj->iDiff1 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0); + pObj->fCompl1 = Abc_LitIsCompl(iLit0); + pObj->iDiff0 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1); + pObj->fCompl0 = Abc_LitIsCompl(iLit1); } if ( p->pFanData ) { @@ -480,8 +460,8 @@ static inline int Gia_ManAppendCo( Gia_Man_t * p, int iLit0 ) { Gia_Obj_t * pObj = Gia_ManAppendObj( p ); pObj->fTerm = 1; - pObj->iDiff0 = Gia_ObjId(p, pObj) - Gia_Lit2Var(iLit0); - pObj->fCompl0 = Gia_LitIsCompl(iLit0); + pObj->iDiff0 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0); + pObj->fCompl0 = Abc_LitIsCompl(iLit0); pObj->iDiff1 = Vec_IntSize( p->vCos ); Vec_IntPush( p->vCos, Gia_ObjId(p, pObj) ); if ( p->pFanData ) @@ -490,9 +470,9 @@ static inline int Gia_ManAppendCo( Gia_Man_t * p, int iLit0 ) } static inline int Gia_ManAppendMux( Gia_Man_t * p, int iCtrl, int iData1, int iData0 ) { - int iTemp0 = Gia_ManAppendAnd( p, Gia_LitNot(iCtrl), iData0 ); + int iTemp0 = Gia_ManAppendAnd( p, Abc_LitNot(iCtrl), iData0 ); int iTemp1 = Gia_ManAppendAnd( p, iCtrl, iData1 ); - return Gia_LitNotCond( Gia_ManAppendAnd( p, Gia_LitNot(iTemp0), Gia_LitNot(iTemp1) ), 1 ); + return Abc_LitNotCond( Gia_ManAppendAnd( p, Abc_LitNot(iTemp0), Abc_LitNot(iTemp1) ), 1 ); } #define GIA_ZER 1 @@ -587,7 +567,7 @@ static inline int Gia_ObjLutFanin( Gia_Man_t * p, int Id, int i ) { re #define Gia_ManForEachObjVec( vVec, p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Gia_ManObj(p, Vec_IntEntry(vVec,i))); i++ ) #define Gia_ManForEachObjVecLit( vVec, p, pObj, fCompl, i ) \ - for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Gia_ManObj(p, Gia_Lit2Var(Vec_IntEntry(vVec,i)))) && (((fCompl) = Gia_LitIsCompl(Vec_IntEntry(vVec,i))),1); i++ ) + for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Gia_ManObj(p, Abc_Lit2Var(Vec_IntEntry(vVec,i)))) && (((fCompl) = Abc_LitIsCompl(Vec_IntEntry(vVec,i))),1); i++ ) #define Gia_ManForEachObjReverse( p, pObj, i ) \ for ( i = p->nObjs - 1; (i > 0) && ((pObj) = Gia_ManObj(p, i)); i-- ) #define Gia_ManForEachAnd( p, pObj, i ) \ @@ -817,7 +797,6 @@ extern Gia_Man_t * Gia_ManReduceConst( Gia_Man_t * pAig, int fVerbose ); /*=== giaUtil.c ===========================================================*/ extern unsigned Gia_ManRandom( int fReset ); extern void Gia_ManRandomInfo( Vec_Ptr_t * vInfo, int iInputStart, int iWordStart, int iWordStop ); -extern unsigned int Gia_PrimeCudd( unsigned int p ); extern char * Gia_TimeStamp(); extern char * Gia_FileNameGenericAppend( char * pBase, char * pSuffix ); extern void Gia_ManIncrementTravId( Gia_Man_t * p ); diff --git a/src/aig/gia/giaAbs.c b/src/aig/gia/giaAbs.c index e9861977..e25ff7fb 100644 --- a/src/aig/gia/giaAbs.c +++ b/src/aig/gia/giaAbs.c @@ -20,7 +20,7 @@ #include "gia.h" #include "giaAig.h" -#include "saig.h" +#include "src/aig/saig/saig.h" ABC_NAMESPACE_IMPL_START @@ -472,7 +472,7 @@ int Gia_ManGlaPbaPerform( Gia_Man_t * pGia, void * pPars, int fNewSolver ) // this obj was abstracted before assert( Gia_ObjIsAnd(pObj) || Gia_ObjIsRo(pGia, pObj) ); // if corresponding AIG object is not abstracted, remove abstraction - if ( !Vec_IntEntry(vGateClasses, Gia_Lit2Var(pObj->Value)) ) + if ( !Vec_IntEntry(vGateClasses, Abc_Lit2Var(pObj->Value)) ) { Vec_IntWriteEntry( pGia->vGateClasses, i, 0 ); Counter++; diff --git a/src/aig/gia/giaAbs.h b/src/aig/gia/giaAbs.h index 090d5dca..366a4d8a 100644 --- a/src/aig/gia/giaAbs.h +++ b/src/aig/gia/giaAbs.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __GIA_ABS_H__ -#define __GIA_ABS_H__ +#ifndef ABC__aig__gia__giaAbs_h +#define ABC__aig__gia__giaAbs_h //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaAbsVta.c b/src/aig/gia/giaAbsVta.c index fe30d0f0..3e7f2a01 100644 --- a/src/aig/gia/giaAbsVta.c +++ b/src/aig/gia/giaAbsVta.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "gia.h" -#include "satSolver2.h" +#include "src/sat/bsat/satSolver2.h" ABC_NAMESPACE_IMPL_START @@ -210,7 +210,7 @@ Vec_Int_t * Gia_VtaConvertToGla( Gia_Man_t * p, Vec_Int_t * vAbs ) int i, Entry, nFrames = Vec_IntEntry( vAbs, 0 ); assert( Vec_IntEntry(vAbs, nFrames+1) == Vec_IntSize(vAbs) ); // get the bitmask - nObjMask = (1 << Gia_Base2Log(nObjs)) - 1; + nObjMask = (1 << Abc_Base2Log(nObjs)) - 1; assert( nObjs <= nObjMask ); // go through objects vPresent = Vec_IntStart( nObjs ); @@ -248,7 +248,7 @@ static inline int Vta_ManReadFrameStart( Vec_Int_t * p, int nWords ) pTotal[w] |= pThis[i]; } for ( i = nWords * 32 - 1; i >= 0; i-- ) - if ( Gia_InfoHasBit(pTotal, i) ) + if ( Abc_InfoHasBit(pTotal, i) ) { ABC_FREE( pTotal ); return i+1; @@ -716,7 +716,7 @@ Abc_Cex_t * Vta_ManRefineAbstraction( Vta_Man_t * p ) if ( Gia_ObjIsRo(p->pGia, pObj) ) assert( pThis->iFrame == 0 && pThis->Value == VTA_VAR0 ); else if ( Gia_ObjIsPi(p->pGia, pObj) && pThis->Value == VTA_VAR1 ) - Gia_InfoSetBit( pCex->pData, pCex->nRegs + pThis->iFrame * pCex->nPis + Gia_ObjCioId(pObj) ); + Abc_InfoSetBit( pCex->pData, pCex->nRegs + pThis->iFrame * pCex->nPis + Gia_ObjCioId(pObj) ); } } // perform refinement @@ -776,7 +776,7 @@ Vta_Man_t * Vga_ManStart( Gia_Man_t * pGia, Gia_ParVta_t * pPars ) p->pBins = ABC_CALLOC( int, p->nBins ); p->vOrder = Vec_IntAlloc( 1013 ); // abstraction - p->nObjBits = Gia_Base2Log( Gia_ManObjNum(pGia) ); + p->nObjBits = Abc_Base2Log( Gia_ManObjNum(pGia) ); p->nObjMask = (1 << p->nObjBits) - 1; assert( Gia_ManObjNum(pGia) <= (int)p->nObjMask ); p->nWords = 1; @@ -922,7 +922,8 @@ Vec_Int_t * Vta_ManUnsatCore( int iLit, Vec_Int_t * vCla2Var, sat_solver2 * pSat ***********************************************************************/ void Vta_ManAbsPrintFrame( Vta_Man_t * p, Vec_Int_t * vCore, int nFrames ) { - unsigned * pInfo, * pCountAll, * pCountUni; + unsigned * pInfo; + int * pCountAll, * pCountUni; int i, k, iFrame, iObj, Entry; // print info about frames pCountAll = ABC_CALLOC( int, nFrames + 1 ); @@ -933,9 +934,9 @@ void Vta_ManAbsPrintFrame( Vta_Man_t * p, Vec_Int_t * vCore, int nFrames ) iFrame = (Entry >> p->nObjBits); assert( iFrame < nFrames ); pInfo = (unsigned *)Vec_IntEntryP( p->vSeens, p->nWords * iObj ); - if ( Gia_InfoHasBit(pInfo, iFrame) == 0 ) + if ( Abc_InfoHasBit(pInfo, iFrame) == 0 ) { - Gia_InfoSetBit( pInfo, iFrame ); + Abc_InfoSetBit( pInfo, iFrame ); pCountUni[iFrame+1]++; pCountUni[0]++; } @@ -1062,7 +1063,7 @@ static inline int Vga_ManGetOutLit( Vta_Man_t * p, int f ) Gia_Obj_t * pObj = Gia_ManPo(p->pGia, 0); Vta_Obj_t * pThis = Vga_ManFind( p, Gia_ObjFaninId0p(p->pGia, pObj), f ); assert( pThis != NULL && pThis->fAdded ); - return Gia_Var2Lit( Vta_ObjId(p, pThis), Gia_ObjFaninC0(pObj) ); + return Abc_Var2Lit( Vta_ObjId(p, pThis), Gia_ObjFaninC0(pObj) ); } /**Function************************************************************* @@ -1105,7 +1106,7 @@ int Gia_VtaPerform( Gia_Man_t * pAig, Gia_ParVta_t * pPars ) if ( f < p->pPars->nFramesStart ) { // load this timeframe - Vga_ManLoadSlice( p, Vec_PtrEntry(p->vFrames, f), 0 ); + Vga_ManLoadSlice( p, (Vec_Int_t *)Vec_PtrEntry(p->vFrames, f), 0 ); // run SAT solver vCore = Vta_ManUnsatCore( Vga_ManGetOutLit(p, f), p->vCla2Var, p->pSat, pPars->nConfLimit, p->pPars->fVerbose, &Status ); assert( (vCore != NULL) == (Status == 1) ); @@ -1123,7 +1124,7 @@ int Gia_VtaPerform( Gia_Man_t * pAig, Gia_ParVta_t * pPars ) { pObj = Gia_ManObj( p->pGia, pThis->iObj ); if ( Gia_ObjIsPi(p->pGia, pObj) && sat_solver2_var_value(p->pSat, Vta_ObjId(p, pThis)) ) - Gia_InfoSetBit( pCex->pData, pCex->nRegs + pThis->iFrame * pCex->nPis + Gia_ObjCioId(pObj) ); + Abc_InfoSetBit( pCex->pData, pCex->nRegs + pThis->iFrame * pCex->nPis + Gia_ObjCioId(pObj) ); } } } @@ -1133,7 +1134,7 @@ int Gia_VtaPerform( Gia_Man_t * pAig, Gia_ParVta_t * pPars ) // load the time frame int Limit = Abc_MinInt(5, p->pPars->nFramesStart); for ( i = 1; i <= Limit; i++ ) - Vga_ManLoadSlice( p, Vec_PtrEntry(p->vCores, f-i), i ); + Vga_ManLoadSlice( p, (Vec_Int_t *)Vec_PtrEntry(p->vCores, f-i), i ); // iterate as long as there are counter-examples do { vCore = Vta_ManUnsatCore( Vga_ManGetOutLit(p, f), p->vCla2Var, p->pSat, pPars->nConfLimit, pPars->fVerbose, &Status ); diff --git a/src/aig/gia/giaAig.c b/src/aig/gia/giaAig.c index 00148451..6da633e0 100644 --- a/src/aig/gia/giaAig.c +++ b/src/aig/gia/giaAig.c @@ -19,9 +19,9 @@ ***********************************************************************/ #include "giaAig.h" -#include "fra.h" -#include "dch.h" -#include "dar.h" +#include "src/proof/fra/fra.h" +#include "src/proof/dch/dch.h" +#include "src/opt/dar/dar.h" ABC_NAMESPACE_IMPL_START @@ -30,8 +30,8 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static inline int Gia_ObjChild0Copy( Aig_Obj_t * pObj ) { return Gia_LitNotCond( Aig_ObjFanin0(pObj)->iData, Aig_ObjFaninC0(pObj) ); } -static inline int Gia_ObjChild1Copy( Aig_Obj_t * pObj ) { return Gia_LitNotCond( Aig_ObjFanin1(pObj)->iData, Aig_ObjFaninC1(pObj) ); } +static inline int Gia_ObjChild0Copy( Aig_Obj_t * pObj ) { return Abc_LitNotCond( Aig_ObjFanin0(pObj)->iData, Aig_ObjFaninC0(pObj) ); } +static inline int Gia_ObjChild1Copy( Aig_Obj_t * pObj ) { return Abc_LitNotCond( Aig_ObjFanin1(pObj)->iData, Aig_ObjFaninC1(pObj) ); } static inline Aig_Obj_t * Gia_ObjChild0Copy2( Aig_Obj_t ** ppNodes, Gia_Obj_t * pObj, int Id ) { return Aig_NotCond( ppNodes[Gia_ObjFaninId0(pObj, Id)], Gia_ObjFaninC0(pObj) ); } static inline Aig_Obj_t * Gia_ObjChild1Copy2( Aig_Obj_t ** ppNodes, Gia_Obj_t * pObj, int Id ) { return Aig_NotCond( ppNodes[Gia_ObjFaninId1(pObj, Id)], Gia_ObjFaninC1(pObj) ); } @@ -64,8 +64,8 @@ void Gia_ManFromAig_rec( Gia_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) { int iObjNew, iNextNew; Gia_ManFromAig_rec( pNew, p, pNext ); - iObjNew = Gia_Lit2Var(pObj->iData); - iNextNew = Gia_Lit2Var(pNext->iData); + iObjNew = Abc_Lit2Var(pObj->iData); + iNextNew = Abc_Lit2Var(pNext->iData); if ( pNew->pNexts ) pNew->pNexts[iObjNew] = iNextNew; } @@ -89,7 +89,7 @@ Gia_Man_t * Gia_ManFromAig( Aig_Man_t * p ) int i; // create the new manager pNew = Gia_ManStart( Aig_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); pNew->nConstrs = p->nConstrs; // create room to store equivalences if ( p->pEquivs ) @@ -128,7 +128,7 @@ Gia_Man_t * Gia_ManFromAigSimple( Aig_Man_t * p ) int i; // create the new manager pNew = Gia_ManStart( Aig_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); pNew->nConstrs = p->nConstrs; // create the PIs Aig_ManCleanData( p ); @@ -167,7 +167,7 @@ Gia_Man_t * Gia_ManFromAigSwitch( Aig_Man_t * p ) int i; // create the new manager pNew = Gia_ManStart( Aig_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); pNew->nConstrs = p->nConstrs; // create the PIs Aig_ManCleanData( p ); @@ -246,9 +246,9 @@ Aig_Man_t * Gia_ManToAig( Gia_Man_t * p, int fChoices ) assert( !fChoices || (p->pNexts && p->pReprs) ); // create the new manager pNew = Aig_ManStart( Gia_ManAndNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); pNew->nConstrs = p->nConstrs; -// pNew->pSpec = Gia_UtilStrsav( p->pName ); +// pNew->pSpec = Abc_UtilStrsav( p->pName ); // duplicate representation of choice nodes if ( fChoices ) pNew->pEquivs = ABC_CALLOC( Aig_Obj_t *, Gia_ManObjNum(p) ); @@ -293,9 +293,9 @@ Aig_Man_t * Gia_ManToAigSkip( Gia_Man_t * p, int nOutDelta ) assert( nOutDelta > 0 && Gia_ManCoNum(p) % nOutDelta == 0 ); // create the new manager pNew = Aig_ManStart( Gia_ManAndNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); pNew->nConstrs = p->nConstrs; -// pNew->pSpec = Gia_UtilStrsav( p->pName ); +// pNew->pSpec = Abc_UtilStrsav( p->pName ); // create the PIs ppNodes = ABC_CALLOC( Aig_Obj_t *, Gia_ManObjNum(p) ); ppNodes[0] = Aig_ManConst0(pNew); @@ -334,7 +334,7 @@ Aig_Man_t * Gia_ManToAigSimple( Gia_Man_t * p ) ppNodes = ABC_FALLOC( Aig_Obj_t *, Gia_ManObjNum(p) ); // create the new manager pNew = Aig_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); pNew->nConstrs = p->nConstrs; // create the PIs Gia_ManForEachObj( p, pObj, i ) @@ -349,7 +349,7 @@ Aig_Man_t * Gia_ManToAigSimple( Gia_Man_t * p ) ppNodes[i] = Aig_ManConst0(pNew); else assert( 0 ); - pObj->Value = Gia_Var2Lit( Aig_ObjId(Aig_Regular(ppNodes[i])), Aig_IsComplement(ppNodes[i]) ); + pObj->Value = Abc_Var2Lit( Aig_ObjId(Aig_Regular(ppNodes[i])), Aig_IsComplement(ppNodes[i]) ); assert( i == 0 || Aig_ObjId(ppNodes[i]) == i ); } Aig_ManSetRegNum( pNew, Gia_ManRegNum(p) ); @@ -402,8 +402,8 @@ void Gia_ManReprToAigRepr( Aig_Man_t * pAig, Gia_Man_t * pGia ) // move pointers from AIG to GIA Aig_ManForEachObj( pAig, pObj, i ) { - assert( i == 0 || !Gia_LitIsCompl(pObj->iData) ); - pGiaObj = Gia_ManObj( pGia, Gia_Lit2Var(pObj->iData) ); + assert( i == 0 || !Abc_LitIsCompl(pObj->iData) ); + pGiaObj = Gia_ManObj( pGia, Abc_Lit2Var(pObj->iData) ); pGiaObj->Value = i; } // set the pointers to the nodes in AIG @@ -441,7 +441,7 @@ void Gia_ManReprToAigRepr2( Aig_Man_t * pAig, Gia_Man_t * pGia ) pGiaRepr = Gia_ObjReprObj( pGia, i ); if ( pGiaRepr == NULL ) continue; - Aig_ObjCreateRepr( pAig, Aig_ManObj(pAig, Gia_Lit2Var(pGiaRepr->Value)), Aig_ManObj(pAig, Gia_Lit2Var(pGiaObj->Value)) ); + Aig_ObjCreateRepr( pAig, Aig_ManObj(pAig, Abc_Lit2Var(pGiaRepr->Value)), Aig_ManObj(pAig, Abc_Lit2Var(pGiaObj->Value)) ); } } @@ -472,8 +472,8 @@ void Gia_ManReprFromAigRepr( Aig_Man_t * pAig, Gia_Man_t * pGia ) // Abc_Print( 1, "%d -> %d %d\n", i, Gia_ObjValue(pObjGia), Gia_ObjValue(pObjGia)/2 ); if ( Gia_ObjIsCo(pObjGia) ) continue; - assert( i == 0 || !Gia_LitIsCompl(Gia_ObjValue(pObjGia)) ); - pObjAig = Aig_ManObj( pAig, Gia_Lit2Var(Gia_ObjValue(pObjGia)) ); + assert( i == 0 || !Abc_LitIsCompl(Gia_ObjValue(pObjGia)) ); + pObjAig = Aig_ManObj( pAig, Abc_Lit2Var(Gia_ObjValue(pObjGia)) ); pObjAig->iData = i; } Aig_ManForEachObj( pAig, pObjAig, i ) diff --git a/src/aig/gia/giaAig.h b/src/aig/gia/giaAig.h index 1c0a24d5..6522a5bc 100644 --- a/src/aig/gia/giaAig.h +++ b/src/aig/gia/giaAig.h @@ -18,15 +18,15 @@ ***********************************************************************/ -#ifndef __GIA_AIG_H__ -#define __GIA_AIG_H__ +#ifndef ABC__aig__gia__giaAig_h +#define ABC__aig__gia__giaAig_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// -#include "aig.h" +#include "src/aig/aig/aig.h" #include "gia.h" ABC_NAMESPACE_HEADER_START diff --git a/src/aig/gia/giaAiger.c b/src/aig/gia/giaAiger.c index db194c69..2ae070d3 100644 --- a/src/aig/gia/giaAiger.c +++ b/src/aig/gia/giaAiger.c @@ -146,7 +146,7 @@ int Gia_FileSize( char * pFileName ) char * Gia_FileNameGeneric( char * FileName ) { char * pDot, * pRes; - pRes = Gia_UtilStrsav( FileName ); + pRes = Abc_UtilStrsav( FileName ); if ( (pDot = strrchr( pRes, '.' )) ) *pDot = 0; return pRes; @@ -445,8 +445,8 @@ Gia_Man_t * Gia_ReadAiger2( char * pFileName, int fCheck ) // allocate the empty AIG pNew = Gia_ManStart( nTotal + nLatches + nOutputs + 1 ); pName = Gia_FileNameGeneric( pFileName ); - pNew->pName = Gia_UtilStrsav( pName ); -// pNew->pSpec = Gia_UtilStrsav( pFileName ); + pNew->pName = Abc_UtilStrsav( pName ); +// pNew->pSpec = Abc_UtilStrsav( pFileName ); ABC_FREE( pName ); pNew->nConstrs = nConstr; @@ -482,8 +482,8 @@ Gia_Man_t * Gia_ReadAiger2( char * pFileName, int fCheck ) uLit1 = uLit - Gia_ReadAigerDecode( &pCur ); uLit0 = uLit1 - Gia_ReadAigerDecode( &pCur ); // assert( uLit1 > uLit0 ); - iNode0 = Gia_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), uLit0 & 1 ); - iNode1 = Gia_LitNotCond( Vec_IntEntry(vNodes, uLit1 >> 1), uLit1 & 1 ); + iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), uLit0 & 1 ); + iNode1 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit1 >> 1), uLit1 & 1 ); assert( Vec_IntSize(vNodes) == i + 1 + nInputs + nLatches ); // Vec_IntPush( vNodes, Gia_And(pNew, iNode0, iNode1) ); Vec_IntPush( vNodes, Gia_ManAppendAnd(pNew, iNode0, iNode1) ); @@ -500,14 +500,14 @@ Gia_Man_t * Gia_ReadAiger2( char * pFileName, int fCheck ) for ( i = 0; i < nLatches; i++ ) { uLit0 = atoi( (char *)pCur ); while ( *pCur++ != '\n' ); - iNode0 = Gia_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); + iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); Vec_IntPush( vDrivers, iNode0 ); } // read the PO driver literals for ( i = 0; i < nOutputs; i++ ) { uLit0 = atoi( (char *)pCur ); while ( *pCur++ != '\n' ); - iNode0 = Gia_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); + iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); Vec_IntPush( vDrivers, iNode0 ); } @@ -518,14 +518,14 @@ Gia_Man_t * Gia_ReadAiger2( char * pFileName, int fCheck ) for ( i = 0; i < nLatches; i++ ) { uLit0 = Vec_IntEntry( vLits, i ); - iNode0 = Gia_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); + iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); Vec_IntPush( vDrivers, iNode0 ); } // read the PO driver literals for ( i = 0; i < nOutputs; i++ ) { uLit0 = Vec_IntEntry( vLits, i+nLatches ); - iNode0 = Gia_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); + iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); Vec_IntPush( vDrivers, iNode0 ); } Vec_IntFree( vLits ); @@ -604,7 +604,7 @@ Gia_Man_t * Gia_ReadAiger2( char * pFileName, int fCheck ) pCur++; // read model name ABC_FREE( pNew->pName ); - pNew->pName = Gia_UtilStrsav( (char *)pCur ); + pNew->pName = Abc_UtilStrsav( (char *)pCur ); } } Vec_IntFree( vNodes ); @@ -753,8 +753,8 @@ Gia_Man_t * Gia_ReadAigerFromMemory( char * pContents, int nFileSize, int fCheck uLit1 = uLit - Gia_ReadAigerDecode( &pCur ); uLit0 = uLit1 - Gia_ReadAigerDecode( &pCur ); // assert( uLit1 > uLit0 ); - iNode0 = Gia_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), uLit0 & 1 ); - iNode1 = Gia_LitNotCond( Vec_IntEntry(vNodes, uLit1 >> 1), uLit1 & 1 ); + iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), uLit0 & 1 ); + iNode1 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit1 >> 1), uLit1 & 1 ); assert( Vec_IntSize(vNodes) == i + 1 + nInputs + nLatches ); // Vec_IntPush( vNodes, Gia_And(pNew, iNode0, iNode1) ); Vec_IntPush( vNodes, Gia_ManHashAnd(pNew, iNode0, iNode1) ); @@ -772,14 +772,14 @@ Gia_Man_t * Gia_ReadAigerFromMemory( char * pContents, int nFileSize, int fCheck for ( i = 0; i < nLatches; i++ ) { uLit0 = atoi( (char *)pCur ); while ( *pCur++ != '\n' ); - iNode0 = Gia_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); + iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); Vec_IntPush( vDrivers, iNode0 ); } // read the PO driver literals for ( i = 0; i < nOutputs; i++ ) { uLit0 = atoi( (char *)pCur ); while ( *pCur++ != '\n' ); - iNode0 = Gia_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); + iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); Vec_IntPush( vDrivers, iNode0 ); } @@ -790,14 +790,14 @@ Gia_Man_t * Gia_ReadAigerFromMemory( char * pContents, int nFileSize, int fCheck for ( i = 0; i < nLatches; i++ ) { uLit0 = Vec_IntEntry( vLits, i ); - iNode0 = Gia_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); + iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); Vec_IntPush( vDrivers, iNode0 ); } // read the PO driver literals for ( i = 0; i < nOutputs; i++ ) { uLit0 = Vec_IntEntry( vLits, i+nLatches ); - iNode0 = Gia_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); + iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); Vec_IntPush( vDrivers, iNode0 ); } Vec_IntFree( vLits ); @@ -877,7 +877,7 @@ Gia_Man_t * Gia_ReadAigerFromMemory( char * pContents, int nFileSize, int fCheck pCur++; // read model name ABC_FREE( pNew->pName ); - pNew->pName = Gia_UtilStrsav( (char *)pCur ); + pNew->pName = Abc_UtilStrsav( (char *)pCur ); } } @@ -1094,7 +1094,7 @@ Gia_Man_t * Gia_ReadAiger( char * pFileName, int fCheck ) { ABC_FREE( pNew->pName ); pName = Gia_FileNameGeneric( pFileName ); - pNew->pName = Gia_UtilStrsav( pName ); + pNew->pName = Abc_UtilStrsav( pName ); // pNew->pSpec = Ioa_UtilStrsav( pFileName ); ABC_FREE( pName ); } @@ -1246,30 +1246,30 @@ unsigned char * Gia_WriteEquivClasses( Gia_Man_t * p, int * pEquivSize ) } pBuffer = ABC_ALLOC( unsigned char, sizeof(int) * (nItems + 1) ); // write constant class - iPos = Gia_WriteAigerEncode( pBuffer, 4, Gia_Var2Lit(0, 1) ); + iPos = Gia_WriteAigerEncode( pBuffer, 4, Abc_Var2Lit(0, 1) ); //printf( "\nRepr = %d ", 0 ); iPrevNode = 0; for ( iNode = 1; iNode < Gia_ManObjNum(p); iNode++ ) if ( Gia_ObjIsConst(p, iNode) ) { //printf( "Node = %d ", iNode ); - iLit = Gia_Var2Lit( iNode - iPrevNode, Gia_ObjProved(p, iNode) ); + iLit = Abc_Var2Lit( iNode - iPrevNode, Gia_ObjProved(p, iNode) ); iPrevNode = iNode; - iPos = Gia_WriteAigerEncode( pBuffer, iPos, Gia_Var2Lit(iLit, 0) ); + iPos = Gia_WriteAigerEncode( pBuffer, iPos, Abc_Var2Lit(iLit, 0) ); } // write non-constant classes iPrevRepr = 0; Gia_ManForEachClass( p, iRepr ) { //printf( "\nRepr = %d ", iRepr ); - iPos = Gia_WriteAigerEncode( pBuffer, iPos, Gia_Var2Lit(iRepr - iPrevRepr, 1) ); + iPos = Gia_WriteAigerEncode( pBuffer, iPos, Abc_Var2Lit(iRepr - iPrevRepr, 1) ); iPrevRepr = iPrevNode = iRepr; Gia_ClassForEachObj1( p, iRepr, iNode ) { //printf( "Node = %d ", iNode ); - iLit = Gia_Var2Lit( iNode - iPrevNode, Gia_ObjProved(p, iNode) ); + iLit = Abc_Var2Lit( iNode - iPrevNode, Gia_ObjProved(p, iNode) ); iPrevNode = iNode; - iPos = Gia_WriteAigerEncode( pBuffer, iPos, Gia_Var2Lit(iLit, 0) ); + iPos = Gia_WriteAigerEncode( pBuffer, iPos, Abc_Var2Lit(iLit, 0) ); } } Gia_WriteInt( pBuffer, iPos ); @@ -1291,8 +1291,8 @@ unsigned char * Gia_WriteEquivClasses( Gia_Man_t * p, int * pEquivSize ) int Gia_WriteDiffValue( unsigned char * pPos, int iPos, int iPrev, int iThis ) { if ( iPrev < iThis ) - return Gia_WriteAigerEncode( pPos, iPos, Gia_Var2Lit(iThis - iPrev, 1) ); - return Gia_WriteAigerEncode( pPos, iPos, Gia_Var2Lit(iPrev - iThis, 0) ); + return Gia_WriteAigerEncode( pPos, iPos, Abc_Var2Lit(iThis - iPrev, 1) ); + return Gia_WriteAigerEncode( pPos, iPos, Abc_Var2Lit(iPrev - iThis, 0) ); } /**Function************************************************************* @@ -1420,7 +1420,7 @@ void Gia_WriteAiger( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int pBuffer = ABC_ALLOC( unsigned char, nBufferSize ); Gia_ManForEachAnd( p, pObj, i ) { - uLit = Gia_Var2Lit( i, 0 ); + uLit = Abc_Var2Lit( i, 0 ); uLit0 = Gia_ObjFaninLit0( pObj, i ); uLit1 = Gia_ObjFaninLit1( pObj, i ); assert( uLit0 < uLit1 ); diff --git a/src/aig/gia/giaBidec.c b/src/aig/gia/giaBidec.c index fc17b582..54f98afd 100644 --- a/src/aig/gia/giaBidec.c +++ b/src/aig/gia/giaBidec.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "gia.h" -#include "bdc.h" +#include "src/bool/bdc/bdc.h" ABC_NAMESPACE_IMPL_START @@ -28,7 +28,7 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static inline int Bdc_FunObjCopy( Bdc_Fun_t * pObj ) { return Gia_LitNotCond( Bdc_FuncCopyInt(Bdc_Regular(pObj)), Bdc_IsComplement(pObj) ); } +static inline int Bdc_FunObjCopy( Bdc_Fun_t * pObj ) { return Abc_LitNotCond( Bdc_FuncCopyInt(Bdc_Regular(pObj)), Bdc_IsComplement(pObj) ); } static inline int Bdc_FunFanin0Copy( Bdc_Fun_t * pObj ) { return Bdc_FunObjCopy( Bdc_FuncFanin0(pObj) ); } static inline int Bdc_FunFanin1Copy( Bdc_Fun_t * pObj ) { return Bdc_FunObjCopy( Bdc_FuncFanin1(pObj) ); } @@ -109,7 +109,7 @@ unsigned * Gia_ManConvertAigToTruth( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t int i, nWords, nVars; // get the number of variables and words nVars = Vec_IntSize( vLeaves ); - nWords = Gia_TruthWordNum( nVars ); + nWords = Abc_TruthWordNum( nVars ); // check the case of a constant if ( Gia_ObjIsConst0( Gia_Regular(pRoot) ) ) { @@ -263,7 +263,7 @@ Gia_Man_t * Gia_ManPerformBidec( Gia_Man_t * p, int fVerbose ) Gia_ManConst0(p)->Value = 0; // start the new manager pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManHashAlloc( pNew ); // Gia_ManCleanLevels( pNew, Gia_ManObjNum(p) ); pManDec = Bdc_ManAlloc( pPars ); diff --git a/src/aig/gia/giaCCof.c b/src/aig/gia/giaCCof.c index 38e5ccdf..b04d5953 100644 --- a/src/aig/gia/giaCCof.c +++ b/src/aig/gia/giaCCof.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "gia.h" -#include "satSolver.h" +#include "src/sat/bsat/satSolver.h" ABC_NAMESPACE_IMPL_START @@ -134,10 +134,10 @@ void Gia_ManCofExtendSolver( Ccf_Man_t * p ) } static inline int Gia_Obj0Copy( Vec_Int_t * vCopies, int Fan0, int fCompl0 ) -{ return Gia_LitNotCond( Vec_IntEntry(vCopies, Fan0), fCompl0 ); } +{ return Abc_LitNotCond( Vec_IntEntry(vCopies, Fan0), fCompl0 ); } static inline int Gia_Obj1Copy( Vec_Int_t * vCopies, int Fan1, int fCompl1 ) -{ return Gia_LitNotCond( Vec_IntEntry(vCopies, Fan1), fCompl1 ); } +{ return Abc_LitNotCond( Vec_IntEntry(vCopies, Fan1), fCompl1 ); } /**Function************************************************************* @@ -173,7 +173,7 @@ void Gia_ManCofOneDerive_rec( Ccf_Man_t * p, int Id ) else if ( Gia_ObjCioId(pObj) >= Gia_ManRegNum(p->pGia) ) // PI Res = sat_solver_var_value( p->pSat, Id ); else - Res = Gia_Var2Lit( Id, 0 ); + Res = Abc_Var2Lit( Id, 0 ); Vec_IntWriteEntry( p->vCopies, Id, Res ); } @@ -193,15 +193,15 @@ int Gia_ManCofOneDerive( Ccf_Man_t * p, int LitProp ) int LitOut; // derive the cofactor of the property node Vec_IntFill( p->vCopies, Gia_ManObjNum(p->pFrames), -1 ); - Gia_ManCofOneDerive_rec( p, Gia_Lit2Var(LitProp) ); - LitOut = Vec_IntEntry( p->vCopies, Gia_Lit2Var(LitProp) ); - LitOut = Gia_LitNotCond( LitOut, Gia_LitIsCompl(LitProp) ); + Gia_ManCofOneDerive_rec( p, Abc_Lit2Var(LitProp) ); + LitOut = Vec_IntEntry( p->vCopies, Abc_Lit2Var(LitProp) ); + LitOut = Abc_LitNotCond( LitOut, Abc_LitIsCompl(LitProp) ); // add new PO for the cofactor Gia_ManAppendCo( p->pFrames, LitOut ); // add SAT clauses Gia_ManCofExtendSolver( p ); // return negative literal of the cofactor - return Gia_LitNot(LitOut); + return Abc_LitNot(LitOut); } /**Function************************************************************* diff --git a/src/aig/gia/giaCSat.c b/src/aig/gia/giaCSat.c index 745b19ba..d83f79e9 100644 --- a/src/aig/gia/giaCSat.c +++ b/src/aig/gia/giaCSat.c @@ -238,8 +238,8 @@ static inline void Cbs_ManSaveModel( Cbs_Man_t * p, Vec_Int_t * vCex ) p->pProp.iHead = 0; Cbs_QueForEachEntry( p->pProp, pVar, i ) if ( Gia_ObjIsCi(pVar) ) -// Vec_IntPush( vCex, Gia_Var2Lit(Gia_ObjId(p->pAig,pVar), !Cbs_VarValue(pVar)) ); - Vec_IntPush( vCex, Gia_Var2Lit(Gia_ObjCioId(pVar), !Cbs_VarValue(pVar)) ); +// Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjId(p->pAig,pVar), !Cbs_VarValue(pVar)) ); + Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjCioId(pVar), !Cbs_VarValue(pVar)) ); } /**Function************************************************************* @@ -377,7 +377,7 @@ static inline int Cbs_VarFaninFanoutMax( Cbs_Man_t * p, Gia_Obj_t * pObj ) assert( Gia_ObjIsAnd(pObj) ); Count0 = Gia_ObjRefs( p->pAig, Gia_ObjFanin0(pObj) ); Count1 = Gia_ObjRefs( p->pAig, Gia_ObjFanin1(pObj) ); - return ABC_MAX( Count0, Count1 ); + return Abc_MaxInt( Count0, Count1 ); } /**Function************************************************************* @@ -504,7 +504,7 @@ static inline void Cbs_ManAssign( Cbs_Man_t * p, Gia_Obj_t * pObj, int Level, Gi Vec_IntPush( p->vLevReas, pRes1 ? pRes1-pObjR : 0 ); assert( Vec_IntSize(p->vLevReas) == 3 * p->pProp.iTail ); // s_Counter++; -// s_Counter = Abc_MaxInt( s_Counter, Vec_IntSize(p->vLevReas)/3 ); +// s_Counter = Abc_MaxIntInt( s_Counter, Vec_IntSize(p->vLevReas)/3 ); } @@ -872,7 +872,7 @@ int Cbs_ManSolve_rec( Cbs_Man_t * p, int Level ) if ( Cbs_QueIsEmpty(&p->pJust) ) return 0; // quit using resource limits - p->Pars.nJustThis = ABC_MAX( p->Pars.nJustThis, p->pJust.iTail - p->pJust.iHead ); + p->Pars.nJustThis = Abc_MaxInt( p->Pars.nJustThis, p->pJust.iTail - p->pJust.iHead ); if ( Cbs_ManCheckLimits( p ) ) return 0; // remember the state before branching @@ -946,7 +946,7 @@ int Cbs_ManSolve( Cbs_Man_t * p, Gia_Obj_t * pObj ) p->pJust.iHead = p->pJust.iTail = 0; p->pClauses.iHead = p->pClauses.iTail = 1; p->Pars.nBTTotal += p->Pars.nBTThis; - p->Pars.nJustTotal = ABC_MAX( p->Pars.nJustTotal, p->Pars.nJustThis ); + p->Pars.nJustTotal = Abc_MaxInt( p->Pars.nJustTotal, p->Pars.nJustThis ); if ( Cbs_ManCheckLimits( p ) ) RetValue = -1; diff --git a/src/aig/gia/giaCSatOld.c b/src/aig/gia/giaCSatOld.c index 983081f0..8198c17f 100644 --- a/src/aig/gia/giaCSatOld.c +++ b/src/aig/gia/giaCSatOld.c @@ -213,8 +213,8 @@ static inline void Cbs0_ManSaveModel( Cbs0_Man_t * p, Vec_Int_t * vCex ) p->pProp.iHead = 0; Cbs0_QueForEachEntry( p->pProp, pVar, i ) if ( Gia_ObjIsCi(pVar) ) -// Vec_IntPush( vCex, Gia_Var2Lit(Gia_ObjId(p->pAig,pVar), !Cbs0_VarValue(pVar)) ); - Vec_IntPush( vCex, Gia_Var2Lit(Gia_ObjCioId(pVar), !Cbs0_VarValue(pVar)) ); +// Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjId(p->pAig,pVar), !Cbs0_VarValue(pVar)) ); + Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjCioId(pVar), !Cbs0_VarValue(pVar)) ); } /**Function************************************************************* @@ -332,7 +332,7 @@ static inline int Cbs0_VarFaninFanoutMax( Cbs0_Man_t * p, Gia_Obj_t * pObj ) assert( Gia_ObjIsAnd(pObj) ); Count0 = Gia_ObjRefs( p->pAig, Gia_ObjFanin0(pObj) ); Count1 = Gia_ObjRefs( p->pAig, Gia_ObjFanin1(pObj) ); - return ABC_MAX( Count0, Count1 ); + return Abc_MaxInt( Count0, Count1 ); } /**Function************************************************************* @@ -596,7 +596,7 @@ int Cbs0_ManSolve_rec( Cbs0_Man_t * p ) if ( Cbs0_QueIsEmpty(&p->pJust) ) return 0; // quit using resource limits - p->Pars.nJustThis = ABC_MAX( p->Pars.nJustThis, p->pJust.iTail - p->pJust.iHead ); + p->Pars.nJustThis = Abc_MaxInt( p->Pars.nJustThis, p->pJust.iTail - p->pJust.iHead ); if ( Cbs0_ManCheckLimits( p ) ) return 0; // remember the state before branching @@ -656,7 +656,7 @@ int Cbs0_ManSolve( Cbs0_Man_t * p, Gia_Obj_t * pObj ) Cbs0_ManCancelUntil( p, 0 ); p->pJust.iHead = p->pJust.iTail = 0; p->Pars.nBTTotal += p->Pars.nBTThis; - p->Pars.nJustTotal = ABC_MAX( p->Pars.nJustTotal, p->Pars.nJustThis ); + p->Pars.nJustTotal = Abc_MaxInt( p->Pars.nJustTotal, p->Pars.nJustThis ); if ( Cbs0_ManCheckLimits( p ) ) RetValue = -1; // printf( "Outcome = %2d. Confs = %6d. Decision level max = %3d.\n", diff --git a/src/aig/gia/giaCTas.c b/src/aig/gia/giaCTas.c index c6aa3fec..7cfdac74 100644 --- a/src/aig/gia/giaCTas.c +++ b/src/aig/gia/giaCTas.c @@ -122,8 +122,8 @@ static inline void Tas_VarSetValue( Gia_Obj_t * pVar, int v ) { assert(pVar->fM static inline int Tas_VarIsJust( Gia_Obj_t * pVar ) { return Gia_ObjIsAnd(pVar) && !Tas_VarIsAssigned(Gia_ObjFanin0(pVar)) && !Tas_VarIsAssigned(Gia_ObjFanin1(pVar)); } static inline int Tas_VarFanin0Value( Gia_Obj_t * pVar ) { return !Tas_VarIsAssigned(Gia_ObjFanin0(pVar)) ? 2 : (Tas_VarValue(Gia_ObjFanin0(pVar)) ^ Gia_ObjFaninC0(pVar)); } static inline int Tas_VarFanin1Value( Gia_Obj_t * pVar ) { return !Tas_VarIsAssigned(Gia_ObjFanin1(pVar)) ? 2 : (Tas_VarValue(Gia_ObjFanin1(pVar)) ^ Gia_ObjFaninC1(pVar)); } -static inline int Tas_VarToLit( Tas_Man_t * p, Gia_Obj_t * pObj ) { assert( Tas_VarIsAssigned(pObj) ); return Gia_Var2Lit( Gia_ObjId(p->pAig, pObj), !Tas_VarValue(pObj) ); } -static inline int Tas_LitIsTrue( Gia_Obj_t * pObj, int Lit ) { assert( Tas_VarIsAssigned(pObj) ); return Tas_VarValue(pObj) != Gia_LitIsCompl(Lit); } +static inline int Tas_VarToLit( Tas_Man_t * p, Gia_Obj_t * pObj ) { assert( Tas_VarIsAssigned(pObj) ); return Abc_Var2Lit( Gia_ObjId(p->pAig, pObj), !Tas_VarValue(pObj) ); } +static inline int Tas_LitIsTrue( Gia_Obj_t * pObj, int Lit ) { assert( Tas_VarIsAssigned(pObj) ); return Tas_VarValue(pObj) != Abc_LitIsCompl(Lit); } static inline int Tas_ClsHandle( Tas_Man_t * p, Tas_Cls_t * pClause ) { return ((int *)pClause) - p->pStore.pData; } static inline Tas_Cls_t * Tas_ClsFromHandle( Tas_Man_t * p, int h ) { return (Tas_Cls_t *)(p->pStore.pData + h); } @@ -292,8 +292,8 @@ static inline void Tas_ManSaveModel( Tas_Man_t * p, Vec_Int_t * vCex ) Tas_QueForEachEntry( p->pProp, pVar, i ) { if ( Gia_ObjIsCi(pVar) ) -// Vec_IntPush( vCex, Gia_Var2Lit(Gia_ObjId(p->pAig,pVar), !Tas_VarValue(pVar)) ); - Vec_IntPush( vCex, Gia_Var2Lit(Gia_ObjCioId(pVar), !Tas_VarValue(pVar)) ); +// Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjId(p->pAig,pVar), !Tas_VarValue(pVar)) ); + Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjCioId(pVar), !Tas_VarValue(pVar)) ); /* printf( "%5d(%d) = ", Gia_ObjId(p->pAig, pVar), Tas_VarValue(pVar) ); if ( Gia_ObjIsCi(pVar) ) @@ -443,7 +443,7 @@ static inline int Tas_VarFaninFanoutMax( Tas_Man_t * p, Gia_Obj_t * pObj ) assert( Gia_ObjIsAnd(pObj) ); Count0 = Gia_ObjRefs( p->pAig, Gia_ObjFanin0(pObj) ); Count1 = Gia_ObjRefs( p->pAig, Gia_ObjFanin1(pObj) ); - return ABC_MAX( Count0, Count1 ); + return Abc_MaxInt( Count0, Count1 ); } @@ -793,11 +793,11 @@ static inline void Tas_ManDeriveReason( Tas_Man_t * p, int Level ) if ( Tas_VarHasReasonCls( p, pObj ) ) { Tas_Cls_t * pCls = Tas_VarReasonCls( p, pObj ); - pReason = Gia_ManObj( p->pAig, Gia_Lit2Var(pCls->pLits[0]) ); + pReason = Gia_ManObj( p->pAig, Abc_Lit2Var(pCls->pLits[0]) ); assert( pReason == pObj ); for ( j = 1; j < pCls->nLits; j++ ) { - pReason = Gia_ManObj( p->pAig, Gia_Lit2Var(pCls->pLits[j]) ); + pReason = Gia_ManObj( p->pAig, Abc_Lit2Var(pCls->pLits[j]) ); iLitLevel2 = Tas_VarDecLevel( p, pReason ); assert( Tas_VarIsAssigned( pReason ) ); assert( !Tas_LitIsTrue( pReason, pCls->pLits[j] ) ); @@ -953,16 +953,16 @@ static inline Tas_Cls_t * Tas_ManAllocCls( Tas_Man_t * p, int nSize ) ***********************************************************************/ static inline void Tas_ManWatchClause( Tas_Man_t * p, Tas_Cls_t * pClause, int Lit ) { - assert( Gia_Lit2Var(Lit) < Gia_ManObjNum(p->pAig) ); + assert( Abc_Lit2Var(Lit) < Gia_ManObjNum(p->pAig) ); assert( pClause->nLits >= 2 ); assert( pClause->pLits[0] == Lit || pClause->pLits[1] == Lit ); if ( pClause->pLits[0] == Lit ) - pClause->iNext[0] = p->pWatches[Gia_LitNot(Lit)]; + pClause->iNext[0] = p->pWatches[Abc_LitNot(Lit)]; else - pClause->iNext[1] = p->pWatches[Gia_LitNot(Lit)]; - if ( p->pWatches[Gia_LitNot(Lit)] == 0 ) - Vec_IntPush( p->vWatchLits, Gia_LitNot(Lit) ); - p->pWatches[Gia_LitNot(Lit)] = Tas_ClsHandle( p, pClause ); + pClause->iNext[1] = p->pWatches[Abc_LitNot(Lit)]; + if ( p->pWatches[Abc_LitNot(Lit)] == 0 ) + Vec_IntPush( p->vWatchLits, Abc_LitNot(Lit) ); + p->pWatches[Abc_LitNot(Lit)] = Tas_ClsHandle( p, pClause ); } /**Function************************************************************* @@ -994,7 +994,7 @@ static inline Tas_Cls_t * Tas_ManCreateCls( Tas_Man_t * p, int hClause ) for ( i = hClause; (pObj = pQue->pData[i]); i++ ) { assert( Tas_VarIsAssigned( pObj ) ); - pClause->pLits[i-hClause] = Gia_LitNot( Tas_VarToLit(p, pObj) ); + pClause->pLits[i-hClause] = Abc_LitNot( Tas_VarToLit(p, pObj) ); } // add the clause as watched one if ( nLits >= 2 ) @@ -1027,7 +1027,7 @@ static inline int Tas_ManCreateFromCls( Tas_Man_t * p, Tas_Cls_t * pCls, int Lev Tas_QuePush( pQue, NULL ); for ( i = 0; i < pCls->nLits; i++ ) { - pObj = Gia_ManObj( p->pAig, Gia_Lit2Var(pCls->pLits[i]) ); + pObj = Gia_ManObj( p->pAig, Abc_Lit2Var(pCls->pLits[i]) ); assert( Tas_VarIsAssigned(pObj) ); assert( !Tas_LitIsTrue( pObj, pCls->pLits[i] ) ); Tas_QuePush( pQue, pObj ); @@ -1052,7 +1052,7 @@ static inline int Tas_ManPropagateWatch( Tas_Man_t * p, int Level, int Lit ) Gia_Obj_t * pObj; Tas_Cls_t * pCur; int * piPrev, iCur, iTemp; - int i, LitF = Gia_LitNot(Lit); + int i, LitF = Abc_LitNot(Lit); // iterate through the clauses piPrev = p->pWatches + Lit; for ( iCur = p->pWatches[Lit]; iCur; iCur = *piPrev ) @@ -1070,8 +1070,8 @@ static inline int Tas_ManPropagateWatch( Tas_Man_t * p, int Level, int Lit ) assert( pCur->pLits[1] == LitF ); // if the first literal is true, the clause is satisfied -// if ( pCur->pLits[0] == p->pAssigns[Gia_Lit2Var(pCur->pLits[0])] ) - pObj = Gia_ManObj( p->pAig, Gia_Lit2Var(pCur->pLits[0]) ); +// if ( pCur->pLits[0] == p->pAssigns[Abc_Lit2Var(pCur->pLits[0])] ) + pObj = Gia_ManObj( p->pAig, Abc_Lit2Var(pCur->pLits[0]) ); if ( Tas_VarIsAssigned(pObj) && Tas_LitIsTrue( pObj, pCur->pLits[0] ) ) { piPrev = &pCur->iNext[1]; @@ -1082,8 +1082,8 @@ static inline int Tas_ManPropagateWatch( Tas_Man_t * p, int Level, int Lit ) for ( i = 2; i < (int)pCur->nLits; i++ ) { // skip the case when the literal is false -// if ( Gia_LitNot(pCur->pLits[i]) == p->pAssigns[Gia_Lit2Var(pCur->pLits[i])] ) - pObj = Gia_ManObj( p->pAig, Gia_Lit2Var(pCur->pLits[i]) ); +// if ( Abc_LitNot(pCur->pLits[i]) == p->pAssigns[Abc_Lit2Var(pCur->pLits[i])] ) + pObj = Gia_ManObj( p->pAig, Abc_Lit2Var(pCur->pLits[i]) ); if ( Tas_VarIsAssigned(pObj) && !Tas_LitIsTrue( pObj, pCur->pLits[i] ) ) continue; // the literal is either true or unassigned - watch it @@ -1099,7 +1099,7 @@ static inline int Tas_ManPropagateWatch( Tas_Man_t * p, int Level, int Lit ) continue; // clause is unit - enqueue new implication - pObj = Gia_ManObj( p->pAig, Gia_Lit2Var(pCur->pLits[0]) ); + pObj = Gia_ManObj( p->pAig, Abc_Lit2Var(pCur->pLits[0]) ); if ( !Tas_VarIsAssigned(pObj) ) { /* @@ -1107,7 +1107,7 @@ static inline int Tas_ManPropagateWatch( Tas_Man_t * p, int Level, int Lit ) int iLitLevel, iPlace; for ( i = 1; i < (int)pCur->nLits; i++ ) { - pObj = Gia_ManObj( p->pAig, Gia_Lit2Var(pCur->pLits[i]) ); + pObj = Gia_ManObj( p->pAig, Abc_Lit2Var(pCur->pLits[i]) ); iLitLevel = Tas_VarDecLevel( p, pObj ); iPlace = pObj->Value; printf( "Lit = %d. Level = %d. Place = %d.\n", pCur->pLits[i], iLitLevel, iPlace ); @@ -1300,7 +1300,7 @@ int Tas_ManSolve_rec( Tas_Man_t * p, int Level ) if ( Tas_QueIsEmpty(&p->pJust) ) return 0; // quit using resource limits - p->Pars.nJustThis = ABC_MAX( p->Pars.nJustThis, p->pJust.iTail - p->pJust.iHead ); + p->Pars.nJustThis = Abc_MaxInt( p->Pars.nJustThis, p->pJust.iTail - p->pJust.iHead ); if ( Tas_ManCheckLimits( p ) ) return 0; // remember the state before branching @@ -1401,7 +1401,7 @@ int Tas_ManSolve( Tas_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pObj2 ) Vec_IntClear( p->vActiveVars ); // statistics p->Pars.nBTTotal += p->Pars.nBTThis; - p->Pars.nJustTotal = ABC_MAX( p->Pars.nJustTotal, p->Pars.nJustThis ); + p->Pars.nJustTotal = Abc_MaxInt( p->Pars.nJustTotal, p->Pars.nJustThis ); if ( Tas_ManCheckLimits( p ) ) RetValue = -1; return RetValue; @@ -1460,7 +1460,7 @@ int Tas_ManSolveArray( Tas_Man_t * p, Vec_Ptr_t * vObjs ) Vec_IntClear( p->vActiveVars ); // statistics p->Pars.nBTTotal += p->Pars.nBTThis; - p->Pars.nJustTotal = ABC_MAX( p->Pars.nJustTotal, p->Pars.nJustThis ); + p->Pars.nJustTotal = Abc_MaxInt( p->Pars.nJustTotal, p->Pars.nJustThis ); if ( Tas_ManCheckLimits( p ) ) RetValue = -1; @@ -1644,19 +1644,19 @@ int Tas_StorePatternTry( Vec_Ptr_t * vInfo, Vec_Ptr_t * vPres, int iBit, int * p int i; for ( i = 0; i < nLits; i++ ) { - pInfo = (unsigned *)Vec_PtrEntry(vInfo, Gia_Lit2Var(pLits[i])); - pPres = (unsigned *)Vec_PtrEntry(vPres, Gia_Lit2Var(pLits[i])); - if ( Gia_InfoHasBit( pPres, iBit ) && - Gia_InfoHasBit( pInfo, iBit ) == Gia_LitIsCompl(pLits[i]) ) + pInfo = (unsigned *)Vec_PtrEntry(vInfo, Abc_Lit2Var(pLits[i])); + pPres = (unsigned *)Vec_PtrEntry(vPres, Abc_Lit2Var(pLits[i])); + if ( Abc_InfoHasBit( pPres, iBit ) && + Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(pLits[i]) ) return 0; } for ( i = 0; i < nLits; i++ ) { - pInfo = (unsigned *)Vec_PtrEntry(vInfo, Gia_Lit2Var(pLits[i])); - pPres = (unsigned *)Vec_PtrEntry(vPres, Gia_Lit2Var(pLits[i])); - Gia_InfoSetBit( pPres, iBit ); - if ( Gia_InfoHasBit( pInfo, iBit ) == Gia_LitIsCompl(pLits[i]) ) - Gia_InfoXorBit( pInfo, iBit ); + pInfo = (unsigned *)Vec_PtrEntry(vInfo, Abc_Lit2Var(pLits[i])); + pPres = (unsigned *)Vec_PtrEntry(vPres, Abc_Lit2Var(pLits[i])); + Abc_InfoSetBit( pPres, iBit ); + if ( Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(pLits[i]) ) + Abc_InfoXorBit( pInfo, iBit ); } return 1; } diff --git a/src/aig/gia/giaCof.c b/src/aig/gia/giaCof.c index 5a04d9d3..60dcf3af 100644 --- a/src/aig/gia/giaCof.c +++ b/src/aig/gia/giaCof.c @@ -457,7 +457,7 @@ int Cof_ManCountRemoved( Cof_Man_t * p, Cof_Obj_t * pRoot, int fConst1 ) pRoot->iNext = 0; p->pLevels[LevelStart] = Cof_ObjHandle( p, pRoot ); // set the new literal - pRoot->iLit = Gia_Var2Lit( 0, fConst1 ); + pRoot->iLit = Abc_Var2Lit( 0, fConst1 ); // process nodes in the levelized order for ( i = LevelStart; i < p->nLevels; i++ ) { @@ -465,7 +465,7 @@ int Cof_ManCountRemoved( Cof_Man_t * p, Cof_Obj_t * pRoot, int fConst1 ) iHandle && (pTemp = Cof_ManObj(p, iHandle)); iHandle = pTemp->iNext ) { - assert( pTemp->Id != Gia_Lit2Var(pTemp->iLit) ); + assert( pTemp->Id != Abc_Lit2Var(pTemp->iLit) ); Cof_ObjForEachFanout( pTemp, pNext, k ) { if ( Cof_ObjIsCo(pNext) ) @@ -477,11 +477,11 @@ int Cof_ManCountRemoved( Cof_Man_t * p, Cof_Obj_t * pRoot, int fConst1 ) assert( pFanin0 == pTemp || pFanin1 == pTemp ); pNextGia = Gia_ManObj( p->pGia, pNext->Id ); if ( Cof_ObjIsTravIdCurrent(p, pFanin0) ) - iLit0 = Gia_LitNotCond( pFanin0->iLit, Gia_ObjFaninC0(pNextGia) ); + iLit0 = Abc_LitNotCond( pFanin0->iLit, Gia_ObjFaninC0(pNextGia) ); else iLit0 = Gia_ObjFaninLit0( pNextGia, pNext->Id ); if ( Cof_ObjIsTravIdCurrent(p, pFanin1) ) - iLit1 = Gia_LitNotCond( pFanin1->iLit, Gia_ObjFaninC1(pNextGia) ); + iLit1 = Abc_LitNotCond( pFanin1->iLit, Gia_ObjFaninC1(pNextGia) ); else iLit1 = Gia_ObjFaninLit1( pNextGia, pNext->Id ); iNextNew = Gia_ManHashAndTry( p->pGia, iLit0, iLit1 ); @@ -578,12 +578,12 @@ void Cof_ManPrintFanio( Cof_Man_t * p ) nFanouts = Cof_ObjFanoutNum(pNode); nFaninsAll += nFanins; nFanoutsAll += nFanouts; - nFaninsMax = ABC_MAX( nFaninsMax, nFanins ); - nFanoutsMax = ABC_MAX( nFanoutsMax, nFanouts ); + nFaninsMax = Abc_MaxInt( nFaninsMax, nFanins ); + nFanoutsMax = Abc_MaxInt( nFanoutsMax, nFanouts ); } // allocate storage for fanin/fanout numbers - nSizeMax = ABC_MAX( 10 * (Gia_Base10Log(nFaninsMax) + 1), 10 * (Gia_Base10Log(nFanoutsMax) + 1) ); + nSizeMax = Abc_MaxInt( 10 * (Abc_Base10Log(nFaninsMax) + 1), 10 * (Abc_Base10Log(nFanoutsMax) + 1) ); vFanins = Vec_IntStart( nSizeMax ); vFanouts = Vec_IntStart( nSizeMax ); @@ -717,7 +717,7 @@ Gia_Man_t * Gia_ManDupCofInt( Gia_Man_t * p, int iVar ) return NULL; } pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManHashAlloc( pNew ); Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; @@ -728,7 +728,7 @@ Gia_Man_t * Gia_ManDupCofInt( Gia_Man_t * p, int iVar ) if ( pObj == pPivot ) { iCofVar = pObj->Value; - pObj->Value = Gia_Var2Lit( 0, 0 ); + pObj->Value = Abc_Var2Lit( 0, 0 ); } } Gia_ManForEachAnd( p, pObj, i ) @@ -737,7 +737,7 @@ Gia_Man_t * Gia_ManDupCofInt( Gia_Man_t * p, int iVar ) if ( pObj == pPivot ) { iCofVar = pObj->Value; - pObj->Value = Gia_Var2Lit( 0, 0 ); + pObj->Value = Abc_Var2Lit( 0, 0 ); } } Gia_ManForEachCo( p, pObj, i ) @@ -745,15 +745,15 @@ Gia_Man_t * Gia_ManDupCofInt( Gia_Man_t * p, int iVar ) // compute the positive cofactor Gia_ManForEachCi( p, pObj, i ) { - pObj->Value = Gia_Var2Lit( Gia_ObjId(pNew, Gia_ManCi(pNew, i)), 0 ); + pObj->Value = Abc_Var2Lit( Gia_ObjId(pNew, Gia_ManCi(pNew, i)), 0 ); if ( pObj == pPivot ) - pObj->Value = Gia_Var2Lit( 0, 1 ); + pObj->Value = Abc_Var2Lit( 0, 1 ); } Gia_ManForEachAnd( p, pObj, i ) { pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); if ( pObj == pPivot ) - pObj->Value = Gia_Var2Lit( 0, 1 ); + pObj->Value = Abc_Var2Lit( 0, 1 ); } // create MUXes assert( iCofVar > 0 ); @@ -836,9 +836,9 @@ Vec_Int_t * Gia_ManTransfer( Gia_Man_t * pAig, Gia_Man_t * pCof, Gia_Man_t * pNe Gia_ManForEachObjVec( vSigs, pAig, pObj, i ) { assert( Gia_ObjIsCand(pObj) ); - pObjF = Gia_ManObj( pCof, Gia_Lit2Var(pObj->Value) ); + pObjF = Gia_ManObj( pCof, Abc_Lit2Var(pObj->Value) ); if ( pObjF->Value && ~pObjF->Value ) - Vec_IntPushUnique( vSigsNew, Gia_Lit2Var(pObjF->Value) ); + Vec_IntPushUnique( vSigsNew, Abc_Lit2Var(pObjF->Value) ); } return vSigsNew; } diff --git a/src/aig/gia/giaDup.c b/src/aig/gia/giaDup.c index 258687fe..b3c04acb 100644 --- a/src/aig/gia/giaDup.c +++ b/src/aig/gia/giaDup.c @@ -55,14 +55,14 @@ void Gia_ManDupRemapEquiv( Gia_Man_t * pNew, Gia_Man_t * p ) Gia_ObjSetRepr( pNew, i, GIA_VOID ); // iterate over constant candidates Gia_ManForEachConst( p, i ) - Gia_ObjSetRepr( pNew, Gia_Lit2Var(Gia_ManObj(p, i)->Value), 0 ); + Gia_ObjSetRepr( pNew, Abc_Lit2Var(Gia_ManObj(p, i)->Value), 0 ); // iterate over class candidates vClass = Vec_IntAlloc( 100 ); Gia_ManForEachClass( p, i ) { Vec_IntClear( vClass ); Gia_ClassForEachObj( p, i, k ) - Vec_IntPushUnique( vClass, Gia_Lit2Var(Gia_ManObj(p, k)->Value) ); + Vec_IntPushUnique( vClass, Abc_Lit2Var(Gia_ManObj(p, k)->Value) ); assert( Vec_IntSize( vClass ) > 1 ); Vec_IntSort( vClass, 0 ); iRepr = iPrev = Vec_IntEntry( vClass, 0 ); @@ -173,7 +173,7 @@ Gia_Man_t * Gia_ManDupOrderDfs( Gia_Man_t * p ) int i; Gia_ManFillValue( p ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCo( p, pObj, i ) Gia_ManDupOrderDfs_rec( pNew, p, pObj ); @@ -205,7 +205,7 @@ Gia_Man_t * Gia_ManDupOutputGroup( Gia_Man_t * p, int iOutStart, int iOutStop ) int i; Gia_ManFillValue( p ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManConst0(p)->Value = 0; for ( i = iOutStart; i < iOutStop; i++ ) { @@ -240,8 +240,8 @@ void Gia_ManDupOrderDfsChoices_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); if ( pNext ) { - pNew->pNexts[Gia_Lit2Var(pObj->Value)] = Gia_Lit2Var( Gia_Lit2Var(pNext->Value) ); - assert( Gia_Lit2Var(pObj->Value) > Gia_Lit2Var(pNext->Value) ); + pNew->pNexts[Abc_Lit2Var(pObj->Value)] = Abc_Lit2Var( Abc_Lit2Var(pNext->Value) ); + assert( Abc_Lit2Var(pObj->Value) > Abc_Lit2Var(pNext->Value) ); } } @@ -264,7 +264,7 @@ Gia_Man_t * Gia_ManDupOrderDfsChoices( Gia_Man_t * p ) assert( p->pReprs && p->pNexts ); Gia_ManFillValue( p ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pNexts = ABC_CALLOC( int, Gia_ManObjNum(p) ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) @@ -297,7 +297,7 @@ Gia_Man_t * Gia_ManDupOrderDfsReverse( Gia_Man_t * p ) int i; Gia_ManFillValue( p ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCoReverse( p, pObj, i ) Gia_ManDupOrderDfs_rec( pNew, p, pObj ); @@ -329,7 +329,7 @@ Gia_Man_t * Gia_ManDupOrderAiger( Gia_Man_t * p ) Gia_Obj_t * pObj; int i; pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); @@ -361,7 +361,7 @@ Gia_Man_t * Gia_ManDupFlip( Gia_Man_t * p, int * pInitState ) Gia_Obj_t * pObj; int i; pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachObj1( p, pObj, i ) { @@ -371,13 +371,13 @@ Gia_Man_t * Gia_ManDupFlip( Gia_Man_t * p, int * pInitState ) { pObj->Value = Gia_ManAppendCi( pNew ); if ( Gia_ObjCioId(pObj) >= Gia_ManPiNum(p) ) - pObj->Value = Gia_LitNotCond( pObj->Value, Gia_InfoHasBit((unsigned *)pInitState, Gia_ObjCioId(pObj) - Gia_ManPiNum(p)) ); + pObj->Value = Abc_LitNotCond( pObj->Value, Abc_InfoHasBit((unsigned *)pInitState, Gia_ObjCioId(pObj) - Gia_ManPiNum(p)) ); } else if ( Gia_ObjIsCo(pObj) ) { pObj->Value = Gia_ObjFanin0Copy(pObj); if ( Gia_ObjCioId(pObj) >= Gia_ManPoNum(p) ) - pObj->Value = Gia_LitNotCond( pObj->Value, Gia_InfoHasBit((unsigned *)pInitState, Gia_ObjCioId(pObj) - Gia_ManPoNum(p)) ); + pObj->Value = Abc_LitNotCond( pObj->Value, Abc_InfoHasBit((unsigned *)pInitState, Gia_ObjCioId(pObj) - Gia_ManPoNum(p)) ); pObj->Value = Gia_ManAppendCo( pNew, pObj->Value ); } } @@ -403,7 +403,7 @@ Gia_Man_t * Gia_ManDup( Gia_Man_t * p ) Gia_Obj_t * pObj; int i; pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachObj1( p, pObj, i ) { @@ -437,7 +437,7 @@ Gia_Man_t * Gia_ManDupSelf( Gia_Man_t * p ) Gia_Obj_t * pObj; int i, iCtrl; pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManHashAlloc( pNew ); Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; @@ -477,7 +477,7 @@ Gia_Man_t * Gia_ManDupFlopClass( Gia_Man_t * p, int iClass ) int i, Counter1 = 0, Counter2 = 0; assert( p->vFlopClasses != NULL ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachPi( p, pObj, i ) @@ -522,7 +522,7 @@ Gia_Man_t * Gia_ManDupMarked( Gia_Man_t * p ) Gia_ManFillValue( p ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->nConstrs = p->nConstrs; - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachObj1( p, pObj, i ) { @@ -561,8 +561,8 @@ Gia_Man_t * Gia_ManDupMarked( Gia_Man_t * p ) // assert( ~pRepr->Value ); if ( !~pRepr->Value ) continue; - if ( Gia_Lit2Var(pObj->Value) != Gia_Lit2Var(pRepr->Value) ) - Gia_ObjSetRepr( pNew, Gia_Lit2Var(pObj->Value), Gia_Lit2Var(pRepr->Value) ); + if ( Abc_Lit2Var(pObj->Value) != Abc_Lit2Var(pRepr->Value) ) + Gia_ObjSetRepr( pNew, Abc_Lit2Var(pObj->Value), Abc_Lit2Var(pRepr->Value) ); } pNew->pNexts = Gia_ManDeriveNexts( pNew ); } @@ -588,7 +588,7 @@ Gia_Man_t * Gia_ManDupTimes( Gia_Man_t * p, int nTimes ) int i, t, Entry; assert( nTimes > 0 ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManConst0(p)->Value = 0; vPis = Vec_IntAlloc( Gia_ManPiNum(p) * nTimes ); vPos = Vec_IntAlloc( Gia_ManPoNum(p) * nTimes ); @@ -604,17 +604,17 @@ Gia_Man_t * Gia_ManDupTimes( Gia_Man_t * p, int nTimes ) { pObj->Value = Gia_ManAppendCi( pNew ); if ( Gia_ObjIsPi(p, pObj) ) - Vec_IntPush( vPis, Gia_Lit2Var(pObj->Value) ); + Vec_IntPush( vPis, Abc_Lit2Var(pObj->Value) ); else - Vec_IntPush( vRos, Gia_Lit2Var(pObj->Value) ); + Vec_IntPush( vRos, Abc_Lit2Var(pObj->Value) ); } else if ( Gia_ObjIsCo(pObj) ) { pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); if ( Gia_ObjIsPo(p, pObj) ) - Vec_IntPush( vPos, Gia_Lit2Var(pObj->Value) ); + Vec_IntPush( vPos, Abc_Lit2Var(pObj->Value) ); else - Vec_IntPush( vRis, Gia_Lit2Var(pObj->Value) ); + Vec_IntPush( vRis, Abc_Lit2Var(pObj->Value) ); } } } @@ -667,7 +667,7 @@ int Gia_ManDupDfs2_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) { Gia_Obj_t * pRepr = Gia_ManObj( p, p->pReprsOld[Gia_ObjId(p, pObj)] ); pRepr->Value = Gia_ManDupDfs2_rec( pNew, p, pRepr ); - return pObj->Value = Gia_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); + return pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); } if ( Gia_ObjIsCi(pObj) ) return pObj->Value = Gia_ManAppendCi(pNew); @@ -698,7 +698,7 @@ Gia_Man_t * Gia_ManDupDfs2( Gia_Man_t * p ) int i; Gia_ManFillValue( p ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCo( p, pObj, i ) Gia_ManDupDfs2_rec( pNew, p, pObj ); @@ -756,7 +756,7 @@ Gia_Man_t * Gia_ManDupDfs( Gia_Man_t * p ) Gia_Obj_t * pObj; int i; pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) @@ -789,7 +789,7 @@ Gia_Man_t * Gia_ManDupDfsSkip( Gia_Man_t * p ) int i; Gia_ManFillValue( p ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); @@ -819,7 +819,7 @@ Gia_Man_t * Gia_ManDupDfsCone( Gia_Man_t * p, Gia_Obj_t * pRoot ) assert( Gia_ObjIsCo(pRoot) ); Gia_ManFillValue( p ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); @@ -847,14 +847,14 @@ Gia_Man_t * Gia_ManDupDfsLitArray( Gia_Man_t * p, Vec_Int_t * vLits ) int i, iLit, iLitRes; Gia_ManFillValue( p ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); Vec_IntForEachEntry( vLits, iLit, i ) { - iLitRes = Gia_ManDupDfs2_rec( pNew, p, Gia_ManObj(p, Gia_Lit2Var(iLit)) ); - Gia_ManAppendCo( pNew, Gia_LitNotCond( iLitRes, Gia_LitIsCompl(iLit)) ); + iLitRes = Gia_ManDupDfs2_rec( pNew, p, Gia_ManObj(p, Abc_Lit2Var(iLit)) ); + Gia_ManAppendCo( pNew, Abc_LitNotCond( iLitRes, Abc_LitIsCompl(iLit)) ); } Gia_ManSetRegNum( pNew, 0 ); return pNew; @@ -877,7 +877,7 @@ Gia_Man_t * Gia_ManDupNormalized( Gia_Man_t * p ) Gia_Obj_t * pObj; int i; pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); @@ -908,7 +908,7 @@ Gia_Man_t * Gia_ManDupTrimmed( Gia_Man_t * p, int fTrimCis, int fTrimCos ) int i; Gia_ManFillValue( p ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManSetRefs( p ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) @@ -943,7 +943,7 @@ Gia_Man_t * Gia_ManDupOntop( Gia_Man_t * p, Gia_Man_t * p2 ) assert( Gia_ManRegNum(p) == 0 ); assert( Gia_ManRegNum(p2) == 0 ); pNew = Gia_ManStart( Gia_ManObjNum(p)+Gia_ManObjNum(p2) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManHashAlloc( pNew ); // dup first AIG Gia_ManConst0(p)->Value = 0; @@ -1005,13 +1005,13 @@ Gia_Man_t * Gia_ManDupDfsCiMap( Gia_Man_t * p, int * pCi2Lit, Vec_Int_t * vLits int i; Gia_ManFillValue( p ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) { pObj->Value = Gia_ManAppendCi(pNew); if ( ~pCi2Lit[i] ) - pObj->Value = Gia_LitNotCond( Gia_ManObj(p, Gia_Lit2Var(pCi2Lit[i]))->Value, Gia_LitIsCompl(pCi2Lit[i]) ); + pObj->Value = Abc_LitNotCond( Gia_ManObj(p, Abc_Lit2Var(pCi2Lit[i]))->Value, Abc_LitIsCompl(pCi2Lit[i]) ); } Gia_ManHashAlloc( pNew ); if ( vLits ) @@ -1019,8 +1019,8 @@ Gia_Man_t * Gia_ManDupDfsCiMap( Gia_Man_t * p, int * pCi2Lit, Vec_Int_t * vLits int iLit, iLitRes; Vec_IntForEachEntry( vLits, iLit, i ) { - iLitRes = Gia_ManDupDfs2_rec( pNew, p, Gia_ManObj(p, Gia_Lit2Var(iLit)) ); - Gia_ManAppendCo( pNew, Gia_LitNotCond( iLitRes, Gia_LitIsCompl(iLit)) ); + iLitRes = Gia_ManDupDfs2_rec( pNew, p, Gia_ManObj(p, Abc_Lit2Var(iLit)) ); + Gia_ManAppendCo( pNew, Abc_LitNotCond( iLitRes, Abc_LitIsCompl(iLit)) ); } } else @@ -1055,7 +1055,7 @@ Gia_Man_t * Gia_ManDupDfsClasses( Gia_Man_t * p ) assert( p->pReprsOld != NULL ); Gia_ManFillValue( p ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); @@ -1112,7 +1112,7 @@ Gia_Man_t * Gia_ManDupTopAnd_iter( Gia_Man_t * p, int fVerbose ) { if ( Gia_ObjIsCi(pObj) ) { - Vec_IntPush( vLeaves, Gia_Var2Lit( Gia_ObjId(p, pObj), 0 ) ); + Vec_IntPush( vLeaves, Abc_Var2Lit( Gia_ObjId(p, pObj), 0 ) ); continue; } assert( Gia_ObjIsAnd(pObj) ); @@ -1132,16 +1132,16 @@ Gia_Man_t * Gia_ManDupTopAnd_iter( Gia_Man_t * p, int fVerbose ) pVar2Val = ABC_FALLOC( char, Gia_ManObjNum(p) ); Vec_IntForEachEntry( vLeaves, iLit, i ) { - iObjId = Gia_Lit2Var(iLit); + iObjId = Abc_Lit2Var(iLit); pObj = Gia_ManObj(p, iObjId); if ( Gia_ObjIsCi(pObj) ) { - pCi2Lit[Gia_ObjCioId(pObj)] = !Gia_LitIsCompl(iLit); + pCi2Lit[Gia_ObjCioId(pObj)] = !Abc_LitIsCompl(iLit); nCiLits++; } if ( pVar2Val[iObjId] != 0 && pVar2Val[iObjId] != 1 ) - pVar2Val[iObjId] = Gia_LitIsCompl(iLit); - else if ( pVar2Val[iObjId] != Gia_LitIsCompl(iLit) ) + pVar2Val[iObjId] = Abc_LitIsCompl(iLit); + else if ( pVar2Val[iObjId] != Abc_LitIsCompl(iLit) ) break; } if ( i < Vec_IntSize(vLeaves) ) @@ -1156,7 +1156,7 @@ Gia_Man_t * Gia_ManDupTopAnd_iter( Gia_Man_t * p, int fVerbose ) Vec_IntClear( vLeaves ); Gia_ManForEachObj( p, pObj, i ) if ( !Gia_ObjIsCi(pObj) && (pVar2Val[i] == 0 || pVar2Val[i] == 1) ) - Vec_IntPush( vLeaves, Gia_Var2Lit(i, pVar2Val[i]) ); + Vec_IntPush( vLeaves, Abc_Var2Lit(i, pVar2Val[i]) ); if ( fVerbose ) printf( "Detected %6d AND leaves and %6d CI leaves.\n", Vec_IntSize(vLeaves), nCiLits ); // create the input map @@ -1272,7 +1272,7 @@ Gia_Man_t * Gia_ManMiter( Gia_Man_t * p0, Gia_Man_t * p1, int fDualOut, int fSeq } // start the manager pNew = Gia_ManStart( Gia_ManObjNum(p0) + Gia_ManObjNum(p1) ); - pNew->pName = Gia_UtilStrsav( "miter" ); + pNew->pName = Abc_UtilStrsav( "miter" ); // map combinational inputs Gia_ManFillValue( p0 ); Gia_ManFillValue( p1 ); @@ -1372,7 +1372,7 @@ Gia_Man_t * Gia_ManTransformMiter( Gia_Man_t * p ) int i, iLit; assert( (Gia_ManPoNum(p) & 1) == 0 ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManConst0(p)->Value = 0; Gia_ManHashAlloc( pNew ); Gia_ManForEachCi( p, pObj, i ) @@ -1444,7 +1444,7 @@ Gia_Man_t * Gia_ManChoiceMiter( Vec_Ptr_t * vGias ) } // start the new manager pNew = Gia_ManStart( Vec_PtrSize(vGias) * Gia_ManObjNum(pGia0) ); - pNew->pName = Gia_UtilStrsav( pGia0->pName ); + pNew->pName = Abc_UtilStrsav( pGia0->pName ); // create new CIs and assign them to the old manager CIs for ( k = 0; k < Gia_ManCiNum(pGia0); k++ ) { @@ -1485,7 +1485,7 @@ Gia_Man_t * Gia_ManDupWithConstraints( Gia_Man_t * p, Vec_Int_t * vPoTypes ) Gia_Obj_t * pObj; int i, nConstr = 0; pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); @@ -1546,7 +1546,7 @@ Gia_Man_t * Gia_ManDupAbsFlops( Gia_Man_t * p, Vec_Int_t * vFlopClasses ) Gia_ManFillValue( p ); // start the new manager pNew = Gia_ManStart( 5000 ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); // create PIs Gia_ManConst0(p)->Value = 0; Gia_ManForEachPi( p, pObj, i ) @@ -1647,7 +1647,7 @@ Gia_Man_t * Gia_ManDupAbsGates( Gia_Man_t * p, Vec_Int_t * vGateClasses ) // start the new manager pNew = Gia_ManStart( 5000 ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); // create constant Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; @@ -1681,7 +1681,7 @@ Gia_Man_t * Gia_ManDupAbsGates( Gia_Man_t * p, Vec_Int_t * vGateClasses ) { if ( !~pObj->Value ) continue; - assert( !Gia_LitIsCompl(pObj->Value) ); + assert( !Abc_LitIsCompl(pObj->Value) ); pCopy = Gia_ObjCopy( pTemp, pObj ); if ( !~pCopy->Value ) { @@ -1689,7 +1689,7 @@ Gia_Man_t * Gia_ManDupAbsGates( Gia_Man_t * p, Vec_Int_t * vGateClasses ) pObj->Value = ~0; continue; } - assert( !Gia_LitIsCompl(pCopy->Value) ); + assert( !Abc_LitIsCompl(pCopy->Value) ); pObj->Value = pCopy->Value; } } diff --git a/src/aig/gia/giaEmbed.c b/src/aig/gia/giaEmbed.c index 5c7092a3..1daf52a1 100644 --- a/src/aig/gia/giaEmbed.c +++ b/src/aig/gia/giaEmbed.c @@ -20,7 +20,7 @@ #include #include "gia.h" -#include "ioa.h" +#include "src/aig/ioa/ioa.h" ABC_NAMESPACE_IMPL_START @@ -690,12 +690,12 @@ void Emb_ManPrintFanio( Emb_Man_t * p ) nFanouts = Emb_ObjFanoutNum(pNode); nFaninsAll += nFanins; nFanoutsAll += nFanouts; - nFaninsMax = ABC_MAX( nFaninsMax, nFanins ); - nFanoutsMax = ABC_MAX( nFanoutsMax, nFanouts ); + nFaninsMax = Abc_MaxInt( nFaninsMax, nFanins ); + nFanoutsMax = Abc_MaxInt( nFanoutsMax, nFanouts ); } // allocate storage for fanin/fanout numbers - nSizeMax = ABC_MAX( 10 * (Gia_Base10Log(nFaninsMax) + 1), 10 * (Gia_Base10Log(nFanoutsMax) + 1) ); + nSizeMax = Abc_MaxInt( 10 * (Abc_Base10Log(nFaninsMax) + 1), 10 * (Abc_Base10Log(nFanoutsMax) + 1) ); vFanins = Vec_IntStart( nSizeMax ); vFanouts = Vec_IntStart( nSizeMax ); @@ -1436,8 +1436,8 @@ void Emb_ManDerivePlacement( Emb_Man_t * p, int nSols ) pY0 = Emb_ManSol( p, 0 ); for ( k = 0; k < p->nObjs; k++ ) { - Min0 = ABC_MIN( Min0, pY0[k] ); - Max0 = ABC_MAX( Max0, pY0[k] ); + Min0 = Abc_MinInt( Min0, pY0[k] ); + Max0 = Abc_MaxInt( Max0, pY0[k] ); } Str0 = 1.0*GIA_PLACE_SIZE/(Max0 - Min0); // update the coordinates @@ -1450,8 +1450,8 @@ void Emb_ManDerivePlacement( Emb_Man_t * p, int nSols ) pY1 = Emb_ManSol( p, 1 ); for ( k = 0; k < p->nObjs; k++ ) { - Min1 = ABC_MIN( Min1, pY1[k] ); - Max1 = ABC_MAX( Max1, pY1[k] ); + Min1 = Abc_MinInt( Min1, pY1[k] ); + Max1 = Abc_MaxInt( Max1, pY1[k] ); } Str1 = 1.0*GIA_PLACE_SIZE/(Max1 - Min1); // update the coordinates @@ -1498,10 +1498,10 @@ double Emb_ManComputeHPWL( Emb_Man_t * p ) iMinY = iMaxY = p->pPlacement[2*pThis->Value+1]; Emb_ObjForEachFanout( pThis, pNext, k ) { - iMinX = ABC_MIN( iMinX, p->pPlacement[2*pNext->Value+0] ); - iMaxX = ABC_MAX( iMaxX, p->pPlacement[2*pNext->Value+0] ); - iMinY = ABC_MIN( iMinY, p->pPlacement[2*pNext->Value+1] ); - iMaxY = ABC_MAX( iMaxY, p->pPlacement[2*pNext->Value+1] ); + iMinX = Abc_MinInt( iMinX, p->pPlacement[2*pNext->Value+0] ); + iMaxX = Abc_MaxInt( iMaxX, p->pPlacement[2*pNext->Value+0] ); + iMinY = Abc_MinInt( iMinY, p->pPlacement[2*pNext->Value+1] ); + iMaxY = Abc_MaxInt( iMaxY, p->pPlacement[2*pNext->Value+1] ); } Result += (iMaxX - iMinX) + (iMaxY - iMinY); } @@ -1548,10 +1548,10 @@ void Emb_ManPlacementRefine( Emb_Man_t * p, int nIters, int fVerbose ) iMinY = iMaxY = p->pPlacement[2*pThis->Value+1]; Emb_ObjForEachFanout( pThis, pNext, k ) { - iMinX = ABC_MIN( iMinX, p->pPlacement[2*pNext->Value+0] ); - iMaxX = ABC_MAX( iMaxX, p->pPlacement[2*pNext->Value+0] ); - iMinY = ABC_MIN( iMinY, p->pPlacement[2*pNext->Value+1] ); - iMaxY = ABC_MAX( iMaxY, p->pPlacement[2*pNext->Value+1] ); + iMinX = Abc_MinInt( iMinX, p->pPlacement[2*pNext->Value+0] ); + iMaxX = Abc_MaxInt( iMaxX, p->pPlacement[2*pNext->Value+0] ); + iMinY = Abc_MinInt( iMinY, p->pPlacement[2*pNext->Value+1] ); + iMaxY = Abc_MaxInt( iMaxY, p->pPlacement[2*pNext->Value+1] ); } pEdgeX[pThis->Value] = 0.5 * (iMaxX + iMinX); pEdgeY[pThis->Value] = 0.5 * (iMaxY + iMinY); diff --git a/src/aig/gia/giaEnable.c b/src/aig/gia/giaEnable.c index 37f0c94f..d23c0c3d 100644 --- a/src/aig/gia/giaEnable.c +++ b/src/aig/gia/giaEnable.c @@ -338,9 +338,9 @@ Vec_Int_t * Gia_ManTransferFrames( Gia_Man_t * pAig, Gia_Man_t * pFrames, int nF assert( Gia_ObjIsCand(pObj) ); for ( f = 0; f < nFrames; f++ ) { - pObjF = Gia_ManObj( pFrames, Gia_Lit2Var(Gia_ObjCopyF( pAig, f, pObj )) ); + pObjF = Gia_ManObj( pFrames, Abc_Lit2Var(Gia_ObjCopyF( pAig, f, pObj )) ); if ( pObjF->Value && ~pObjF->Value ) - Vec_IntPushUnique( vSigsNew, Gia_Lit2Var(pObjF->Value) ); + Vec_IntPushUnique( vSigsNew, Abc_Lit2Var(pObjF->Value) ); } } return vSigsNew; @@ -365,7 +365,7 @@ Gia_Man_t * Gia_ManUnrollInit( Gia_Man_t * p, int nFrames ) ABC_FREE( p->pCopies ); p->pCopies = ABC_FALLOC( int, nFrames * Gia_ManObjNum(p) ); pNew = Gia_ManStart( nFrames * Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManHashAlloc( pNew ); Gia_ManForEachRo( p, pObj, i ) Gia_ObjSetCopyF( p, 0, pObj, 0 ); @@ -440,7 +440,7 @@ Gia_Man_t * Gia_ManRemoveEnables2( Gia_Man_t * p ) Gia_Obj_t * pThis, * pNode; int i; pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManHashAlloc( pNew ); Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; @@ -481,13 +481,13 @@ Gia_Man_t * Gia_ManRemoveEnables2( Gia_Man_t * p ) { // printf( "FlopIn compl = %d. FlopOut is d0. Complement = %d.\n", // Gia_ObjFaninC0(pFlopIn), Gia_IsComplement(pObj0) ); - pFlopIn->Value = Gia_LitNotCond(Gia_Regular(pObj1)->Value, !Gia_IsComplement(pObj1)); + pFlopIn->Value = Abc_LitNotCond(Gia_Regular(pObj1)->Value, !Gia_IsComplement(pObj1)); } else if ( Gia_Regular(pObj1) == pFlopOut ) { // printf( "FlopIn compl = %d. FlopOut is d1. Complement = %d.\n", // Gia_ObjFaninC0(pFlopIn), Gia_IsComplement(pObj1) ); - pFlopIn->Value = Gia_LitNotCond(Gia_Regular(pObj0)->Value, !Gia_IsComplement(pObj0)); + pFlopIn->Value = Abc_LitNotCond(Gia_Regular(pObj0)->Value, !Gia_IsComplement(pObj0)); } } Gia_ManForEachCo( p, pThis, i ) @@ -610,7 +610,7 @@ Gia_Man_t * Gia_ManRemoveEnables( Gia_Man_t * p ) pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachObj1( p, pObj, i ) { @@ -627,7 +627,7 @@ Gia_Man_t * Gia_ManRemoveEnables( Gia_Man_t * p ) if ( pData == NULL ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); else - pObj->Value = Gia_ManAppendCo( pNew, Gia_LitNotCond(Gia_Regular(pData)->Value, Gia_IsComplement(pData)) ); + pObj->Value = Gia_ManAppendCo( pNew, Abc_LitNotCond(Gia_Regular(pData)->Value, Gia_IsComplement(pData)) ); } Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); Vec_PtrFree( vDatas ); diff --git a/src/aig/gia/giaEquiv.c b/src/aig/gia/giaEquiv.c index c93da86e..43724871 100644 --- a/src/aig/gia/giaEquiv.c +++ b/src/aig/gia/giaEquiv.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "gia.h" -#include "cec.h" +#include "src/proof/cec/cec.h" ABC_NAMESPACE_IMPL_START @@ -417,7 +417,7 @@ void Gia_ManEquivReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, if ( (pRepr = Gia_ManEquivRepr(p, pObj, fUseAll, fDualOut)) ) { Gia_ManEquivReduce_rec( pNew, p, pRepr, fUseAll, fDualOut ); - pObj->Value = Gia_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); + pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); return; } if ( ~pObj->Value ) @@ -474,7 +474,7 @@ Gia_Man_t * Gia_ManEquivReduce( Gia_Man_t * p, int fUseAll, int fDualOut, int fV if ( fDualOut ) Gia_ManEquivSetColors( p, fVerbose ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) @@ -536,7 +536,7 @@ void Gia_ManEquivUpdatePointers( Gia_Man_t * p, Gia_Man_t * pNew ) { if ( !~pObj->Value ) continue; - pObjNew = Gia_ManObj( pNew, Gia_Lit2Var(pObj->Value) ); + pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(pObj->Value) ); if ( pObjNew->fMark0 ) pObj->Value = ~0; } @@ -568,10 +568,10 @@ void Gia_ManEquivDeriveReprs( Gia_Man_t * p, Gia_Man_t * pNew, Gia_Man_t * pFina pObj = Gia_ManObj( p, i ); if ( !~pObj->Value ) continue; - pObjNew = Gia_ManObj( pNew, Gia_Lit2Var(pObj->Value) ); - if ( Gia_Lit2Var(pObjNew->Value) == 0 ) + pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(pObj->Value) ); + if ( Abc_Lit2Var(pObjNew->Value) == 0 ) continue; - Gia_ObjSetRepr( pFinal, Gia_Lit2Var(pObjNew->Value), 0 ); + Gia_ObjSetRepr( pFinal, Abc_Lit2Var(pObjNew->Value), 0 ); } // iterate over class candidates vClass = Vec_IntAlloc( 100 ); @@ -583,8 +583,8 @@ void Gia_ManEquivDeriveReprs( Gia_Man_t * p, Gia_Man_t * pNew, Gia_Man_t * pFina pObj = Gia_ManObj( p, k ); if ( !~pObj->Value ) continue; - pObjNew = Gia_ManObj( pNew, Gia_Lit2Var(pObj->Value) ); - Vec_IntPushUnique( vClass, Gia_Lit2Var(pObjNew->Value) ); + pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(pObj->Value) ); + Vec_IntPushUnique( vClass, Abc_Lit2Var(pObjNew->Value) ); } if ( Vec_IntSize( vClass ) < 2 ) continue; @@ -624,14 +624,14 @@ Gia_Man_t * Gia_ManEquivRemapDfs( Gia_Man_t * p ) Gia_ObjSetRepr( pNew, i, GIA_VOID ); // iterate over constant candidates Gia_ManForEachConst( p, i ) - Gia_ObjSetRepr( pNew, Gia_Lit2Var(Gia_ManObj(p, i)->Value), 0 ); + Gia_ObjSetRepr( pNew, Abc_Lit2Var(Gia_ManObj(p, i)->Value), 0 ); // iterate over class candidates vClass = Vec_IntAlloc( 100 ); Gia_ManForEachClass( p, i ) { Vec_IntClear( vClass ); Gia_ClassForEachObj( p, i, k ) - Vec_IntPushUnique( vClass, Gia_Lit2Var(Gia_ManObj(p, k)->Value) ); + Vec_IntPushUnique( vClass, Abc_Lit2Var(Gia_ManObj(p, k)->Value) ); assert( Vec_IntSize( vClass ) > 1 ); Vec_IntSort( vClass, 0 ); iRepr = iPrev = Vec_IntEntry( vClass, 0 ); @@ -758,7 +758,7 @@ static inline void Gia_ManSpecBuild( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t // if ( fDualOut && !Gia_ObjDiffColors( p, Gia_ObjId(p, pObj), Gia_ObjId(p, pRepr) ) ) if ( fDualOut && !Gia_ObjDiffColors2( p, Gia_ObjId(p, pObj), Gia_ObjId(p, pRepr) ) ) return; - iLitNew = Gia_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); + iLitNew = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); if ( pObj->Value != iLitNew && !Gia_ObjProved(p, Gia_ObjId(p,pObj)) ) { if ( vTrace ) @@ -847,7 +847,7 @@ Gia_Man_t * Gia_ManSpecReduceTrace( Gia_Man_t * p, Vec_Int_t * vTrace ) Gia_ManSetPhase( p ); Gia_ManFillValue( p ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManHashAlloc( pNew ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) @@ -917,7 +917,7 @@ Gia_Man_t * Gia_ManSpecReduce( Gia_Man_t * p, int fDualOut, int fSynthesis, int if ( fDualOut ) Gia_ManEquivSetColors( p, fVerbose ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManHashAlloc( pNew ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) @@ -983,7 +983,7 @@ void Gia_ManSpecBuildInit( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Ve // if ( fDualOut && !Gia_ObjDiffColors( p, Gia_ObjId(p, pObj), Gia_ObjId(p, pRepr) ) ) if ( fDualOut && !Gia_ObjDiffColors2( p, Gia_ObjId(p, pObj), Gia_ObjId(p, pRepr) ) ) return; - iLitNew = Gia_LitNotCond( Gia_ObjCopyF(p, f, pRepr), Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); + iLitNew = Abc_LitNotCond( Gia_ObjCopyF(p, f, pRepr), Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); if ( Gia_ObjCopyF(p, f, pObj) != iLitNew && !Gia_ObjProved(p, Gia_ObjId(p,pObj)) ) Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, Gia_ObjCopyF(p, f, pObj), iLitNew) ); Gia_ObjSetCopyF( p, f, pObj, iLitNew ); @@ -1063,10 +1063,10 @@ Gia_Man_t * Gia_ManSpecReduceInit( Gia_Man_t * p, Abc_Cex_t * pInit, int nFrames if ( fDualOut ) Gia_ManEquivSetColors( p, 0 ); pNew = Gia_ManStart( nFrames * Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManHashAlloc( pNew ); Gia_ManForEachRo( p, pObj, i ) - Gia_ObjSetCopyF( p, 0, pObj, Gia_InfoHasBit(pInit->pData, i) ); + Gia_ObjSetCopyF( p, 0, pObj, Abc_InfoHasBit(pInit->pData, i) ); for ( f = 0; f < nFrames; f++ ) { Gia_ObjSetCopyF( p, f, Gia_ManConst0(p), 0 ); @@ -1463,7 +1463,7 @@ void Gia_ManEquivToChoices_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pOb { if ( Gia_ObjIsConst0(pRepr) ) { - pObj->Value = Gia_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); + pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); return; } Gia_ManEquivToChoices_rec( pNew, p, pRepr ); @@ -1471,22 +1471,22 @@ void Gia_ManEquivToChoices_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pOb Gia_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin0(pObj) ); Gia_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin1(pObj) ); pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); - if ( Gia_LitRegular(pObj->Value) == Gia_LitRegular(pRepr->Value) ) + if ( Abc_LitRegular(pObj->Value) == Abc_LitRegular(pRepr->Value) ) { - assert( (int)pObj->Value == Gia_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ) ); + assert( (int)pObj->Value == Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ) ); return; } if ( pRepr->Value > pObj->Value ) // should never happen with high resource limit return; assert( pRepr->Value < pObj->Value ); - pReprNew = Gia_ManObj( pNew, Gia_Lit2Var(pRepr->Value) ); - pObjNew = Gia_ManObj( pNew, Gia_Lit2Var(pObj->Value) ); + pReprNew = Gia_ManObj( pNew, Abc_Lit2Var(pRepr->Value) ); + pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(pObj->Value) ); if ( Gia_ObjReprObj( pNew, Gia_ObjId(pNew, pObjNew) ) ) { // assert( Gia_ObjReprObj( pNew, Gia_ObjId(pNew, pObjNew) ) == pReprNew ); if ( Gia_ObjReprObj( pNew, Gia_ObjId(pNew, pObjNew) ) != pReprNew ) return; - pObj->Value = Gia_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); + pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); return; } if ( !Gia_ObjCheckTfi( pNew, pReprNew, pObjNew ) ) @@ -1495,7 +1495,7 @@ void Gia_ManEquivToChoices_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pOb Gia_ObjSetRepr( pNew, Gia_ObjId(pNew, pObjNew), Gia_ObjId(pNew, pReprNew) ); Gia_ManAddNextEntry_rec( pNew, pReprNew, pObjNew ); } - pObj->Value = Gia_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); + pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); return; } assert( Gia_ObjIsAnd(pObj) ); @@ -1573,7 +1573,7 @@ Gia_Man_t * Gia_ManEquivToChoices( Gia_Man_t * p, int nSnapshots ) assert( (Gia_ManCoNum(p) % nSnapshots) == 0 ); Gia_ManSetPhase( p ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) ); pNew->pNexts = ABC_CALLOC( int, Gia_ManObjNum(p) ); for ( i = 0; i < Gia_ManObjNum(p); i++ ) @@ -1654,9 +1654,9 @@ int Gia_ManCountChoices( Gia_Man_t * p ) ABC_NAMESPACE_IMPL_END -#include "aig.h" -#include "saig.h" -#include "cec.h" +#include "src/aig/aig/aig.h" +#include "src/aig/saig/saig.h" +#include "src/proof/cec/cec.h" #include "giaAig.h" ABC_NAMESPACE_IMPL_START @@ -1826,7 +1826,7 @@ int Gia_ManFilterEquivsForSpeculation( Gia_Man_t * pGia, char * pName1, char * p { if ( pObj1->Value == ~0 ) continue; - pObjM = Gia_ManObj( pMiter, Gia_Lit2Var(pObj1->Value) ); + pObjM = Gia_ManObj( pMiter, Abc_Lit2Var(pObj1->Value) ); pObj = Gia_ManObj( pGia, Gia_ObjId(pMiter, pObjM) ); pObj->fMark0 = 1; } @@ -1835,7 +1835,7 @@ int Gia_ManFilterEquivsForSpeculation( Gia_Man_t * pGia, char * pName1, char * p { if ( pObj2->Value == ~0 ) continue; - pObjM = Gia_ManObj( pMiter, Gia_Lit2Var(pObj2->Value) ); + pObjM = Gia_ManObj( pMiter, Abc_Lit2Var(pObj2->Value) ); pObj = Gia_ManObj( pGia, Gia_ObjId(pMiter, pObjM) ); pObj->fMark1 = 1; } @@ -1965,7 +1965,7 @@ int Gia_ManFilterEquivsUsingParts( Gia_Man_t * pGia, char * pName1, char * pName { if ( pObj1->Value == ~0 ) continue; - pObjM = Gia_ManObj( pMiter, Gia_Lit2Var(pObj1->Value) ); + pObjM = Gia_ManObj( pMiter, Abc_Lit2Var(pObj1->Value) ); pObj = Gia_ManObj( pGia, Gia_ObjId(pMiter, pObjM) ); pObj->fMark0 = 1; } @@ -1974,7 +1974,7 @@ int Gia_ManFilterEquivsUsingParts( Gia_Man_t * pGia, char * pName1, char * pName { if ( pObj2->Value == ~0 ) continue; - pObjM = Gia_ManObj( pMiter, Gia_Lit2Var(pObj2->Value) ); + pObjM = Gia_ManObj( pMiter, Abc_Lit2Var(pObj2->Value) ); pObj = Gia_ManObj( pGia, Gia_ObjId(pMiter, pObjM) ); pObj->fMark1 = 1; } diff --git a/src/aig/gia/giaEra.c b/src/aig/gia/giaEra.c index ec3e1b1b..672149bc 100644 --- a/src/aig/gia/giaEra.c +++ b/src/aig/gia/giaEra.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "gia.h" -#include "mem.h" +#include "src/misc/mem/mem.h" ABC_NAMESPACE_IMPL_START @@ -45,7 +45,7 @@ struct Gia_ManEra_t_ { Gia_Man_t * pAig; // user's AIG manager int nWordsSim; // 2^(PInum) - int nWordsDat; // Gia_BitWordNum + int nWordsDat; // Abc_BitWordNum unsigned * pDataSim; // simulation data Mem_Fixed_t * pMemory; // memory manager Vec_Ptr_t * vStates; // reached states @@ -83,12 +83,12 @@ Gia_ManEra_t * Gia_ManEraCreate( Gia_Man_t * pAig ) int i; p = ABC_CALLOC( Gia_ManEra_t, 1 ); p->pAig = pAig; - p->nWordsSim = Gia_TruthWordNum( Gia_ManPiNum(pAig) ); - p->nWordsDat = Gia_BitWordNum( Gia_ManRegNum(pAig) ); + p->nWordsSim = Abc_TruthWordNum( Gia_ManPiNum(pAig) ); + p->nWordsDat = Abc_BitWordNum( Gia_ManRegNum(pAig) ); p->pDataSim = ABC_ALLOC( unsigned, p->nWordsSim*Gia_ManObjNum(pAig) ); p->pMemory = Mem_FixedStart( sizeof(Gia_ObjEra_t) + sizeof(unsigned) * p->nWordsDat ); p->vStates = Vec_PtrAlloc( 100000 ); - p->nBins = Gia_PrimeCudd( 100000 ); + p->nBins = Abc_PrimeCudd( 100000 ); p->pBins = ABC_CALLOC( unsigned, p->nBins ); Vec_PtrPush( p->vStates, NULL ); // assign primary input values @@ -226,7 +226,7 @@ void Gia_ManEraHashResize( Gia_ManEra_t * p ) // replace the table pBinsOld = p->pBins; nBinsOld = p->nBins; - p->nBins = Gia_PrimeCudd( 3 * p->nBins ); + p->nBins = Abc_PrimeCudd( 3 * p->nBins ); p->pBins = ABC_CALLOC( unsigned, p->nBins ); // rehash the entries from the old table Counter = 0; @@ -266,7 +266,7 @@ void Gia_ManInsertState( Gia_ManEra_t * p, Gia_ObjEra_t * pState ) Gia_ManForEachRo( p->pAig, pObj, i ) { pSimInfo = Gia_ManEraData( p, Gia_ObjId(p->pAig, pObj) ); - if ( Gia_InfoHasBit(pState->pData, i) ) + if ( Abc_InfoHasBit(pState->pData, i) ) memset( pSimInfo, 0xff, sizeof(unsigned) * p->nWordsSim ); else memset( pSimInfo, 0, sizeof(unsigned) * p->nWordsSim ); @@ -465,8 +465,8 @@ int Gia_ManAnalyzeResult( Gia_ManEra_t * p, Gia_ObjEra_t * pState, int fMiter ) Gia_ManForEachRi( p->pAig, pObj, i ) { pSimInfo = Gia_ManEraData( p, Gia_ObjId(p->pAig, pObj) ); - if ( Gia_InfoHasBit(p->pStateNew->pData, i) != Gia_InfoHasBit(pSimInfo, k) ) - Gia_InfoXorBit( p->pStateNew->pData, i ); + if ( Abc_InfoHasBit(p->pStateNew->pData, i) != Abc_InfoHasBit(pSimInfo, k) ) + Abc_InfoXorBit( p->pStateNew->pData, i ); } piPlace = Gia_ManEraHashFind( p, p->pStateNew ); if ( piPlace == NULL ) diff --git a/src/aig/gia/giaEra2.c b/src/aig/gia/giaEra2.c index b3e516eb..265335e2 100644 --- a/src/aig/gia/giaEra2.c +++ b/src/aig/gia/giaEra2.c @@ -136,11 +136,11 @@ static inline Gia_ObjAre_t * Gia_ObjNextObj0( Gia_ManAre_t * p, Gia_ObjAre_t * static inline Gia_ObjAre_t * Gia_ObjNextObj1( Gia_ManAre_t * p, Gia_ObjAre_t * q ) { return Gia_ManAreObj( p, q->F[1] ); } static inline Gia_ObjAre_t * Gia_ObjNextObj2( Gia_ManAre_t * p, Gia_ObjAre_t * q ) { return Gia_ManAreObj( p, q->F[2] ); } -static inline int Gia_StaHasValue0( Gia_StaAre_t * p, int iReg ) { return Gia_InfoHasBit( p->pData, iReg << 1 ); } -static inline int Gia_StaHasValue1( Gia_StaAre_t * p, int iReg ) { return Gia_InfoHasBit( p->pData, (iReg << 1) + 1 ); } +static inline int Gia_StaHasValue0( Gia_StaAre_t * p, int iReg ) { return Abc_InfoHasBit( p->pData, iReg << 1 ); } +static inline int Gia_StaHasValue1( Gia_StaAre_t * p, int iReg ) { return Abc_InfoHasBit( p->pData, (iReg << 1) + 1 ); } -static inline void Gia_StaSetValue0( Gia_StaAre_t * p, int iReg ) { Gia_InfoSetBit( p->pData, iReg << 1 ); } -static inline void Gia_StaSetValue1( Gia_StaAre_t * p, int iReg ) { Gia_InfoSetBit( p->pData, (iReg << 1) + 1 ); } +static inline void Gia_StaSetValue0( Gia_StaAre_t * p, int iReg ) { Abc_InfoSetBit( p->pData, iReg << 1 ); } +static inline void Gia_StaSetValue1( Gia_StaAre_t * p, int iReg ) { Abc_InfoSetBit( p->pData, (iReg << 1) + 1 ); } static inline Gia_StaAre_t * Gia_StaPrev( Gia_ManAre_t * p, Gia_StaAre_t * pS ) { return Gia_ManAreSta(p, pS->iPrev); } static inline Gia_StaAre_t * Gia_StaNext( Gia_ManAre_t * p, Gia_StaAre_t * pS ) { return Gia_ManAreSta(p, pS->iNext); } @@ -198,7 +198,7 @@ void Gia_ManCountMintermsInCube( Gia_StaAre_t * pCube, int nVars, unsigned * pSt for ( i = 0; i < nVars; i++ ) if ( m & (1 << i) ) Mint |= (1 << Dashes[i]); - Gia_InfoSetBit( pStore, Mint ); + Abc_InfoSetBit( pStore, Mint ); } } @@ -220,7 +220,7 @@ int Gia_ManCountMinterms( Gia_ManAre_t * p ) int i, nMemSize, Counter = 0; if ( Gia_ManRegNum(p->pAig) > 30 ) return -1; - nMemSize = Gia_BitWordNum( 1 << Gia_ManRegNum(p->pAig) ); + nMemSize = Abc_BitWordNum( 1 << Gia_ManRegNum(p->pAig) ); pMemory = ABC_CALLOC( unsigned, nMemSize ); Gia_ManAreForEachCubeStore( p, pCube, i ) if ( Gia_StaIsUsed(pCube) ) @@ -477,7 +477,7 @@ Gia_ManAre_t * Gia_ManAreCreate( Gia_Man_t * pAig ) assert( sizeof(Gia_ObjAre_t) == 16 ); p = ABC_CALLOC( Gia_ManAre_t, 1 ); p->pAig = pAig; - p->nWords = Gia_BitWordNum( 2 * Gia_ManRegNum(pAig) ); + p->nWords = Abc_BitWordNum( 2 * Gia_ManRegNum(pAig) ); p->nSize = sizeof(Gia_StaAre_t)/4 + p->nWords; p->ppObjs = ABC_CALLOC( unsigned *, MAX_PAGE_NUM ); p->ppStas = ABC_CALLOC( unsigned *, MAX_PAGE_NUM ); @@ -1421,7 +1421,7 @@ static inline Gia_Obj_t * Gia_ManAreMostUsedPi( Gia_ManAre_t * p ) if ( pObj->Value <= 1 ) continue; Gia_ManIncrementTravId( p->pNew ); - Gia_ManAreMostUsedPi_rec( p->pNew, Gia_ManObj(p->pNew, Gia_Lit2Var(pObj->Value)) ); + Gia_ManAreMostUsedPi_rec( p->pNew, Gia_ManObj(p->pNew, Abc_Lit2Var(pObj->Value)) ); } // check the CI counters Gia_ManForEachCi( p->pNew, pObj, i ) @@ -1471,7 +1471,7 @@ static inline int Gia_ManCheckPOs( Gia_ManAre_t * p ) int i, CountCur, CountMax = 0; Gia_ManForEachPo( p->pAig, pObj, i ) { - pObjNew = Gia_ManObj( p->pNew, Gia_Lit2Var(pObj->Value) ); + pObjNew = Gia_ManObj( p->pNew, Abc_Lit2Var(pObj->Value) ); if ( Gia_ObjIsConst0(pObjNew) ) CountCur = 0; else @@ -1479,7 +1479,7 @@ static inline int Gia_ManCheckPOs( Gia_ManAre_t * p ) Gia_ManIncrementTravId( p->pNew ); CountCur = Gia_ManCheckPOs_rec( p->pNew, pObjNew ); } - CountMax = ABC_MAX( CountMax, CountCur ); + CountMax = Abc_MaxInt( CountMax, CountCur ); } return CountMax; } @@ -1501,10 +1501,10 @@ static inline int Gia_ManCheckPOstatus( Gia_ManAre_t * p ) int i; Gia_ManForEachPo( p->pAig, pObj, i ) { - pObjNew = Gia_ManObj( p->pNew, Gia_Lit2Var(pObj->Value) ); + pObjNew = Gia_ManObj( p->pNew, Abc_Lit2Var(pObj->Value) ); if ( Gia_ObjIsConst0(pObjNew) ) { - if ( Gia_LitIsCompl(pObj->Value) ) + if ( Abc_LitIsCompl(pObj->Value) ) { p->iOutFail = i; return 1; @@ -1638,7 +1638,7 @@ int Gia_ManAreDeriveNexts( Gia_ManAre_t * p, Gia_PtrAre_t Sta ) else if ( Gia_StaHasValue1( pSta, i ) ) pObj->Value = 1; else // don't-care literal - pObj->Value = Gia_Var2Lit( Gia_ObjId( p->pNew, Gia_ManCi(p->pNew, Gia_ObjCioId(pObj)) ), 0 ); + pObj->Value = Abc_Var2Lit( Gia_ObjId( p->pNew, Gia_ManCi(p->pNew, Gia_ObjCioId(pObj)) ), 0 ); } Gia_ManForEachAnd( p->pAig, pObj, i ) pObj->Value = Gia_ManHashAnd( p->pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); @@ -1770,8 +1770,8 @@ int Gia_ManArePerform( Gia_Man_t * pAig, int nStatesMax, int fMiter, int fVerbos ABC_NAMESPACE_IMPL_END #include "giaAig.h" -#include "cnf.h" -#include "satSolver.h" +#include "src/sat/cnf/cnf.h" +#include "src/sat/bsat/satSolver.h" ABC_NAMESPACE_IMPL_START @@ -1848,22 +1848,22 @@ void Gia_ManAreDeriveCexSat( Gia_ManAre_t * p, Gia_StaAre_t * pCur, Gia_StaAre_t for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) { if ( Gia_StaHasValue0(pCur, i) ) - Vec_IntPush( p->vAssumps, Gia_Var2Lit( Vec_IntEntry(p->vSatNumCis, Gia_ManPiNum(p->pAig)+i), 1 ) ); + Vec_IntPush( p->vAssumps, Abc_Var2Lit( Vec_IntEntry(p->vSatNumCis, Gia_ManPiNum(p->pAig)+i), 1 ) ); else if ( Gia_StaHasValue1(pCur, i) ) - Vec_IntPush( p->vAssumps, Gia_Var2Lit( Vec_IntEntry(p->vSatNumCis, Gia_ManPiNum(p->pAig)+i), 0 ) ); + Vec_IntPush( p->vAssumps, Abc_Var2Lit( Vec_IntEntry(p->vSatNumCis, Gia_ManPiNum(p->pAig)+i), 0 ) ); } if ( pNext ) for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) { if ( Gia_StaHasValue0(pNext, i) ) - Vec_IntPush( p->vAssumps, Gia_Var2Lit( Vec_IntEntry(p->vSatNumCos, Gia_ManPoNum(p->pAig)+i), 1 ) ); + Vec_IntPush( p->vAssumps, Abc_Var2Lit( Vec_IntEntry(p->vSatNumCos, Gia_ManPoNum(p->pAig)+i), 1 ) ); else if ( Gia_StaHasValue1(pNext, i) ) - Vec_IntPush( p->vAssumps, Gia_Var2Lit( Vec_IntEntry(p->vSatNumCos, Gia_ManPoNum(p->pAig)+i), 0 ) ); + Vec_IntPush( p->vAssumps, Abc_Var2Lit( Vec_IntEntry(p->vSatNumCos, Gia_ManPoNum(p->pAig)+i), 0 ) ); } if ( iOutFailed >= 0 ) { assert( iOutFailed < Gia_ManPoNum(p->pAig) ); - Vec_IntPush( p->vAssumps, Gia_Var2Lit( Vec_IntEntry(p->vSatNumCos, iOutFailed), 0 ) ); + Vec_IntPush( p->vAssumps, Abc_Var2Lit( Vec_IntEntry(p->vSatNumCos, iOutFailed), 0 ) ); } // solve SAT status = sat_solver_solve( (sat_solver *)p->pSat, (int *)Vec_IntArray(p->vAssumps), (int *)Vec_IntArray(p->vAssumps) + Vec_IntSize(p->vAssumps), @@ -1935,7 +1935,7 @@ Abc_Cex_t * Gia_ManAreDeriveCex( Gia_ManAre_t * p, Gia_StaAre_t * pLast ) Vec_IntForEachEntry( p->vCofVars, Var, v ) { assert( Var < Gia_ManPiNum(p->pAig) ); - Gia_InfoSetBit( pCex->pData, Gia_ManRegNum(p->pAig) + (Vec_PtrSize(vStates)-1-i) * Gia_ManPiNum(p->pAig) + Var ); + Abc_InfoSetBit( pCex->pData, Gia_ManRegNum(p->pAig) + (Vec_PtrSize(vStates)-1-i) * Gia_ManPiNum(p->pAig) + Var ); } } // free temporary things diff --git a/src/aig/gia/giaFanout.c b/src/aig/gia/giaFanout.c index c3e39405..412594ad 100644 --- a/src/aig/gia/giaFanout.c +++ b/src/aig/gia/giaFanout.c @@ -120,7 +120,7 @@ void Gia_ObjAddFanout( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanout ) assert( Gia_ObjId(p, pFanout) > 0 ); if ( Gia_ObjId(p, pObj) >= p->nFansAlloc || Gia_ObjId(p, pFanout) >= p->nFansAlloc ) { - int nFansAlloc = 2 * ABC_MAX( Gia_ObjId(p, pObj), Gia_ObjId(p, pFanout) ); + int nFansAlloc = 2 * Abc_MaxInt( Gia_ObjId(p, pObj), Gia_ObjId(p, pFanout) ); p->pFanData = ABC_REALLOC( int, p->pFanData, 5 * nFansAlloc ); memset( p->pFanData + 5 * p->nFansAlloc, 0, sizeof(int) * 5 * (nFansAlloc - p->nFansAlloc) ); p->nFansAlloc = nFansAlloc; diff --git a/src/aig/gia/giaForce.c b/src/aig/gia/giaForce.c index b9135404..6927266b 100644 --- a/src/aig/gia/giaForce.c +++ b/src/aig/gia/giaForce.c @@ -609,7 +609,7 @@ int Frc_ManCrossCut_rec( Frc_Man_t * p, Frc_Obj_t * pObj ) Frc_Obj_t * pFanin; int i; p->nCutCur++; - p->nCutMax = ABC_MAX( p->nCutMax, p->nCutCur ); + p->nCutMax = Abc_MaxInt( p->nCutMax, p->nCutCur ); if ( !Frc_ObjIsCi(pObj) ) Frc_ObjForEachFanin( pObj, pFanin, i ) p->nCutCur -= Frc_ManCrossCut_rec( p, pFanin ); @@ -636,7 +636,7 @@ int Frc_ManCrossCut2_rec( Frc_Man_t * p, Frc_Obj_t * pObj ) Frc_Obj_t * pFanin; int i; p->nCutCur++; - p->nCutMax = ABC_MAX( p->nCutMax, p->nCutCur ); + p->nCutMax = Abc_MaxInt( p->nCutMax, p->nCutCur ); if ( !Frc_ObjIsCi(pObj) ) Frc_ObjForEachFaninReverse( pObj, pFanin, i ) p->nCutCur -= Frc_ManCrossCut2_rec( p, pFanin ); @@ -912,8 +912,8 @@ void Frc_ManPlacementRefine( Frc_Man_t * p, int nIters, int fVerbose ) iMinX = iMaxX = pThis->pPlace; Frc_ObjForEachFanout( pThis, pNext, k ) { - iMinX = ABC_MIN( iMinX, pNext->pPlace ); - iMaxX = ABC_MAX( iMaxX, pNext->pPlace ); + iMinX = Abc_MinInt( iMinX, pNext->pPlace ); + iMaxX = Abc_MaxInt( iMaxX, pNext->pPlace ); } pThis->fEdgeCenter = 0.5 * (iMaxX + iMinX); CostThis += (iMaxX - iMinX); diff --git a/src/aig/gia/giaFrames.c b/src/aig/gia/giaFrames.c index 480326bd..237e6c5c 100644 --- a/src/aig/gia/giaFrames.c +++ b/src/aig/gia/giaFrames.c @@ -90,7 +90,7 @@ void Gia_ManUnrollDup_rec( Gia_Man_t * pNew, Gia_Obj_t * pObj, int Id ) pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } else assert( 0 ); - Gia_ManObj(pNew, Gia_Lit2Var(pObj->Value))->Value = Id; + Gia_ManObj(pNew, Abc_Lit2Var(pObj->Value))->Value = Id; } /**Function************************************************************* @@ -111,7 +111,7 @@ Gia_Man_t * Gia_ManUnrollDup( Gia_Man_t * p, Vec_Int_t * vLimit ) int i; assert( Vec_IntSize(vLimit) == 0 ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); // save constant class Gia_ManFillValue( p ); @@ -161,7 +161,7 @@ Vec_Ptr_t * Gia_ManUnrollAbs( Gia_Man_t * p, int nFrames ) int nObjBits, nObjMask; int f, fMax, k, Entry, Prev, iStart, iStop, Size; // get the bitmasks - nObjBits = Gia_Base2Log( Gia_ManObjNum(p) ); + nObjBits = Abc_Base2Log( Gia_ManObjNum(p) ); nObjMask = (1 << nObjBits) - 1; assert( Gia_ManObjNum(p) <= nObjMask ); // derive the tents @@ -349,12 +349,12 @@ static inline int Gia_ObjUnrRead( Gia_ManUnr_t * p, int Id, int Degree ) static inline int Gia_ObjUnrReadCopy0( Gia_ManUnr_t * p, Gia_Obj_t * pObj, int Id ) { int Lit = Gia_ObjUnrRead(p, Gia_ObjFaninId0(pObj, Id), Vec_IntEntry(p->vDegDiff, 2*Id)); - return Gia_LitNotCond( Lit, Gia_ObjFaninC0(pObj) ); + return Abc_LitNotCond( Lit, Gia_ObjFaninC0(pObj) ); } static inline int Gia_ObjUnrReadCopy1( Gia_ManUnr_t * p, Gia_Obj_t * pObj, int Id ) { int Lit = Gia_ObjUnrRead(p, Gia_ObjFaninId1(pObj, Id), Vec_IntEntry(p->vDegDiff, 2*Id+1)); - return Gia_LitNotCond( Lit, Gia_ObjFaninC1(pObj) ); + return Abc_LitNotCond( Lit, Gia_ObjFaninC1(pObj) ); } static inline int Gia_ObjUnrReadCi( Gia_ManUnr_t * p, int Id, int f, Gia_Man_t * pNew ) { @@ -367,7 +367,7 @@ static inline int Gia_ObjUnrReadCi( Gia_ManUnr_t * p, int Id, int f, Gia_Man_t * pObj = Gia_ManPi( pNew, Gia_ManPiNum(p->pAig) * f + Gia_ObjCioId(pObjReal) ); else pObj = Gia_ManPi( pNew, Gia_ManRegNum(p->pAig) + Gia_ManPiNum(p->pAig) * f + Gia_ObjCioId(pObjReal) ); - return Gia_Var2Lit( Gia_ObjId(pNew, pObj), 0 ); + return Abc_Var2Lit( Gia_ObjId(pNew, pObj), 0 ); } if ( f == 0 ) // initialize! { @@ -378,9 +378,9 @@ static inline int Gia_ObjUnrReadCi( Gia_ManUnr_t * p, int Id, int f, Gia_Man_t * pObj = Gia_ManPi( pNew, Gia_ManPiNum(p->pAig) * p->pPars->nFrames + Gia_ObjCioId(pObjReal)-Gia_ManPiNum(p->pAig) ); else pObj = Gia_ManPi( pNew, Gia_ObjCioId(pObjReal)-Gia_ManPiNum(p->pAig) ); - return Gia_Var2Lit( Gia_ObjId(pNew, pObj), 0 ); + return Abc_Var2Lit( Gia_ObjId(pNew, pObj), 0 ); } - pObj = Gia_ManObj( p->pOrder, Gia_Lit2Var(Gia_ObjRoToRi(p->pAig, pObjReal)->Value) ); + pObj = Gia_ManObj( p->pOrder, Abc_Lit2Var(Gia_ObjRoToRi(p->pAig, pObjReal)->Value) ); assert( Gia_ObjIsCo(pObj) ); return Gia_ObjUnrRead( p, Gia_ObjId(p->pOrder, pObj), 0 ); } @@ -405,7 +405,7 @@ void * Gia_ManUnrollStart( Gia_Man_t * pAig, Gia_ParFra_t * pPars ) // start timeframes assert( p->pNew == NULL ); p->pNew = Gia_ManStart( 10000 ); - p->pNew->pName = Gia_UtilStrsav( p->pAig->pName ); + p->pNew->pName = Abc_UtilStrsav( p->pAig->pName ); Gia_ManHashAlloc( p->pNew ); // create combinational inputs if ( !p->pPars->fSaveLastLit ) // only in the case when unrolling depth is known @@ -541,7 +541,7 @@ Gia_Man_t * Gia_ManUnroll( Gia_ManUnr_t * p ) int fMax, f, i, Lit, Beg, End; // start timeframes pNew = Gia_ManStart( 10000 ); - pNew->pName = Gia_UtilStrsav( p->pAig->pName ); + pNew->pName = Abc_UtilStrsav( p->pAig->pName ); Gia_ManHashAlloc( pNew ); // create combinational inputs for ( f = 0; f < p->pPars->nFrames; f++ ) @@ -754,7 +754,7 @@ Gia_Man_t * Gia_ManFramesInit( Gia_Man_t * pAig, Gia_ParFra_t * pPars ) Gia_ManFraSupports( p ); pFrames = Gia_ManStart( Vec_VecSizeSize((Vec_Vec_t*)p->vIns)+ Vec_VecSizeSize((Vec_Vec_t*)p->vAnds)+Vec_VecSizeSize((Vec_Vec_t*)p->vOuts) ); - pFrames->pName = Gia_UtilStrsav( pAig->pName ); + pFrames->pName = Abc_UtilStrsav( pAig->pName ); Gia_ManHashAlloc( pFrames ); Gia_ManConst0(pAig)->Value = 0; for ( f = 0; f < pPars->nFrames; f++ ) @@ -864,7 +864,7 @@ Gia_Man_t * Gia_ManFrames( Gia_Man_t * pAig, Gia_ParFra_t * pPars ) if ( pPars->fInit ) return Gia_ManFramesInit( pAig, pPars ); pFrames = Gia_ManStart( pPars->nFrames * Gia_ManObjNum(pAig) ); - pFrames->pName = Gia_UtilStrsav( pAig->pName ); + pFrames->pName = Abc_UtilStrsav( pAig->pName ); Gia_ManHashAlloc( pFrames ); Gia_ManConst0(pAig)->Value = 0; for ( f = 0; f < pPars->nFrames; f++ ) diff --git a/src/aig/gia/giaFront.c b/src/aig/gia/giaFront.c index 6eb20635..903a66e7 100644 --- a/src/aig/gia/giaFront.c +++ b/src/aig/gia/giaFront.c @@ -115,7 +115,7 @@ Gia_Man_t * Gia_ManFront( Gia_Man_t * p ) Gia_ManSetRefs( p ); // start the new manager pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); pNew->nFront = 1 + (int)((float)1.1 * nCrossCutMaxInit); // start the frontier pFront = ABC_CALLOC( char, pNew->nFront ); @@ -134,7 +134,7 @@ Gia_Man_t * Gia_ManFront( Gia_Man_t * p ) nCrossCutMax = nCrossCut; // create new node iLit = Gia_ManAppendCi( pNew ); - pObjNew = Gia_ManObj( pNew, Gia_Lit2Var(iLit) ); + pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(iLit) ); assert( Gia_ObjId(pNew, pObjNew) == Gia_ObjId(p, pObj) ); pObjNew->Value = iFront = Gia_ManFrontFindNext( pFront, pNew->nFront, iFront ); // handle CIs without fanout @@ -147,7 +147,7 @@ Gia_Man_t * Gia_ManFront( Gia_Man_t * p ) assert( Gia_ObjValue(pObj) == 0 ); // create new node iLit = Gia_ManAppendCo( pNew, 0 ); - pObjNew = Gia_ManObj( pNew, Gia_Lit2Var(iLit) ); + pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(iLit) ); assert( Gia_ObjId(pNew, pObjNew) == Gia_ObjId(p, pObj) ); // get the fanin pFanin0New = Gia_ManObj( pNew, Gia_ObjFaninId0(pObj, i) ); diff --git a/src/aig/gia/giaGiarf.c b/src/aig/gia/giaGiarf.c index 501f9bb3..2f18c16d 100644 --- a/src/aig/gia/giaGiarf.c +++ b/src/aig/gia/giaGiarf.c @@ -301,7 +301,7 @@ int Hcd_ManHashKey( unsigned * pSim, int nWords, int nTableSize ) void Hcd_ManClassesRehash( Hcd_Man_t * p, Vec_Int_t * vRefined ) { int * pTable, nTableSize, Key, i, k; - nTableSize = Gia_PrimeCudd( 100 + Vec_IntSize(vRefined) / 5 ); + nTableSize = Abc_PrimeCudd( 100 + Vec_IntSize(vRefined) / 5 ); pTable = ABC_CALLOC( int, nTableSize ); Vec_IntForEachEntry( vRefined, i, k ) { @@ -538,7 +538,7 @@ Gia_Man_t * Gia_GenerateReducedLevel( Gia_Man_t * p, int Level, Vec_Ptr_t ** pvR vRoots = Vec_PtrAlloc( 100 ); // copy unmarked nodes pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); @@ -553,7 +553,7 @@ Gia_Man_t * Gia_GenerateReducedLevel( Gia_Man_t * p, int Level, Vec_Ptr_t ** pvR { // printf( "Substituting %d <--- %d\n", Gia_ObjId(p, pRepr), Gia_ObjId(p, pObj) ); assert( pRepr < pObj ); - pObj->Value = Gia_LitNotCond( pRepr->Value, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); + pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); continue; } pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); @@ -644,19 +644,19 @@ int Gia_GiarfStorePatternTry( Vec_Ptr_t * vInfo, Vec_Ptr_t * vPres, int iBit, in int i; for ( i = 0; i < nLits; i++ ) { - pInfo = (unsigned *)Vec_PtrEntry(vInfo, Gia_Lit2Var(pLits[i])); - pPres = (unsigned *)Vec_PtrEntry(vPres, Gia_Lit2Var(pLits[i])); - if ( Gia_InfoHasBit( pPres, iBit ) && - Gia_InfoHasBit( pInfo, iBit ) == Gia_LitIsCompl(pLits[i]) ) + pInfo = (unsigned *)Vec_PtrEntry(vInfo, Abc_Lit2Var(pLits[i])); + pPres = (unsigned *)Vec_PtrEntry(vPres, Abc_Lit2Var(pLits[i])); + if ( Abc_InfoHasBit( pPres, iBit ) && + Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(pLits[i]) ) return 0; } for ( i = 0; i < nLits; i++ ) { - pInfo = (unsigned *)Vec_PtrEntry(vInfo, Gia_Lit2Var(pLits[i])); - pPres = (unsigned *)Vec_PtrEntry(vPres, Gia_Lit2Var(pLits[i])); - Gia_InfoSetBit( pPres, iBit ); - if ( Gia_InfoHasBit( pInfo, iBit ) == Gia_LitIsCompl(pLits[i]) ) - Gia_InfoXorBit( pInfo, iBit ); + pInfo = (unsigned *)Vec_PtrEntry(vInfo, Abc_Lit2Var(pLits[i])); + pPres = (unsigned *)Vec_PtrEntry(vPres, Abc_Lit2Var(pLits[i])); + Abc_InfoSetBit( pPres, iBit ); + if ( Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(pLits[i]) ) + Abc_InfoXorBit( pInfo, iBit ); } return 1; } @@ -699,10 +699,10 @@ void Gia_GiarfInsertPattern( Hcd_Man_t * p, Vec_Int_t * vCex, int k ) int Lit, i; Vec_IntForEachEntry( vCex, Lit, i ) { - pObj = Gia_ManCi( p->pGia, Gia_Lit2Var(Lit) ); + pObj = Gia_ManCi( p->pGia, Abc_Lit2Var(Lit) ); pInfo = Hcd_ObjSimP( p, Gia_ObjId( p->pGia, pObj ) ); - if ( Gia_InfoHasBit( pInfo, k ) == Gia_LitIsCompl(Lit) ) - Gia_InfoXorBit( pInfo, k ); + if ( Abc_InfoHasBit( pInfo, k ) == Abc_LitIsCompl(Lit) ) + Abc_InfoXorBit( pInfo, k ); } } @@ -737,7 +737,7 @@ void Gia_GiarfPrintClasses( Gia_Man_t * pGia ) ABC_NAMESPACE_IMPL_END -#include "cecInt.h" +#include "src/proof/cec/cecInt.h" ABC_NAMESPACE_IMPL_START @@ -785,7 +785,7 @@ int Gia_ComputeEquivalencesLevel( Hcd_Man_t * p, Gia_Man_t * pGiaLev, Vec_Ptr_t iRoot = Gia_ObjId( p->pGia, pRoot ); if ( !Gia_ObjIsConst( p->pGia, iRoot ) ) continue; - iRootNew = Gia_LitNotCond( pRoot->Value, pRoot->fPhase ); + iRootNew = Abc_LitNotCond( pRoot->Value, pRoot->fPhase ); assert( iRootNew != 1 ); if ( fUse2Solver ) { @@ -880,8 +880,8 @@ int Gia_ComputeEquivalencesLevel( Hcd_Man_t * p, Gia_Man_t * pGiaLev, Vec_Ptr_t pMemberPrev = (Gia_Obj_t *)Vec_PtrEntryLast( vMembers ); Vec_PtrForEachEntry( Gia_Obj_t *, vMembers, pMember, k ) { - iMemberPrev = Gia_LitNotCond( pMemberPrev->Value, pMemberPrev->fPhase ); - iMember = Gia_LitNotCond( pMember->Value, !pMember->fPhase ); + iMemberPrev = Abc_LitNotCond( pMemberPrev->Value, pMemberPrev->fPhase ); + iMember = Abc_LitNotCond( pMember->Value, !pMember->fPhase ); assert( iMemberPrev != iMember ); if ( fUse2Solver ) { diff --git a/src/aig/gia/giaGlitch.c b/src/aig/gia/giaGlitch.c index a6e5315a..35d076e5 100644 --- a/src/aig/gia/giaGlitch.c +++ b/src/aig/gia/giaGlitch.c @@ -333,7 +333,7 @@ static inline int Gli_NodeComputeValue( Gli_Obj_t * pNode ) int i, Phase = 0; for ( i = 0; i < (int)pNode->nFanins; i++ ) Phase |= (Gli_ObjFanin(pNode, i)->fPhase << i); - return Gia_InfoHasBit( pNode->uTruth, Phase ); + return Abc_InfoHasBit( pNode->uTruth, Phase ); } /**Function************************************************************* @@ -352,7 +352,7 @@ static inline int Gli_NodeComputeValue2( Gli_Obj_t * pNode ) int i, Phase = 0; for ( i = 0; i < (int)pNode->nFanins; i++ ) Phase |= (Gli_ObjFanin(pNode, i)->fPhase2 << i); - return Gia_InfoHasBit( pNode->uTruth, Phase ); + return Abc_InfoHasBit( pNode->uTruth, Phase ); } /**Function************************************************************* @@ -593,7 +593,7 @@ unsigned Gli_ManSimulateSeqNode( Gli_Man_t * p, Gli_Obj_t * pNode ) for ( k = 0; k < nFanins; k++ ) if ( (pSimInfos[k] >> i) & 1 ) Phase |= (1 << k); - if ( Gia_InfoHasBit( pNode->uTruth, Phase ) ) + if ( Abc_InfoHasBit( pNode->uTruth, Phase ) ) Result |= (1 << i); } return Result; @@ -755,7 +755,7 @@ void Gli_ManSwitchesAndGlitches( Gli_Man_t * p, int nPatterns, float PiTransProb } else { - int nIters = Gia_BitWordNum(nPatterns); + int nIters = Abc_BitWordNum(nPatterns); Gli_ManSimulateSeqPref( p, 16 ); for ( i = 0; i < 32; i++ ) { diff --git a/src/aig/gia/giaHash.c b/src/aig/gia/giaHash.c index f346a310..41092cc7 100644 --- a/src/aig/gia/giaHash.c +++ b/src/aig/gia/giaHash.c @@ -46,10 +46,10 @@ static inline int Gia_ManHashOne( int iLit0, int iLit1, int TableSize ) { unsigned Key = 0; assert( iLit0 < iLit1 ); - Key ^= Gia_Lit2Var(iLit0) * 7937; - Key ^= Gia_Lit2Var(iLit1) * 2971; - Key ^= Gia_LitIsCompl(iLit0) * 911; - Key ^= Gia_LitIsCompl(iLit1) * 353; + Key ^= Abc_Lit2Var(iLit0) * 7937; + Key ^= Abc_Lit2Var(iLit1) * 2971; + Key ^= Abc_LitIsCompl(iLit0) * 911; + Key ^= Abc_LitIsCompl(iLit1) * 353; return (int)(Key % TableSize); } @@ -68,8 +68,8 @@ static inline int * Gia_ManHashFind( Gia_Man_t * p, int iLit0, int iLit1 ) { Gia_Obj_t * pThis; int * pPlace = p->pHTable + Gia_ManHashOne( iLit0, iLit1, p->nHTable ); - for ( pThis = (*pPlace)? Gia_ManObj(p, Gia_Lit2Var(*pPlace)) : NULL; pThis; - pPlace = (int *)&pThis->Value, pThis = (*pPlace)? Gia_ManObj(p, Gia_Lit2Var(*pPlace)) : NULL ) + for ( pThis = (*pPlace)? Gia_ManObj(p, Abc_Lit2Var(*pPlace)) : NULL; pThis; + pPlace = (int *)&pThis->Value, pThis = (*pPlace)? Gia_ManObj(p, Abc_Lit2Var(*pPlace)) : NULL ) if ( Gia_ObjFaninLit0p(p, pThis) == iLit0 && Gia_ObjFaninLit1p(p, pThis) == iLit1 ) break; return pPlace; @@ -109,7 +109,7 @@ int Gia_ManHashLookup( Gia_Man_t * p, Gia_Obj_t * p0, Gia_Obj_t * p1 ) void Gia_ManHashAlloc( Gia_Man_t * p ) { assert( p->pHTable == NULL ); - p->nHTable = Gia_PrimeCudd( p->nObjsAlloc ); + p->nHTable = Abc_PrimeCudd( p->nObjsAlloc ); p->pHTable = ABC_CALLOC( int, p->nHTable ); } @@ -134,7 +134,7 @@ void Gia_ManHashStart( Gia_Man_t * p ) { pPlace = Gia_ManHashFind( p, Gia_ObjFaninLit0(pObj, i), Gia_ObjFaninLit1(pObj, i) ); assert( *pPlace == 0 ); - *pPlace = Gia_Var2Lit( i, 0 ); + *pPlace = Abc_Var2Lit( i, 0 ); } } @@ -175,20 +175,20 @@ void Gia_ManHashResize( Gia_Man_t * p ) // replace the table pHTableOld = p->pHTable; nHTableOld = p->nHTable; - p->nHTable = Gia_PrimeCudd( 2 * Gia_ManAndNum(p) ); + p->nHTable = Abc_PrimeCudd( 2 * Gia_ManAndNum(p) ); p->pHTable = ABC_CALLOC( int, p->nHTable ); // rehash the entries from the old table Counter = 0; for ( i = 0; i < nHTableOld; i++ ) - for ( pThis = (pHTableOld[i]? Gia_ManObj(p, Gia_Lit2Var(pHTableOld[i])) : NULL), + for ( pThis = (pHTableOld[i]? Gia_ManObj(p, Abc_Lit2Var(pHTableOld[i])) : NULL), iNext = (pThis? pThis->Value : 0); - pThis; pThis = (iNext? Gia_ManObj(p, Gia_Lit2Var(iNext)) : NULL), + pThis; pThis = (iNext? Gia_ManObj(p, Abc_Lit2Var(iNext)) : NULL), iNext = (pThis? pThis->Value : 0) ) { pThis->Value = 0; pPlace = Gia_ManHashFind( p, Gia_ObjFaninLit0p(p, pThis), Gia_ObjFaninLit1p(p, pThis) ); assert( *pPlace == 0 ); // should not be there - *pPlace = Gia_Var2Lit( Gia_ObjId(p, pThis), 0 ); + *pPlace = Abc_Var2Lit( Gia_ObjId(p, pThis), 0 ); assert( *pPlace != 0 ); Counter++; } @@ -220,9 +220,9 @@ void Gia_ManHashProfile( Gia_Man_t * p ) for ( i = 0; i < Limit; i++ ) { Counter = 0; - for ( pEntry = (p->pHTable[i]? Gia_ManObj(p, Gia_Lit2Var(p->pHTable[i])) : NULL); + for ( pEntry = (p->pHTable[i]? Gia_ManObj(p, Abc_Lit2Var(p->pHTable[i])) : NULL); pEntry; - pEntry = (pEntry->Value? Gia_ManObj(p, Gia_Lit2Var(pEntry->Value)) : NULL) ) + pEntry = (pEntry->Value? Gia_ManObj(p, Abc_Lit2Var(pEntry->Value)) : NULL) ) Counter++; if ( Counter ) printf( "%d ", Counter ); @@ -480,7 +480,7 @@ int Gia_ManHashAnd( Gia_Man_t * p, int iLit0, int iLit1 ) return iLit1 ? iLit0 : 0; if ( iLit0 == iLit1 ) return iLit1; - if ( iLit0 == Gia_LitNot(iLit1) ) + if ( iLit0 == Abc_LitNot(iLit1) ) return 0; if ( (p->nObjs & 0xFF) == 0 && 2 * p->nHTable < Gia_ManAndNum(p) ) Gia_ManHashResize( p ); @@ -531,7 +531,7 @@ int Gia_ManHashAndTry( Gia_Man_t * p, int iLit0, int iLit1 ) return iLit1 ? iLit0 : 0; if ( iLit0 == iLit1 ) return iLit1; - if ( iLit0 == Gia_LitNot(iLit1) ) + if ( iLit0 == Abc_LitNot(iLit1) ) return 0; if ( iLit0 > iLit1 ) iLit0 ^= iLit1, iLit1 ^= iLit0, iLit0 ^= iLit1; @@ -556,10 +556,10 @@ int Gia_ManHashAndTry( Gia_Man_t * p, int iLit0, int iLit1 ) ***********************************************************************/ int Gia_ManHashXor( Gia_Man_t * p, int iLit0, int iLit1 ) { - int fCompl = Gia_LitIsCompl(iLit0) ^ Gia_LitIsCompl(iLit1); - int iTemp0 = Gia_ManHashAnd( p, Gia_LitRegular(iLit0), Gia_LitNot(Gia_LitRegular(iLit1)) ); - int iTemp1 = Gia_ManHashAnd( p, Gia_LitRegular(iLit1), Gia_LitNot(Gia_LitRegular(iLit0)) ); - return Gia_LitNotCond( Gia_ManHashAnd( p, Gia_LitNot(iTemp0), Gia_LitNot(iTemp1) ), !fCompl ); + int fCompl = Abc_LitIsCompl(iLit0) ^ Abc_LitIsCompl(iLit1); + int iTemp0 = Gia_ManHashAnd( p, Abc_LitRegular(iLit0), Abc_LitNot(Abc_LitRegular(iLit1)) ); + int iTemp1 = Gia_ManHashAnd( p, Abc_LitRegular(iLit1), Abc_LitNot(Abc_LitRegular(iLit0)) ); + return Abc_LitNotCond( Gia_ManHashAnd( p, Abc_LitNot(iTemp0), Abc_LitNot(iTemp1) ), !fCompl ); } /**Function************************************************************* @@ -575,9 +575,9 @@ int Gia_ManHashXor( Gia_Man_t * p, int iLit0, int iLit1 ) ***********************************************************************/ int Gia_ManHashMux( Gia_Man_t * p, int iCtrl, int iData1, int iData0 ) { - int iTemp0 = Gia_ManHashAnd( p, Gia_LitNot(iCtrl), iData0 ); + int iTemp0 = Gia_ManHashAnd( p, Abc_LitNot(iCtrl), iData0 ); int iTemp1 = Gia_ManHashAnd( p, iCtrl, iData1 ); - return Gia_LitNotCond( Gia_ManHashAnd( p, Gia_LitNot(iTemp0), Gia_LitNot(iTemp1) ), 1 ); + return Abc_LitNotCond( Gia_ManHashAnd( p, Abc_LitNot(iTemp0), Abc_LitNot(iTemp1) ), 1 ); } /**Function************************************************************* @@ -597,7 +597,7 @@ Gia_Man_t * Gia_ManRehash( Gia_Man_t * p, int fAddStrash ) Gia_Obj_t * pObj; int i; pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); pNew->fAddStrash = fAddStrash; Gia_ManHashAlloc( pNew ); Gia_ManConst0(p)->Value = 0; diff --git a/src/aig/gia/giaHcd.c b/src/aig/gia/giaHcd.c index 454785b9..3f37e724 100644 --- a/src/aig/gia/giaHcd.c +++ b/src/aig/gia/giaHcd.c @@ -20,8 +20,8 @@ #include "gia.h" #include "giaAig.h" -#include "aig.h" -#include "dar.h" +#include "src/aig/aig/aig.h" +#include "src/opt/dar/dar.h" ABC_NAMESPACE_IMPL_START @@ -332,7 +332,7 @@ Gia_Man_t * Hcd_ManChoiceMiter( Vec_Ptr_t * vGias ) } // start the new manager pNew = Gia_ManStart( Vec_PtrSize(vGias) * Gia_ManObjNum(pGia0) ); - pNew->pName = Gia_UtilStrsav( pGia0->pName ); + pNew->pName = Abc_UtilStrsav( pGia0->pName ); // create new CIs and assign them to the old manager CIs for ( k = 0; k < Gia_ManCiNum(pGia0); k++ ) { @@ -457,7 +457,7 @@ void Hcd_ManEquivToChoices_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pOb { if ( Gia_ObjIsConst0(pRepr) ) { - pObj->Value = Gia_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); + pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); return; } Hcd_ManEquivToChoices_rec( pNew, p, pRepr ); @@ -465,20 +465,20 @@ void Hcd_ManEquivToChoices_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pOb Hcd_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin0(pObj) ); Hcd_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin1(pObj) ); pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); - if ( Gia_LitRegular(pObj->Value) == Gia_LitRegular(pRepr->Value) ) + if ( Abc_LitRegular(pObj->Value) == Abc_LitRegular(pRepr->Value) ) { - assert( (int)pObj->Value == Gia_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ) ); + assert( (int)pObj->Value == Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ) ); return; } if ( pRepr->Value > pObj->Value ) // should never happen with high resource limit return; assert( pRepr->Value < pObj->Value ); - pReprNew = Gia_ManObj( pNew, Gia_Lit2Var(pRepr->Value) ); - pObjNew = Gia_ManObj( pNew, Gia_Lit2Var(pObj->Value) ); + pReprNew = Gia_ManObj( pNew, Abc_Lit2Var(pRepr->Value) ); + pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(pObj->Value) ); if ( Gia_ObjReprObj( pNew, Gia_ObjId(pNew, pObjNew) ) ) { assert( Gia_ObjReprObj( pNew, Gia_ObjId(pNew, pObjNew) ) == pReprNew ); - pObj->Value = Gia_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); + pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); return; } if ( !Hcd_ObjCheckTfi( pNew, pReprNew, pObjNew ) ) @@ -487,7 +487,7 @@ void Hcd_ManEquivToChoices_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pOb Gia_ObjSetRepr( pNew, Gia_ObjId(pNew, pObjNew), Gia_ObjId(pNew, pReprNew) ); Hcd_ManAddNextEntry_rec( pNew, pReprNew, pObjNew ); } - pObj->Value = Gia_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); + pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); return; } assert( Gia_ObjIsAnd(pObj) ); @@ -563,7 +563,7 @@ Gia_Man_t * Hcd_ManEquivToChoices( Gia_Man_t * p, int nSnapshots ) assert( (Gia_ManCoNum(p) % nSnapshots) == 0 ); Gia_ManSetPhase( p ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) ); pNew->pNexts = ABC_CALLOC( int, Gia_ManObjNum(p) ); for ( i = 0; i < Gia_ManObjNum(p); i++ ) diff --git a/src/aig/gia/giaIf.c b/src/aig/gia/giaIf.c index 787aa090..e03439d0 100644 --- a/src/aig/gia/giaIf.c +++ b/src/aig/gia/giaIf.c @@ -19,9 +19,9 @@ ***********************************************************************/ #include "gia.h" -#include "aig.h" -#include "if.h" -#include "dar.h" +#include "src/aig/aig/aig.h" +#include "src/map/if/if.h" +#include "src/opt/dar/dar.h" ABC_NAMESPACE_IMPL_START @@ -306,11 +306,11 @@ void Gia_ManPrintMappingStats( Gia_Man_t * p ) { nLuts++; nFanins += Gia_ObjLutSize(p, i); - nLutSize = ABC_MAX( nLutSize, Gia_ObjLutSize(p, i) ); + nLutSize = Abc_MaxInt( nLutSize, Gia_ObjLutSize(p, i) ); Gia_LutForEachFanin( p, i, iFan, k ) - pLevels[i] = ABC_MAX( pLevels[i], pLevels[iFan] ); + pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[iFan] ); pLevels[i]++; - LevelMax = ABC_MAX( LevelMax, pLevels[i] ); + LevelMax = Abc_MaxInt( LevelMax, pLevels[i] ); } ABC_FREE( pLevels ); Abc_Print( 1, "mapping (K=%d) : ", nLutSize ); @@ -355,7 +355,7 @@ int Gia_ManLutSizeMax( Gia_Man_t * p ) { int i, nSizeMax = -1; Gia_ManForEachLut( p, i ) - nSizeMax = ABC_MAX( nSizeMax, Gia_ObjLutSize(p, i) ); + nSizeMax = Abc_MaxInt( nSizeMax, Gia_ObjLutSize(p, i) ); return nSizeMax; } diff --git a/src/aig/gia/giaMan.c b/src/aig/gia/giaMan.c index 39b0059d..972958bb 100644 --- a/src/aig/gia/giaMan.c +++ b/src/aig/gia/giaMan.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "gia.h" -#include "tim.h" +#include "src/misc/tim/tim.h" ABC_NAMESPACE_IMPL_START @@ -262,7 +262,8 @@ void Gia_ManPrintObjClasses( Gia_Man_t * p ) Vec_Int_t * vAbs = p->vObjClasses; int i, k, Entry, iStart, iStop, nFrames; int nObjBits, nObjMask, iObj, iFrame, nWords; - unsigned * pInfo, * pCountAll, * pCountUni; + unsigned * pInfo; + int * pCountAll, * pCountUni; if ( vAbs == NULL ) return; nFrames = Vec_IntEntry( vAbs, 0 ); @@ -270,10 +271,10 @@ void Gia_ManPrintObjClasses( Gia_Man_t * p ) pCountAll = ABC_ALLOC( int, nFrames + 1 ); pCountUni = ABC_ALLOC( int, nFrames + 1 ); // start storage for seen objects - nWords = Gia_BitWordNum( nFrames ); + nWords = Abc_BitWordNum( nFrames ); vSeens = Vec_IntStart( Gia_ManObjNum(p) * nWords ); // get the bitmasks - nObjBits = Gia_Base2Log( Gia_ManObjNum(p) ); + nObjBits = Abc_Base2Log( Gia_ManObjNum(p) ); nObjMask = (1 << nObjBits) - 1; assert( Gia_ManObjNum(p) <= nObjMask ); // print info about frames @@ -289,16 +290,16 @@ void Gia_ManPrintObjClasses( Gia_Man_t * p ) iObj = (Entry & nObjMask); iFrame = (Entry >> nObjBits); pInfo = (unsigned *)Vec_IntEntryP( vSeens, nWords * iObj ); - if ( Gia_InfoHasBit(pInfo, iFrame) == 0 ) + if ( Abc_InfoHasBit(pInfo, iFrame) == 0 ) { - Gia_InfoSetBit( pInfo, iFrame ); + Abc_InfoSetBit( pInfo, iFrame ); pCountUni[iFrame+1]++; pCountUni[0]++; } pCountAll[iFrame+1]++; pCountAll[0]++; } - assert( pCountAll[0] == (unsigned)(iStop - iStart) ); + assert( pCountAll[0] == (iStop - iStart) ); // printf( "%5d%5d ", pCountAll[0], pCountUni[0] ); printf( "%3d :", i ); printf( "%6d", pCountAll[0] ); diff --git a/src/aig/gia/giaPat.c b/src/aig/gia/giaPat.c index 643ae6b7..124f5e0b 100644 --- a/src/aig/gia/giaPat.c +++ b/src/aig/gia/giaPat.c @@ -100,8 +100,8 @@ void Gia_SatVerifyPattern( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vCex, V Gia_SatCollectCone( p, Gia_ObjFanin0(pRoot), vVisit ); // set binary values to nodes in the counter-example Vec_IntForEachEntry( vCex, Entry, i ) -// Sat_ObjSetXValue( Gia_ManObj(p, Gia_Lit2Var(Entry)), Gia_LitIsCompl(Entry)? GIA_ZER : GIA_ONE ); - Sat_ObjSetXValue( Gia_ManCi(p, Gia_Lit2Var(Entry)), Gia_LitIsCompl(Entry)? GIA_ZER : GIA_ONE ); +// Sat_ObjSetXValue( Gia_ManObj(p, Abc_Lit2Var(Entry)), Abc_LitIsCompl(Entry)? GIA_ZER : GIA_ONE ); + Sat_ObjSetXValue( Gia_ManCi(p, Abc_Lit2Var(Entry)), Abc_LitIsCompl(Entry)? GIA_ZER : GIA_ONE ); // simulate Gia_ManForEachObjVec( vVisit, p, pObj, i ) { diff --git a/src/aig/gia/giaReparam.c b/src/aig/gia/giaReparam.c index 5210f998..10294671 100644 --- a/src/aig/gia/giaReparam.c +++ b/src/aig/gia/giaReparam.c @@ -20,7 +20,7 @@ #include "gia.h" #include "giaAig.h" -#include "saig.h" +#include "src/aig/saig/saig.h" ABC_NAMESPACE_IMPL_START @@ -52,7 +52,7 @@ Gia_Man_t * Gia_ManDupIn2Ff( Gia_Man_t * p ) int i; vPiOuts = Vec_IntAlloc( Gia_ManPiNum(p) ); pNew = Gia_ManStart( Gia_ManObjNum(p) + 2 * Gia_ManPiNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachPi( p, pObj, i ) @@ -112,7 +112,7 @@ Gia_Man_t * Gia_ManDupFf2In( Gia_Man_t * p, int nFlopsOld ) Gia_Obj_t * pObj; int i; pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachRo( p, pObj, i ) diff --git a/src/aig/gia/giaRetime.c b/src/aig/gia/giaRetime.c index 58029b66..0b9a6bfb 100644 --- a/src/aig/gia/giaRetime.c +++ b/src/aig/gia/giaRetime.c @@ -125,7 +125,7 @@ Gia_Man_t * Gia_ManRetimeDupForward( Gia_Man_t * p, Vec_Ptr_t * vCut ) int i; // create the new manager pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManHashAlloc( pNew ); // create the true PIs Gia_ManFillValue( p ); @@ -135,7 +135,7 @@ Gia_Man_t * Gia_ManRetimeDupForward( Gia_Man_t * p, Vec_Ptr_t * vCut ) pObj->Value = Gia_ManAppendCi( pNew ); // create the registers Vec_PtrForEachEntry( Gia_Obj_t *, vCut, pObj, i ) - pObj->Value = Gia_LitNotCond( Gia_ManAppendCi(pNew), pObj->fPhase ); + pObj->Value = Abc_LitNotCond( Gia_ManAppendCi(pNew), pObj->fPhase ); // duplicate logic above the cut Gia_ManForEachCo( p, pObj, i ) Gia_ManRetimeDup_rec( pNew, Gia_ObjFanin0(pObj) ); @@ -156,7 +156,7 @@ Gia_Man_t * Gia_ManRetimeDupForward( Gia_Man_t * p, Vec_Ptr_t * vCut ) Vec_PtrForEachEntry( Gia_Obj_t *, vCut, pObj, i ) { Gia_ManRetimeDup_rec( pNew, pObj ); - Gia_ManAppendCo( pNew, Gia_LitNotCond( pObj->Value, pObj->fPhase ) ); + Gia_ManAppendCo( pNew, Abc_LitNotCond( pObj->Value, pObj->fPhase ) ); } Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Vec_PtrSize(vCut) ); diff --git a/src/aig/gia/giaSat.c b/src/aig/gia/giaSat.c index c2d70795..cb410dd7 100644 --- a/src/aig/gia/giaSat.c +++ b/src/aig/gia/giaSat.c @@ -265,7 +265,7 @@ int Gia_ManSatPartCount( Gia_Man_t * p, Gia_Obj_t * pObj, int * pnLeaves, int * (*pnLeaves)++; else Level1 = Gia_ManSatPartCount(p, pFanin, pnLeaves, pnNodes) + Gia_ObjFaninC1(pObj); - return ABC_MAX( Level0, Level1 ); + return Abc_MaxInt( Level0, Level1 ); } /**Function************************************************************* diff --git a/src/aig/gia/giaScl.c b/src/aig/gia/giaScl.c index a482d024..0ec67c93 100644 --- a/src/aig/gia/giaScl.c +++ b/src/aig/gia/giaScl.c @@ -199,7 +199,7 @@ Gia_Man_t * Gia_ManReduceEquiv( Gia_Man_t * p, int fVerbose ) else if ( ~pMaps[iLit] ) // in this case, ID(pObj) > ID(pRepr) pCi2Lit[Gia_ManPiNum(p)+i] = pMaps[iLit], Counter++; else - pMaps[iLit] = Gia_Var2Lit( Gia_ObjId(p, pObjRo), 0 ); + pMaps[iLit] = Abc_Var2Lit( Gia_ObjId(p, pObjRo), 0 ); } /* Gia_ManForEachCi( p, pObjRo, i ) diff --git a/src/aig/gia/giaShrink.c b/src/aig/gia/giaShrink.c index fc9e80d6..07119daf 100644 --- a/src/aig/gia/giaShrink.c +++ b/src/aig/gia/giaShrink.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "gia.h" -#include "aig.h" -#include "dar.h" +#include "src/aig/aig/aig.h" +#include "src/opt/dar/dar.h" ABC_NAMESPACE_IMPL_START @@ -75,7 +75,7 @@ Gia_Man_t * Gia_ManPerformMapShrink( Gia_Man_t * p, int fKeepLevel, int fVerbose Gia_ManConst0(p)->Value = 0; // start the new manager pNew = Gia_ManStart( Gia_ManObjNum(p) ); - pNew->pName = Gia_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManHashAlloc( pNew ); Gia_ManCleanLevels( pNew, Gia_ManObjNum(p) ); Gia_ManForEachObj1( p, pObj, i ) @@ -114,7 +114,7 @@ Gia_Man_t * Gia_ManPerformMapShrink( Gia_Man_t * p, int fKeepLevel, int fVerbose else { pObj->Value = Dar_LibEvalBuild( pNew, vLeaves, 0xffff & *pTruth, fKeepLevel, vLeavesBest ); - pObj->Value = Gia_LitNotCond( pObj->Value, Gia_ObjPhaseRealLit(pNew, pObj->Value) ^ pObj->fPhase ); + pObj->Value = Abc_LitNotCond( pObj->Value, Gia_ObjPhaseRealLit(pNew, pObj->Value) ^ pObj->fPhase ); } } } diff --git a/src/aig/gia/giaSim.c b/src/aig/gia/giaSim.c index 4be740cd..817fc2e2 100644 --- a/src/aig/gia/giaSim.c +++ b/src/aig/gia/giaSim.c @@ -133,18 +133,18 @@ Vec_Int_t * Gia_ManSimDeriveResets( Gia_Man_t * pGia ) { if ( Count < nImpLimit ) continue; - pObj = Gia_ManObj( pGia, Gia_Lit2Var(Lit) ); - if ( Gia_LitIsCompl(Lit) ) // const 0 + pObj = Gia_ManObj( pGia, Abc_Lit2Var(Lit) ); + if ( Abc_LitIsCompl(Lit) ) // const 0 { // Ssm_ObjSetLogic0( pObj ); - Vec_IntWriteEntry( vResult, Gia_Lit2Var(Lit), 0 ); + Vec_IntWriteEntry( vResult, Abc_Lit2Var(Lit), 0 ); CounterPi0 += Gia_ObjIsPi(pGia, pObj); Counter0++; } else { // Ssm_ObjSetLogic1( pObj ); - Vec_IntWriteEntry( vResult, Gia_Lit2Var(Lit), 1 ); + Vec_IntWriteEntry( vResult, Abc_Lit2Var(Lit), 1 ); CounterPi1 += Gia_ObjIsPi(pGia, pObj); Counter1++; } @@ -568,8 +568,8 @@ Abc_Cex_t * Gia_ManGenerateCounter( Gia_Man_t * pAig, int iFrame, int iOut, int continue; for ( w = nWords-1; w >= 0; w-- ) pData[w] = Gia_ManRandom( 0 ); - if ( Gia_InfoHasBit( pData, iPat ) ) - Gia_InfoSetBit( p->pData, Counter + iPioId ); + if ( Abc_InfoHasBit( pData, iPat ) ) + Abc_InfoSetBit( p->pData, Counter + iPioId ); } ABC_FREE( pData ); return p; diff --git a/src/aig/gia/giaSim2.c b/src/aig/gia/giaSim2.c index 27945704..74a34d1b 100644 --- a/src/aig/gia/giaSim2.c +++ b/src/aig/gia/giaSim2.c @@ -471,7 +471,7 @@ void Gia_Sim2ProcessRefined( Gia_Sim2_t * p, Vec_Int_t * vRefined ) int * pTable, nTableSize, i, k, Key; if ( Vec_IntSize(vRefined) == 0 ) return; - nTableSize = Gia_PrimeCudd( 1000 + Vec_IntSize(vRefined) / 3 ); + nTableSize = Abc_PrimeCudd( 1000 + Vec_IntSize(vRefined) / 3 ); pTable = ABC_CALLOC( int, nTableSize ); Vec_IntForEachEntry( vRefined, i, k ) { @@ -617,8 +617,8 @@ Abc_Cex_t * Gia_Sim2GenerateCounter( Gia_Man_t * pAig, int iFrame, int iOut, int { for ( w = nWords-1; w >= 0; w-- ) pData[w] = Gia_ManRandom( 0 ); - if ( Gia_InfoHasBit( pData, iPat ) ) - Gia_InfoSetBit( p->pData, Counter + i ); + if ( Abc_InfoHasBit( pData, iPat ) ) + Abc_InfoSetBit( p->pData, Counter + i ); } ABC_FREE( pData ); return p; diff --git a/src/aig/gia/giaSpeedup.c b/src/aig/gia/giaSpeedup.c index cce0b68d..d20fe1a4 100644 --- a/src/aig/gia/giaSpeedup.c +++ b/src/aig/gia/giaSpeedup.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "gia.h" -#include "if.h" +#include "src/map/if/if.h" ABC_NAMESPACE_IMPL_START @@ -597,7 +597,7 @@ void Gia_ManSpeedupObj( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_I for ( i = 0; i < nCofs; i++ ) { Gia_ManForEachObjVec( vLeaves, p, pTemp, k ) - pTemp->Value = Gia_Var2Lit( Gia_ObjId(p, pTemp), 0 ); + pTemp->Value = Abc_Var2Lit( Gia_ObjId(p, pTemp), 0 ); Gia_ManForEachObjVec( vTimes, p, pTemp, k ) pTemp->Value = ((i & (1<nObjs, Gia_ManCiNum(pAig) + Gia_ManAndNum(pAig), p->pAig->nFront, - 4.0*Gia_BitWordNum(2 * p->pAig->nFront)/(1<<20) ); + 4.0*Abc_BitWordNum(2 * p->pAig->nFront)/(1<<20) ); printf( "AIG = %7.2f Mb. F-mem = %7.2f Mb. Other = %7.2f Mb. ", 12.0*Gia_ManObjNum(p->pAig)/(1<<20), 4.0*p->nWords*p->pAig->nFront/(1<<20), @@ -691,8 +691,8 @@ Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * pAig, int nFrames, int nPref Aig_ManForEachObj( pAig, pObj, i ) { // if ( Aig_ObjIsPo(pObj) ) -// printf( "%d=%f\n", i, Aig_Int2Float( Vec_IntEntry(vSwitching, Gia_Lit2Var(pObj->iData)) ) ); - Vec_IntWriteEntry( vResult, i, Vec_IntEntry(vSwitching, Gia_Lit2Var(pObj->iData)) ); +// printf( "%d=%f\n", i, Abc_Int2Float( Vec_IntEntry(vSwitching, Abc_Lit2Var(pObj->iData)) ) ); + Vec_IntWriteEntry( vResult, i, Vec_IntEntry(vSwitching, Abc_Lit2Var(pObj->iData)) ); } // delete intermediate results Vec_IntFree( vSwitching ); diff --git a/src/aig/gia/giaTsim.c b/src/aig/gia/giaTsim.c index e829ff5b..c4fb7f26 100644 --- a/src/aig/gia/giaTsim.c +++ b/src/aig/gia/giaTsim.c @@ -84,15 +84,15 @@ Gia_ManTer_t * Gia_ManTerCreate( Gia_Man_t * pAig ) p = ABC_CALLOC( Gia_ManTer_t, 1 ); p->pAig = Gia_ManFront( pAig ); p->nIters = 300; - p->pDataSim = ABC_ALLOC( unsigned, Gia_BitWordNum(2*p->pAig->nFront) ); - p->pDataSimCis = ABC_ALLOC( unsigned, Gia_BitWordNum(2*Gia_ManCiNum(p->pAig)) ); - p->pDataSimCos = ABC_ALLOC( unsigned, Gia_BitWordNum(2*Gia_ManCoNum(p->pAig)) ); + p->pDataSim = ABC_ALLOC( unsigned, Abc_BitWordNum(2*p->pAig->nFront) ); + p->pDataSimCis = ABC_ALLOC( unsigned, Abc_BitWordNum(2*Gia_ManCiNum(p->pAig)) ); + p->pDataSimCos = ABC_ALLOC( unsigned, Abc_BitWordNum(2*Gia_ManCoNum(p->pAig)) ); // allocate storage for terminary states - p->nStateWords = Gia_BitWordNum( 2*Gia_ManRegNum(pAig) ); + p->nStateWords = Abc_BitWordNum( 2*Gia_ManRegNum(pAig) ); p->vStates = Vec_PtrAlloc( 1000 ); p->pCount0 = ABC_CALLOC( int, Gia_ManRegNum(pAig) ); p->pCountX = ABC_CALLOC( int, Gia_ManRegNum(pAig) ); - p->nBins = Gia_PrimeCudd( 500 ); + p->nBins = Abc_PrimeCudd( 500 ); p->pBins = ABC_CALLOC( unsigned *, p->nBins ); p->vRetired = Vec_IntAlloc( 100 ); p->pRetired = ABC_CALLOC( char, Gia_ManRegNum(pAig) ); @@ -511,7 +511,7 @@ void Gia_ManTerAnalyze2( Vec_Ptr_t * vStates, int nRegs ) unsigned * pTemp, * pStates = (unsigned *)Vec_PtrPop( vStates ); int i, w, nZeros, nConsts, nStateWords; // detect constant zero registers - nStateWords = Gia_BitWordNum( 2*nRegs ); + nStateWords = Abc_BitWordNum( 2*nRegs ); memset( pStates, 0, sizeof(int) * nStateWords ); Vec_PtrForEachEntry( unsigned *, vStates, pTemp, i ) for ( w = 0; w < nStateWords; w++ ) @@ -579,7 +579,7 @@ Vec_Ptr_t * Gia_ManTerTranspose( Gia_ManTer_t * p ) unsigned * pState, * pFlop; int i, k, nFlopWords; vFlops = Vec_PtrAlloc( 100 ); - nFlopWords = Gia_BitWordNum( 2*Vec_PtrSize(p->vStates) ); + nFlopWords = Abc_BitWordNum( 2*Vec_PtrSize(p->vStates) ); for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) { if ( p->pCount0[i] == Vec_PtrSize(p->vStates) ) @@ -634,7 +634,7 @@ int * Gia_ManTerCreateMap( Gia_ManTer_t * p, int fVerbose ) Gia_Obj_t * pObj; Vec_Int_t * vMapKtoI; int i, iRepr, nFlopWords, Counter0 = 0, CounterE = 0; - nFlopWords = Gia_BitWordNum( 2*Vec_PtrSize(p->vStates) ); + nFlopWords = Abc_BitWordNum( 2*Vec_PtrSize(p->vStates) ); p->vFlops = Gia_ManTerTranspose( p ); pCi2Lit = ABC_FALLOC( int, Gia_ManCiNum(p->pAig) ); vMapKtoI = Vec_IntAlloc( 100 ); @@ -648,7 +648,7 @@ int * Gia_ManTerCreateMap( Gia_ManTer_t * p, int fVerbose ) if ( iRepr < 0 ) continue; pObj = Gia_ManCi( p->pAig, Gia_ManPiNum(p->pAig)+Vec_IntEntry(vMapKtoI, iRepr) ); - pCi2Lit[Gia_ManPiNum(p->pAig)+i] = Gia_Var2Lit( Gia_ObjId( p->pAig, pObj ), 0 ); + pCi2Lit[Gia_ManPiNum(p->pAig)+i] = Abc_Var2Lit( Gia_ObjId( p->pAig, pObj ), 0 ); CounterE++; } Vec_IntFree( vMapKtoI ); @@ -684,8 +684,8 @@ Gia_ManTer_t * Gia_ManTerSimulate( Gia_Man_t * pAig, int fVerbose ) pAig->nObjs, Gia_ManCiNum(pAig) + Gia_ManAndNum(pAig), p->pAig->nFront ); printf( "AIG = %7.2f Mb. F-mem = %7.2f Mb. Other = %7.2f Mb. ", 12.0*Gia_ManObjNum(p->pAig)/(1<<20), - 4.0*Gia_BitWordNum(2 * p->pAig->nFront)/(1<<20), - 4.0*Gia_BitWordNum(2 * (Gia_ManCiNum(pAig) + Gia_ManCoNum(pAig)))/(1<<20) ); + 4.0*Abc_BitWordNum(2 * p->pAig->nFront)/(1<<20), + 4.0*Abc_BitWordNum(2 * (Gia_ManCiNum(pAig) + Gia_ManCoNum(pAig)))/(1<<20) ); ABC_PRT( "Time", clock() - clk ); } // perform simulation diff --git a/src/aig/gia/giaUtil.c b/src/aig/gia/giaUtil.c index f19f0602..e56f6ea9 100644 --- a/src/aig/gia/giaUtil.c +++ b/src/aig/gia/giaUtil.c @@ -80,42 +80,6 @@ void Gia_ManRandomInfo( Vec_Ptr_t * vInfo, int iInputStart, int iWordStart, int pInfo[w] = Gia_ManRandom(0); } -/**Function******************************************************************** - - Synopsis [Returns the next prime >= p.] - - Description [Copied from CUDD, for stand-aloneness.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -unsigned int Gia_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************************************************************* @@ -483,7 +447,7 @@ int Gia_ManLevelNum( Gia_Man_t * p ) else if ( Gia_ObjIsCo(pObj) ) { Gia_ObjSetCoLevel( p, pObj ); - p->nLevels = ABC_MAX( p->nLevels, Gia_ObjLevel(p, pObj) ); + p->nLevels = Abc_MaxInt( p->nLevels, Gia_ObjLevel(p, pObj) ); } else Gia_ObjSetLevel( p, pObj, 0 ); @@ -1150,11 +1114,11 @@ int Gia_ManVerifyCex( Gia_Man_t * pAig, Abc_Cex_t * p, int fDualOut ) int RetValue, i, k, iBit = 0; Gia_ManCleanMark0(pAig); Gia_ManForEachRo( pAig, pObj, i ) - pObj->fMark0 = Gia_InfoHasBit(p->pData, iBit++); + pObj->fMark0 = Abc_InfoHasBit(p->pData, iBit++); for ( i = 0; i <= p->iFrame; i++ ) { Gia_ManForEachPi( pAig, pObj, k ) - pObj->fMark0 = Gia_InfoHasBit(p->pData, iBit++); + pObj->fMark0 = Abc_InfoHasBit(p->pData, iBit++); Gia_ManForEachAnd( pAig, pObj, k ) pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)); @@ -1194,12 +1158,12 @@ int Gia_ManFindFailedPoCex( Gia_Man_t * pAig, Abc_Cex_t * p, int nOutputs ) assert( Gia_ManPiNum(pAig) == p->nPis ); Gia_ManCleanMark0(pAig); // Gia_ManForEachRo( pAig, pObj, i ) -// pObj->fMark0 = Gia_InfoHasBit(p->pData, iBit++); +// pObj->fMark0 = Abc_InfoHasBit(p->pData, iBit++); iBit = p->nRegs; for ( i = 0; i <= p->iFrame; i++ ) { Gia_ManForEachPi( pAig, pObj, k ) - pObj->fMark0 = Gia_InfoHasBit(p->pData, iBit++); + pObj->fMark0 = Abc_InfoHasBit(p->pData, iBit++); Gia_ManForEachAnd( pAig, pObj, k ) pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)); diff --git a/src/aig/hop/cudd2.c b/src/aig/hop/cudd2.c index 3ad44e4c..57a85dc8 100644 --- a/src/aig/hop/cudd2.c +++ b/src/aig/hop/cudd2.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "hop.h" -#include "st.h" +#include "misc/st/st.h" ABC_NAMESPACE_IMPL_START diff --git a/src/aig/hop/cudd2.h b/src/aig/hop/cudd2.h index 2382b22f..e38118f4 100644 --- a/src/aig/hop/cudd2.h +++ b/src/aig/hop/cudd2.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __CUDD2_H__ -#define __CUDD2_H__ +#ifndef ABC__aig__hop__cudd2_h +#define ABC__aig__hop__cudd2_h // HA: Added for printing messages diff --git a/src/aig/hop/hop.h b/src/aig/hop/hop.h index a634f136..eff904fd 100644 --- a/src/aig/hop/hop.h +++ b/src/aig/hop/hop.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __HOP_H__ -#define __HOP_H__ +#ifndef ABC__aig__hop__hop_h +#define ABC__aig__hop__hop_h //////////////////////////////////////////////////////////////////////// @@ -32,7 +32,7 @@ #include #include -#include "vec.h" +#include "src/misc/vec/vec.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// @@ -186,7 +186,7 @@ static inline Hop_Obj_t * Hop_ObjChild1( Hop_Obj_t * pObj ) { return pObj- 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) + ABC_MAX(Hop_ObjFanin0(pObj)->nRefs, Hop_ObjFanin1(pObj)->nRefs); } +static inline int Hop_ObjLevelNew( Hop_Obj_t * pObj ) { return 1 + Hop_ObjIsExor(pObj) + Abc_MaxInt(Hop_ObjFanin0(pObj)->nRefs, Hop_ObjFanin1(pObj)->nRefs); } static inline int Hop_ObjPhaseCompl( 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 ) diff --git a/src/aig/hop/hopDfs.c b/src/aig/hop/hopDfs.c index be1e6c0b..f6f8c507 100644 --- a/src/aig/hop/hopDfs.c +++ b/src/aig/hop/hopDfs.c @@ -128,13 +128,13 @@ int Hop_ManCountLevels( Hop_Man_t * p ) { Level0 = (int)(ABC_PTRUINT_T)Hop_ObjFanin0(pObj)->pData; Level1 = (int)(ABC_PTRUINT_T)Hop_ObjFanin1(pObj)->pData; - pObj->pData = (void *)(ABC_PTRUINT_T)(1 + Hop_ObjIsExor(pObj) + ABC_MAX(Level0, Level1)); + pObj->pData = (void *)(ABC_PTRUINT_T)(1 + Hop_ObjIsExor(pObj) + Abc_MaxInt(Level0, Level1)); } Vec_PtrFree( vNodes ); // get levels of the POs LevelsMax = 0; Hop_ManForEachPo( p, pObj, i ) - LevelsMax = ABC_MAX( LevelsMax, (int)(ABC_PTRUINT_T)Hop_ObjFanin0(pObj)->pData ); + LevelsMax = Abc_MaxInt( LevelsMax, (int)(ABC_PTRUINT_T)Hop_ObjFanin0(pObj)->pData ); return LevelsMax; } diff --git a/src/aig/hop/hopTable.c b/src/aig/hop/hopTable.c index 8148a125..7db93f62 100644 --- a/src/aig/hop/hopTable.c +++ b/src/aig/hop/hopTable.c @@ -52,7 +52,6 @@ static Hop_Obj_t ** Hop_TableFind( Hop_Man_t * p, Hop_Obj_t * pObj ) } static void Hop_TableResize( Hop_Man_t * p ); -static unsigned int Cudd_PrimeAig( unsigned int p ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -174,7 +173,7 @@ clk = clock(); pTableOld = p->pTable; nTableSizeOld = p->nTableSize; // get the new table - p->nTableSize = Cudd_PrimeAig( 2 * Hop_ManNodeNum(p) ); + p->nTableSize = Abc_PrimeCudd( 2 * Hop_ManNodeNum(p) ); p->pTable = ABC_ALLOC( Hop_Obj_t *, p->nTableSize ); memset( p->pTable, 0, sizeof(Hop_Obj_t *) * p->nTableSize ); // rehash the entries from the old table @@ -223,41 +222,6 @@ void Hop_TableProfile( Hop_Man_t * p ) } } -/**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/int/int.h b/src/aig/int/int.h deleted file mode 100644 index 4b8d78bb..00000000 --- a/src/aig/int/int.h +++ /dev/null @@ -1,94 +0,0 @@ -/**CFile**************************************************************** - - FileName [int.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Interpolation engine.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 24, 2008.] - - Revision [$Id: int.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __INT_H__ -#define __INT_H__ - - -/* - The interpolation algorithm implemented here was introduced in the paper: - K. L. McMillan. Interpolation and SAT-based model checking. CAV’03, pp. 1-13. -*/ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -// simulation manager -typedef struct Inter_ManParams_t_ Inter_ManParams_t; -struct Inter_ManParams_t_ -{ - int nBTLimit; // limit on the number of conflicts - int nFramesMax; // the max number timeframes to unroll - int nSecLimit; // time limit in seconds - int nFramesK; // the number of timeframes to use in induction - int fRewrite; // use additional rewriting to simplify timeframes - int fTransLoop; // add transition into the init state under new PI var - int fUsePudlak; // use Pudluk interpolation procedure - int fUseOther; // use other undisclosed option - int fUseMiniSat; // use MiniSat-1.14p instead of internal proof engine - int fCheckKstep; // check using K-step induction - int fUseBias; // bias decisions to global variables - int fUseBackward; // perform backward interpolation - int fUseSeparate; // solve each output separately - int fDropSatOuts; // replace by 1 the solved outputs - int fDropInvar; // dump inductive invariant into file - int fVerbose; // print verbose statistics - int iFrameMax; // the time frame reached -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== intCore.c ==========================================================*/ -extern void Inter_ManSetDefaultParams( Inter_ManParams_t * p ); -extern int Inter_ManPerformInterpolation( Aig_Man_t * pAig, Inter_ManParams_t * pPars, int * piFrame ); - - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/int/intCheck.c b/src/aig/int/intCheck.c deleted file mode 100644 index 6b36fe30..00000000 --- a/src/aig/int/intCheck.c +++ /dev/null @@ -1,305 +0,0 @@ -/**CFile**************************************************************** - - FileName [intCheck.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Interpolation engine.] - - Synopsis [Procedures to perform incremental inductive check.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 24, 2008.] - - Revision [$Id: intCheck.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "intInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// checking manager -struct Inter_Check_t_ -{ - int nFramesK; // the number of timeframes (K=1 for simple induction) - int nVars; // the current number of variables in the solver - Aig_Man_t * pFrames; // unrolled timeframes - Cnf_Dat_t * pCnf; // CNF of unrolled timeframes - sat_solver * pSat; // SAT solver - Vec_Int_t * vOrLits; // OR vars in each time frame (total number is the number nFrames) - Vec_Int_t * vAndLits; // AND vars in the last timeframe (total number is the number of interpolants) - Vec_Int_t * vAssLits; // assumptions (the union of the two) -}; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Create timeframes of the manager for interpolation.] - - Description [The resulting manager is combinational. The primary inputs - corresponding to register outputs are ordered first.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Inter_ManUnrollFrames( Aig_Man_t * pAig, int nFrames ) -{ - Aig_Man_t * pFrames; - Aig_Obj_t * pObj, * pObjLi, * pObjLo; - int i, f; - assert( Saig_ManRegNum(pAig) > 0 ); - pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFrames ); - // map the constant node - Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames ); - // create variables for register outputs - Saig_ManForEachLo( pAig, pObj, i ) - pObj->pData = Aig_ObjCreatePi( pFrames ); - // add timeframes - for ( f = 0; f < nFrames; f++ ) - { - // create PI nodes for this frame - Saig_ManForEachPi( pAig, pObj, i ) - pObj->pData = Aig_ObjCreatePi( pFrames ); - // add internal nodes of this frame - Aig_ManForEachNode( pAig, pObj, i ) - pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - // save register inputs - Saig_ManForEachLi( pAig, pObj, i ) - pObj->pData = Aig_ObjChild0Copy(pObj); - // transfer to register outputs - Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) - { - pObjLo->pData = pObjLi->pData; - Aig_ObjCreatePo( pFrames, (Aig_Obj_t *)pObjLo->pData ); - } - } - Aig_ManCleanup( pFrames ); - return pFrames; -} - -/**Function************************************************************* - - Synopsis [This procedure sets default values of interpolation parameters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Inter_Check_t * Inter_CheckStart( Aig_Man_t * pTrans, int nFramesK ) -{ - Inter_Check_t * p; - // create solver - p = ABC_CALLOC( Inter_Check_t, 1 ); - p->vOrLits = Vec_IntAlloc( 100 ); - p->vAndLits = Vec_IntAlloc( 100 ); - p->vAssLits = Vec_IntAlloc( 100 ); - // generate the timeframes - p->pFrames = Inter_ManUnrollFrames( pTrans, nFramesK ); - assert( Aig_ManPiNum(p->pFrames) == nFramesK * Saig_ManPiNum(pTrans) + Saig_ManRegNum(pTrans) ); - assert( Aig_ManPoNum(p->pFrames) == nFramesK * Saig_ManRegNum(pTrans) ); - // convert to CNF - p->pCnf = Cnf_Derive( p->pFrames, Aig_ManPoNum(p->pFrames) ); - p->pSat = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, 1, 0 ); - // assign parameters - p->nFramesK = nFramesK; - p->nVars = p->pCnf->nVars; - return p; -} - -/**Function************************************************************* - - Synopsis [This procedure sets default values of interpolation parameters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Inter_CheckStop( Inter_Check_t * p ) -{ - if ( p == NULL ) - return; - Vec_IntFree( p->vOrLits ); - Vec_IntFree( p->vAndLits ); - Vec_IntFree( p->vAssLits ); - Cnf_DataFree( p->pCnf ); - Aig_ManStop( p->pFrames ); - sat_solver_delete( p->pSat ); - ABC_FREE( p ); -} - - -/**Function************************************************************* - - Synopsis [Creates one OR-gate: A + B = C.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Inter_CheckAddOrGate( Inter_Check_t * p, int iVarA, int iVarB, int iVarC ) -{ - int RetValue, pLits[3]; - // add A => C or !A + C - pLits[0] = toLitCond(iVarA, 1); - pLits[1] = toLitCond(iVarC, 0); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); - assert( RetValue ); - // add B => C or !B + C - pLits[0] = toLitCond(iVarB, 1); - pLits[1] = toLitCond(iVarC, 0); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); - assert( RetValue ); - // add !A & !B => !C or A + B + !C - pLits[0] = toLitCond(iVarA, 0); - pLits[1] = toLitCond(iVarB, 0); - pLits[2] = toLitCond(iVarC, 1); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); - assert( RetValue ); -} - -/**Function************************************************************* - - Synopsis [Creates equality: A = B.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Inter_CheckAddEqual( Inter_Check_t * p, int iVarA, int iVarB ) -{ - int RetValue, pLits[3]; - // add A => B or !A + B - pLits[0] = toLitCond(iVarA, 1); - pLits[1] = toLitCond(iVarB, 0); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); - assert( RetValue ); - // add B => A or !B + A - pLits[0] = toLitCond(iVarB, 1); - pLits[1] = toLitCond(iVarA, 0); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); - assert( RetValue ); -} - -/**Function************************************************************* - - Synopsis [Perform the checking.] - - Description [Returns 1 if the check has passed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Inter_CheckPerform( Inter_Check_t * p, Cnf_Dat_t * pCnfInt, int nTimeNewOut ) -{ - Aig_Obj_t * pObj, * pObj2; - int i, f, VarA, VarB, RetValue, Entry, status; - int nRegs = Aig_ManPiNum(pCnfInt->pMan); - assert( Aig_ManPoNum(p->pCnf->pMan) == p->nFramesK * nRegs ); - assert( Aig_ManPoNum(pCnfInt->pMan) == 1 ); - - // set runtime limit - if ( nTimeNewOut ) - sat_solver_set_runtime_limit( p->pSat, nTimeNewOut ); - - // add clauses to the SAT solver - Cnf_DataLift( pCnfInt, p->nVars ); - for ( f = 0; f <= p->nFramesK; f++ ) - { - // add clauses to the solver - for ( i = 0; i < pCnfInt->nClauses; i++ ) - { - RetValue = sat_solver_addclause( p->pSat, pCnfInt->pClauses[i], pCnfInt->pClauses[i+1] ); - assert( RetValue ); - } - // add equality clauses for the flop variables - Aig_ManForEachPi( pCnfInt->pMan, pObj, i ) - { - pObj2 = f ? Aig_ManPo(p->pFrames, i + (f-1) * nRegs) : Aig_ManPi(p->pFrames, i); - Inter_CheckAddEqual( p, pCnfInt->pVarNums[pObj->Id], p->pCnf->pVarNums[pObj2->Id] ); - } - // add final clauses - if ( f < p->nFramesK ) - { - if ( f == Vec_IntSize(p->vOrLits) ) // find time here - { - // add literal to this frame - VarB = pCnfInt->pVarNums[ Aig_ManPo(pCnfInt->pMan, 0)->Id ]; - Vec_IntPush( p->vOrLits, VarB ); - } - else - { - // add OR gate for this frame - VarA = Vec_IntEntry( p->vOrLits, f ); - VarB = pCnfInt->pVarNums[ Aig_ManPo(pCnfInt->pMan, 0)->Id ]; - Inter_CheckAddOrGate( p, VarA, VarB, p->nVars + pCnfInt->nVars ); - Vec_IntWriteEntry( p->vOrLits, f, p->nVars + pCnfInt->nVars ); // using var ID! - } - } - else - { - // add AND gate for this frame - VarB = pCnfInt->pVarNums[ Aig_ManPo(pCnfInt->pMan, 0)->Id ]; - Vec_IntPush( p->vAndLits, VarB ); - } - // update variable IDs - Cnf_DataLift( pCnfInt, pCnfInt->nVars + 1 ); - p->nVars += pCnfInt->nVars + 1; - } - Cnf_DataLift( pCnfInt, -p->nVars ); - assert( Vec_IntSize(p->vOrLits) == p->nFramesK ); - - // collect the assumption literals - Vec_IntClear( p->vAssLits ); - Vec_IntForEachEntry( p->vOrLits, Entry, i ) - Vec_IntPush( p->vAssLits, toLitCond(Entry, 0) ); - Vec_IntForEachEntry( p->vAndLits, Entry, i ) - Vec_IntPush( p->vAssLits, toLitCond(Entry, 1) ); -/* - if ( pCnfInt->nLiterals == 3635 ) - { - int s = 0; - } -*/ - // call the SAT solver - status = sat_solver_solve( p->pSat, Vec_IntArray(p->vAssLits), - Vec_IntArray(p->vAssLits) + Vec_IntSize(p->vAssLits), - (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); - - return status == l_False; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/int/intContain.c b/src/aig/int/intContain.c deleted file mode 100644 index 77b057a7..00000000 --- a/src/aig/int/intContain.c +++ /dev/null @@ -1,341 +0,0 @@ -/**CFile**************************************************************** - - FileName [intContain.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Interpolation engine.] - - Synopsis [Interpolant containment checking.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 24, 2008.] - - Revision [$Id: intContain.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "intInt.h" -#include "fra.h" - -ABC_NAMESPACE_IMPL_START - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -extern int Inter_ManCheckUniqueness( Aig_Man_t * p, sat_solver * pSat, Cnf_Dat_t * pCnf, int nFrames ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Checks constainment of two interpolants.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Inter_ManCheckContainment( Aig_Man_t * pNew, Aig_Man_t * pOld ) -{ - Aig_Man_t * pMiter, * pAigTemp; - int RetValue; - pMiter = Aig_ManCreateMiter( pNew, pOld, 1 ); -// pMiter = Dar_ManRwsat( pAigTemp = pMiter, 1, 0 ); -// Aig_ManStop( pAigTemp ); - RetValue = Fra_FraigMiterStatus( pMiter ); - if ( RetValue == -1 ) - { - pAigTemp = Fra_FraigEquivence( pMiter, 1000000, 1 ); - RetValue = Fra_FraigMiterStatus( pAigTemp ); - Aig_ManStop( pAigTemp ); -// RetValue = Fra_FraigSat( pMiter, 1000000, 0, 0, 0, 0 ); - } - assert( RetValue != -1 ); - Aig_ManStop( pMiter ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Checks constainment of two interpolants.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Inter_ManCheckEquivalence( Aig_Man_t * pNew, Aig_Man_t * pOld ) -{ - Aig_Man_t * pMiter, * pAigTemp; - int RetValue; - pMiter = Aig_ManCreateMiter( pNew, pOld, 0 ); -// pMiter = Dar_ManRwsat( pAigTemp = pMiter, 1, 0 ); -// Aig_ManStop( pAigTemp ); - RetValue = Fra_FraigMiterStatus( pMiter ); - if ( RetValue == -1 ) - { - pAigTemp = Fra_FraigEquivence( pMiter, 1000000, 1 ); - RetValue = Fra_FraigMiterStatus( pAigTemp ); - Aig_ManStop( pAigTemp ); -// RetValue = Fra_FraigSat( pMiter, 1000000, 0, 0, 0, 0 ); - } - assert( RetValue != -1 ); - Aig_ManStop( pMiter ); - return RetValue; -} - - -/**Function************************************************************* - - Synopsis [Create timeframes of the manager for interpolation.] - - Description [The resulting manager is combinational. The primary inputs - corresponding to register outputs are ordered first.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Inter_ManFramesLatches( Aig_Man_t * pAig, int nFrames, Vec_Ptr_t ** pvMapReg ) -{ - Aig_Man_t * pFrames; - Aig_Obj_t * pObj, * pObjLi, * pObjLo; - int i, f; - assert( Saig_ManRegNum(pAig) > 0 ); - pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFrames ); - // map the constant node - Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames ); - // create variables for register outputs - *pvMapReg = Vec_PtrAlloc( (nFrames+1) * Saig_ManRegNum(pAig) ); - Saig_ManForEachLo( pAig, pObj, i ) - { - pObj->pData = Aig_ObjCreatePi( pFrames ); - Vec_PtrPush( *pvMapReg, pObj->pData ); - } - // add timeframes - for ( f = 0; f < nFrames; f++ ) - { - // create PI nodes for this frame - Saig_ManForEachPi( pAig, pObj, i ) - pObj->pData = Aig_ObjCreatePi( pFrames ); - // add internal nodes of this frame - Aig_ManForEachNode( pAig, pObj, i ) - pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - // save register inputs - Saig_ManForEachLi( pAig, pObj, i ) - pObj->pData = Aig_ObjChild0Copy(pObj); - // transfer to register outputs - Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) - { - pObjLo->pData = pObjLi->pData; - Vec_PtrPush( *pvMapReg, pObjLo->pData ); - } - } - return pFrames; -} - -/**Function************************************************************* - - Synopsis [Duplicates AIG while mapping PIs into the given array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Inter_ManAppendCone( Aig_Man_t * pOld, Aig_Man_t * pNew, Aig_Obj_t ** ppNewPis, int fCompl ) -{ - Aig_Obj_t * pObj; - int i; - assert( Aig_ManPoNum(pOld) == 1 ); - // create the PIs - Aig_ManCleanData( pOld ); - Aig_ManConst1(pOld)->pData = Aig_ManConst1(pNew); - Aig_ManForEachPi( pOld, pObj, i ) - pObj->pData = ppNewPis[i]; - // duplicate internal nodes - Aig_ManForEachNode( pOld, pObj, i ) - pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - // add one PO to new - pObj = Aig_ManPo( pOld, 0 ); - Aig_ObjCreatePo( pNew, Aig_NotCond( Aig_ObjChild0Copy(pObj), fCompl ) ); -} - - -/**Function************************************************************* - - Synopsis [Checks constainment of two interpolants inductively.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Inter_ManCheckInductiveContainment( Aig_Man_t * pTrans, Aig_Man_t * pInter, int nSteps, int fBackward ) -{ - Aig_Man_t * pFrames; - Aig_Obj_t ** ppNodes; - Vec_Ptr_t * vMapRegs; - Cnf_Dat_t * pCnf; - sat_solver * pSat; - int f, nRegs, status; - nRegs = Saig_ManRegNum(pTrans); - assert( nRegs > 0 ); - // generate the timeframes - pFrames = Inter_ManFramesLatches( pTrans, nSteps, &vMapRegs ); - assert( Vec_PtrSize(vMapRegs) == (nSteps + 1) * nRegs ); - // add main constraints to the timeframes - ppNodes = (Aig_Obj_t **)Vec_PtrArray(vMapRegs); - if ( !fBackward ) - { - // forward inductive check: p -> p -> ... -> !p - for ( f = 0; f < nSteps; f++ ) - Inter_ManAppendCone( pInter, pFrames, ppNodes + f * nRegs, 0 ); - Inter_ManAppendCone( pInter, pFrames, ppNodes + f * nRegs, 1 ); - } - else - { - // backward inductive check: p -> !p -> ... -> !p - Inter_ManAppendCone( pInter, pFrames, ppNodes + 0 * nRegs, 1 ); - for ( f = 1; f <= nSteps; f++ ) - Inter_ManAppendCone( pInter, pFrames, ppNodes + f * nRegs, 0 ); - } - Vec_PtrFree( vMapRegs ); - Aig_ManCleanup( pFrames ); - - // convert to CNF - pCnf = Cnf_Derive( pFrames, 0 ); - pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); -// Cnf_DataFree( pCnf ); -// Aig_ManStop( pFrames ); - - if ( pSat == NULL ) - { - Cnf_DataFree( pCnf ); - Aig_ManStop( pFrames ); - return 1; - } - - // solve the problem - status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); - -// Inter_ManCheckUniqueness( pTrans, pSat, pCnf, nSteps ); - - Cnf_DataFree( pCnf ); - Aig_ManStop( pFrames ); - - sat_solver_delete( pSat ); - return status == l_False; -} -ABC_NAMESPACE_IMPL_END - -#include "fra.h" - -ABC_NAMESPACE_IMPL_START - - -/**Function************************************************************* - - Synopsis [Check if cex satisfies uniqueness constraints.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Inter_ManCheckUniqueness( Aig_Man_t * p, sat_solver * pSat, Cnf_Dat_t * pCnf, int nFrames ) -{ - extern int Fra_SmlNodesCompareInFrame( Fra_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1, int iFrame0, int iFrame1 ); - extern void Fra_SmlAssignConst( Fra_Sml_t * p, Aig_Obj_t * pObj, int fConst1, int iFrame ); - extern void Fra_SmlSimulateOne( Fra_Sml_t * p ); - - Fra_Sml_t * pSml; - Vec_Int_t * vPis; - Aig_Obj_t * pObj, * pObj0; - int i, k, v, iBit, * pCounterEx; - int Counter; - if ( nFrames == 1 ) - return 1; -// if ( pSat->model.size == 0 ) - - // possible consequences here!!! - assert( 0 ); - - if ( sat_solver_nvars(pSat) == 0 ) - return 1; -// assert( Saig_ManPoNum(p) == 1 ); - assert( Aig_ManRegNum(p) > 0 ); - assert( Aig_ManRegNum(p) < Aig_ManPiNum(p) ); - - // get the counter-example - vPis = Vec_IntAlloc( 100 ); - Aig_ManForEachPi( pCnf->pMan, pObj, k ) - Vec_IntPush( vPis, pCnf->pVarNums[Aig_ObjId(pObj)] ); - assert( Vec_IntSize(vPis) == Aig_ManRegNum(p) + nFrames * Saig_ManPiNum(p) ); - pCounterEx = Sat_SolverGetModel( pSat, vPis->pArray, vPis->nSize ); - Vec_IntFree( vPis ); - - // start a new sequential simulator - pSml = Fra_SmlStart( p, 0, nFrames, 1 ); - // assign simulation info for the registers - iBit = 0; - Aig_ManForEachLoSeq( p, pObj, i ) - Fra_SmlAssignConst( pSml, pObj, pCounterEx[iBit++], 0 ); - // assign simulation info for the primary inputs - for ( i = 0; i < nFrames; i++ ) - Aig_ManForEachPiSeq( p, pObj, k ) - Fra_SmlAssignConst( pSml, pObj, pCounterEx[iBit++], i ); - assert( iBit == Aig_ManPiNum(pCnf->pMan) ); - // run simulation - Fra_SmlSimulateOne( pSml ); - - // check if the given output has failed -// RetValue = !Fra_SmlNodeIsZero( pSml, Aig_ManPo(pAig, 0) ); -// assert( RetValue ); - - // check values at the internal nodes - Counter = 0; - for ( i = 0; i < nFrames; i++ ) - for ( k = i+1; k < nFrames; k++ ) - { - for ( v = 0; v < Aig_ManRegNum(p); v++ ) - { - pObj0 = Aig_ManLo(p, v); - if ( !Fra_SmlNodesCompareInFrame( pSml, pObj0, pObj0, i, k ) ) - break; - } - if ( v == Aig_ManRegNum(p) ) - Counter++; - } - printf( "Uniquness does not hold in %d frames.\n", Counter ); - - Fra_SmlStop( pSml ); - ABC_FREE( pCounterEx ); - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/int/intCore.c b/src/aig/int/intCore.c deleted file mode 100644 index 3bd111be..00000000 --- a/src/aig/int/intCore.c +++ /dev/null @@ -1,389 +0,0 @@ -/**CFile**************************************************************** - - FileName [intCore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Interpolation engine.] - - Synopsis [Core procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 24, 2008.] - - Revision [$Id: intCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "intInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [This procedure sets default values of interpolation parameters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Inter_ManSetDefaultParams( Inter_ManParams_t * p ) -{ - memset( p, 0, sizeof(Inter_ManParams_t) ); - p->nBTLimit = 10000; // limit on the number of conflicts - p->nFramesMax = 40; // the max number timeframes to unroll - p->nSecLimit = 0; // time limit in seconds - p->nFramesK = 1; // the number of timeframes to use in induction - p->fRewrite = 0; // use additional rewriting to simplify timeframes - p->fTransLoop = 0; // add transition into the init state under new PI var - p->fUsePudlak = 0; // use Pudluk interpolation procedure - p->fUseOther = 0; // use other undisclosed option - p->fUseMiniSat = 0; // use MiniSat-1.14p instead of internal proof engine - p->fCheckKstep = 1; // check using K-step induction - p->fUseBias = 0; // bias decisions to global variables - p->fUseBackward = 0; // perform backward interpolation - p->fUseSeparate = 0; // solve each output separately - p->fDropSatOuts = 0; // replace by 1 the solved outputs - p->fVerbose = 0; // print verbose statistics - p->iFrameMax =-1; -} - -/**Function************************************************************* - - Synopsis [Interplates while the number of conflicts is not exceeded.] - - Description [Returns 1 if proven. 0 if failed. -1 if undecided.] - - SideEffects [Does not check the property in 0-th frame.] - - SeeAlso [] - -***********************************************************************/ -int Inter_ManPerformInterpolation( Aig_Man_t * pAig, Inter_ManParams_t * pPars, int * piFrame ) -{ - extern int Inter_ManCheckInductiveContainment( Aig_Man_t * pTrans, Aig_Man_t * pInter, int nSteps, int fBackward ); - Inter_Man_t * p; - Inter_Check_t * pCheck = NULL; - Aig_Man_t * pAigTemp; - int s, i, RetValue, Status, clk, clk2, clkTotal = clock(), timeTemp; - int nTimeNewOut = pPars->nSecLimit ? time(NULL) + pPars->nSecLimit : 0; - - // sanity checks - assert( Saig_ManRegNum(pAig) > 0 ); - assert( Saig_ManPiNum(pAig) > 0 ); - assert( Saig_ManPoNum(pAig)-Saig_ManConstrNum(pAig) == 1 ); - if ( pPars->fVerbose && Saig_ManConstrNum(pAig) ) - printf( "Performing interpolation with %d constraints...\n", Saig_ManConstrNum(pAig) ); - - if ( Inter_ManCheckInitialState(pAig) ) - { - *piFrame = 0; - printf( "Property trivially fails in the initial state.\n" ); - return 0; - } -/* - if ( Inter_ManCheckAllStates(pAig) ) - { - printf( "Property trivially holds in all states.\n" ); - return 1; - } -*/ - // create interpolation manager - // can perform SAT sweeping and/or rewriting of this AIG... - p = Inter_ManCreate( pAig, pPars ); - if ( pPars->fTransLoop ) - p->pAigTrans = Inter_ManStartOneOutput( pAig, 0 ); - else - p->pAigTrans = Inter_ManStartDuplicated( pAig ); - // derive CNF for the transformed AIG -clk = clock(); - p->pCnfAig = Cnf_Derive( p->pAigTrans, Aig_ManRegNum(p->pAigTrans) ); -p->timeCnf += clock() - clk; - if ( pPars->fVerbose ) - { - printf( "AIG: PI/PO/Reg = %d/%d/%d. And = %d. Lev = %d. CNF: Var/Cla = %d/%d.\n", - Saig_ManPiNum(pAig), Saig_ManPoNum(pAig), Saig_ManRegNum(pAig), - Aig_ManAndNum(pAig), Aig_ManLevelNum(pAig), - p->pCnfAig->nVars, p->pCnfAig->nClauses ); - } - - // derive interpolant - *piFrame = -1; - p->nFrames = 1; - for ( s = 0; ; s++ ) - { - Cnf_Dat_t * pCnfInter2; - -clk2 = clock(); - // initial state - if ( pPars->fUseBackward ) - p->pInter = Inter_ManStartOneOutput( pAig, 1 ); - else - p->pInter = Inter_ManStartInitState( Aig_ManRegNum(pAig) ); - assert( Aig_ManPoNum(p->pInter) == 1 ); -clk = clock(); - p->pCnfInter = Cnf_Derive( p->pInter, 0 ); -p->timeCnf += clock() - clk; - // timeframes - p->pFrames = Inter_ManFramesInter( pAig, p->nFrames, pPars->fUseBackward ); -clk = clock(); - if ( pPars->fRewrite ) - { - p->pFrames = Dar_ManRwsat( pAigTemp = p->pFrames, 1, 0 ); - Aig_ManStop( pAigTemp ); -// p->pFrames = Fra_FraigEquivence( pAigTemp = p->pFrames, 100, 0 ); -// Aig_ManStop( pAigTemp ); - } -p->timeRwr += clock() - clk; - // can also do SAT sweeping on the timeframes... -clk = clock(); - if ( pPars->fUseBackward ) - p->pCnfFrames = Cnf_Derive( p->pFrames, Aig_ManPoNum(p->pFrames) ); - else -// p->pCnfFrames = Cnf_Derive( p->pFrames, 0 ); - p->pCnfFrames = Cnf_DeriveSimple( p->pFrames, 0 ); -p->timeCnf += clock() - clk; - // report statistics - if ( pPars->fVerbose ) - { - printf( "Step = %2d. Frames = 1 + %d. And = %5d. Lev = %5d. ", - s+1, p->nFrames, Aig_ManNodeNum(p->pFrames), Aig_ManLevelNum(p->pFrames) ); - ABC_PRT( "Time", clock() - clk2 ); - } - - - ////////////////////////////////////////// - // start containment checking - if ( !(pPars->fTransLoop || pPars->fUseBackward) ) - { - pCheck = Inter_CheckStart( p->pAigTrans, pPars->nFramesK ); - // try new containment check for the initial state -clk = clock(); - pCnfInter2 = Cnf_Derive( p->pInter, 1 ); -p->timeCnf += clock() - clk; - RetValue = Inter_CheckPerform( pCheck, pCnfInter2, nTimeNewOut ); -// assert( RetValue == 0 ); - Cnf_DataFree( pCnfInter2 ); - if ( p->vInters ) - Vec_PtrPush( p->vInters, Aig_ManDupSimple(p->pInter) ); - } - ////////////////////////////////////////// - - // iterate the interpolation procedure - for ( i = 0; ; i++ ) - { - if ( p->nFrames + i >= pPars->nFramesMax ) - { - if ( pPars->fVerbose ) - printf( "Reached limit (%d) on the number of timeframes.\n", pPars->nFramesMax ); - p->timeTotal = clock() - clkTotal; - Inter_ManStop( p, 0 ); - Inter_CheckStop( pCheck ); - return -1; - } - - // perform interpolation - clk = clock(); -#ifdef ABC_USE_LIBRARIES - if ( pPars->fUseMiniSat ) - { - assert( !pPars->fUseBackward ); - RetValue = Inter_ManPerformOneStepM114p( p, pPars->fUsePudlak, pPars->fUseOther ); - } - else -#endif - RetValue = Inter_ManPerformOneStep( p, pPars->fUseBias, pPars->fUseBackward, nTimeNewOut ); - - if ( pPars->fVerbose ) - { - printf( " I = %2d. Bmc =%3d. IntAnd =%6d. IntLev =%5d. Conf =%6d. ", - i+1, i + 1 + p->nFrames, Aig_ManNodeNum(p->pInter), Aig_ManLevelNum(p->pInter), p->nConfCur ); - ABC_PRT( "Time", clock() - clk ); - } - // remember the number of timeframes completed - pPars->iFrameMax = i + 1 + p->nFrames; - if ( RetValue == 0 ) // found a (spurious?) counter-example - { - if ( i == 0 ) // real counterexample - { - if ( pPars->fVerbose ) - printf( "Found a real counterexample in frame %d.\n", p->nFrames ); - p->timeTotal = clock() - clkTotal; - *piFrame = p->nFrames; -// pAig->pSeqModel = (Abc_Cex_t *)Inter_ManGetCounterExample( pAig, p->nFrames+1, pPars->fVerbose ); - { - int RetValue; - Saig_ParBmc_t ParsBmc, * pParsBmc = &ParsBmc; - Saig_ParBmcSetDefaultParams( pParsBmc ); - pParsBmc->nConfLimit = 100000000; - pParsBmc->nStart = p->nFrames; - pParsBmc->fVerbose = pPars->fVerbose; - RetValue = Saig_ManBmcScalable( pAig, pParsBmc ); - if ( RetValue == 1 ) - printf( "Error: The problem should be SAT but it is UNSAT.\n" ); - else if ( RetValue == -1 ) - printf( "Error: The problem timed out.\n" ); - } - Inter_ManStop( p, 0 ); - Inter_CheckStop( pCheck ); - return 0; - } - // likely spurious counter-example - p->nFrames += i; - Inter_ManClean( p ); - break; - } - else if ( RetValue == -1 ) - { - if ( pPars->nSecLimit && time(NULL) > nTimeNewOut ) // timed out - { - if ( pPars->fVerbose ) - printf( "Reached timeout (%d seconds).\n", pPars->nSecLimit ); - } - else - { - assert( p->nConfCur >= p->nConfLimit ); - if ( pPars->fVerbose ) - printf( "Reached limit (%d) on the number of conflicts.\n", p->nConfLimit ); - } - p->timeTotal = clock() - clkTotal; - Inter_ManStop( p, 0 ); - Inter_CheckStop( pCheck ); - return -1; - } - assert( RetValue == 1 ); // found new interpolant - // compress the interpolant -clk = clock(); - if ( p->pInterNew ) - { -// Ioa_WriteAiger( p->pInterNew, "interpol.aig", 0, 0 ); - p->pInterNew = Dar_ManRwsat( pAigTemp = p->pInterNew, 1, 0 ); -// p->pInterNew = Dar_ManRwsat( pAigTemp = p->pInterNew, 0, 0 ); - Aig_ManStop( pAigTemp ); - } -p->timeRwr += clock() - clk; - - // check if interpolant is trivial - if ( p->pInterNew == NULL || Aig_ObjChild0(Aig_ManPo(p->pInterNew,0)) == Aig_ManConst0(p->pInterNew) ) - { -// printf( "interpolant is constant 0\n" ); - if ( pPars->fVerbose ) - printf( "The problem is trivially true for all states.\n" ); - p->timeTotal = clock() - clkTotal; - Inter_ManStop( p, 1 ); - Inter_CheckStop( pCheck ); - return 1; - } - - // check containment of interpolants -clk = clock(); - if ( pPars->fCheckKstep ) // k-step unique-state induction - { - if ( Aig_ManPiNum(p->pInterNew) == Aig_ManPiNum(p->pInter) ) - { - if ( pPars->fTransLoop || pPars->fUseBackward ) - Status = Inter_ManCheckInductiveContainment( p->pAigTrans, p->pInterNew, pPars->nFramesK, pPars->fUseBackward ); - else - { // new containment check -clk2 = clock(); - pCnfInter2 = Cnf_Derive( p->pInterNew, 1 ); -p->timeCnf += clock() - clk2; -timeTemp = clock() - clk2; - - Status = Inter_CheckPerform( pCheck, pCnfInter2, nTimeNewOut ); - Cnf_DataFree( pCnfInter2 ); - if ( p->vInters ) - Vec_PtrPush( p->vInters, Aig_ManDupSimple(p->pInterNew) ); - } - } - else - Status = 0; - } - else // combinational containment - { - if ( Aig_ManPiNum(p->pInterNew) == Aig_ManPiNum(p->pInter) ) - Status = Inter_ManCheckContainment( p->pInterNew, p->pInter ); - else - Status = 0; - } -p->timeEqu += clock() - clk - timeTemp; - if ( Status ) // contained - { - if ( pPars->fVerbose ) - printf( "Proved containment of interpolants.\n" ); - p->timeTotal = clock() - clkTotal; - Inter_ManStop( p, 1 ); - Inter_CheckStop( pCheck ); - return 1; - } - if ( pPars->nSecLimit && time(NULL) > nTimeNewOut ) - { - printf( "Reached timeout (%d seconds).\n", pPars->nSecLimit ); - p->timeTotal = clock() - clkTotal; - Inter_ManStop( p, 1 ); - Inter_CheckStop( pCheck ); - return -1; - } - // save interpolant and convert it into CNF - if ( pPars->fTransLoop ) - { - Aig_ManStop( p->pInter ); - p->pInter = p->pInterNew; - } - else - { - if ( pPars->fUseBackward ) - { - p->pInter = Aig_ManCreateMiter( pAigTemp = p->pInter, p->pInterNew, 2 ); - Aig_ManStop( pAigTemp ); - Aig_ManStop( p->pInterNew ); - // compress the interpolant -clk = clock(); - p->pInter = Dar_ManRwsat( pAigTemp = p->pInter, 1, 0 ); - Aig_ManStop( pAigTemp ); -p->timeRwr += clock() - clk; - } - else // forward with the new containment checking (using only the frontier) - { - Aig_ManStop( p->pInter ); - p->pInter = p->pInterNew; - } - } - p->pInterNew = NULL; - Cnf_DataFree( p->pCnfInter ); -clk = clock(); - p->pCnfInter = Cnf_Derive( p->pInter, 0 ); -p->timeCnf += clock() - clk; - } - - // start containment checking - Inter_CheckStop( pCheck ); - } - assert( 0 ); - return RetValue; -} - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/int/intCtrex.c b/src/aig/int/intCtrex.c deleted file mode 100644 index 0aa60040..00000000 --- a/src/aig/int/intCtrex.c +++ /dev/null @@ -1,167 +0,0 @@ -/**CFile**************************************************************** - - FileName [intCtrex.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Interpolation engine.] - - Synopsis [Counter-example generation after disproving the property.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 24, 2008.] - - Revision [$Id: intCtrex.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "intInt.h" -#include "ssw.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Unroll the circuit the given number of timeframes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Inter_ManFramesBmc( Aig_Man_t * pAig, int nFrames ) -{ - Aig_Man_t * pFrames; - Aig_Obj_t * pObj, * pObjLi, * pObjLo; - int i, f; - assert( Saig_ManRegNum(pAig) > 0 ); - assert( Saig_ManPoNum(pAig) == 1 ); - pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFrames ); - // map the constant node - Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames ); - // create variables for register outputs - Saig_ManForEachLo( pAig, pObj, i ) - pObj->pData = Aig_ManConst0( pFrames ); - // add timeframes - for ( f = 0; f < nFrames; f++ ) - { - // create PI nodes for this frame - Saig_ManForEachPi( pAig, pObj, i ) - pObj->pData = Aig_ObjCreatePi( pFrames ); - // add internal nodes of this frame - Aig_ManForEachNode( pAig, pObj, i ) - pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - if ( f == nFrames - 1 ) - break; - // transfer to register outputs - Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) - pObjLi->pData = Aig_ObjChild0Copy(pObjLi); - // transfer to register outputs - Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) - pObjLo->pData = pObjLi->pData; - } - // create POs for the output of the last frame - pObj = Aig_ManPo( pAig, 0 ); - Aig_ObjCreatePo( pFrames, Aig_ObjChild0Copy(pObj) ); - Aig_ManCleanup( pFrames ); - return pFrames; -} - -/**Function************************************************************* - - Synopsis [Run the SAT solver on the unrolled instance.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Inter_ManGetCounterExample( Aig_Man_t * pAig, int nFrames, int fVerbose ) -{ - int nConfLimit = 1000000; - Abc_Cex_t * pCtrex = NULL; - Aig_Man_t * pFrames; - sat_solver * pSat; - Cnf_Dat_t * pCnf; - int status, clk = clock(); - Vec_Int_t * vCiIds; - // create timeframes - assert( Saig_ManPoNum(pAig) == 1 ); - pFrames = Inter_ManFramesBmc( pAig, nFrames ); - // derive CNF - pCnf = Cnf_Derive( pFrames, 0 ); - Cnf_DataTranformPolarity( pCnf, 0 ); - vCiIds = Cnf_DataCollectPiSatNums( pCnf, pFrames ); - Aig_ManStop( pFrames ); - // convert into SAT solver - pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); - Cnf_DataFree( pCnf ); - if ( pSat == NULL ) - { - printf( "Counter-example generation in command \"int\" has failed.\n" ); - printf( "Use command \"bmc2\" to produce a valid counter-example.\n" ); - Vec_IntFree( vCiIds ); - return NULL; - } - // simplify the problem - status = sat_solver_simplify(pSat); - if ( status == 0 ) - { - Vec_IntFree( vCiIds ); - sat_solver_delete( pSat ); - return NULL; - } - // solve the miter - status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); - // if the problem is SAT, get the counterexample - if ( status == l_True ) - { - int i, * pModel = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize ); - pCtrex = Abc_CexAlloc( Saig_ManRegNum(pAig), Saig_ManPiNum(pAig), nFrames ); - pCtrex->iFrame = nFrames - 1; - pCtrex->iPo = 0; - for ( i = 0; i < Vec_IntSize(vCiIds); i++ ) - if ( pModel[i] ) - Aig_InfoSetBit( pCtrex->pData, Saig_ManRegNum(pAig) + i ); - ABC_FREE( pModel ); - } - // free the sat_solver - sat_solver_delete( pSat ); - Vec_IntFree( vCiIds ); - // verify counter-example - status = Saig_ManVerifyCex( pAig, pCtrex ); - if ( status == 0 ) - printf( "Inter_ManGetCounterExample(): Counter-example verification has FAILED.\n" ); - // report the results - if ( fVerbose ) - { - ABC_PRT( "Total ctrex generation time", clock() - clk ); - } - return pCtrex; - -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/int/intDup.c b/src/aig/int/intDup.c deleted file mode 100644 index 800375a9..00000000 --- a/src/aig/int/intDup.c +++ /dev/null @@ -1,184 +0,0 @@ -/**CFile**************************************************************** - - FileName [intDup.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Interpolation engine.] - - Synopsis [Specialized AIG duplication procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 24, 2008.] - - Revision [$Id: intDup.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "intInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Create trivial AIG manager for the init state.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Inter_ManStartInitState( int nRegs ) -{ - Aig_Man_t * p; - Aig_Obj_t * pRes; - Aig_Obj_t ** ppInputs; - int i; - assert( nRegs > 0 ); - ppInputs = ABC_ALLOC( Aig_Obj_t *, nRegs ); - p = Aig_ManStart( nRegs ); - for ( i = 0; i < nRegs; i++ ) - ppInputs[i] = Aig_Not( Aig_ObjCreatePi(p) ); - pRes = Aig_Multi( p, ppInputs, nRegs, AIG_OBJ_AND ); - Aig_ObjCreatePo( p, pRes ); - ABC_FREE( ppInputs ); - return p; -} - -/**Function************************************************************* - - Synopsis [Duplicate the AIG w/o POs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Inter_ManStartDuplicated( Aig_Man_t * p ) -{ - Aig_Man_t * pNew; - Aig_Obj_t * pObj; - int i; - assert( Aig_ManRegNum(p) > 0 ); - // create the new manager - pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->pSpec = Aig_UtilStrsav( p->pSpec ); - // create the PIs - Aig_ManCleanData( p ); - Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); - Aig_ManForEachPi( p, pObj, i ) - pObj->pData = Aig_ObjCreatePi( pNew ); - // set registers - pNew->nTruePis = p->nTruePis; - pNew->nTruePos = Saig_ManConstrNum(p); - pNew->nRegs = p->nRegs; - // duplicate internal nodes - Aig_ManForEachNode( p, pObj, i ) - pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - - // create constraint outputs - Saig_ManForEachPo( p, pObj, i ) - { - if ( i < Saig_ManPoNum(p)-Saig_ManConstrNum(p) ) - continue; - Aig_ObjCreatePo( pNew, Aig_Not( Aig_ObjChild0Copy(pObj) ) ); - } - - // create register inputs with MUXes - Saig_ManForEachLi( p, pObj, i ) - Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); - Aig_ManCleanup( pNew ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Duplicate the AIG w/o POs and transforms to transit into init state.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Inter_ManStartOneOutput( Aig_Man_t * p, int fAddFirstPo ) -{ - Aig_Man_t * pNew; - Aig_Obj_t * pObj, * pObjLi, * pObjLo; - Aig_Obj_t * pCtrl = NULL; // Suppress "might be used uninitialized" - int i; - assert( Aig_ManRegNum(p) > 0 ); - // create the new manager - pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->pSpec = Aig_UtilStrsav( p->pSpec ); - // create the PIs - Aig_ManCleanData( p ); - Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); - Aig_ManForEachPi( p, pObj, i ) - { - if ( i == Saig_ManPiNum(p) ) - pCtrl = Aig_ObjCreatePi( pNew ); - pObj->pData = Aig_ObjCreatePi( pNew ); - } - // set registers - pNew->nRegs = fAddFirstPo? 0 : p->nRegs; - pNew->nTruePis = fAddFirstPo? Aig_ManPiNum(p) + 1 : p->nTruePis + 1; - pNew->nTruePos = fAddFirstPo + Saig_ManConstrNum(p); - // duplicate internal nodes - Aig_ManForEachNode( p, pObj, i ) - pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - - // create constraint outputs - Saig_ManForEachPo( p, pObj, i ) - { - if ( i < Saig_ManPoNum(p)-Saig_ManConstrNum(p) ) - continue; - Aig_ObjCreatePo( pNew, Aig_Not( Aig_ObjChild0Copy(pObj) ) ); - } - - // add the PO - if ( fAddFirstPo ) - { - pObj = Aig_ManPo( p, 0 ); - Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); - } - else - { - // create register inputs with MUXes - Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) - { - pObj = Aig_Mux( pNew, pCtrl, (Aig_Obj_t *)pObjLo->pData, Aig_ObjChild0Copy(pObjLi) ); - // pObj = Aig_Mux( pNew, pCtrl, Aig_ManConst0(pNew), Aig_ObjChild0Copy(pObjLi) ); - Aig_ObjCreatePo( pNew, pObj ); - } - } - Aig_ManCleanup( pNew ); - return pNew; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/int/intFrames.c b/src/aig/int/intFrames.c deleted file mode 100644 index 0fbab6cb..00000000 --- a/src/aig/int/intFrames.c +++ /dev/null @@ -1,115 +0,0 @@ -/**CFile**************************************************************** - - FileName [intFrames.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Interpolation engine.] - - Synopsis [Sequential AIG unrolling for interpolation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 24, 2008.] - - Revision [$Id: intFrames.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "intInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Create timeframes of the manager for interpolation.] - - Description [The resulting manager is combinational. The primary inputs - corresponding to register outputs are ordered first. The only POs of the - manager is the property output of the last timeframe.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Inter_ManFramesInter( Aig_Man_t * pAig, int nFrames, int fAddRegOuts ) -{ - Aig_Man_t * pFrames; - Aig_Obj_t * pObj, * pObjLi, * pObjLo; - int i, f; - assert( Saig_ManRegNum(pAig) > 0 ); - assert( Saig_ManPoNum(pAig)-Saig_ManConstrNum(pAig) == 1 ); - pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFrames ); - // map the constant node - Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames ); - // create variables for register outputs - if ( fAddRegOuts ) - { - Saig_ManForEachLo( pAig, pObj, i ) - pObj->pData = Aig_ManConst0( pFrames ); - } - else - { - Saig_ManForEachLo( pAig, pObj, i ) - pObj->pData = Aig_ObjCreatePi( pFrames ); - } - // add timeframes - for ( f = 0; f < nFrames; f++ ) - { - // create PI nodes for this frame - Saig_ManForEachPi( pAig, pObj, i ) - pObj->pData = Aig_ObjCreatePi( pFrames ); - // add internal nodes of this frame - Aig_ManForEachNode( pAig, pObj, i ) - pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - // add outputs for constraints - Saig_ManForEachPo( pAig, pObj, i ) - { - if ( i < Saig_ManPoNum(pAig)-Saig_ManConstrNum(pAig) ) - continue; - Aig_ObjCreatePo( pFrames, Aig_Not( Aig_ObjChild0Copy(pObj) ) ); - } - if ( f == nFrames - 1 ) - break; - // save register inputs - Saig_ManForEachLi( pAig, pObj, i ) - pObj->pData = Aig_ObjChild0Copy(pObj); - // transfer to register outputs - Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) - pObjLo->pData = pObjLi->pData; - } - // create POs for each register output - if ( fAddRegOuts ) - { - Saig_ManForEachLi( pAig, pObj, i ) - Aig_ObjCreatePo( pFrames, Aig_ObjChild0Copy(pObj) ); - } - // create the only PO of the manager - else - { - pObj = Aig_ManPo( pAig, 0 ); - Aig_ObjCreatePo( pFrames, Aig_ObjChild0Copy(pObj) ); - } - Aig_ManCleanup( pFrames ); - return pFrames; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/int/intInt.h b/src/aig/int/intInt.h deleted file mode 100644 index 66ff9578..00000000 --- a/src/aig/int/intInt.h +++ /dev/null @@ -1,142 +0,0 @@ -/**CFile**************************************************************** - - FileName [intInt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Interpolation engine.] - - Synopsis [Internal declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 24, 2008.] - - Revision [$Id: intInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __INT_INT_H__ -#define __INT_INT_H__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "saig.h" -#include "cnf.h" -#include "satSolver.h" -#include "satStore.h" -#include "int.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -// interpolation manager -typedef struct Inter_Man_t_ Inter_Man_t; -struct Inter_Man_t_ -{ - // AIG manager - Aig_Man_t * pAig; // the original AIG manager - Aig_Man_t * pAigTrans; // the transformed original AIG manager - Cnf_Dat_t * pCnfAig; // CNF for the original manager - // interpolant - Aig_Man_t * pInter; // the current interpolant - Cnf_Dat_t * pCnfInter; // CNF for the current interplant - // timeframes - Aig_Man_t * pFrames; // the timeframes - Cnf_Dat_t * pCnfFrames; // CNF for the timeframes - // other data - Vec_Int_t * vVarsAB; // the variables participating in - // temporary place for the new interpolant - Aig_Man_t * pInterNew; - Vec_Ptr_t * vInters; - // parameters - int nFrames; // the number of timeframes - int nConfCur; // the current number of conflicts - int nConfLimit; // the limit on the number of conflicts - int fVerbose; // the verbosiness flag - // runtime - int timeRwr; - int timeCnf; - int timeSat; - int timeInt; - int timeEqu; - int timeOther; - int timeTotal; -}; - -// containment checking manager -typedef struct Inter_Check_t_ Inter_Check_t; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== intCheck.c ============================================================*/ -extern Inter_Check_t * Inter_CheckStart( Aig_Man_t * pTrans, int nFramesK ); -extern void Inter_CheckStop( Inter_Check_t * p ); -extern int Inter_CheckPerform( Inter_Check_t * p, Cnf_Dat_t * pCnf, int nTimeNewOut ); - -/*=== intContain.c ============================================================*/ -extern int Inter_ManCheckContainment( Aig_Man_t * pNew, Aig_Man_t * pOld ); -extern int Inter_ManCheckEquivalence( Aig_Man_t * pNew, Aig_Man_t * pOld ); -extern int Inter_ManCheckInductiveContainment( Aig_Man_t * pTrans, Aig_Man_t * pInter, int nSteps, int fBackward ); - -/*=== intCtrex.c ============================================================*/ -extern void * Inter_ManGetCounterExample( Aig_Man_t * pAig, int nFrames, int fVerbose ); - -/*=== intDup.c ============================================================*/ -extern Aig_Man_t * Inter_ManStartInitState( int nRegs ); -extern Aig_Man_t * Inter_ManStartDuplicated( Aig_Man_t * p ); -extern Aig_Man_t * Inter_ManStartOneOutput( Aig_Man_t * p, int fAddFirstPo ); - -/*=== intFrames.c ============================================================*/ -extern Aig_Man_t * Inter_ManFramesInter( Aig_Man_t * pAig, int nFrames, int fAddRegOuts ); - -/*=== intMan.c ============================================================*/ -extern Inter_Man_t * Inter_ManCreate( Aig_Man_t * pAig, Inter_ManParams_t * pPars ); -extern void Inter_ManClean( Inter_Man_t * p ); -extern void Inter_ManStop( Inter_Man_t * p, int fProved ); - -/*=== intM114.c ============================================================*/ -extern int Inter_ManPerformOneStep( Inter_Man_t * p, int fUseBias, int fUseBackward, int nTimeNewOut ); - -/*=== intM114p.c ============================================================*/ -#ifdef ABC_USE_LIBRARIES -extern int Inter_ManPerformOneStepM114p( Inter_Man_t * p, int fUsePudlak, int fUseOther ); -#endif - -/*=== intUtil.c ============================================================*/ -extern int Inter_ManCheckInitialState( Aig_Man_t * p ); -extern int Inter_ManCheckAllStates( Aig_Man_t * p ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/int/intInter.c b/src/aig/int/intInter.c deleted file mode 100644 index ef32294b..00000000 --- a/src/aig/int/intInter.c +++ /dev/null @@ -1,145 +0,0 @@ -/**CFile**************************************************************** - - FileName [intInter.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Interpolation engine.] - - Synopsis [Experimental procedures to derive and compare interpolants.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 24, 2008.] - - Revision [$Id: intInter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "intInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Inter_ManDupExpand( Aig_Man_t * pInter, Aig_Man_t * pOther ) -{ - Aig_Man_t * pInterC; - assert( Aig_ManPiNum(pInter) <= Aig_ManPiNum(pOther) ); - pInterC = Aig_ManDupSimple( pInter ); - Aig_IthVar( pInterC, Aig_ManPiNum(pOther)-1 ); - assert( Aig_ManPiNum(pInterC) == Aig_ManPiNum(pOther) ); - return pInterC; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Inter_ManVerifyInterpolant1( Inta_Man_t * pMan, Sto_Man_t * pCnf, Aig_Man_t * pInter ) -{ - extern Aig_Man_t * Inta_ManDeriveClauses( Inta_Man_t * pMan, Sto_Man_t * pCnf, int fClausesA ); - Aig_Man_t * pLower, * pUpper, * pInterC; - int RetValue1, RetValue2; - - pLower = Inta_ManDeriveClauses( pMan, pCnf, 1 ); - pUpper = Inta_ManDeriveClauses( pMan, pCnf, 0 ); - Aig_ManFlipFirstPo( pUpper ); - - pInterC = Inter_ManDupExpand( pInter, pLower ); - RetValue1 = Inter_ManCheckContainment( pLower, pInterC ); - Aig_ManStop( pInterC ); - - pInterC = Inter_ManDupExpand( pInter, pUpper ); - RetValue2 = Inter_ManCheckContainment( pInterC, pUpper ); - Aig_ManStop( pInterC ); - - if ( RetValue1 && RetValue2 ) - printf( "Im is correct.\n" ); - if ( !RetValue1 ) - printf( "Property A => Im fails.\n" ); - if ( !RetValue2 ) - printf( "Property Im => !B fails.\n" ); - - Aig_ManStop( pLower ); - Aig_ManStop( pUpper ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Inter_ManVerifyInterpolant2( Intb_Man_t * pMan, Sto_Man_t * pCnf, Aig_Man_t * pInter ) -{ - extern Aig_Man_t * Intb_ManDeriveClauses( Intb_Man_t * pMan, Sto_Man_t * pCnf, int fClausesA ); - Aig_Man_t * pLower, * pUpper, * pInterC; - int RetValue1, RetValue2; - - pLower = Intb_ManDeriveClauses( pMan, pCnf, 1 ); - pUpper = Intb_ManDeriveClauses( pMan, pCnf, 0 ); - Aig_ManFlipFirstPo( pUpper ); - - pInterC = Inter_ManDupExpand( pInter, pLower ); -//Aig_ManPrintStats( pLower ); -//Aig_ManPrintStats( pUpper ); -//Aig_ManPrintStats( pInterC ); -//Aig_ManDumpBlif( pInterC, "inter_c.blif", NULL, NULL ); - RetValue1 = Inter_ManCheckContainment( pLower, pInterC ); - Aig_ManStop( pInterC ); - - pInterC = Inter_ManDupExpand( pInter, pUpper ); - RetValue2 = Inter_ManCheckContainment( pInterC, pUpper ); - Aig_ManStop( pInterC ); - - if ( RetValue1 && RetValue2 ) - printf( "Ip is correct.\n" ); - if ( !RetValue1 ) - printf( "Property A => Ip fails.\n" ); - if ( !RetValue2 ) - printf( "Property Ip => !B fails.\n" ); - - Aig_ManStop( pLower ); - Aig_ManStop( pUpper ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/int/intM114.c b/src/aig/int/intM114.c deleted file mode 100644 index 139c9bbd..00000000 --- a/src/aig/int/intM114.c +++ /dev/null @@ -1,320 +0,0 @@ -/**CFile**************************************************************** - - FileName [intM114.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Interpolation engine.] - - Synopsis [Intepolation using ABC's proof generator added to MiniSat-1.14c.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 24, 2008.] - - Revision [$Id: intM114.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "intInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns the SAT solver for one interpolation run.] - - Description [pInter is the previous interpolant. pAig is one time frame. - pFrames is the unrolled time frames.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -sat_solver * Inter_ManDeriveSatSolver( - Aig_Man_t * pInter, Cnf_Dat_t * pCnfInter, - Aig_Man_t * pAig, Cnf_Dat_t * pCnfAig, - Aig_Man_t * pFrames, Cnf_Dat_t * pCnfFrames, - Vec_Int_t * vVarsAB, int fUseBackward ) -{ - sat_solver * pSat; - Aig_Obj_t * pObj, * pObj2; - int i, Lits[2]; - -//Aig_ManDumpBlif( pInter, "out_inter.blif", NULL, NULL ); -//Aig_ManDumpBlif( pAig, "out_aig.blif", NULL, NULL ); -//Aig_ManDumpBlif( pFrames, "out_frames.blif", NULL, NULL ); - - // sanity checks - assert( Aig_ManRegNum(pInter) == 0 ); - assert( Aig_ManRegNum(pAig) > 0 ); - assert( Aig_ManRegNum(pFrames) == 0 ); - assert( Aig_ManPoNum(pInter) == 1 ); - assert( Aig_ManPoNum(pFrames) == fUseBackward? Saig_ManRegNum(pAig) : 1 ); - assert( fUseBackward || Aig_ManPiNum(pInter) == Aig_ManRegNum(pAig) ); -// assert( (Aig_ManPiNum(pFrames) - Aig_ManRegNum(pAig)) % Saig_ManPiNum(pAig) == 0 ); - - // prepare CNFs - Cnf_DataLift( pCnfAig, pCnfFrames->nVars ); - Cnf_DataLift( pCnfInter, pCnfFrames->nVars + pCnfAig->nVars ); - - // start the solver - pSat = sat_solver_new(); - sat_solver_store_alloc( pSat ); - sat_solver_setnvars( pSat, pCnfInter->nVars + pCnfAig->nVars + pCnfFrames->nVars ); - - // add clauses of A - // interpolant - for ( i = 0; i < pCnfInter->nClauses; i++ ) - { - if ( !sat_solver_addclause( pSat, pCnfInter->pClauses[i], pCnfInter->pClauses[i+1] ) ) - { - sat_solver_delete( pSat ); - // return clauses to the original state - Cnf_DataLift( pCnfAig, -pCnfFrames->nVars ); - Cnf_DataLift( pCnfInter, -pCnfFrames->nVars -pCnfAig->nVars ); - return NULL; - } - } - // connector clauses - if ( fUseBackward ) - { - Saig_ManForEachLi( pAig, pObj2, i ) - { - if ( Saig_ManRegNum(pAig) == Aig_ManPiNum(pInter) ) - pObj = Aig_ManPi( pInter, i ); - else - { - assert( Aig_ManPiNum(pAig) == Aig_ManPiNum(pInter) ); - pObj = Aig_ManPi( pInter, Aig_ManPiNum(pAig)-Saig_ManRegNum(pAig) + i ); - } - - Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 0 ); - Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 ); - if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) - assert( 0 ); - Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 1 ); - Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 ); - if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) - assert( 0 ); - } - } - else - { - Aig_ManForEachPi( pInter, pObj, i ) - { - pObj2 = Saig_ManLo( pAig, i ); - - Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 0 ); - Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 ); - if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) - assert( 0 ); - Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 1 ); - Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 ); - if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) - assert( 0 ); - } - } - // one timeframe - for ( i = 0; i < pCnfAig->nClauses; i++ ) - { - if ( !sat_solver_addclause( pSat, pCnfAig->pClauses[i], pCnfAig->pClauses[i+1] ) ) - assert( 0 ); - } - // connector clauses - Vec_IntClear( vVarsAB ); - if ( fUseBackward ) - { - Aig_ManForEachPo( pFrames, pObj, i ) - { - assert( pCnfFrames->pVarNums[pObj->Id] >= 0 ); - Vec_IntPush( vVarsAB, pCnfFrames->pVarNums[pObj->Id] ); - - pObj2 = Saig_ManLo( pAig, i ); - Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 0 ); - Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 ); - if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) - assert( 0 ); - Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 1 ); - Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 ); - if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) - assert( 0 ); - } - } - else - { - Aig_ManForEachPi( pFrames, pObj, i ) - { - if ( i == Aig_ManRegNum(pAig) ) - break; - Vec_IntPush( vVarsAB, pCnfFrames->pVarNums[pObj->Id] ); - - pObj2 = Saig_ManLi( pAig, i ); - Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 0 ); - Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 ); - if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) - assert( 0 ); - Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 1 ); - Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 ); - if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) - assert( 0 ); - } - } - // add clauses of B - sat_solver_store_mark_clauses_a( pSat ); - for ( i = 0; i < pCnfFrames->nClauses; i++ ) - { - if ( !sat_solver_addclause( pSat, pCnfFrames->pClauses[i], pCnfFrames->pClauses[i+1] ) ) - { - pSat->fSolved = 1; - break; - } - } - sat_solver_store_mark_roots( pSat ); - // return clauses to the original state - Cnf_DataLift( pCnfAig, -pCnfFrames->nVars ); - Cnf_DataLift( pCnfInter, -pCnfFrames->nVars -pCnfAig->nVars ); - return pSat; -} - -/**Function************************************************************* - - Synopsis [Performs one SAT run with interpolation.] - - Description [Returns 1 if proven. 0 if failed. -1 if undecided.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Inter_ManPerformOneStep( Inter_Man_t * p, int fUseBias, int fUseBackward, int nTimeNewOut ) -{ - sat_solver * pSat; - void * pSatCnf = NULL; - Inta_Man_t * pManInterA; -// Intb_Man_t * pManInterB; - int * pGlobalVars; - int clk, status, RetValue; - int i, Var; -// assert( p->pInterNew == NULL ); - - // derive the SAT solver - pSat = Inter_ManDeriveSatSolver( p->pInter, p->pCnfInter, p->pAigTrans, p->pCnfAig, p->pFrames, p->pCnfFrames, p->vVarsAB, fUseBackward ); - if ( pSat == NULL ) - { - p->pInterNew = NULL; - return 1; - } - - // set runtime limit - if ( nTimeNewOut ) - sat_solver_set_runtime_limit( pSat, nTimeNewOut ); - - // collect global variables - pGlobalVars = ABC_CALLOC( int, sat_solver_nvars(pSat) ); - Vec_IntForEachEntry( p->vVarsAB, Var, i ) - pGlobalVars[Var] = 1; - pSat->pGlobalVars = fUseBias? pGlobalVars : NULL; - - // solve the problem -clk = clock(); - status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)p->nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); - p->nConfCur = pSat->stats.conflicts; -p->timeSat += clock() - clk; - - pSat->pGlobalVars = NULL; - ABC_FREE( pGlobalVars ); - if ( status == l_False ) - { - pSatCnf = sat_solver_store_release( pSat ); - RetValue = 1; - } - else if ( status == l_True ) - { - RetValue = 0; - } - else - { - RetValue = -1; - } - sat_solver_delete( pSat ); - if ( pSatCnf == NULL ) - return RetValue; - - // create the resulting manager -clk = clock(); -/* - if ( !fUseIp ) - { - pManInterA = Inta_ManAlloc(); - p->pInterNew = Inta_ManInterpolate( pManInterA, pSatCnf, p->vVarsAB, 0 ); - Inta_ManFree( pManInterA ); - } - else - { - Aig_Man_t * pInterNew2; - int RetValue; - - pManInterA = Inta_ManAlloc(); - p->pInterNew = Inta_ManInterpolate( pManInterA, pSatCnf, p->vVarsAB, 0 ); -// Inter_ManVerifyInterpolant1( pManInterA, pSatCnf, p->pInterNew ); - Inta_ManFree( pManInterA ); - - pManInterB = Intb_ManAlloc(); - pInterNew2 = Intb_ManInterpolate( pManInterB, pSatCnf, p->vVarsAB, 0 ); - Inter_ManVerifyInterpolant2( pManInterB, pSatCnf, pInterNew2 ); - Intb_ManFree( pManInterB ); - - // check relationship - RetValue = Inter_ManCheckEquivalence( pInterNew2, p->pInterNew ); - if ( RetValue ) - printf( "Equivalence \"Ip == Im\" holds\n" ); - else - { -// printf( "Equivalence \"Ip == Im\" does not hold\n" ); - RetValue = Inter_ManCheckContainment( pInterNew2, p->pInterNew ); - if ( RetValue ) - printf( "Containment \"Ip -> Im\" holds\n" ); - else - printf( "Containment \"Ip -> Im\" does not hold\n" ); - - RetValue = Inter_ManCheckContainment( p->pInterNew, pInterNew2 ); - if ( RetValue ) - printf( "Containment \"Im -> Ip\" holds\n" ); - else - printf( "Containment \"Im -> Ip\" does not hold\n" ); - } - - Aig_ManStop( pInterNew2 ); - } -*/ - - pManInterA = Inta_ManAlloc(); - p->pInterNew = (Aig_Man_t *)Inta_ManInterpolate( pManInterA, (Sto_Man_t *)pSatCnf, p->vVarsAB, 0 ); - Inta_ManFree( pManInterA ); - -p->timeInt += clock() - clk; - Sto_ManFree( (Sto_Man_t *)pSatCnf ); - return RetValue; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/int/intM114p.c b/src/aig/int/intM114p.c deleted file mode 100644 index 0ad0552f..00000000 --- a/src/aig/int/intM114p.c +++ /dev/null @@ -1,442 +0,0 @@ -/**CFile**************************************************************** - - FileName [intM114p.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Interpolation engine.] - - Synopsis [Intepolation using interfaced to MiniSat-1.14p.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 24, 2008.] - - Revision [$Id: intM114p.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "intInt.h" -#include "m114p.h" - -#ifdef ABC_USE_LIBRARIES - -ABC_NAMESPACE_IMPL_START - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns the SAT solver for one interpolation run.] - - Description [pInter is the previous interpolant. pAig is one time frame. - pFrames is the unrolled time frames.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -M114p_Solver_t Inter_ManDeriveSatSolverM114p( - Aig_Man_t * pInter, Cnf_Dat_t * pCnfInter, - Aig_Man_t * pAig, Cnf_Dat_t * pCnfAig, - Aig_Man_t * pFrames, Cnf_Dat_t * pCnfFrames, - Vec_Int_t ** pvMapRoots, Vec_Int_t ** pvMapVars ) -{ - M114p_Solver_t pSat; - Aig_Obj_t * pObj, * pObj2; - int i, Lits[2]; - - // sanity checks - assert( Aig_ManRegNum(pInter) == 0 ); - assert( Aig_ManRegNum(pAig) > 0 ); - assert( Aig_ManRegNum(pFrames) == 0 ); - assert( Aig_ManPoNum(pInter) == 1 ); - assert( Aig_ManPoNum(pFrames) == 1 ); - assert( Aig_ManPiNum(pInter) == Aig_ManRegNum(pAig) ); -// assert( (Aig_ManPiNum(pFrames) - Aig_ManRegNum(pAig)) % Saig_ManPiNum(pAig) == 0 ); - - // prepare CNFs - Cnf_DataLift( pCnfAig, pCnfFrames->nVars ); - Cnf_DataLift( pCnfInter, pCnfFrames->nVars + pCnfAig->nVars ); - - *pvMapRoots = Vec_IntAlloc( 10000 ); - *pvMapVars = Vec_IntAlloc( 0 ); - Vec_IntFill( *pvMapVars, pCnfInter->nVars + pCnfAig->nVars + pCnfFrames->nVars, -1 ); - for ( i = 0; i < pCnfFrames->nVars; i++ ) - Vec_IntWriteEntry( *pvMapVars, i, -2 ); - - // start the solver - pSat = M114p_SolverNew( 1 ); - M114p_SolverSetVarNum( pSat, pCnfInter->nVars + pCnfAig->nVars + pCnfFrames->nVars ); - - // add clauses of A - // interpolant - for ( i = 0; i < pCnfInter->nClauses; i++ ) - { - Vec_IntPush( *pvMapRoots, 0 ); - if ( !M114p_SolverAddClause( pSat, pCnfInter->pClauses[i], pCnfInter->pClauses[i+1] ) ) - assert( 0 ); - } - // connector clauses - Aig_ManForEachPi( pInter, pObj, i ) - { - pObj2 = Saig_ManLo( pAig, i ); - Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 0 ); - Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 ); - Vec_IntPush( *pvMapRoots, 0 ); - if ( !M114p_SolverAddClause( pSat, Lits, Lits+2 ) ) - assert( 0 ); - Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 1 ); - Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 ); - Vec_IntPush( *pvMapRoots, 0 ); - if ( !M114p_SolverAddClause( pSat, Lits, Lits+2 ) ) - assert( 0 ); - } - // one timeframe - for ( i = 0; i < pCnfAig->nClauses; i++ ) - { - Vec_IntPush( *pvMapRoots, 0 ); - if ( !M114p_SolverAddClause( pSat, pCnfAig->pClauses[i], pCnfAig->pClauses[i+1] ) ) - assert( 0 ); - } - // connector clauses - Aig_ManForEachPi( pFrames, pObj, i ) - { - if ( i == Aig_ManRegNum(pAig) ) - break; -// Vec_IntPush( vVarsAB, pCnfFrames->pVarNums[pObj->Id] ); - Vec_IntWriteEntry( *pvMapVars, pCnfFrames->pVarNums[pObj->Id], i ); - - pObj2 = Saig_ManLi( pAig, i ); - Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 0 ); - Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 ); - Vec_IntPush( *pvMapRoots, 0 ); - if ( !M114p_SolverAddClause( pSat, Lits, Lits+2 ) ) - assert( 0 ); - Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 1 ); - Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 ); - Vec_IntPush( *pvMapRoots, 0 ); - if ( !M114p_SolverAddClause( pSat, Lits, Lits+2 ) ) - assert( 0 ); - } - // add clauses of B - for ( i = 0; i < pCnfFrames->nClauses; i++ ) - { - Vec_IntPush( *pvMapRoots, 1 ); - if ( !M114p_SolverAddClause( pSat, pCnfFrames->pClauses[i], pCnfFrames->pClauses[i+1] ) ) - { -// assert( 0 ); - break; - } - } - // return clauses to the original state - Cnf_DataLift( pCnfAig, -pCnfFrames->nVars ); - Cnf_DataLift( pCnfInter, -pCnfFrames->nVars -pCnfAig->nVars ); - return pSat; -} - - -/**Function************************************************************* - - Synopsis [Performs one resolution step.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Inter_ManResolveM114p( Vec_Int_t * vResolvent, int * pLits, int nLits, int iVar ) -{ - int i, k, iLit = -1, fFound = 0; - // find the variable in the clause - for ( i = 0; i < vResolvent->nSize; i++ ) - if ( lit_var(vResolvent->pArray[i]) == iVar ) - { - iLit = vResolvent->pArray[i]; - vResolvent->pArray[i] = vResolvent->pArray[--vResolvent->nSize]; - break; - } - assert( iLit != -1 ); - // add other variables - for ( i = 0; i < nLits; i++ ) - { - if ( lit_var(pLits[i]) == iVar ) - { - assert( iLit == lit_neg(pLits[i]) ); - fFound = 1; - continue; - } - // check if this literal appears - for ( k = 0; k < vResolvent->nSize; k++ ) - if ( vResolvent->pArray[k] == pLits[i] ) - break; - if ( k < vResolvent->nSize ) - continue; - // add this literal - Vec_IntPush( vResolvent, pLits[i] ); - } - assert( fFound ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Computes interpolant using MiniSat-1.14p.] - - Description [Assumes that the solver returned UNSAT and proof - logging was enabled. Array vMapRoots maps number of each root clause - into 0 (clause of A) or 1 (clause of B). Array vMapVars maps each SAT - solver variable into -1 (var of A), -2 (var of B), and (var of C), - where is the var's 0-based number in the ordering of C variables.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Inter_ManInterpolateM114pPudlak( M114p_Solver_t s, Vec_Int_t * vMapRoots, Vec_Int_t * vMapVars ) -{ - Aig_Man_t * p; - Aig_Obj_t * pInter, * pInter2, * pVar; - Vec_Ptr_t * vInters; - Vec_Int_t * vLiterals, * vClauses, * vResolvent; - int * pLitsNext, nLitsNext, nOffset, iLit; - int * pLits, * pClauses, * pVars; - int nLits, nVars, i, k, v, iVar; - assert( M114p_SolverProofIsReady(s) ); - vInters = Vec_PtrAlloc( 1000 ); - - vLiterals = Vec_IntAlloc( 10000 ); - vClauses = Vec_IntAlloc( 1000 ); - vResolvent = Vec_IntAlloc( 100 ); - - // create elementary variables - p = Aig_ManStart( 10000 ); - Vec_IntForEachEntry( vMapVars, iVar, i ) - if ( iVar >= 0 ) - Aig_IthVar(p, iVar); - // process root clauses - M114p_SolverForEachRoot( s, &pLits, nLits, i ) - { - if ( Vec_IntEntry(vMapRoots, i) == 1 ) // clause of B - pInter = Aig_ManConst1(p); - else // clause of A - pInter = Aig_ManConst0(p); - Vec_PtrPush( vInters, pInter ); - - // save the root clause - Vec_IntPush( vClauses, Vec_IntSize(vLiterals) ); - Vec_IntPush( vLiterals, nLits ); - for ( v = 0; v < nLits; v++ ) - Vec_IntPush( vLiterals, pLits[v] ); - } - assert( Vec_PtrSize(vInters) == Vec_IntSize(vMapRoots) ); - - // process learned clauses - M114p_SolverForEachChain( s, &pClauses, &pVars, nVars, i ) - { - pInter = Vec_PtrEntry( vInters, pClauses[0] ); - - // initialize the resolvent - nOffset = Vec_IntEntry( vClauses, pClauses[0] ); - nLitsNext = Vec_IntEntry( vLiterals, nOffset ); - pLitsNext = Vec_IntArray(vLiterals) + nOffset + 1; - Vec_IntClear( vResolvent ); - for ( v = 0; v < nLitsNext; v++ ) - Vec_IntPush( vResolvent, pLitsNext[v] ); - - for ( k = 0; k < nVars; k++ ) - { - iVar = Vec_IntEntry( vMapVars, pVars[k] ); - pInter2 = Vec_PtrEntry( vInters, pClauses[k+1] ); - - // resolve it with the next clause - nOffset = Vec_IntEntry( vClauses, pClauses[k+1] ); - nLitsNext = Vec_IntEntry( vLiterals, nOffset ); - pLitsNext = Vec_IntArray(vLiterals) + nOffset + 1; - Inter_ManResolveM114p( vResolvent, pLitsNext, nLitsNext, pVars[k] ); - - if ( iVar == -1 ) // var of A - pInter = Aig_Or( p, pInter, pInter2 ); - else if ( iVar == -2 ) // var of B - pInter = Aig_And( p, pInter, pInter2 ); - else // var of C - { - // check polarity of the pivot variable in the clause - for ( v = 0; v < nLitsNext; v++ ) - if ( lit_var(pLitsNext[v]) == pVars[k] ) - break; - assert( v < nLitsNext ); - pVar = Aig_NotCond( Aig_IthVar(p, iVar), lit_sign(pLitsNext[v]) ); - pInter = Aig_Mux( p, pVar, pInter, pInter2 ); - } - } - Vec_PtrPush( vInters, pInter ); - - // store the resulting clause - Vec_IntPush( vClauses, Vec_IntSize(vLiterals) ); - Vec_IntPush( vLiterals, Vec_IntSize(vResolvent) ); - Vec_IntForEachEntry( vResolvent, iLit, v ) - Vec_IntPush( vLiterals, iLit ); - } - assert( Vec_PtrSize(vInters) == M114p_SolverProofClauseNum(s) ); - assert( Vec_IntSize(vResolvent) == 0 ); // the empty clause - Vec_PtrFree( vInters ); - Vec_IntFree( vLiterals ); - Vec_IntFree( vClauses ); - Vec_IntFree( vResolvent ); - Aig_ObjCreatePo( p, pInter ); - Aig_ManCleanup( p ); - return p; -} - - -/**Function************************************************************* - - Synopsis [Computes interpolant using MiniSat-1.14p.] - - Description [Assumes that the solver returned UNSAT and proof - logging was enabled. Array vMapRoots maps number of each root clause - into 0 (clause of A) or 1 (clause of B). Array vMapVars maps each SAT - solver variable into -1 (var of A), -2 (var of B), and (var of C), - where is the var's 0-based number in the ordering of C variables.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Inter_ManpInterpolateM114( M114p_Solver_t s, Vec_Int_t * vMapRoots, Vec_Int_t * vMapVars ) -{ - Aig_Man_t * p; - Aig_Obj_t * pInter, * pInter2, * pVar; - Vec_Ptr_t * vInters; - int * pLits, * pClauses, * pVars; - int nLits, nVars, i, k, iVar; - int nClauses; - - nClauses = M114p_SolverProofClauseNum(s); - - assert( M114p_SolverProofIsReady(s) ); - - vInters = Vec_PtrAlloc( 1000 ); - // process root clauses - p = Aig_ManStart( 10000 ); - M114p_SolverForEachRoot( s, &pLits, nLits, i ) - { - if ( Vec_IntEntry(vMapRoots, i) == 1 ) // clause of B - pInter = Aig_ManConst1(p); - else // clause of A - { - pInter = Aig_ManConst0(p); - for ( k = 0; k < nLits; k++ ) - { - iVar = Vec_IntEntry( vMapVars, lit_var(pLits[k]) ); - if ( iVar < 0 ) // var of A or B - continue; - // this is a variable of C - pVar = Aig_NotCond( Aig_IthVar(p, iVar), lit_sign(pLits[k]) ); - pInter = Aig_Or( p, pInter, pVar ); - } - } - Vec_PtrPush( vInters, pInter ); - } -// assert( Vec_PtrSize(vInters) == Vec_IntSize(vMapRoots) ); - - // process learned clauses - M114p_SolverForEachChain( s, &pClauses, &pVars, nVars, i ) - { - pInter = Vec_PtrEntry( vInters, pClauses[0] ); - for ( k = 0; k < nVars; k++ ) - { - iVar = Vec_IntEntry( vMapVars, pVars[k] ); - pInter2 = Vec_PtrEntry( vInters, pClauses[k+1] ); - if ( iVar == -1 ) // var of A - pInter = Aig_Or( p, pInter, pInter2 ); - else // var of B or C - pInter = Aig_And( p, pInter, pInter2 ); - } - Vec_PtrPush( vInters, pInter ); - } - - assert( Vec_PtrSize(vInters) == M114p_SolverProofClauseNum(s) ); - Vec_PtrFree( vInters ); - Aig_ObjCreatePo( p, pInter ); - Aig_ManCleanup( p ); - assert( Aig_ManCheck(p) ); - return p; -} - - -/**Function************************************************************* - - Synopsis [Performs one SAT run with interpolation.] - - Description [Returns 1 if proven. 0 if failed. -1 if undecided.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Inter_ManPerformOneStepM114p( Inter_Man_t * p, int fUsePudlak, int fUseOther ) -{ - M114p_Solver_t pSat; - Vec_Int_t * vMapRoots, * vMapVars; - int clk, status, RetValue; - assert( p->pInterNew == NULL ); - // derive the SAT solver - pSat = Inter_ManDeriveSatSolverM114p( p->pInter, p->pCnfInter, - p->pAigTrans, p->pCnfAig, p->pFrames, p->pCnfFrames, - &vMapRoots, &vMapVars ); - // solve the problem -clk = clock(); - status = M114p_SolverSolve( pSat, NULL, NULL, 0 ); - p->nConfCur = M114p_SolverGetConflictNum( pSat ); -p->timeSat += clock() - clk; - if ( status == 0 ) - { - RetValue = 1; -// Inter_ManpInterpolateM114Report( pSat, vMapRoots, vMapVars ); - -clk = clock(); - if ( fUsePudlak ) - p->pInterNew = Inter_ManInterpolateM114pPudlak( pSat, vMapRoots, vMapVars ); - else - p->pInterNew = Inter_ManpInterpolateM114( pSat, vMapRoots, vMapVars ); -p->timeInt += clock() - clk; - } - else if ( status == 1 ) - { - RetValue = 0; - } - else - { - RetValue = -1; - } - M114p_SolverDelete( pSat ); - Vec_IntFree( vMapRoots ); - Vec_IntFree( vMapVars ); - return RetValue; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - -ABC_NAMESPACE_IMPL_END - -#endif - - diff --git a/src/aig/int/intMan.c b/src/aig/int/intMan.c deleted file mode 100644 index d6219f6b..00000000 --- a/src/aig/int/intMan.c +++ /dev/null @@ -1,163 +0,0 @@ -/**CFile**************************************************************** - - FileName [intMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Interpolation engine.] - - Synopsis [Interpolation manager procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 24, 2008.] - - Revision [$Id: intMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "intInt.h" -#include "ioa.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates the interpolation manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Inter_Man_t * Inter_ManCreate( Aig_Man_t * pAig, Inter_ManParams_t * pPars ) -{ - Inter_Man_t * p; - // create interpolation manager - p = ABC_ALLOC( Inter_Man_t, 1 ); - memset( p, 0, sizeof(Inter_Man_t) ); - p->vVarsAB = Vec_IntAlloc( Aig_ManRegNum(pAig) ); - p->nConfLimit = pPars->nBTLimit; - p->fVerbose = pPars->fVerbose; - p->pAig = pAig; - if ( pPars->fDropInvar ) - p->vInters = Vec_PtrAlloc( 100 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Cleans the interpolation manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Inter_ManClean( Inter_Man_t * p ) -{ - if ( p->vInters ) - { - Aig_Man_t * pMan; - int i; - Vec_PtrForEachEntry( Aig_Man_t *, p->vInters, pMan, i ) - Aig_ManStop( pMan ); - Vec_PtrClear( p->vInters ); - } - if ( p->pCnfInter ) - Cnf_DataFree( p->pCnfInter ); - if ( p->pCnfFrames ) - Cnf_DataFree( p->pCnfFrames ); - if ( p->pInter ) - Aig_ManStop( p->pInter ); - if ( p->pFrames ) - Aig_ManStop( p->pFrames ); -} - -/**Function************************************************************* - - Synopsis [Writes interpolant into a file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Inter_ManInterDump( Inter_Man_t * p, int fProved ) -{ - Aig_Man_t * pMan; - pMan = Aig_ManDupArray( p->vInters ); - Ioa_WriteAiger( pMan, "invar.aig", 0, 0 ); - Aig_ManStop( pMan ); - if ( fProved ) - printf( "Inductive invariant is dumped into file \"invar.aig\".\n" ); - else - printf( "Interpolants are dumped into file \"inter.aig\".\n" ); -} - -/**Function************************************************************* - - Synopsis [Frees the interpolation manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Inter_ManStop( Inter_Man_t * p, int fProved ) -{ - if ( p->fVerbose ) - { - p->timeOther = p->timeTotal-p->timeRwr-p->timeCnf-p->timeSat-p->timeInt-p->timeEqu; - printf( "Runtime statistics:\n" ); - ABC_PRTP( "Rewriting ", p->timeRwr, p->timeTotal ); - ABC_PRTP( "CNF mapping", p->timeCnf, p->timeTotal ); - ABC_PRTP( "SAT solving", p->timeSat, p->timeTotal ); - ABC_PRTP( "Interpol ", p->timeInt, p->timeTotal ); - ABC_PRTP( "Containment", p->timeEqu, p->timeTotal ); - ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); - ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); - } - - if ( p->vInters ) - Inter_ManInterDump( p, fProved ); - - if ( p->pCnfAig ) - Cnf_DataFree( p->pCnfAig ); - if ( p->pAigTrans ) - Aig_ManStop( p->pAigTrans ); - if ( p->pInterNew ) - Aig_ManStop( p->pInterNew ); - Inter_ManClean( p ); - Vec_PtrFreeP( &p->vInters ); - Vec_IntFreeP( &p->vVarsAB ); - ABC_FREE( p ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/int/intUtil.c b/src/aig/int/intUtil.c deleted file mode 100644 index ce48c37d..00000000 --- a/src/aig/int/intUtil.c +++ /dev/null @@ -1,108 +0,0 @@ -/**CFile**************************************************************** - - FileName [intUtil.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Interpolation engine.] - - Synopsis [Various interpolation utilities.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 24, 2008.] - - Revision [$Id: intUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "intInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - - -/**Function************************************************************* - - Synopsis [Returns 1 if the property fails in the initial state.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Inter_ManCheckInitialState( Aig_Man_t * p ) -{ - Cnf_Dat_t * pCnf; - Aig_Obj_t * pObj; - sat_solver * pSat; - int i, status; - int clk = clock(); - pCnf = Cnf_Derive( p, Saig_ManRegNum(p) ); - pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 1 ); - if ( pSat == NULL ) - { - Cnf_DataFree( pCnf ); - return 0; - } - status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); - ABC_PRT( "Time", clock() - clk ); - if ( status == l_True ) - { - p->pSeqModel = Abc_CexAlloc( Aig_ManRegNum(p), Saig_ManPiNum(p), 1 ); - Saig_ManForEachPi( p, pObj, i ) - if ( sat_solver_var_value( pSat, pCnf->pVarNums[Aig_ObjId(pObj)] ) ) - Aig_InfoSetBit( p->pSeqModel->pData, Aig_ManRegNum(p) + i ); - } - Cnf_DataFree( pCnf ); - sat_solver_delete( pSat ); - return status == l_True; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the property holds in all states.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Inter_ManCheckAllStates( Aig_Man_t * p ) -{ - Cnf_Dat_t * pCnf; - sat_solver * pSat; - int status; - int clk = clock(); - pCnf = Cnf_Derive( p, Saig_ManRegNum(p) ); - pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); - Cnf_DataFree( pCnf ); - if ( pSat == NULL ) - return 1; - status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); - sat_solver_delete( pSat ); - ABC_PRT( "Time", clock() - clk ); - return status == l_False; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/int/module.make b/src/aig/int/module.make deleted file mode 100644 index 8e0e4319..00000000 --- a/src/aig/int/module.make +++ /dev/null @@ -1,11 +0,0 @@ -SRC += src/aig/int/intCheck.c \ - src/aig/int/intContain.c \ - src/aig/int/intCore.c \ - src/aig/int/intCtrex.c \ - src/aig/int/intDup.c \ - src/aig/int/intFrames.c \ - src/aig/int/intInter.c \ - src/aig/int/intM114.c \ - src/aig/int/intM114p.c \ - src/aig/int/intMan.c \ - src/aig/int/intUtil.c diff --git a/src/aig/ioa/ioa.h b/src/aig/ioa/ioa.h index 46dbda09..b86bc13a 100644 --- a/src/aig/ioa/ioa.h +++ b/src/aig/ioa/ioa.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __IOA_H__ -#define __IOA_H__ +#ifndef ABC__aig__ioa__ioa_h +#define ABC__aig__ioa__ioa_h //////////////////////////////////////////////////////////////////////// @@ -32,9 +32,9 @@ #include #include -#include "vec.h" +#include "src/misc/vec/vec.h" //#include "bar.h" -#include "aig.h" +#include "src/aig/aig/aig.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// diff --git a/src/aig/ioa/ioaReadAig.c b/src/aig/ioa/ioaReadAig.c index 17c93e58..a1f09edf 100644 --- a/src/aig/ioa/ioaReadAig.c +++ b/src/aig/ioa/ioaReadAig.c @@ -392,7 +392,7 @@ Aig_Man_t * Ioa_ReadAigerFromMemory( char * pContents, int nFileSize, int fCheck pCur++; // read model name ABC_FREE( pNew->pName ); - pNew->pName = Aig_UtilStrsav( pCur ); + pNew->pName = Abc_UtilStrsav( pCur ); } } @@ -447,7 +447,7 @@ Aig_Man_t * Ioa_ReadAiger( char * pFileName, int fCheck ) if ( pNew ) { pName = Ioa_FileNameGeneric( pFileName ); - pNew->pName = Aig_UtilStrsav( pName ); + pNew->pName = Abc_UtilStrsav( pName ); // pNew->pSpec = Ioa_UtilStrsav( pFileName ); ABC_FREE( pName ); } diff --git a/src/aig/ioa/ioaUtil.c b/src/aig/ioa/ioaUtil.c index 06034956..a2748382 100644 --- a/src/aig/ioa/ioaUtil.c +++ b/src/aig/ioa/ioaUtil.c @@ -73,7 +73,7 @@ int Ioa_FileSize( char * pFileName ) char * Ioa_FileNameGeneric( char * FileName ) { char * pDot, * pRes; - pRes = Aig_UtilStrsav( FileName ); + pRes = Abc_UtilStrsav( FileName ); if ( (pDot = strrchr( pRes, '.' )) ) *pDot = 0; return pRes; diff --git a/src/aig/ivy/attr.h b/src/aig/ivy/attr.h index b65906cf..07586832 100644 --- a/src/aig/ivy/attr.h +++ b/src/aig/ivy/attr.h @@ -18,15 +18,15 @@ ***********************************************************************/ -#ifndef __ATTR_H__ -#define __ATTR_H__ +#ifndef ABC__aig__ivy__attr_h +#define ABC__aig__ivy__attr_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// -#include "extra.h" +#include "misc/extra/extra.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// diff --git a/src/aig/ivy/ivy.h b/src/aig/ivy/ivy.h index 870c0906..8d062134 100644 --- a/src/aig/ivy/ivy.h +++ b/src/aig/ivy/ivy.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __IVY_H__ -#define __IVY_H__ +#ifndef ABC__aig__ivy__ivy_h +#define ABC__aig__ivy__ivy_h //////////////////////////////////////////////////////////////////////// @@ -27,8 +27,8 @@ //////////////////////////////////////////////////////////////////////// #include -#include "extra.h" -#include "vec.h" +#include "src/misc/extra/extra.h" +#include "src/misc/vec/vec.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// diff --git a/src/aig/ivy/ivyFraig.c b/src/aig/ivy/ivyFraig.c index 7cf97132..2bc6f0de 100644 --- a/src/aig/ivy/ivyFraig.c +++ b/src/aig/ivy/ivyFraig.c @@ -18,8 +18,10 @@ ***********************************************************************/ -#include "satSolver.h" -#include "extra.h" +#include + +#include "src/sat/bsat/satSolver.h" +#include "src/misc/extra/extra.h" #include "ivy.h" ABC_NAMESPACE_IMPL_START @@ -2649,7 +2651,7 @@ p->timeTrav += clock() - clk; ABC_NAMESPACE_IMPL_END -#include "cuddInt.h" +#include "src/bdd/cudd/cuddInt.h" ABC_NAMESPACE_IMPL_START @@ -2807,7 +2809,7 @@ int Ivy_FraigNodesAreEquivBdd( Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2 ) ABC_NAMESPACE_IMPL_END -#include "aig.h" +#include "src/aig/aig/aig.h" ABC_NAMESPACE_IMPL_START diff --git a/src/aig/ivy/ivyRwr.c b/src/aig/ivy/ivyRwr.c index 4e79e87f..39131210 100644 --- a/src/aig/ivy/ivyRwr.c +++ b/src/aig/ivy/ivyRwr.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "ivy.h" -#include "deco.h" -#include "rwt.h" +#include "src/bool/deco/deco.h" +#include "src/opt/rwt/rwt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/aig/ivy/ivySeq.c b/src/aig/ivy/ivySeq.c index 7f9674ac..283bf9fe 100644 --- a/src/aig/ivy/ivySeq.c +++ b/src/aig/ivy/ivySeq.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "ivy.h" -#include "deco.h" -#include "rwt.h" +#include "src/bool/deco/deco.h" +#include "src/opt/rwt/rwt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/aig/ivy/ivyTable.c b/src/aig/ivy/ivyTable.c index 0fe5c7ba..d2c1ab9a 100644 --- a/src/aig/ivy/ivyTable.c +++ b/src/aig/ivy/ivyTable.c @@ -212,7 +212,7 @@ clk = clock(); pTableOld = p->pTable; nTableSizeOld = p->nTableSize; // get the new table - p->nTableSize = Cudd_PrimeAig( 5 * Ivy_ManHashObjNum(p) ); + p->nTableSize = Abc_PrimeCudd( 5 * Ivy_ManHashObjNum(p) ); p->pTable = ABC_ALLOC( int, p->nTableSize ); memset( p->pTable, 0, sizeof(int) * p->nTableSize ); // rehash the entries from the old table @@ -261,41 +261,6 @@ void Ivy_TableProfile( Ivy_Man_t * p ) } } -/**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/kit/cloud.c b/src/aig/kit/cloud.c deleted file mode 100644 index fd372970..00000000 --- a/src/aig/kit/cloud.c +++ /dev/null @@ -1,992 +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" - -ABC_NAMESPACE_IMPL_START - - -// 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 = ABC_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 = ABC_CALLOC( CloudNode, dd->nNodesAlloc ); - dd->nMemUsed += sizeof(CloudNode) * dd->nNodesAlloc; -clk2 = clock(); -//ABC_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 = NULL; - dd->tUnique[0].t = NULL; - 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 = ABC_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; - ABC_FREE( dd->ppNodes ); - ABC_FREE( dd->tUnique ); - ABC_FREE( dd->vars ); - for ( i = 0; i < 4; i++ ) - ABC_FREE( dd->tCaches[i] ); - ABC_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 *)ABC_CALLOC( CloudCacheEntry1, nCacheEntries ); - dd->nMemUsed += sizeof(CloudCacheEntry1) * nCacheEntries; - } - else if ( CacheSize[oper] == 2 ) - { - dd->tCaches[oper] = (CloudCacheEntry2 *)ABC_CALLOC( CloudCacheEntry2, nCacheEntries ); - dd->nMemUsed += sizeof(CloudCacheEntry2) * nCacheEntries; - } - else if ( CacheSize[oper] == 3 ) - { - dd->tCaches[oper] = (CloudCacheEntry2 *)ABC_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 != NULL ) - 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 NULL; - } - // 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 != NULL ) - { - 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 == NULL ) - return NULL; - - if ( fnv <= gnv ) - e = cloudBddAnd( dd, fnv, gnv ); - else - e = cloudBddAnd( dd, gnv, fnv ); - - if ( e == NULL ) - return NULL; - - if ( t == e ) - r = t; - else - { - if ( Cloud_IsComplement(t) ) - { - r = cloudMakeNode( dd, var, Cloud_Not(t), Cloud_Not(e) ); - if ( r == NULL ) - return NULL; - r = Cloud_Not(r); - } - else - { - r = cloudMakeNode( dd, var, t, e ); - if ( r == NULL ) - return NULL; - } - } - 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) == NULL || Cloud_Regular(g) == NULL ) - return NULL; - 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) == NULL || Cloud_Regular(g) == NULL ) - return NULL; - 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 != NULL ); - 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) == NULL || Cloud_Regular(g) == NULL ) - return NULL; - 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 == NULL ) - return NULL; - t1 = cloudBddAnd_gate( dd, Cloud_Not(f), g ); - if ( t1 == NULL ) - return NULL; - 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 = ABC_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 == NULL ) - break; - } - ABC_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 = ABC_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++; - } - - ABC_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 = ABC_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 == NULL ) - return NULL; - - 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 == NULL ) - return NULL; - 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 == NULL || 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 /// -//////////////////////////////////////////////////////////////////////// - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/kit/cloud.h b/src/aig/kit/cloud.h deleted file mode 100644 index c48b55de..00000000 --- a/src/aig/kit/cloud.h +++ /dev/null @@ -1,255 +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__ - - -#include -#include -#include -#include - -#include "abc_global.h" - - - -ABC_NAMESPACE_HEADER_START - - -#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_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)(ABC_PTRUINT_T)(f) * DD_P1 + (unsigned)(ABC_PTRUINT_T)(g)) * DD_P2) >> (s)) -#define cloudHashCudd3(f,g,h,s) (((((unsigned)(ABC_PTRUINT_T)(f) * DD_P1 + (unsigned)(ABC_PTRUINT_T)(g)) * DD_P2 + (unsigned)(ABC_PTRUINT_T)(h)) * DD_P3) >> (s)) - -// node complementation (using node) -#define Cloud_Regular(p) ((CloudNode*)(((ABC_PTRUINT_T)(p)) & ~01)) // get the regular node (w/o bubble) -#define Cloud_Not(p) ((CloudNode*)(((ABC_PTRUINT_T)(p)) ^ 01)) // complement the node -#define Cloud_NotCond(p,c) ((CloudNode*)(((ABC_PTRUINT_T)(p)) ^ (c))) // complement the node conditionally -#define Cloud_IsComplement(p) ((int)(((ABC_PTRUINT_T)(p)) & 01)) // 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): (0)) -#define cloudCacheLookup2(p,sign,f,g) (((p)->s == (sign) && (p)->a == (f) && (p)->b == (g))? ((p)->r): (0)) -#define cloudCacheLookup3(p,sign,f,g,h) (((p)->s == (sign) && (p)->a == (f) && (p)->b == (g) && (p)->c == (h))? ((p)->r): (0)) -// 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) - -//////////////////////////////////////////////////////////////////////// -/// 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 ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/aig/kit/kit.h b/src/aig/kit/kit.h deleted file mode 100644 index 9e15e994..00000000 --- a/src/aig/kit/kit.h +++ /dev/null @@ -1,655 +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__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include -#include "vec.h" -#include "extra.h" -#include "cloud.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 < (int)(pObj)->nFans) && ((iLit) = (pObj)->pFans[i], 1); i++ ) -#define Kit_DsdObjForEachFaninReverse( pNtk, pObj, iLit, i ) \ - for ( i = (int)(pObj)->nFans - 1; (i >= 0) && ((iLit) = (pObj)->pFans[i], 1); i-- ) - -#define Kit_PlaForEachCube( pSop, nFanins, pCube ) \ - for ( pCube = (pSop); *pCube; pCube += (nFanins) + 3 ) -#define Kit_PlaCubeForEachVar( pCube, Value, i ) \ - for ( i = 0; (pCube[i] != ' ') && (Value = pCube[i]); 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) - -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 unsigned Kit_EdgeToInt_( Kit_Edge_t m ) { union { Kit_Edge_t x; unsigned y; } v; v.x = m; return v.y; } -static inline Kit_Edge_t Kit_IntToEdge_( unsigned m ) { union { Kit_Edge_t x; unsigned y; } v; v.y = m; return v.x; } - -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_SuppIsMinBase( int Supp ) { return (Supp & (Supp+1)) == 0; } - -//static inline int Kit_Float2Int( float Val ) { return *((int *)&Val); } -//static inline float Kit_Int2Float( int Num ) { return *((float *)&Num); } -static inline int Kit_Float2Int( float Val ) { union { int x; float y; } v; v.y = Val; return v.x; } -static inline float Kit_Int2Float( int Num ) { union { int x; float y; } v; v.x = Num; return v.y; } -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_TruthIsEqualWithCare( unsigned * pIn0, unsigned * pIn1, unsigned * pCare, int nVars ) -{ - int w; - for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) - if ( (pIn0[w] & pCare[w]) != (pIn1[w] & pCare[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_TruthOrPhase( 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 void Kit_DsdPrintFromTruth2( FILE * pFile, unsigned * pTruth, int nVars ); -extern void Kit_DsdWriteFromTruth( char * pBuffer, 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 Kit_DsdObj_t * Kit_DsdNonDsdPrimeMax( 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 ); -/*=== kitPla.c ==========================================================*/ -extern int Kit_PlaIsConst0( char * pSop ); -extern int Kit_PlaIsConst1( char * pSop ); -extern int Kit_PlaIsBuf( char * pSop ); -extern int Kit_PlaIsInv( char * pSop ); -extern int Kit_PlaGetVarNum( char * pSop ); -extern int Kit_PlaGetCubeNum( char * pSop ); -extern int Kit_PlaIsComplement( char * pSop ); -extern void Kit_PlaComplement( char * pSop ); -extern char * Kit_PlaStart( void * p, int nCubes, int nVars ); -extern char * Kit_PlaCreateFromIsop( void * p, int nVars, Vec_Int_t * vCover ); -extern void Kit_PlaToIsop( char * pSop, Vec_Int_t * vCover ); -extern char * Kit_PlaStoreSop( void * p, char * pSop ); -extern char * Kit_PlaFromTruth( void * p, unsigned * pTruth, int nVars, Vec_Int_t * vCover ); -extern char * Kit_PlaFromTruthNew( unsigned * pTruth, int nVars, Vec_Int_t * vCover, Vec_Str_t * vStr ); -extern ABC_UINT64_T Kit_PlaToTruth6( char * pSop, int nVars ); -extern void Kit_PlaToTruth( char * pSop, int nVars, Vec_Ptr_t * vVars, unsigned * pTemp, unsigned * pTruth ); -/*=== 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_TruthPermute( unsigned * pOut, unsigned * pIn, int nVars, char * pPerm, 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 int Kit_TruthVarIsVacuous( unsigned * pOnset, unsigned * pOffset, 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_TruthVarsSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1, unsigned * pCof0, unsigned * pCof1 ); -extern int Kit_TruthVarsAntiSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1, unsigned * pCof0, unsigned * pCof1 ); -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_TruthCountOnesInCofs0( 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 ); -extern void Kit_TruthPrintProfile( unsigned * pTruth, int nVars ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/kit/kitAig.c b/src/aig/kit/kitAig.c deleted file mode 100644 index 88f17fc2..00000000 --- a/src/aig/kit/kitAig.c +++ /dev/null @@ -1,126 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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( (Aig_Obj_t *)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( (Aig_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); - pAnd1 = Aig_NotCond( (Aig_Obj_t *)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( (Aig_Obj_t *)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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/kit/kitBdd.c b/src/aig/kit/kitBdd.c deleted file mode 100644 index 1b24ac24..00000000 --- a/src/aig/kit/kitBdd.c +++ /dev/null @@ -1,236 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 = NULL; // Suppress "might be used uninitialized" - 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( (DdNode *)pNode->pFunc ); - } - - // deref the intermediate results - bFunc = (DdNode *)pNode->pFunc; Cudd_Ref( bFunc ); - Kit_GraphForEachNode( pGraph, pNode, i ) - Cudd_RecursiveDeref( dd, (DdNode *)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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/kit/kitCloud.c b/src/aig/kit/kitCloud.c deleted file mode 100644 index dea56749..00000000 --- a/src/aig/kit/kitCloud.c +++ /dev/null @@ -1,378 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 -}; - -static inline int Kit_Mux2Int( Kit_Mux_t m ) { union { Kit_Mux_t x; int y; } v; v.x = m; return v.y; } -static inline Kit_Mux_t Kit_Int2Mux( int m ) { union { Kit_Mux_t x; int y; } v; v.y = m; return v.x; } - -//////////////////////////////////////////////////////////////////////// -/// 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, Kit_Mux2Int(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 = (unsigned *)Vec_PtrEntry( vStore, 0 ); - Kit_TruthFill( pThis, nVars ); - Vec_IntForEachEntryStart( vNodes, Entry, i, 1 ) - { - Mux = Kit_Int2Mux(Entry); - assert( (int)Mux.e < i && (int)Mux.t < i && (int)Mux.v < nVars ); - pFan0 = (unsigned *)Vec_PtrEntry( vStore, Mux.e ); - pFan1 = (unsigned *)Vec_PtrEntry( vStore, Mux.t ); - pThis = (unsigned *)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 = (unsigned *)Vec_PtrEntry( vStore, 0 ); - Kit_TruthFill( pThis, nVarsAll ); - Vec_IntForEachEntryStart( vNodes, Entry, i, 1 ) - { - Mux = Kit_Int2Mux(Entry); - pFan0 = (unsigned *)Vec_PtrEntry( vStore, Mux.e ); - pFan1 = (unsigned *)Vec_PtrEntry( vStore, Mux.t ); - pThis = (unsigned *)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; - unsigned * pThis = NULL; // Suppress "might be used uninitialized" - unsigned * 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 = (unsigned *)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_Int2Mux(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<nVarsMax = nVarsMax; - p->nWordsMax = Kit_TruthWordNum( p->nVarsMax ); - p->vTruthVars = Vec_PtrAllocTruthTables( p->nVarsMax ); - p->vTruthNodes = Vec_PtrAllocSimInfo( 64, p->nWordsMax ); - p->vLutsIn = Vec_IntAlloc( 50 ); - p->vSuppIn = Vec_IntAlloc( 50 ); - p->vLutsOut = Vec_IntAlloc( 50 ); - p->vSuppOut = Vec_IntAlloc( 50 ); - p->pTruthIn = ABC_ALLOC( unsigned, p->nWordsMax ); - p->pTruthOut = ABC_ALLOC( unsigned, p->nWordsMax ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops Decmetry manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_ManDecStop( Kit_ManDec_t * p ) -{ - ABC_FREE( p->pTruthIn ); - ABC_FREE( p->pTruthOut ); - Vec_IntFreeP( &p->vLutsIn ); - Vec_IntFreeP( &p->vSuppIn ); - Vec_IntFreeP( &p->vLutsOut ); - Vec_IntFreeP( &p->vSuppOut ); - Vec_PtrFreeP( &p->vTruthVars ); - Vec_PtrFreeP( &p->vTruthNodes ); - ABC_FREE( p ); -} - - -/**Function************************************************************* - - Synopsis [Deriving timing information for the decomposed structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_DecComputeOuputArrival( int nVars, Vec_Int_t * vSupps, int LutSize, char ATimesIn[], char ATimesOut[] ) -{ - int i, v, iVar, nLuts, Delay; - nLuts = Vec_IntSize(vSupps) / LutSize; - assert( nLuts > 0 ); - assert( Vec_IntSize(vSupps) % LutSize == 0 ); - for ( v = 0; v < nVars; v++ ) - ATimesOut[v] = ATimesIn[v]; - for ( v = 0; v < nLuts; v++ ) - { - Delay = 0; - for ( i = 0; i < LutSize; i++ ) - { - iVar = Vec_IntEntry( vSupps, v * LutSize + i ); - assert( iVar < nVars + v ); - Delay = ABC_MAX( Delay, ATimesOut[iVar] ); - } - ATimesOut[nVars + v] = Delay + 1; - } - return ATimesOut[nVars + nLuts - 1]; -} - -/**Function************************************************************* - - Synopsis [Derives the truth table] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_DecComputeTruthOne( int LutSize, unsigned * pTruthLut, int nVars, unsigned * pTruths[], unsigned * pTemp, unsigned * pRes ) -{ - int i, v; - Kit_TruthClear( pRes, nVars ); - for ( i = 0; i < (1< 0 ); - assert( Vec_IntSize(vSupps) % LutSize == 0 ); - assert( nLuts * nTruthLutWords == Vec_IntSize(vLuts) ); - for ( v = 0; v < nLuts; v++ ) - { - for ( i = 0; i < LutSize; i++ ) - { - iVar = Vec_IntEntry( vSupps, v * LutSize + i ); - assert( iVar < nVars + v ); - pTruths[i] = (iVar < nVars)? Vec_PtrEntry(p->vTruthVars, iVar) : Vec_PtrEntry(p->vTruthNodes, iVar-nVars); - } - pResult = (v == nLuts - 1) ? pRes : Vec_PtrEntry(p->vTruthNodes, v); - Kit_DecComputeTruthOne( LutSize, pTruthLuts, nVars, pTruths, Vec_PtrEntry(p->vTruthNodes, v+1), pResult ); - pTruthLuts += nTruthLutWords; - } -} - -/**Function************************************************************* - - Synopsis [Derives the truth table] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_DecComputePattern( int nVars, unsigned * pTruth, int LutSize, int Pattern[] ) -{ - int nCofs = (1 << LutSize); - int i, k, nMyu = 0; - assert( LutSize <= 6 ); - assert( LutSize < nVars ); - if ( nVars - LutSize <= 5 ) - { - unsigned uCofs[64]; - int nBits = (1 << (nVars - LutSize)); - for ( i = 0; i < nCofs; i++ ) - uCofs[i] = (pTruth[(i*nBits)/32] >> ((i*nBits)%32)) & ((1<= 0 && Shared1[m] >= 0 && Shared0[u] == Shared1[m] ) - { - Shared[nShared++] = Shared0[u]; - Shared0[u] = Shared1[m] = -1; - } - return nShared; - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Returns the number of shared variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_DecComputeShared( int Pattern[], int LutSize, int Shared[] ) -{ - int i, Vars[6]; - assert( LutSize <= 6 ); - for ( i = 0; i < LutSize; i++ ) - Vars[i] = i; - return Kit_DecComputeShared_rec( Pattern, Vars, LutSize, Shared, 0 ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/kit/kitDsd.c b/src/aig/kit/kitDsd.c deleted file mode 100644 index dffbe315..00000000 --- a/src/aig/kit/kitDsd.c +++ /dev/null @@ -1,3200 +0,0 @@ -/**CFile**************************************************************** - - FileName [kitDsd.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Computation kit.] - - Synopsis [Performs disjoint-support decomposition based on truth tables.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - Dec 6, 2006.] - - Revision [$Id: kitDsd.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "kit.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates the DSD manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Kit_DsdMan_t * Kit_DsdManAlloc( int nVars, int nNodes ) -{ - Kit_DsdMan_t * p; - p = ABC_ALLOC( Kit_DsdMan_t, 1 ); - memset( p, 0, sizeof(Kit_DsdMan_t) ); - p->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 ); - ABC_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 *)ABC_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 = ABC_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 ) -{ - ABC_FREE( pObj ); -} - -/**Function************************************************************* - - Synopsis [Allocates the DSD network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Kit_DsdNtk_t * Kit_DsdNtkAlloc( int nVars ) -{ - Kit_DsdNtk_t * pNtk; - pNtk = ABC_ALLOC( Kit_DsdNtk_t, 1 ); - memset( pNtk, 0, sizeof(Kit_DsdNtk_t) ); - pNtk->pNodes = ABC_ALLOC( Kit_DsdObj_t *, nVars+1 ); - pNtk->nVars = nVars; - pNtk->nNodesAlloc = nVars+1; - pNtk->pMem = ABC_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 ) - ABC_FREE( pObj ); - ABC_FREE( pNtk->pSupps ); - ABC_FREE( pNtk->pNodes ); - ABC_FREE( pNtk->pMem ); - ABC_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 [Prints the hex unsigned into a file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Kit_DsdWriteHex( char * pBuff, 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 ) - *pBuff++ = '0' + Digit; - else - *pBuff++ = 'A' + Digit-10; - } - return pBuff; -} - -/**Function************************************************************* - - Synopsis [Recursively print the DSD formula.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_DsdPrint2_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 ) - fprintf( pFile, "[" ); - else - fprintf( pFile, "(" ); - Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - { - if ( Kit_DsdLitIsCompl(iLit) ) - fprintf( pFile, "!" ); - Kit_DsdPrint2_rec( pFile, pNtk, Kit_DsdLit2Var(iLit) ); - if ( i < pObj->nFans - 1 ) - fprintf( pFile, "%c", Symbol ); - } - if ( pObj->Type == KIT_DSD_PRIME ) - fprintf( pFile, "]" ); - else - fprintf( pFile, ")" ); -} - -/**Function************************************************************* - - Synopsis [Print the DSD formula.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_DsdPrint2( FILE * pFile, Kit_DsdNtk_t * pNtk ) -{ -// fprintf( pFile, "F = " ); - if ( Kit_DsdLitIsCompl(pNtk->Root) ) - fprintf( pFile, "!" ); - Kit_DsdPrint2_rec( pFile, pNtk, Kit_DsdLit2Var(pNtk->Root) ); -// fprintf( pFile, "\n" ); -} - -/**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( pFile, 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 [Recursively print the DSD formula.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Kit_DsdWrite_rec( char * pBuff, 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 ); - *pBuff++ = 'a' + Id; - return pBuff; - } - - if ( pObj->Type == KIT_DSD_CONST1 ) - { - assert( pObj->nFans == 0 ); - sprintf( pBuff, "%s", "Const1" ); - return pBuff + strlen("Const1"); - } - - 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 ) - pBuff = Kit_DsdWriteHex( pBuff, Kit_DsdObjTruth(pObj), pObj->nFans ); - - *pBuff++ = '('; - Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - { - if ( Kit_DsdLitIsCompl(iLit) ) - *pBuff++ = '!'; - pBuff = Kit_DsdWrite_rec( pBuff, pNtk, Kit_DsdLit2Var(iLit) ); - if ( i < pObj->nFans - 1 ) - *pBuff++ = Symbol; - } - *pBuff++ = ')'; - return pBuff; -} - -/**Function************************************************************* - - Synopsis [Print the DSD formula.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_DsdWrite( char * pBuff, Kit_DsdNtk_t * pNtk ) -{ - if ( Kit_DsdLitIsCompl(pNtk->Root) ) - *pBuff++ = '!'; - pBuff = Kit_DsdWrite_rec( pBuff, pNtk, Kit_DsdLit2Var(pNtk->Root) ); - *pBuff = 0; -} - -/**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, * pTemp2; -// pTemp = Kit_DsdDecomposeMux( pTruth, nVars, 5 ); - pTemp = Kit_DsdDecomposeMux( pTruth, nVars, 8 ); -// Kit_DsdPrintExpanded( pTemp ); - pTemp2 = Kit_DsdExpand( pTemp ); - Kit_DsdPrint( stdout, pTemp2 ); - Kit_DsdVerify( pTemp2, pTruth, nVars ); - Kit_DsdNtkFree( pTemp2 ); - Kit_DsdNtkFree( pTemp ); -} - -/**Function************************************************************* - - Synopsis [Print the DSD formula.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_DsdPrintFromTruth2( FILE * pFile, unsigned * pTruth, int nVars ) -{ - Kit_DsdNtk_t * pTemp, * pTemp2; - pTemp = Kit_DsdDecomposeMux( pTruth, nVars, 0 ); - pTemp2 = Kit_DsdExpand( pTemp ); - Kit_DsdPrint2( pFile, pTemp2 ); - Kit_DsdVerify( pTemp2, pTruth, nVars ); - Kit_DsdNtkFree( pTemp2 ); - Kit_DsdNtkFree( pTemp ); -} - -/**Function************************************************************* - - Synopsis [Print the DSD formula.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_DsdWriteFromTruth( char * pBuffer, unsigned * pTruth, int nVars ) -{ - Kit_DsdNtk_t * pTemp, * pTemp2; -// pTemp = Kit_DsdDecomposeMux( pTruth, nVars, 5 ); - pTemp = Kit_DsdDecomposeMux( pTruth, nVars, 8 ); -// Kit_DsdPrintExpanded( pTemp ); - pTemp2 = Kit_DsdExpand( pTemp ); - Kit_DsdWrite( pBuffer, pTemp2 ); - Kit_DsdVerify( pTemp2, pTruth, nVars ); - Kit_DsdNtkFree( pTemp2 ); - 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 = (unsigned *)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 ); - } -*/ - Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - if ( Kit_DsdLitIsCompl(iLit) ) - Kit_TruthNot( pTruthFans[i], pTruthFans[i], pNtk->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( (unsigned *)Vec_PtrEntry(p->vTtNodes, i), (unsigned *)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 = (unsigned *)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 ); - } -*/ - Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - if ( Kit_DsdLitIsCompl(iLit) ) - Kit_TruthNot( pTruthFans[i], pTruthFans[i], pNtk->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( (unsigned *)Vec_PtrEntry(p->vTtNodes, i), (unsigned *)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 = (unsigned *)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) ); - Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - if ( Kit_DsdLitIsCompl(iLit) ) - Kit_TruthNot( pTruthFans[i], pTruthFans[i], pNtk->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_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( (unsigned *)Vec_PtrEntry(p->vTtNodes, i), (unsigned *)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 [Returns the size of the largest non-DSD block.] - - 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 [Returns the largest non-DSD block.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Kit_DsdObj_t * Kit_DsdNonDsdPrimeMax( Kit_DsdNtk_t * pNtk ) -{ - Kit_DsdObj_t * pObj, * pObjMax = NULL; - unsigned i, nSizeMax = 0; - Kit_DsdNtkForEachObj( pNtk, pObj, i ) - { - if ( pObj->Type != KIT_DSD_PRIME ) - continue; - if ( nSizeMax < pObj->nFans ) - { - nSizeMax = pObj->nFans; - pObjMax = pObj; - } - } - return pObjMax; -} - -/**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; -// ABC_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, unsigned iLit, unsigned * 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, unsigned iLit, unsigned * 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, (int *)&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, (int *)&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 ( pObj->nFans == 3 && - (pTruthNew[0] == 0xCACACACA || pTruthNew[0] == 0xC5C5C5C5 || - pTruthNew[0] == 0x3A3A3A3A || pTruthNew[0] == 0x35353535) ) - { - // translate into regular MUXes - if ( pTruthNew[0] == 0xC5C5C5C5 ) - pObjNew->pFans[0] = Kit_DsdLitNot(pObjNew->pFans[0]); - else if ( pTruthNew[0] == 0x3A3A3A3A ) - pObjNew->pFans[1] = Kit_DsdLitNot(pObjNew->pFans[1]); - else if ( pTruthNew[0] == 0x35353535 ) - { - pObjNew->pFans[0] = Kit_DsdLitNot(pObjNew->pFans[0]); - pObjNew->pFans[1] = Kit_DsdLitNot(pObjNew->pFans[1]); - } - pTruthNew[0] = 0xCACACACA; - // resolve the complemented control input - if ( Kit_DsdLitIsCompl(pObjNew->pFans[2]) ) - { - unsigned char Temp = pObjNew->pFans[0]; - pObjNew->pFans[0] = pObjNew->pFans[1]; - pObjNew->pFans[1] = Temp; - pObjNew->pFans[2] = Kit_DsdLitNot(pObjNew->pFans[2]); - } - // resolve the complemented true input - if ( Kit_DsdLitIsCompl(pObjNew->pFans[1]) ) - { - iLit = Kit_DsdLitNot(iLit); - pObjNew->pFans[0] = Kit_DsdLitNot(pObjNew->pFans[0]); - pObjNew->pFans[1] = Kit_DsdLitNot(pObjNew->pFans[1]); - } - return Kit_DsdVar2Lit( pObjNew->Id, Kit_DsdLitIsCompl(iLit) ); - } - else - { - // 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, unsigned 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; - Kit_DsdObj_t * pObjNew = NULL; // Suppress "might be used uninitialized" - 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 = ABC_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[2] = pObj->pFans[iBestVar]; - 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 ); - } - -} - -/**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 ) -{ -/* - Kit_DsdNtk_t * pNew; - Kit_DsdObj_t * pObjNew; - assert( nVars <= 16 ); - // create a new network - pNew = Kit_DsdNtkAlloc( nVars ); - // consider simple special cases - if ( nVars == 0 ) - { - pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_CONST1, 0 ); - pNew->Root = Kit_DsdVar2Lit( pObjNew->Id, (int)(pTruth[0] == 0) ); - return pNew; - } - if ( nVars == 1 ) - { - pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_VAR, 1 ); - pObjNew->pFans[0] = Kit_DsdVar2Lit( 0, 0 ); - pNew->Root = Kit_DsdVar2Lit( pObjNew->Id, (int)(pTruth[0] != 0xAAAAAAAA) ); - return pNew; - } -*/ - 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 ), printf( "\n" ); - } - 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 ), printf( "\n" ); - } - - 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 ), printf( "\n" ); - } - -// 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 ), printf( "\n" ); - -// 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 ), printf( "\n" ); - - 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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} - }; - Kit_DsdNtk_t * 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] = ABC_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( "\n" ); - printf( "Cof%d%d: ", nStep+1, 2*i+1 ); - Kit_DsdPrint( stdout, ppNtks[nStep+1][2*i+1] ), printf( "\n" ); - } - } - } - - // free the networks - for ( i = 0; i < 5; i++ ) - for ( k = 0; k < 16; k++ ) - if ( ppNtks[i][k] ) - Kit_DsdNtkFree( ppNtks[i][k] ); - ABC_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] ), printf( "\n" ); - Kit_DsdNtkFree( ppNtks[0] ); - - // allocate storage for cofactors - nMemSize = Kit_TruthWordNum(nVars); - ppCofs[0][0] = ABC_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] ), printf( "\n" ); - } - // 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] ), printf( "\n" ); - } - // 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] ), printf( "\n" ); - } - // 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] ), printf( "\n" ); - } - // 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 ); - } - - - ABC_FREE( ppCofs[0][0] ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char ** Kit_DsdNpn4ClassNames() -{ - static const char * pNames[222] = { - "F = 0", /* 0 */ - "F = (!d*(!c*(!b*!a)))", /* 1 */ - "F = (!d*(!c*!b))", /* 2 */ - "F = (!d*(!c*(b+a)))", /* 3 */ - "F = (!d*(!c*!(b*a)))", /* 4 */ - "F = (!d*!c)", /* 5 */ - "F = (!d*16(a,b,c))", /* 6 */ - "F = (!d*17(a,b,c))", /* 7 */ - "F = (!d*18(a,b,c))", /* 8 */ - "F = (!d*19(a,b,c))", /* 9 */ - "F = (!d*CA(!b,!c,a))", /* 10 */ - "F = (!d*(c+!(!b*!a)))", /* 11 */ - "F = (!d*!(c*!(!b*!a)))", /* 12 */ - "F = (!d*(c+b))", /* 13 */ - "F = (!d*3D(a,b,c))", /* 14 */ - "F = (!d*!(c*b))", /* 15 */ - "F = (!d*(c+(b+!a)))", /* 16 */ - "F = (!d*6B(a,b,c))", /* 17 */ - "F = (!d*!(c*!(b+a)))", /* 18 */ - "F = (!d*7E(a,b,c))", /* 19 */ - "F = (!d*!(c*(b*a)))", /* 20 */ - "F = (!d)", /* 21 */ - "F = 0116(a,b,c,d)", /* 22 */ - "F = 0117(a,b,c,d)", /* 23 */ - "F = 0118(a,b,c,d)", /* 24 */ - "F = 0119(a,b,c,d)", /* 25 */ - "F = 011A(a,b,c,d)", /* 26 */ - "F = 011B(a,b,c,d)", /* 27 */ - "F = 29((!b*!a),c,d)", /* 28 */ - "F = 2B((!b*!a),c,d)", /* 29 */ - "F = 012C(a,b,c,d)", /* 30 */ - "F = 012D(a,b,c,d)", /* 31 */ - "F = 012F(a,b,c,d)", /* 32 */ - "F = 013C(a,b,c,d)", /* 33 */ - "F = 013D(a,b,c,d)", /* 34 */ - "F = 013E(a,b,c,d)", /* 35 */ - "F = 013F(a,b,c,d)", /* 36 */ - "F = 0168(a,b,c,d)", /* 37 */ - "F = 0169(a,b,c,d)", /* 38 */ - "F = 016A(a,b,c,d)", /* 39 */ - "F = 016B(a,b,c,d)", /* 40 */ - "F = 016E(a,b,c,d)", /* 41 */ - "F = 016F(a,b,c,d)", /* 42 */ - "F = 017E(a,b,c,d)", /* 43 */ - "F = 017F(a,b,c,d)", /* 44 */ - "F = 0180(a,b,c,d)", /* 45 */ - "F = 0181(a,b,c,d)", /* 46 */ - "F = 0182(a,b,c,d)", /* 47 */ - "F = 0183(a,b,c,d)", /* 48 */ - "F = 0186(a,b,c,d)", /* 49 */ - "F = 0187(a,b,c,d)", /* 50 */ - "F = 0189(a,b,c,d)", /* 51 */ - "F = 018B(a,b,c,d)", /* 52 */ - "F = 018F(a,b,c,d)", /* 53 */ - "F = 0196(a,b,c,d)", /* 54 */ - "F = 0197(a,b,c,d)", /* 55 */ - "F = 0198(a,b,c,d)", /* 56 */ - "F = 0199(a,b,c,d)", /* 57 */ - "F = 019A(a,b,c,d)", /* 58 */ - "F = 019B(a,b,c,d)", /* 59 */ - "F = 019E(a,b,c,d)", /* 60 */ - "F = 019F(a,b,c,d)", /* 61 */ - "F = 42(a,(!c*!b),d)", /* 62 */ - "F = 46(a,(!c*!b),d)", /* 63 */ - "F = 4A(a,(!c*!b),d)", /* 64 */ - "F = CA((!c*!b),!d,a)", /* 65 */ - "F = 01AC(a,b,c,d)", /* 66 */ - "F = 01AD(a,b,c,d)", /* 67 */ - "F = 01AE(a,b,c,d)", /* 68 */ - "F = 01AF(a,b,c,d)", /* 69 */ - "F = 01BC(a,b,c,d)", /* 70 */ - "F = 01BD(a,b,c,d)", /* 71 */ - "F = 01BE(a,b,c,d)", /* 72 */ - "F = 01BF(a,b,c,d)", /* 73 */ - "F = 01E8(a,b,c,d)", /* 74 */ - "F = 01E9(a,b,c,d)", /* 75 */ - "F = 01EA(a,b,c,d)", /* 76 */ - "F = 01EB(a,b,c,d)", /* 77 */ - "F = 25((!b*!a),c,d)", /* 78 */ - "F = !CA(d,c,(!b*!a))", /* 79 */ - "F = (d+!(!c*(!b*!a)))", /* 80 */ - "F = 16(b,c,d)", /* 81 */ - "F = 033D(a,b,c,d)", /* 82 */ - "F = 17(b,c,d)", /* 83 */ - "F = ((!d*!a)+(!c*!b))", /* 84 */ - "F = !(!(!c*!b)*!(!d*!a))", /* 85 */ - "F = 0358(a,b,c,d)", /* 86 */ - "F = 0359(a,b,c,d)", /* 87 */ - "F = 035A(a,b,c,d)", /* 88 */ - "F = 035B(a,b,c,d)", /* 89 */ - "F = 035E(a,b,c,d)", /* 90 */ - "F = 035F(a,b,c,d)", /* 91 */ - "F = 0368(a,b,c,d)", /* 92 */ - "F = 0369(a,b,c,d)", /* 93 */ - "F = 036A(a,b,c,d)", /* 94 */ - "F = 036B(a,b,c,d)", /* 95 */ - "F = 036C(a,b,c,d)", /* 96 */ - "F = 036D(a,b,c,d)", /* 97 */ - "F = 036E(a,b,c,d)", /* 98 */ - "F = 036F(a,b,c,d)", /* 99 */ - "F = 037C(a,b,c,d)", /* 100 */ - "F = 037D(a,b,c,d)", /* 101 */ - "F = 037E(a,b,c,d)", /* 102 */ - "F = 18(b,c,d)", /* 103 */ - "F = 03C1(a,b,c,d)", /* 104 */ - "F = 19(b,c,d)", /* 105 */ - "F = 03C5(a,b,c,d)", /* 106 */ - "F = 03C6(a,b,c,d)", /* 107 */ - "F = 03C7(a,b,c,d)", /* 108 */ - "F = CA(!c,!d,b)", /* 109 */ - "F = 03D4(a,b,c,d)", /* 110 */ - "F = 03D5(a,b,c,d)", /* 111 */ - "F = 03D6(a,b,c,d)", /* 112 */ - "F = 03D7(a,b,c,d)", /* 113 */ - "F = 03D8(a,b,c,d)", /* 114 */ - "F = 03D9(a,b,c,d)", /* 115 */ - "F = 03DB(a,b,c,d)", /* 116 */ - "F = 03DC(a,b,c,d)", /* 117 */ - "F = 03DD(a,b,c,d)", /* 118 */ - "F = 03DE(a,b,c,d)", /* 119 */ - "F = (d+!(!c*!b))", /* 120 */ - "F = ((d+c)*(b+a))", /* 121 */ - "F = 0661(a,b,c,d)", /* 122 */ - "F = 0662(a,b,c,d)", /* 123 */ - "F = 0663(a,b,c,d)", /* 124 */ - "F = (!(d*c)*(b+a))", /* 125 */ - "F = 0667(a,b,c,d)", /* 126 */ - "F = 29((b+a),c,d)", /* 127 */ - "F = 066B(a,b,c,d)", /* 128 */ - "F = 2B((b+a),c,d)", /* 129 */ - "F = 0672(a,b,c,d)", /* 130 */ - "F = 0673(a,b,c,d)", /* 131 */ - "F = 0676(a,b,c,d)", /* 132 */ - "F = 0678(a,b,c,d)", /* 133 */ - "F = 0679(a,b,c,d)", /* 134 */ - "F = 067A(a,b,c,d)", /* 135 */ - "F = 067B(a,b,c,d)", /* 136 */ - "F = 067E(a,b,c,d)", /* 137 */ - "F = 24((b+a),c,d)", /* 138 */ - "F = 0691(a,b,c,d)", /* 139 */ - "F = 0693(a,b,c,d)", /* 140 */ - "F = 26((b+a),c,d)", /* 141 */ - "F = 0697(a,b,c,d)", /* 142 */ - "F = !CA(d,c,(b+a))", /* 143 */ - "F = 06B0(a,b,c,d)", /* 144 */ - "F = 06B1(a,b,c,d)", /* 145 */ - "F = 06B2(a,b,c,d)", /* 146 */ - "F = 06B3(a,b,c,d)", /* 147 */ - "F = 06B4(a,b,c,d)", /* 148 */ - "F = 06B5(a,b,c,d)", /* 149 */ - "F = 06B6(a,b,c,d)", /* 150 */ - "F = 06B7(a,b,c,d)", /* 151 */ - "F = 06B9(a,b,c,d)", /* 152 */ - "F = 06BD(a,b,c,d)", /* 153 */ - "F = 2C((b+a),c,d)", /* 154 */ - "F = 06F1(a,b,c,d)", /* 155 */ - "F = 06F2(a,b,c,d)", /* 156 */ - "F = CA((b+a),!d,c)", /* 157 */ - "F = (d+!(!c*!(b+!a)))", /* 158 */ - "F = 0776(a,b,c,d)", /* 159 */ - "F = 16((b*a),c,d)", /* 160 */ - "F = 0779(a,b,c,d)", /* 161 */ - "F = 077A(a,b,c,d)", /* 162 */ - "F = 077E(a,b,c,d)", /* 163 */ - "F = 07B0(a,b,c,d)", /* 164 */ - "F = 07B1(a,b,c,d)", /* 165 */ - "F = 07B4(a,b,c,d)", /* 166 */ - "F = 07B5(a,b,c,d)", /* 167 */ - "F = 07B6(a,b,c,d)", /* 168 */ - "F = 07BC(a,b,c,d)", /* 169 */ - "F = 07E0(a,b,c,d)", /* 170 */ - "F = 07E1(a,b,c,d)", /* 171 */ - "F = 07E2(a,b,c,d)", /* 172 */ - "F = 07E3(a,b,c,d)", /* 173 */ - "F = 07E6(a,b,c,d)", /* 174 */ - "F = 07E9(a,b,c,d)", /* 175 */ - "F = 1C((b*a),c,d)", /* 176 */ - "F = 07F1(a,b,c,d)", /* 177 */ - "F = 07F2(a,b,c,d)", /* 178 */ - "F = (d+!(!c*!(b*a)))", /* 179 */ - "F = (d+c)", /* 180 */ - "F = 1668(a,b,c,d)", /* 181 */ - "F = 1669(a,b,c,d)", /* 182 */ - "F = 166A(a,b,c,d)", /* 183 */ - "F = 166B(a,b,c,d)", /* 184 */ - "F = 166E(a,b,c,d)", /* 185 */ - "F = 167E(a,b,c,d)", /* 186 */ - "F = 1681(a,b,c,d)", /* 187 */ - "F = 1683(a,b,c,d)", /* 188 */ - "F = 1686(a,b,c,d)", /* 189 */ - "F = 1687(a,b,c,d)", /* 190 */ - "F = 1689(a,b,c,d)", /* 191 */ - "F = 168B(a,b,c,d)", /* 192 */ - "F = 168E(a,b,c,d)", /* 193 */ - "F = 1696(a,b,c,d)", /* 194 */ - "F = 1697(a,b,c,d)", /* 195 */ - "F = 1698(a,b,c,d)", /* 196 */ - "F = 1699(a,b,c,d)", /* 197 */ - "F = 169A(a,b,c,d)", /* 198 */ - "F = 169B(a,b,c,d)", /* 199 */ - "F = 169E(a,b,c,d)", /* 200 */ - "F = 16A9(a,b,c,d)", /* 201 */ - "F = 16AC(a,b,c,d)", /* 202 */ - "F = 16AD(a,b,c,d)", /* 203 */ - "F = 16BC(a,b,c,d)", /* 204 */ - "F = (d+E9(a,b,c))", /* 205 */ - "F = 177E(a,b,c,d)", /* 206 */ - "F = 178E(a,b,c,d)", /* 207 */ - "F = 1796(a,b,c,d)", /* 208 */ - "F = 1798(a,b,c,d)", /* 209 */ - "F = 179A(a,b,c,d)", /* 210 */ - "F = 17AC(a,b,c,d)", /* 211 */ - "F = (d+E8(a,b,c))", /* 212 */ - "F = (d+E7(a,b,c))", /* 213 */ - "F = 19E1(a,b,c,d)", /* 214 */ - "F = 19E3(a,b,c,d)", /* 215 */ - "F = (d+E6(a,b,c))", /* 216 */ - "F = 1BD8(a,b,c,d)", /* 217 */ - "F = (d+CA(b,c,a))", /* 218 */ - "F = (d+(c+(!b*!a)))", /* 219 */ - "F = (d+(c+!b))", /* 220 */ - "F = (d+(c+(b+a)))" /* 221 */ - }; - return (char **)pNames; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/kit/kitFactor.c b/src/aig/kit/kitFactor.c deleted file mode 100644 index ec4775ca..00000000 --- a/src/aig/kit/kitFactor.c +++ /dev/null @@ -1,344 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// factoring fails if intermediate memory usage exceed this limit -#define KIT_FACTOR_MEM_LIMIT (1<<20) - -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 ABC_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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/kit/kitGraph.c b/src/aig/kit/kitGraph.c deleted file mode 100644 index e4eea885..00000000 --- a/src/aig/kit/kitGraph.c +++ /dev/null @@ -1,402 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 = ABC_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 = ABC_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 = ABC_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 = ABC_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 ) -{ - ABC_FREE( pGraph->pNodes ); - ABC_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 = ABC_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) > (1<<16) ) - 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 /// -//////////////////////////////////////////////////////////////////////// - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/kit/kitHop.c b/src/aig/kit/kitHop.c deleted file mode 100644 index 9dfa67a8..00000000 --- a/src/aig/kit/kitHop.c +++ /dev/null @@ -1,155 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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( (Hop_Obj_t *)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( (Hop_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); - pAnd1 = Hop_NotCond( (Hop_Obj_t *)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( (Hop_Obj_t *)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 ); - if ( pGraph == NULL ) - { - printf( "Kit_TruthToHop(): Converting truth table to AIG has failed for function:\n" ); - Kit_DsdPrintFromTruth( pTruth, nVars ); printf( "\n" ); - } - // 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 - Vec_IntClear( vMemory ); - 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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/kit/kitIsop.c b/src/aig/kit/kitIsop.c deleted file mode 100644 index fc017c0e..00000000 --- a/src/aig/kit/kitIsop.c +++ /dev/null @@ -1,330 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// ISOP computation fails if intermediate memory usage exceed this limit -#define KIT_ISOP_MEM_LIMIT (1<<20) - -// 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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/kit/kitPerm.c b/src/aig/kit/kitPerm.c deleted file mode 100644 index d3e9ff5a..00000000 --- a/src/aig/kit/kitPerm.c +++ /dev/null @@ -1,355 +0,0 @@ -/**CFile**************************************************************** - - FileName [kitPerm.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Computation kit.] - - Synopsis [Procedures for permuting truth tables.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - Oct 26, 2011.] - - Revision [$Id: kitPerm.c,v 1.00 2011/11/26 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include -#include -#include -#include -#include - -#define inline __inline // compatible with MS VS 6.0 - -//ABC_NAMESPACE_IMPL_START - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef unsigned __int64 word; -typedef unsigned short shot; -typedef unsigned char byte; - -static shot S[256] = -{ - 0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015, - 0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055, - 0x0100, 0x0101, 0x0104, 0x0105, 0x0110, 0x0111, 0x0114, 0x0115, - 0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155, - 0x0400, 0x0401, 0x0404, 0x0405, 0x0410, 0x0411, 0x0414, 0x0415, - 0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455, - 0x0500, 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515, - 0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554, 0x0555, - 0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015, - 0x1040, 0x1041, 0x1044, 0x1045, 0x1050, 0x1051, 0x1054, 0x1055, - 0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115, - 0x1140, 0x1141, 0x1144, 0x1145, 0x1150, 0x1151, 0x1154, 0x1155, - 0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415, - 0x1440, 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455, - 0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514, 0x1515, - 0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555, - 0x4000, 0x4001, 0x4004, 0x4005, 0x4010, 0x4011, 0x4014, 0x4015, - 0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055, - 0x4100, 0x4101, 0x4104, 0x4105, 0x4110, 0x4111, 0x4114, 0x4115, - 0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155, - 0x4400, 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415, - 0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454, 0x4455, - 0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515, - 0x4540, 0x4541, 0x4544, 0x4545, 0x4550, 0x4551, 0x4554, 0x4555, - 0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015, - 0x5040, 0x5041, 0x5044, 0x5045, 0x5050, 0x5051, 0x5054, 0x5055, - 0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115, - 0x5140, 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155, - 0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414, 0x5415, - 0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455, - 0x5500, 0x5501, 0x5504, 0x5505, 0x5510, 0x5511, 0x5514, 0x5515, - 0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555 -}; - -static byte P[256] = -{ - 0x00, 0x01, 0x10, 0x11, 0x04, 0x05, 0x14, 0x15, 0x40, 0x41, 0x50, 0x51, 0x44, 0x45, 0x54, 0x55, - 0x02, 0x03, 0x12, 0x13, 0x06, 0x07, 0x16, 0x17, 0x42, 0x43, 0x52, 0x53, 0x46, 0x47, 0x56, 0x57, - 0x20, 0x21, 0x30, 0x31, 0x24, 0x25, 0x34, 0x35, 0x60, 0x61, 0x70, 0x71, 0x64, 0x65, 0x74, 0x75, - 0x22, 0x23, 0x32, 0x33, 0x26, 0x27, 0x36, 0x37, 0x62, 0x63, 0x72, 0x73, 0x66, 0x67, 0x76, 0x77, - 0x08, 0x09, 0x18, 0x19, 0x0c, 0x0d, 0x1c, 0x1d, 0x48, 0x49, 0x58, 0x59, 0x4c, 0x4d, 0x5c, 0x5d, - 0x0a, 0x0b, 0x1a, 0x1b, 0x0e, 0x0f, 0x1e, 0x1f, 0x4a, 0x4b, 0x5a, 0x5b, 0x4e, 0x4f, 0x5e, 0x5f, - 0x28, 0x29, 0x38, 0x39, 0x2c, 0x2d, 0x3c, 0x3d, 0x68, 0x69, 0x78, 0x79, 0x6c, 0x6d, 0x7c, 0x7d, - 0x2a, 0x2b, 0x3a, 0x3b, 0x2e, 0x2f, 0x3e, 0x3f, 0x6a, 0x6b, 0x7a, 0x7b, 0x6e, 0x6f, 0x7e, 0x7f, - 0x80, 0x81, 0x90, 0x91, 0x84, 0x85, 0x94, 0x95, 0xc0, 0xc1, 0xd0, 0xd1, 0xc4, 0xc5, 0xd4, 0xd5, - 0x82, 0x83, 0x92, 0x93, 0x86, 0x87, 0x96, 0x97, 0xc2, 0xc3, 0xd2, 0xd3, 0xc6, 0xc7, 0xd6, 0xd7, - 0xa0, 0xa1, 0xb0, 0xb1, 0xa4, 0xa5, 0xb4, 0xb5, 0xe0, 0xe1, 0xf0, 0xf1, 0xe4, 0xe5, 0xf4, 0xf5, - 0xa2, 0xa3, 0xb2, 0xb3, 0xa6, 0xa7, 0xb6, 0xb7, 0xe2, 0xe3, 0xf2, 0xf3, 0xe6, 0xe7, 0xf6, 0xf7, - 0x88, 0x89, 0x98, 0x99, 0x8c, 0x8d, 0x9c, 0x9d, 0xc8, 0xc9, 0xd8, 0xd9, 0xcc, 0xcd, 0xdc, 0xdd, - 0x8a, 0x8b, 0x9a, 0x9b, 0x8e, 0x8f, 0x9e, 0x9f, 0xca, 0xcb, 0xda, 0xdb, 0xce, 0xcf, 0xde, 0xdf, - 0xa8, 0xa9, 0xb8, 0xb9, 0xac, 0xad, 0xbc, 0xbd, 0xe8, 0xe9, 0xf8, 0xf9, 0xec, 0xed, 0xfc, 0xfd, - 0xaa, 0xab, 0xba, 0xbb, 0xae, 0xaf, 0xbe, 0xbf, 0xea, 0xeb, 0xfa, 0xfb, 0xee, 0xef, 0xfe, 0xff -}; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_PermCreateS() -{ - int i, n, r; - for ( i = 0; i < 256; i++ ) - { - if ( i % 8 == 0 ) - printf( "\n" ); - for ( r = n = 0; n < 8; n++ ) - r |= ((i & (1 << n)) << n); - printf( "0x%04x, ", r ); - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_PermCreateP() -{ - int i, s1, s2, r; - for ( i = 0; i < 256; i++ ) - { - if ( i % 16 == 0 ) - printf( "\n" ); - s1 = i & 0x0A; - s2 = i & 0x50; - r = i ^ s1 ^ s2 ^ (s1 << 3) ^ (s2 >> 3); - assert( r < 256 ); - printf( "0x%02x, ", r ); - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Kit_PermCycleOne( shot * s, byte * b, int v ) -{ - int i, n = (1 << (v-3)); - assert( v > 2 && v < 16 ); - for ( i = 0; i < n; i++ ) - s[i] = S[b[i]] | (S[b[i+n]] << 1); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Kit_PermCycleMany( shot * s, byte * b, int V, int v ) -{ - int i, n = (1 << (V - 1 - v)), m = (1 << (v-2)); - assert( v > 2 && v < V ); - for ( i = 0; i < n; i++, s += (m >> 1), b += m ) - Kit_PermCycleOne( s, b, v ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_PermCompute( word * o, word * i, int V ) -{ - word * t; - int v, n = (1 << (V-3)); - assert( V >= 6 && V <= 16 ); - for ( v = 0; v < n; v++ ) - ((byte *)i)[v] = P[((byte *)i)[v]]; - for ( v = 3; v < V; v++ ) - { - Kit_PermCycleMany( (shot *)o, (byte *)i, V, v ); - t = i; i = o; o = t; - } - if ( V & 1 ) - { - n = (1 << (V-6)); - for ( v = 0; v < n; v++ ) - o[v] = i[v]; - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_PermComputeNaive( word * F, int nVars ) -{ - extern void If_CluReverseOrder( word * pF, int nVars, int * V2P, int * P2V, int iVarStart ); - int i, V2P[16], P2V[16]; - for ( i = 0; i < nVars; i++ ) - V2P[i] = P2V[i] = i; - If_CluReverseOrder( F, nVars, V2P, P2V, 0 ); -} - - -word M ( word f1, word f2, int n) -{ - word temp = 0; - word a = 1; - int i; - for( i = 0; i < n; i++) - temp = temp + (((f1>>i)&a) << (2*i) ) + (((f2>>i)&a) << (2*i+1)); - return temp; -} - -word Tf ( word f, int n) -{ - if(n==1) - return f; - else - { -// int x = (int)pow(2,n-1); - int x; - x = (1 << (n-1)); - return ( M (Tf( (f << x) >> x, n-1), Tf( (f >> x), n-1), x) ); //def. of M just below the function - } -} - - -#define ABC_PRT(a,t) (printf("%s = ", (a)), printf("%7.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC))) -#define NFUNCS (1<<20) - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_PermComputeTest() -{ - word * T = (word *)malloc( 8 * NFUNCS ); - word i, o, w = 0; - int k, b, clk; - - srand( 0 ); - - clk = clock(); - for ( k = 0; k < NFUNCS; k++ ) - for ( b = 0; b < 8; b++ ) - ((byte *)(T + k))[b] = (byte)(rand() & 0xFF); - ABC_PRT( "Assign", clock() - clk ); - -// T[0] = 0xacaccacaaccaacca; -// Kit_DsdPrintFromTruth( T, 6 ); - - // perform measurements - clk = clock(); - for ( k = 0; k < NFUNCS; k++ ) - { - i = T[k]; -// Kit_PermComputeNaive( &i, 6 ); - Tf( i, 6 ); - } - ABC_PRT( "Perm1 ", clock() - clk ); - - // perform measurements - clk = clock(); - for ( k = 0; k < NFUNCS; k++ ) - { - i = T[k]; - Kit_PermCompute( &o, &i, 6 ); - -// w = T[k]; -// Kit_PermComputeNaive( &w, 6 ); -// assert( w == o ); - } - ABC_PRT( "Perm2 ", clock() - clk ); - - assert( w == 0 ); - free( T ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] -` -***********************************************************************/ -void Kit_PermComputeTest_() -{ - word t, s; - t = 0xacaccacaaccaacca; -// Kit_DsdPrintFromTruth( &t, 6 ); printf( "\n" ); - s = Tf( t, 6 ); -// Kit_PermComputeNaive( &t, 6 ); -// Kit_DsdPrintFromTruth( &s, 6 ); printf( "\n" ); -} - -/* - { - extern void Kit_PermComputeTest(); - Kit_PermComputeTest(); - } -*/ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -//ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/kit/kitPla.c b/src/aig/kit/kitPla.c deleted file mode 100644 index df6d4e11..00000000 --- a/src/aig/kit/kitPla.c +++ /dev/null @@ -1,535 +0,0 @@ -/**CFile**************************************************************** - - FileName [kitPla.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Computation kit.] - - Synopsis [Manipulating SOP in the form of a C-string.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - Dec 6, 2006.] - - Revision [$Id: kitPla.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "kit.h" -#include "aig.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Checks if the cover is constant 0.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_PlaIsConst0( char * pSop ) -{ - return pSop[0] == ' ' && pSop[1] == '0'; -} - -/**Function************************************************************* - - Synopsis [Checks if the cover is constant 1.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_PlaIsConst1( char * pSop ) -{ - return pSop[0] == ' ' && pSop[1] == '1'; -} - -/**Function************************************************************* - - Synopsis [Checks if the cover is a buffer.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_PlaIsBuf( char * pSop ) -{ - if ( pSop[4] != 0 ) - return 0; - if ( (pSop[0] == '1' && pSop[2] == '1') || (pSop[0] == '0' && pSop[2] == '0') ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Checks if the cover is an inverter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_PlaIsInv( char * pSop ) -{ - if ( pSop[4] != 0 ) - return 0; - if ( (pSop[0] == '0' && pSop[2] == '1') || (pSop[0] == '1' && pSop[2] == '0') ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Reads the number of variables in the cover.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_PlaGetVarNum( char * pSop ) -{ - char * pCur; - for ( pCur = pSop; *pCur != '\n'; pCur++ ) - if ( *pCur == 0 ) - return -1; - return pCur - pSop - 2; -} - -/**Function************************************************************* - - Synopsis [Reads the number of cubes in the cover.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_PlaGetCubeNum( 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 Kit_PlaIsComplement( 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 Kit_PlaComplement( 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 * Kit_PlaStart( void * p, int nCubes, int nVars ) -{ - Aig_MmFlex_t * pMan = (Aig_MmFlex_t *)p; - 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 * Kit_PlaCreateFromIsop( void * p, int nVars, Vec_Int_t * vCover ) -{ - Aig_MmFlex_t * pMan = (Aig_MmFlex_t *)p; - char * pSop, * pCube; - int i, k, Entry, Literal; - assert( Vec_IntSize(vCover) > 0 ); - if ( Vec_IntSize(vCover) == 0 ) - return NULL; - // start the cover - pSop = Kit_PlaStart( 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 [Creates the cover from the ISOP computed from TT.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_PlaToIsop( char * pSop, Vec_Int_t * vCover ) -{ - char * pCube; - int k, nVars, Entry; - nVars = Kit_PlaGetVarNum( pSop ); - assert( nVars > 0 ); - // create cubes - Vec_IntClear( vCover ); - for ( pCube = pSop; *pCube; pCube += nVars + 3 ) - { - Entry = 0; - for ( k = nVars - 1; k >= 0; k-- ) - if ( pCube[k] == '0' ) - Entry = (Entry << 2) | 1; - else if ( pCube[k] == '1' ) - Entry = (Entry << 2) | 2; - else if ( pCube[k] == '-' ) - Entry = (Entry << 2); - else - assert( 0 ); - Vec_IntPush( vCover, Entry ); - } -} - -/**Function************************************************************* - - Synopsis [Allocates memory and copies the SOP into it.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Kit_PlaStoreSop( void * p, char * pSop ) -{ - Aig_MmFlex_t * pMan = (Aig_MmFlex_t *)p; - char * pStore; - pStore = Aig_MmFlexEntryFetch( pMan, strlen(pSop) + 1 ); - strcpy( pStore, pSop ); - return pStore; -} - -/**Function************************************************************* - - Synopsis [Transforms truth table into the SOP.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Kit_PlaFromTruth( void * p, unsigned * pTruth, int nVars, Vec_Int_t * vCover ) -{ - Aig_MmFlex_t * pMan = (Aig_MmFlex_t *)p; - char * pSop; - int RetValue; - if ( Kit_TruthIsConst0(pTruth, nVars) ) - return Kit_PlaStoreSop( pMan, " 0\n" ); - if ( Kit_TruthIsConst1(pTruth, nVars) ) - return Kit_PlaStoreSop( pMan, " 1\n" ); - RetValue = Kit_TruthIsop( pTruth, nVars, vCover, 0 ); // 1 ); - assert( RetValue == 0 || RetValue == 1 ); - pSop = Kit_PlaCreateFromIsop( pMan, nVars, vCover ); - if ( RetValue ) - Kit_PlaComplement( pSop ); - return pSop; -} - - -/**Function************************************************************* - - Synopsis [Creates the cover from the ISOP computed from TT.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Kit_PlaFromIsop( Vec_Str_t * vStr, int nVars, Vec_Int_t * vCover ) -{ - int i, k, Entry, Literal; - assert( Vec_IntSize(vCover) > 0 ); - if ( Vec_IntSize(vCover) == 0 ) - return NULL; - Vec_StrClear( vStr ); - Vec_IntForEachEntry( vCover, Entry, i ) - { - for ( k = 0; k < nVars; k++ ) - { - Literal = 3 & (Entry >> (k << 1)); - if ( Literal == 1 ) - Vec_StrPush( vStr, '0' ); - else if ( Literal == 2 ) - Vec_StrPush( vStr, '1' ); - else if ( Literal == 0 ) - Vec_StrPush( vStr, '-' ); - else - assert( 0 ); - } - Vec_StrPush( vStr, ' ' ); - Vec_StrPush( vStr, '1' ); - Vec_StrPush( vStr, '\n' ); - } - Vec_StrPush( vStr, '\0' ); - return Vec_StrArray( vStr ); -} - -/**Function************************************************************* - - Synopsis [Creates the SOP from TT.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Kit_PlaFromTruthNew( unsigned * pTruth, int nVars, Vec_Int_t * vCover, Vec_Str_t * vStr ) -{ - char * pResult; - // transform truth table into the SOP - int RetValue = Kit_TruthIsop( pTruth, nVars, 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 ); - Vec_StrClear( vStr ); - Vec_StrAppend( vStr, (Vec_IntSize(vCover) == 0) ? " 0\n" : " 1\n" ); - Vec_StrPush( vStr, '\0' ); - return Vec_StrArray( vStr ); - } - pResult = Kit_PlaFromIsop( vStr, nVars, vCover ); - if ( RetValue ) - Kit_PlaComplement( pResult ); - if ( nVars < 6 ) - assert( pTruth[0] == (unsigned)Kit_PlaToTruth6(pResult, nVars) ); - else if ( nVars == 6 ) - assert( *((ABC_UINT64_T*)pTruth) == Kit_PlaToTruth6(pResult, nVars) ); - return pResult; -} - -/**Function************************************************************* - - Synopsis [Converts SOP into a truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -ABC_UINT64_T Kit_PlaToTruth6( char * pSop, int nVars ) -{ - static ABC_UINT64_T Truth[8] = { - 0xAAAAAAAAAAAAAAAA, - 0xCCCCCCCCCCCCCCCC, - 0xF0F0F0F0F0F0F0F0, - 0xFF00FF00FF00FF00, - 0xFFFF0000FFFF0000, - 0xFFFFFFFF00000000, - 0x0000000000000000, - 0xFFFFFFFFFFFFFFFF - }; - ABC_UINT64_T valueAnd, valueOr = Truth[6]; - int v, lit = 0; - assert( nVars < 7 ); - do { - valueAnd = Truth[7]; - for ( v = 0; v < nVars; v++, lit++ ) - { - if ( pSop[lit] == '1' ) - valueAnd &= Truth[v]; - else if ( pSop[lit] == '0' ) - valueAnd &= ~Truth[v]; - else if ( pSop[lit] != '-' ) - assert( 0 ); - } - valueOr |= valueAnd; - assert( pSop[lit] == ' ' ); - lit++; - lit++; - assert( pSop[lit] == '\n' ); - lit++; - } while ( pSop[lit] ); - if ( Kit_PlaIsComplement(pSop) ) - valueOr = ~valueOr; - return valueOr; -} - -/**Fnction************************************************************* - - Synopsis [Converting SOP into a truth table.] - - Description [The SOP is represented as a C-string, as documented in - file "bblif.h". The truth table is returned as a bit-string composed - of 2^nVars bits. For functions of less than 6 variables, the full - machine word is returned. (The truth table looks as if the function - had 5 variables.) The use of this procedure should be limited to - Boolean functions with no more than 16 inputs.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_PlaToTruth( char * pSop, int nVars, Vec_Ptr_t * vVars, unsigned * pTemp, unsigned * pTruth ) -{ - int v, c, nCubes, fCompl = 0; - assert( pSop != NULL ); - assert( nVars >= 0 ); - if ( strlen(pSop) % (nVars + 3) != 0 ) - { - printf( "Kit_PlaToTruth(): SOP is represented incorrectly.\n" ); - return; - } - // iterate through the cubes - Kit_TruthClear( pTruth, nVars ); - nCubes = strlen(pSop) / (nVars + 3); - for ( c = 0; c < nCubes; c++ ) - { - fCompl = (pSop[nVars+1] == '0'); - Kit_TruthFill( pTemp, nVars ); - // iterate through the literals of the cube - for ( v = 0; v < nVars; v++ ) - if ( pSop[v] == '1' ) - Kit_TruthAnd( pTemp, pTemp, (unsigned *)Vec_PtrEntry(vVars, v), nVars ); - else if ( pSop[v] == '0' ) - Kit_TruthSharp( pTemp, pTemp, (unsigned *)Vec_PtrEntry(vVars, v), nVars ); - // add cube to storage - Kit_TruthOr( pTruth, pTruth, pTemp, nVars ); - // go to the next cube - pSop += (nVars + 3); - } - if ( fCompl ) - Kit_TruthNot( pTruth, pTruth, nVars ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/kit/kitSop.c b/src/aig/kit/kitSop.c deleted file mode 100644 index 21ea69b8..00000000 --- a/src/aig/kit/kitSop.c +++ /dev/null @@ -1,579 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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; - unsigned uCube2 = 0; // Suppress "might be used uninitialized" - unsigned 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-ABC_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-ABC_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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/kit/kitTruth.c b/src/aig/kit/kitTruth.c deleted file mode 100644 index bd8bbb1c..00000000 --- a/src/aig/kit/kitTruth.c +++ /dev/null @@ -1,2222 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 [The input truth table is modified.] - - 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) shows what variables should remain.] - - SideEffects [The input truth table is modified.] - - 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 [Implement give permutation.] - - Description [The input and output truth tables are in pIn/pOut. - The number of variables is nVars. Permutation is in pPerm.] - - SideEffects [The input truth table is modified.] - - SeeAlso [] - -***********************************************************************/ -void Kit_TruthPermute( unsigned * pOut, unsigned * pIn, int nVars, char * pPerm, int fReturnIn ) -{ - unsigned * pTemp; - int i, Temp, fChange, Counter = 0; - do { - fChange = 0; - for ( i = 0; i < nVars-1; i++ ) - { - assert( pPerm[i] != pPerm[i+1] ); - if ( pPerm[i] <= pPerm[i+1] ) - continue; - Counter++; - fChange = 1; - - Temp = pPerm[i]; - pPerm[i] = pPerm[i+1]; - pPerm[i+1] = Temp; - - Kit_TruthSwapAdjacentVars( pOut, pIn, nVars, i ); - pTemp = pIn; pIn = pOut; pOut = pTemp; - } - } while ( fChange ); - if ( fReturnIn ^ !(Counter & 1) ) - Kit_TruthCopy( pOut, pIn, nVars ); -} - -/**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 negative cofactor of the function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_TruthCofactor0Count( unsigned * pTruth, int nVars, int iVar ) -{ - int nWords = Kit_TruthWordNum( nVars ); - int i, k, Step, Counter = 0; - - assert( iVar < nVars ); - switch ( iVar ) - { - case 0: - for ( i = 0; i < nWords; i++ ) - Counter += Kit_WordCountOnes(pTruth[i] & 0x55555555); - return Counter; - case 1: - for ( i = 0; i < nWords; i++ ) - Counter += Kit_WordCountOnes(pTruth[i] & 0x33333333); - return Counter; - case 2: - for ( i = 0; i < nWords; i++ ) - Counter += Kit_WordCountOnes(pTruth[i] & 0x0F0F0F0F); - return Counter; - case 3: - for ( i = 0; i < nWords; i++ ) - Counter += Kit_WordCountOnes(pTruth[i] & 0x00FF00FF); - return Counter; - case 4: - for ( i = 0; i < nWords; i++ ) - Counter += Kit_WordCountOnes(pTruth[i] & 0x0000FFFF); - return Counter; - default: - Step = (1 << (iVar - 5)); - for ( k = 0; k < nWords; k += 2*Step ) - { - for ( i = 0; i < Step; i++ ) - Counter += Kit_WordCountOnes(pTruth[i]); - pTruth += 2*Step; - } - return Counter; - } -} - -/**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 [Computes negative cofactor of the function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_TruthVarIsVacuous( unsigned * pOnset, unsigned * pOffset, 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 ( ((pOnset[i] & (pOffset[i] >> 1)) | (pOffset[i] & (pOnset[i] >> 1))) & 0x55555555 ) - return 0; - return 1; - case 1: - for ( i = 0; i < nWords; i++ ) - if ( ((pOnset[i] & (pOffset[i] >> 2)) | (pOffset[i] & (pOnset[i] >> 2))) & 0x33333333 ) - return 0; - return 1; - case 2: - for ( i = 0; i < nWords; i++ ) - if ( ((pOnset[i] & (pOffset[i] >> 4)) | (pOffset[i] & (pOnset[i] >> 4))) & 0x0F0F0F0F ) - return 0; - return 1; - case 3: - for ( i = 0; i < nWords; i++ ) - if ( ((pOnset[i] & (pOffset[i] >> 8)) | (pOffset[i] & (pOnset[i] >> 8))) & 0x00FF00FF ) - return 0; - return 1; - case 4: - for ( i = 0; i < nWords; i++ ) - if ( ((pOnset[i] & (pOffset[i] >> 16)) | (pOffset[i] & (pOnset[i] >> 16))) & 0x0000FFFF ) - return 0; - return 1; - default: - Step = (1 << (iVar - 5)); - for ( k = 0; k < nWords; k += 2*Step ) - { - for ( i = 0; i < Step; i++ ) - if ( (pOnset[i] & pOffset[Step+i]) | (pOffset[i] & pOnset[Step+i]) ) - return 0; - pOnset += 2*Step; - pOffset += 2*Step; - } - return 1; - } -} - - -/**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 [Returns the number of minterms in the Boolean difference.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_TruthBooleanDiffCount( unsigned * pTruth, int nVars, int iVar ) -{ - int nWords = Kit_TruthWordNum( nVars ); - int i, k, Step, Counter = 0; - - assert( iVar < nVars ); - switch ( iVar ) - { - case 0: - for ( i = 0; i < nWords; i++ ) - Counter += Kit_WordCountOnes( (pTruth[i] ^ (pTruth[i] >> 1)) & 0x55555555 ); - return Counter; - case 1: - for ( i = 0; i < nWords; i++ ) - Counter += Kit_WordCountOnes( (pTruth[i] ^ (pTruth[i] >> 2)) & 0x33333333 ); - return Counter; - case 2: - for ( i = 0; i < nWords; i++ ) - Counter += Kit_WordCountOnes( (pTruth[i] ^ (pTruth[i] >> 4)) & 0x0F0F0F0F ); - return Counter; - case 3: - for ( i = 0; i < nWords; i++ ) - Counter += Kit_WordCountOnes( (pTruth[i] ^ (pTruth[i] >> 8)) & 0x00FF00FF ); - return Counter; - case 4: - for ( i = 0; i < nWords; i++ ) - Counter += Kit_WordCountOnes( (pTruth[i] ^ (pTruth[i] >>16)) & 0x0000FFFF ); - return Counter; - default: - Step = (1 << (iVar - 5)); - for ( k = 0; k < nWords; k += 2*Step ) - { - for ( i = 0; i < Step; i++ ) - Counter += Kit_WordCountOnes( pTruth[i] ^ pTruth[Step+i] ); - pTruth += 2*Step; - } - return Counter; - } -} - -/**Function************************************************************* - - Synopsis [Returns the number of minterms in the Boolean difference.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_TruthXorCount( unsigned * pTruth0, unsigned * pTruth1, int nVars ) -{ - int nWords = Kit_TruthWordNum( nVars ); - int i, Counter = 0; - for ( i = 0; i < nWords; i++ ) - Counter += Kit_WordCountOnes( pTruth0[i] ^ pTruth1[i] ); - return Counter; -} - -/**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, unsigned * pCof0, unsigned * pCof1 ) -{ - static unsigned uTemp0[32], uTemp1[32]; - if ( pCof0 == NULL ) - { - assert( nVars <= 10 ); - pCof0 = uTemp0; - } - if ( pCof1 == NULL ) - { - assert( nVars <= 10 ); - pCof1 = uTemp1; - } - // compute Cof01 - Kit_TruthCopy( pCof0, pTruth, nVars ); - Kit_TruthCofactor0( pCof0, nVars, iVar0 ); - Kit_TruthCofactor1( pCof0, nVars, iVar1 ); - // compute Cof10 - Kit_TruthCopy( pCof1, pTruth, nVars ); - Kit_TruthCofactor1( pCof1, nVars, iVar0 ); - Kit_TruthCofactor0( pCof1, nVars, iVar1 ); - // compare - return Kit_TruthIsEqual( pCof0, pCof1, nVars ); -} - -/**Function************************************************************* - - Synopsis [Checks antisymmetry of two variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_TruthVarsAntiSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1, unsigned * pCof0, unsigned * pCof1 ) -{ - static unsigned uTemp0[32], uTemp1[32]; - if ( pCof0 == NULL ) - { - assert( nVars <= 10 ); - pCof0 = uTemp0; - } - if ( pCof1 == NULL ) - { - assert( nVars <= 10 ); - pCof1 = uTemp1; - } - // compute Cof00 - Kit_TruthCopy( pCof0, pTruth, nVars ); - Kit_TruthCofactor0( pCof0, nVars, iVar0 ); - Kit_TruthCofactor0( pCof0, nVars, iVar1 ); - // compute Cof11 - Kit_TruthCopy( pCof1, pTruth, nVars ); - Kit_TruthCofactor1( pCof1, nVars, iVar0 ); - Kit_TruthCofactor1( pCof1, nVars, iVar1 ); - // compare - return Kit_TruthIsEqual( pCof0, pCof1, 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 negative cofactor.] - - Description [The resulting numbers are stored in the array of shorts, - whose length is 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_TruthCountOnesInCofs0( unsigned * pTruth, int nVars, short * pStore ) -{ - int nWords = Kit_TruthWordNum( nVars ); - int i, k, Counter; - memset( pStore, 0, sizeof(short) * nVars ); - if ( nVars <= 5 ) - { - if ( nVars > 0 ) - pStore[0] = Kit_WordCountOnes( pTruth[0] & 0x55555555 ); - if ( nVars > 1 ) - pStore[1] = Kit_WordCountOnes( pTruth[0] & 0x33333333 ); - if ( nVars > 2 ) - pStore[2] = Kit_WordCountOnes( pTruth[0] & 0x0F0F0F0F ); - if ( nVars > 3 ) - pStore[3] = Kit_WordCountOnes( pTruth[0] & 0x00FF00FF ); - if ( nVars > 4 ) - pStore[4] = Kit_WordCountOnes( pTruth[0] & 0x0000FFFF ); - 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))) == 0 ) - pStore[i] += Counter; - } - // count 1's for the first five variables - for ( k = 0; k < nWords/2; k++ ) - { - pStore[0] += Kit_WordCountOnes( (pTruth[0] & 0x55555555) | ((pTruth[1] & 0x55555555) << 1) ); - pStore[1] += Kit_WordCountOnes( (pTruth[0] & 0x33333333) | ((pTruth[1] & 0x33333333) << 2) ); - pStore[2] += Kit_WordCountOnes( (pTruth[0] & 0x0F0F0F0F) | ((pTruth[1] & 0x0F0F0F0F) << 4) ); - pStore[3] += Kit_WordCountOnes( (pTruth[0] & 0x00FF00FF) | ((pTruth[1] & 0x00FF00FF) << 8) ); - pStore[4] += Kit_WordCountOnes( (pTruth[0] & 0x0000FFFF) | ((pTruth[1] & 0x0000FFFF) << 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(pIn[0] & 1) - 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 * pBytesInit ) -{ - // 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 * pBytes = pBytesInit; - 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] += pBytesInit[i]; - pBytesInit[i] += pBytesInit[i+Step]; - } - assert( pBytesInit[0] == nTotal ); - assert( iVar == nVars ); - - for ( i = 0; i < nVars; i++ ) - assert( pRes[i] == Kit_TruthCofactor0Count(pTruth, nVars, i) ); - 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; -} - - -/**Function************************************************************* - - Synopsis [Dumps truth table into a file.] - - Description [Generates script file for reading into ABC.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_TruthPrintProfile_int( unsigned * pTruth, int nVars ) -{ - int Mints[20]; - int Mints0[20]; - int Mints1[20]; - int Unique1[20]; - int Total2[20][20]; - int Unique2[20][20]; - int Common2[20][20]; - int nWords = Kit_TruthWordNum( nVars ); - int * pBytes = ABC_ALLOC( int, nWords * 4 ); - unsigned * pIn = ABC_ALLOC( unsigned, nWords ); - unsigned * pOut = ABC_ALLOC( unsigned, nWords ); - unsigned * pCof00 = ABC_ALLOC( unsigned, nWords ); - unsigned * pCof01 = ABC_ALLOC( unsigned, nWords ); - unsigned * pCof10 = ABC_ALLOC( unsigned, nWords ); - unsigned * pCof11 = ABC_ALLOC( unsigned, nWords ); - unsigned * pTemp; - int nTotalMints, nTotalMints0, nTotalMints1; - int v, u, i, iVar, nMints1; - int Cof00, Cof01, Cof10, Cof11; - int Coz00, Coz01, Coz10, Coz11; - assert( nVars <= 20 ); - assert( nVars >= 6 ); - - nTotalMints = Kit_TruthCountMinterms( pTruth, nVars, Mints, pBytes ); - for ( v = 0; v < nVars; v++ ) - Unique1[v] = Kit_TruthBooleanDiffCount( pTruth, nVars, v ); - - for ( v = 0; v < nVars; v++ ) - for ( u = 0; u < nVars; u++ ) - Total2[v][u] = Unique2[v][u] = Common2[v][u] = -1; - - nMints1 = (1<<(nVars-2)); - for ( v = 0; v < nVars; v++ ) - { - // move this var to be the first - Kit_TruthCopy( pIn, pTruth, nVars ); -// Extra_PrintBinary( stdout, pIn, (1<= 0 && Cof00 <= nMints1 ); - assert( Cof01 >= 0 && Cof01 <= nMints1 ); - assert( Cof10 >= 0 && Cof10 <= nMints1 ); - assert( Cof11 >= 0 && Cof11 <= nMints1 ); - - assert( Coz00 >= 0 && Coz00 <= nMints1 ); - assert( Coz01 >= 0 && Coz01 <= nMints1 ); - assert( Coz10 >= 0 && Coz10 <= nMints1 ); - assert( Coz11 >= 0 && Coz11 <= nMints1 ); - - Common2[v][iVar] = Common2[iVar][v] = Cof00 * Coz11 + Coz00 * Cof11 + Cof01 * Coz10 + Coz01 * Cof10; - - Total2[v][iVar] = Total2[iVar][v] = - Cof00 * Coz01 + Coz00 * Cof01 + - Cof00 * Coz10 + Coz00 * Cof10 + - Cof00 * Coz11 + Coz00 * Cof11 + - Cof01 * Coz10 + Coz01 * Cof10 + - Cof01 * Coz11 + Coz01 * Cof11 + - Cof10 * Coz11 + Coz10 * Cof11 ; - - - Kit_TruthCofactor0New( pCof00, pIn, nVars-1, u ); - Kit_TruthCofactor1New( pCof01, pIn, nVars-1, u ); - Kit_TruthCofactor0New( pCof10, pIn+nWords/2, nVars-1, u ); - Kit_TruthCofactor1New( pCof11, pIn+nWords/2, nVars-1, u ); - - Unique2[v][iVar] = Unique2[iVar][v] = - Kit_TruthXorCount( pCof00, pCof01, nVars-1 ) + - Kit_TruthXorCount( pCof00, pCof10, nVars-1 ) + - Kit_TruthXorCount( pCof00, pCof11, nVars-1 ) + - Kit_TruthXorCount( pCof01, pCof10, nVars-1 ) + - Kit_TruthXorCount( pCof01, pCof11, nVars-1 ) + - Kit_TruthXorCount( pCof10, pCof11, nVars-1 ); - } - } - - printf( "\n" ); - printf( " V: " ); - for ( v = 0; v < nVars; v++ ) - printf( "%8c ", v+'a' ); - printf( "\n" ); - - printf( " M: " ); - for ( v = 0; v < nVars; v++ ) - printf( "%8d ", Mints[v] ); - printf( "\n" ); - - printf( " U: " ); - for ( v = 0; v < nVars; v++ ) - printf( "%8d ", Unique1[v] ); - printf( "\n" ); - printf( "\n" ); - - printf( "Unique:\n" ); - for ( i = 0; i < nVars; i++ ) - { - printf( " %2d ", i ); - for ( v = 0; v < nVars; v++ ) - printf( "%8d ", Unique2[i][v] ); - printf( "\n" ); - } - - printf( "Common:\n" ); - for ( i = 0; i < nVars; i++ ) - { - printf( " %2d ", i ); - for ( v = 0; v < nVars; v++ ) - printf( "%8d ", Common2[i][v] ); - printf( "\n" ); - } - - printf( "Total:\n" ); - for ( i = 0; i < nVars; i++ ) - { - printf( " %2d ", i ); - for ( v = 0; v < nVars; v++ ) - printf( "%8d ", Total2[i][v] ); - printf( "\n" ); - } - - ABC_FREE( pIn ); - ABC_FREE( pOut ); - ABC_FREE( pCof00 ); - ABC_FREE( pCof01 ); - ABC_FREE( pCof10 ); - ABC_FREE( pCof11 ); - ABC_FREE( pBytes ); -} - -/**Function************************************************************* - - Synopsis [Dumps truth table into a file.] - - Description [Generates script file for reading into ABC.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_TruthPrintProfile( unsigned * pTruth, int nVars ) -{ - unsigned uTruth[2]; - if ( nVars >= 6 ) - { - Kit_TruthPrintProfile_int( pTruth, nVars ); - return; - } - assert( nVars >= 2 ); - uTruth[0] = pTruth[0]; - uTruth[1] = pTruth[0]; - Kit_TruthPrintProfile( uTruth, 6 ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/kit/kit_.c b/src/aig/kit/kit_.c deleted file mode 100644 index 37be0b49..00000000 --- a/src/aig/kit/kit_.c +++ /dev/null @@ -1,53 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/kit/module.make b/src/aig/kit/module.make deleted file mode 100644 index a592aeec..00000000 --- a/src/aig/kit/module.make +++ /dev/null @@ -1,11 +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/kitPla.c \ - src/aig/kit/kitSop.c \ - src/aig/kit/kitTruth.c diff --git a/src/aig/live/liveness.c b/src/aig/live/liveness.c deleted file mode 100644 index 324865a9..00000000 --- a/src/aig/live/liveness.c +++ /dev/null @@ -1,2575 +0,0 @@ -/**CFile**************************************************************** - - FileName [liveness.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Liveness property checking.] - - Synopsis [Main implementation module.] - - Author [Sayak Ray] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 1, 2009.] - - Revision [$Id: liveness.c,v 1.00 2009/01/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include -#include "main.h" -#include "aig.h" -#include "saig.h" -#include -#include "mainInt.h" - -ABC_NAMESPACE_IMPL_START - -#define PROPAGATE_NAMES -#define MULTIPLE_LTL_FORMULA -#define ALLOW_SAFETY_PROPERTIES - -#define FULL_BIERE_MODE 0 -#define IGNORE_LIVENESS_KEEP_SAFETY_MODE 1 -#define IGNORE_SAFETY_KEEP_LIVENESS_MODE 2 -#define IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE 3 -#define FULL_BIERE_ONE_LOOP_MODE 4 -//#define DUPLICATE_CKT_DEBUG - -extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); -extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); -//char *strdup(const char *string); - -//****************************************** -//external functions defined in ltl_parser.c -//****************************************** -typedef struct ltlNode_t ltlNode; -extern ltlNode *readLtlFormula( char *formula ); -extern void traverseAbstractSyntaxTree( ltlNode *node ); -extern ltlNode *parseFormulaCreateAST( char *inputFormula ); -extern int isWellFormed( ltlNode *topNode ); -extern int checkSignalNameExistence( Abc_Ntk_t *pNtk, ltlNode *topASTNode ); -extern void populateBoolWithAigNodePtr( Abc_Ntk_t *pNtk, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, ltlNode *topASTNode ); -extern int checkAllBoolHaveAIGPointer( ltlNode *topASTNode ); -extern void populateAigPointerUnitGF( Aig_Man_t *pAigNew, ltlNode *topASTNode, Vec_Ptr_t *vSignal, Vec_Vec_t *vAigGFMap ); -extern void setAIGNodePtrOfGloballyNode( ltlNode *astNode, Aig_Obj_t *pObjLo ); -extern Aig_Obj_t *buildLogicFromLTLNode( Aig_Man_t *pAig, ltlNode *pLtlNode ); -extern Aig_Obj_t *retriveAIGPointerFromLTLNode( ltlNode *astNode ); -extern void traverseAbstractSyntaxTree_postFix( ltlNode *node ); -//********************************** -//external function declaration ends -//********************************** - - -/******************************************************************* -LAYOUT OF PI VECTOR: - -+------------------------------------------------------------------------------------------------------------------------------------+ -| TRUE ORIGINAL PI (n) | SAVE(PI) (1) | ORIGINAL LO (k) | SAVED(LO) (1) | SHADOW_ORIGINAL LO (k) | LIVENESS LO (l) | FAIRNESS LO (f) | -+------------------------------------------------------------------------------------------------------------------------------------+ -<------------True PI----------------->|<----------------------------LO---------------------------------------------------------------> - -LAYOUT OF PO VECTOR: - -+-----------------------------------------------------------------------------------------------------------+ -| SOLE PO (1) | ORIGINAL LI (k) | SAVED LI (1) | SHADOW_ORIGINAL LI (k) | LIVENESS LI (l) | FAIRNESS LI (f) | -+-----------------------------------------------------------------------------------------------------------+ -<--True PO--->|<--------------------------------------LI----------------------------------------------------> - -********************************************************************/ - - -static int nodeName_starts_with( Abc_Obj_t *pNode, const char *prefix ) -{ - if( strstr( Abc_ObjName( pNode ), prefix ) == Abc_ObjName( pNode ) ) - return 1; - else - return 0; -} - -void printVecPtrOfString( Vec_Ptr_t *vec ) -{ - int i; - - for( i=0; i< Vec_PtrSize( vec ); i++ ) - { - printf("vec[%d] = %s\n", i, (char *)Vec_PtrEntry(vec, i) ); - } -} - -int getPoIndex( Aig_Man_t *pAig, Aig_Obj_t *pPivot ) -{ - int i; - Aig_Obj_t *pObj; - - Saig_ManForEachPo( pAig, pObj, i ) - { - if( pObj == pPivot ) - return i; - } - return -1; -} - -char * retrieveTruePiName( Abc_Ntk_t *pNtkOld, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, Aig_Obj_t *pObjPivot ) -{ - Aig_Obj_t *pObjOld, *pObj; - Abc_Obj_t *pNode; - int index; - - assert( Saig_ObjIsPi( pAigNew, pObjPivot ) ); - Aig_ManForEachPi( pAigNew, pObj, index ) - if( pObj == pObjPivot ) - break; - assert( index < Aig_ManPiNum( pAigNew ) - Aig_ManRegNum( pAigNew ) ); - if( index == Saig_ManPiNum( pAigNew ) - 1 ) - return "SAVE_BIERE"; - else - { - pObjOld = Aig_ManPi( pAigOld, index ); - pNode = Abc_NtkPi( pNtkOld, index ); - assert( pObjOld->pData == pObjPivot ); - return Abc_ObjName( pNode ); - } -} - -char * retrieveLOName( Abc_Ntk_t *pNtkOld, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, Aig_Obj_t *pObjPivot, Vec_Ptr_t *vLive, Vec_Ptr_t * vFair ) -{ - Aig_Obj_t *pObjOld, *pObj; - Abc_Obj_t *pNode; - int index, oldIndex, originalLatchNum = Saig_ManRegNum(pAigOld), strMatch, i; - char *dummyStr = (char *)malloc( sizeof(char) * 50 ); - - assert( Saig_ObjIsLo( pAigNew, pObjPivot ) ); - Saig_ManForEachLo( pAigNew, pObj, index ) - if( pObj == pObjPivot ) - break; - if( index < originalLatchNum ) - { - oldIndex = Saig_ManPiNum( pAigOld ) + index; - pObjOld = Aig_ManPi( pAigOld, oldIndex ); - pNode = Abc_NtkCi( pNtkOld, oldIndex ); - assert( pObjOld->pData == pObjPivot ); - return Abc_ObjName( pNode ); - } - else if( index == originalLatchNum ) - return "SAVED_LO"; - else if( index > originalLatchNum && index < 2 * originalLatchNum + 1 ) - { - oldIndex = Saig_ManPiNum( pAigOld ) + index - originalLatchNum - 1; - pObjOld = Aig_ManPi( pAigOld, oldIndex ); - pNode = Abc_NtkCi( pNtkOld, oldIndex ); - sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "SHADOW"); - return dummyStr; - } - else if( index >= 2 * originalLatchNum + 1 && index < 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) ) - { - oldIndex = index - 2 * originalLatchNum - 1; - strMatch = 0; - dummyStr[0] = '\0'; - Saig_ManForEachPo( pAigOld, pObj, i ) - { - pNode = Abc_NtkPo( pNtkOld, i ); - //if( strstr( Abc_ObjName( pNode ), "assert_fair" ) != NULL ) - if( nodeName_starts_with( pNode, "assert_fair" ) ) - { - if( strMatch == oldIndex ) - { - sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "LIVENESS"); - //return dummyStr; - break; - } - else - strMatch++; - } - } - assert( dummyStr[0] != '\0' ); - return dummyStr; - } - else if( index >= 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) && index < 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ) - { - oldIndex = index - 2 * originalLatchNum - 1 - Vec_PtrSize( vLive ); - strMatch = 0; - dummyStr[0] = '\0'; - Saig_ManForEachPo( pAigOld, pObj, i ) - { - pNode = Abc_NtkPo( pNtkOld, i ); - //if( strstr( Abc_ObjName( pNode ), "assume_fair" ) != NULL ) - if( nodeName_starts_with( pNode, "assume_fair" ) ) - { - if( strMatch == oldIndex ) - { - sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "FAIRNESS"); - //return dummyStr; - break; - } - else - strMatch++; - } - } - assert( dummyStr[0] != '\0' ); - return dummyStr; - } - else - return "UNKNOWN"; -} - -Vec_Ptr_t *vecPis, *vecPiNames; -Vec_Ptr_t *vecLos, *vecLoNames; - - -int Aig_ManPiCleanupBiere( Aig_Man_t * p ) -{ - int k = 0, nPisOld = Aig_ManPiNum(p); - - p->nObjs[AIG_OBJ_PI] = Vec_PtrSize( p->vPis ); - if ( Aig_ManRegNum(p) ) - p->nTruePis = Aig_ManPiNum(p) - Aig_ManRegNum(p); - - return nPisOld - Aig_ManPiNum(p); -} - - -int Aig_ManPoCleanupBiere( Aig_Man_t * p ) -{ - int k = 0, nPosOld = Aig_ManPoNum(p); - - p->nObjs[AIG_OBJ_PO] = Vec_PtrSize( p->vPos ); - if ( Aig_ManRegNum(p) ) - p->nTruePos = Aig_ManPoNum(p) - Aig_ManRegNum(p); - return nPosOld - Aig_ManPoNum(p); -} - -Aig_Man_t * LivenessToSafetyTransformation( int mode, Abc_Ntk_t * pNtk, Aig_Man_t * p, - Vec_Ptr_t *vLive, Vec_Ptr_t *vFair, Vec_Ptr_t *vAssertSafety, Vec_Ptr_t *vAssumeSafety ) -{ - Aig_Man_t * pNew; - int i, nRegCount; - Aig_Obj_t * pObjSavePi; - Aig_Obj_t *pObjSavedLo, *pObjSavedLi; - Aig_Obj_t *pObj, *pMatch; - Aig_Obj_t *pObjSaveOrSaved, *pObjSaveAndNotSaved, *pObjSavedLoAndEquality; - Aig_Obj_t *pObjShadowLo, *pObjShadowLi, *pObjShadowLiDriver; - Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc; - Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate; - Aig_Obj_t *pObjSafetyPropertyOutput; - Aig_Obj_t *pObjOriginalSafetyPropertyOutput; - Aig_Obj_t *pDriverImage, *pArgument, *collectiveAssertSafety, *collectiveAssumeSafety; - char *nodeName; - int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, piVecIndex = 0, liveLatch = 0, fairLatch = 0; - - vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); - vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); - - vecLos = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); - vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); - - //**************************************************************** - // Step1: create the new manager - // Note: The new manager is created with "2 * Aig_ManObjNumMax(p)" - // nodes, but this selection is arbitrary - need to be justified - //**************************************************************** - pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) ); - pNew->pName = (char *)malloc( strlen( pNtk->pName ) + strlen("_l2s") + 1 ); - sprintf(pNew->pName, "%s_%s", pNtk->pName, "l2s"); - pNew->pSpec = NULL; - - //**************************************************************** - // Step 2: map constant nodes - //**************************************************************** - pObj = Aig_ManConst1( p ); - pObj->pData = Aig_ManConst1( pNew ); - - //**************************************************************** - // Step 3: create true PIs - //**************************************************************** - Saig_ManForEachPi( p, pObj, i ) - { - piCopied++; - pObj->pData = Aig_ObjCreatePi(pNew); - Vec_PtrPush( vecPis, pObj->pData ); - nodeName = Aig_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) )); - Vec_PtrPush( vecPiNames, nodeName ); - } - - //**************************************************************** - // Step 4: create the special Pi corresponding to SAVE - //**************************************************************** - if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) - { - pObjSavePi = Aig_ObjCreatePi( pNew ); - nodeName = "SAVE_BIERE", - Vec_PtrPush( vecPiNames, nodeName ); - } - - //**************************************************************** - // Step 5: create register outputs - //**************************************************************** - Saig_ManForEachLo( p, pObj, i ) - { - loCopied++; - pObj->pData = Aig_ObjCreatePi(pNew); - Vec_PtrPush( vecLos, pObj->pData ); - nodeName = Aig_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) )); - Vec_PtrPush( vecLoNames, nodeName ); - } - - //**************************************************************** - // Step 6: create "saved" register output - //**************************************************************** - if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) - { - loCreated++; - pObjSavedLo = Aig_ObjCreatePi( pNew ); - Vec_PtrPush( vecLos, pObjSavedLo ); - nodeName = "SAVED_LO"; - Vec_PtrPush( vecLoNames, nodeName ); - } - - //**************************************************************** - // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi - //**************************************************************** - if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) - { - pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo ); - pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) ); - } - - //******************************************************************** - // Step 8: create internal nodes - //******************************************************************** - Aig_ManForEachNode( p, pObj, i ) - { - pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - } - - - //******************************************************************** - // Step 8.x : create PO for each safety assertions - // NOTE : Here the output is purposely inverted as it will be thrown to - // dprove - //******************************************************************** - if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) - { - if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) == 0 ) - { - pObjAndAcc = Aig_ManConst1( pNew ); - Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) - { - pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); - pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); - } - pObjOriginalSafetyPropertyOutput = Aig_ObjCreatePo( pNew, Aig_Not(pObjAndAcc) ); - } - else if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) != 0 ) - { - pObjAndAcc = Aig_ManConst1( pNew ); - Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) - { - pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); - pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); - } - collectiveAssertSafety = pObjAndAcc; - - pObjAndAcc = Aig_ManConst1( pNew ); - Vec_PtrForEachEntry( Aig_Obj_t *, vAssumeSafety, pObj, i ) - { - pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); - pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); - } - collectiveAssumeSafety = pObjAndAcc; - pObjOriginalSafetyPropertyOutput = Aig_ObjCreatePo( pNew, Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ) ); - } - else - { - printf("WARNING!! No safety property is found, a new (negated) constant 1 output is created\n"); - pObjOriginalSafetyPropertyOutput = Aig_ObjCreatePo( pNew, Aig_Not( Aig_ManConst1(pNew) ) ); - } - } - - //******************************************************************** - // Step 9: create the safety property output gate for the liveness properties - // discuss with Sat/Alan for an alternative implementation - //******************************************************************** - if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) - { - pObjSafetyPropertyOutput = Aig_ObjCreatePo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData ); - } - - // create register inputs for the original registers - nRegCount = 0; - - Saig_ManForEachLo( p, pObj, i ) - { - pMatch = Saig_ObjLoToLi( p, pObj ); - Aig_ObjCreatePo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) ); - nRegCount++; - liCopied++; - } - - // create register input corresponding to the register "saved" - if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) - { - #ifndef DUPLICATE_CKT_DEBUG - pObjSavedLi = Aig_ObjCreatePo( pNew, pObjSaveOrSaved ); - nRegCount++; - liCreated++; - - //Changed on October 13, 2009 - //pObjAndAcc = NULL; - pObjAndAcc = Aig_ManConst1( pNew ); - - // create the family of shadow registers, then create the cascade of Xnor and And gates for the comparator - Saig_ManForEachLo( p, pObj, i ) - { - pObjShadowLo = Aig_ObjCreatePi( pNew ); - - #ifdef PROPAGATE_NAMES - Vec_PtrPush( vecLos, pObjShadowLo ); - nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ) ) + 10 ); - sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "SHADOW" ); - - Vec_PtrPush( vecLoNames, nodeName ); - #endif - - pObjShadowLiDriver = Aig_Mux( pNew, pObjSaveAndNotSaved, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); - pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver ); - nRegCount++; - loCreated++; liCreated++; - - pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); - pObjXnor = Aig_Not( pObjXor ); - - pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAcc ); - } - - // create the AND gate whose output will be the signal "looped" - pObjSavedLoAndEquality = Aig_And( pNew, pObjSavedLo, pObjAndAcc ); - - // create the master AND gate and corresponding AND and OR logic for the liveness properties - pObjAndAcc = Aig_ManConst1( pNew ); - if( vLive == NULL || Vec_PtrSize( vLive ) == 0 ) - { - printf("Circuit without any liveness property\n"); - } - else - { - Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i ) - { - liveLatch++; - pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); - pObjShadowLo = Aig_ObjCreatePi( pNew ); - - #ifdef PROPAGATE_NAMES - Vec_PtrPush( vecLos, pObjShadowLo ); - nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); - sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "LIVENESS" ); - Vec_PtrPush( vecLoNames, nodeName ); - #endif - - pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) ); - pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver ); - nRegCount++; - loCreated++; liCreated++; - - pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAcc ); - } - } - - pObjLive = pObjAndAcc; - - pObjAndAcc = Aig_ManConst1( pNew ); - if( vFair == NULL || Vec_PtrSize( vFair ) == 0 ) - printf("Circuit without any fairness property\n"); - else - { - Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i ) - { - fairLatch++; - pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); - pObjShadowLo = Aig_ObjCreatePi( pNew ); - - #ifdef PROPAGATE_NAMES - Vec_PtrPush( vecLos, pObjShadowLo ); - nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); - sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "FAIRNESS" ); - Vec_PtrPush( vecLoNames, nodeName ); - #endif - - pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) ); - pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver ); - nRegCount++; - loCreated++; liCreated++; - - pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAcc ); - } - } - - pObjFair = pObjAndAcc; - - //pObjSafetyGate = Aig_Exor( pNew, Aig_Not(Aig_ManConst1( pNew )), Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ) ); - //Following is the actual Biere translation - pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ); - - Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate ); - #endif - } - - Aig_ManSetRegNum( pNew, nRegCount ); - - Aig_ManPiCleanupBiere( pNew ); - Aig_ManPoCleanupBiere( pNew ); - - Aig_ManCleanup( pNew ); - - assert( Aig_ManCheck( pNew ) ); - - if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) - { - assert((Aig_Obj_t *)Vec_PtrEntry(pNew->vPos, Saig_ManPoNum(pNew)+Aig_ObjPioNum(pObjSavedLo)-Saig_ManPiNum(p)-1) == pObjSavedLi); - assert( Saig_ManPiNum( p ) + 1 == Saig_ManPiNum( pNew ) ); - assert( Saig_ManRegNum( pNew ) == Saig_ManRegNum( p ) * 2 + 1 + liveLatch + fairLatch ); - } - - return pNew; -} - - - - - -Aig_Man_t * LivenessToSafetyTransformationAbs( int mode, Abc_Ntk_t * pNtk, Aig_Man_t * p, Vec_Int_t *vFlops, - Vec_Ptr_t *vLive, Vec_Ptr_t *vFair, Vec_Ptr_t *vAssertSafety, Vec_Ptr_t *vAssumeSafety ) -{ - Aig_Man_t * pNew; - int i, nRegCount, iEntry; - Aig_Obj_t * pObjSavePi; - Aig_Obj_t *pObjSavedLo, *pObjSavedLi; - Aig_Obj_t *pObj, *pMatch; - Aig_Obj_t *pObjSaveOrSaved, *pObjSaveAndNotSaved, *pObjSavedLoAndEquality; - Aig_Obj_t *pObjShadowLo, *pObjShadowLi, *pObjShadowLiDriver; - Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc; - Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate; - Aig_Obj_t *pObjSafetyPropertyOutput; - Aig_Obj_t *pDriverImage, *pArgument, *collectiveAssertSafety, *collectiveAssumeSafety; - char *nodeName; - int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, piVecIndex = 0, liveLatch = 0, fairLatch = 0; - - vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); - vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); - - vecLos = Vec_PtrAlloc( Saig_ManRegNum( p ) + Vec_IntSize( vFlops ) + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); - vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p ) + Vec_IntSize( vFlops ) + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); - - //**************************************************************** - // Step1: create the new manager - // Note: The new manager is created with "2 * Aig_ManObjNumMax(p)" - // nodes, but this selection is arbitrary - need to be justified - //**************************************************************** - pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) ); - pNew->pName = (char *)malloc( strlen( pNtk->pName ) + strlen("_l2s") + 1 ); - sprintf(pNew->pName, "%s_%s", pNtk->pName, "l2s"); - pNew->pSpec = NULL; - - //**************************************************************** - // Step 2: map constant nodes - //**************************************************************** - pObj = Aig_ManConst1( p ); - pObj->pData = Aig_ManConst1( pNew ); - - //**************************************************************** - // Step 3: create true PIs - //**************************************************************** - Saig_ManForEachPi( p, pObj, i ) - { - piCopied++; - pObj->pData = Aig_ObjCreatePi(pNew); - Vec_PtrPush( vecPis, pObj->pData ); - nodeName = Aig_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) )); - Vec_PtrPush( vecPiNames, nodeName ); - } - - //**************************************************************** - // Step 4: create the special Pi corresponding to SAVE - //**************************************************************** - if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) - { - pObjSavePi = Aig_ObjCreatePi( pNew ); - nodeName = "SAVE_BIERE", - Vec_PtrPush( vecPiNames, nodeName ); - } - - //**************************************************************** - // Step 5: create register outputs - //**************************************************************** - Saig_ManForEachLo( p, pObj, i ) - { - loCopied++; - pObj->pData = Aig_ObjCreatePi(pNew); - Vec_PtrPush( vecLos, pObj->pData ); - nodeName = Aig_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) )); - Vec_PtrPush( vecLoNames, nodeName ); - } - - //**************************************************************** - // Step 6: create "saved" register output - //**************************************************************** - if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) - { - loCreated++; - pObjSavedLo = Aig_ObjCreatePi( pNew ); - Vec_PtrPush( vecLos, pObjSavedLo ); - nodeName = "SAVED_LO"; - Vec_PtrPush( vecLoNames, nodeName ); - } - - //**************************************************************** - // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi - //**************************************************************** - if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) - { - pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo ); - pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) ); - } - - //******************************************************************** - // Step 8: create internal nodes - //******************************************************************** - Aig_ManForEachNode( p, pObj, i ) - { - pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - } - - - //******************************************************************** - // Step 8.x : create PO for each safety assertions - // NOTE : Here the output is purposely inverted as it will be thrown to - // dprove - //******************************************************************** - if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) - { - if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) == 0 ) - { - pObjAndAcc = Aig_ManConst1( pNew ); - Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) - { - pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); - pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); - } - Aig_ObjCreatePo( pNew, Aig_Not(pObjAndAcc) ); - } - else if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) != 0 ) - { - pObjAndAcc = Aig_ManConst1( pNew ); - Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) - { - pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); - pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); - } - collectiveAssertSafety = pObjAndAcc; - - pObjAndAcc = Aig_ManConst1( pNew ); - Vec_PtrForEachEntry( Aig_Obj_t *, vAssumeSafety, pObj, i ) - { - pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); - pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); - } - collectiveAssumeSafety = pObjAndAcc; - Aig_ObjCreatePo( pNew, Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ) ); - } - else - { - printf("WARNING!! No safety property is found, a new (negated) constant 1 output is created\n"); - Aig_ObjCreatePo( pNew, Aig_Not( Aig_ManConst1(pNew) ) ); - } - } - - //******************************************************************** - // Step 9: create the safety property output gate for the liveness properties - // discuss with Sat/Alan for an alternative implementation - //******************************************************************** - if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) - { - pObjSafetyPropertyOutput = Aig_ObjCreatePo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData ); - } - - // create register inputs for the original registers - nRegCount = 0; - - Saig_ManForEachLo( p, pObj, i ) - { - pMatch = Saig_ObjLoToLi( p, pObj ); - Aig_ObjCreatePo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) ); - nRegCount++; - liCopied++; - } - - // create register input corresponding to the register "saved" - if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) - { - #ifndef DUPLICATE_CKT_DEBUG - pObjSavedLi = Aig_ObjCreatePo( pNew, pObjSaveOrSaved ); - nRegCount++; - liCreated++; - - //Changed on October 13, 2009 - //pObjAndAcc = NULL; - pObjAndAcc = Aig_ManConst1( pNew ); - - // create the family of shadow registers, then create the cascade of Xnor and And gates for the comparator - //Saig_ManForEachLo( p, pObj, i ) - Saig_ManForEachLo( p, pObj, i ) - { - printf("Flop[%d] = %s\n", i, Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ) ); - } - Vec_IntForEachEntry( vFlops, iEntry, i ) - { - pObjShadowLo = Aig_ObjCreatePi( pNew ); - pObj = Aig_ManLo( p, iEntry ); - - #ifdef PROPAGATE_NAMES - Vec_PtrPush( vecLos, pObjShadowLo ); - nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + iEntry ) ) ) + 10 ); - sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + iEntry ) ), "SHADOW" ); - printf("Flop copied [%d] = %s\n", iEntry, nodeName ); - Vec_PtrPush( vecLoNames, nodeName ); - #endif - - pObjShadowLiDriver = Aig_Mux( pNew, pObjSaveAndNotSaved, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); - pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver ); - nRegCount++; - loCreated++; liCreated++; - - pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); - pObjXnor = Aig_Not( pObjXor ); - - pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAcc ); - } - - // create the AND gate whose output will be the signal "looped" - pObjSavedLoAndEquality = Aig_And( pNew, pObjSavedLo, pObjAndAcc ); - - // create the master AND gate and corresponding AND and OR logic for the liveness properties - pObjAndAcc = Aig_ManConst1( pNew ); - if( vLive == NULL || Vec_PtrSize( vLive ) == 0 ) - { - printf("Circuit without any liveness property\n"); - } - else - { - Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i ) - { - liveLatch++; - pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); - pObjShadowLo = Aig_ObjCreatePi( pNew ); - - #ifdef PROPAGATE_NAMES - Vec_PtrPush( vecLos, pObjShadowLo ); - nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); - sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "LIVENESS" ); - Vec_PtrPush( vecLoNames, nodeName ); - #endif - - pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) ); - pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver ); - nRegCount++; - loCreated++; liCreated++; - - pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAcc ); - } - } - - pObjLive = pObjAndAcc; - - pObjAndAcc = Aig_ManConst1( pNew ); - if( vFair == NULL || Vec_PtrSize( vFair ) == 0 ) - printf("Circuit without any fairness property\n"); - else - { - Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i ) - { - fairLatch++; - pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); - pObjShadowLo = Aig_ObjCreatePi( pNew ); - - #ifdef PROPAGATE_NAMES - Vec_PtrPush( vecLos, pObjShadowLo ); - nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); - sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "FAIRNESS" ); - Vec_PtrPush( vecLoNames, nodeName ); - #endif - - pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) ); - pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver ); - nRegCount++; - loCreated++; liCreated++; - - pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAcc ); - } - } - - pObjFair = pObjAndAcc; - - //pObjSafetyGate = Aig_Exor( pNew, Aig_Not(Aig_ManConst1( pNew )), Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ) ); - //Following is the actual Biere translation - pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ); - - Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate ); - #endif - } - - Aig_ManSetRegNum( pNew, nRegCount ); - - Aig_ManPiCleanupBiere( pNew ); - Aig_ManPoCleanupBiere( pNew ); - - Aig_ManCleanup( pNew ); - - assert( Aig_ManCheck( pNew ) ); - - if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) - { - assert((Aig_Obj_t *)Vec_PtrEntry(pNew->vPos, Saig_ManPoNum(pNew)+Aig_ObjPioNum(pObjSavedLo)-Saig_ManPiNum(p)-1) == pObjSavedLi); - assert( Saig_ManPiNum( p ) + 1 == Saig_ManPiNum( pNew ) ); - assert( Saig_ManRegNum( pNew ) == Saig_ManRegNum( p ) + Vec_IntSize( vFlops ) + 1 + liveLatch + fairLatch ); - } - - return pNew; -} - - - -Aig_Man_t * LivenessToSafetyTransformationOneStepLoop( int mode, Abc_Ntk_t * pNtk, Aig_Man_t * p, - Vec_Ptr_t *vLive, Vec_Ptr_t *vFair, Vec_Ptr_t *vAssertSafety, Vec_Ptr_t *vAssumeSafety ) -{ - Aig_Man_t * pNew; - int i, nRegCount; - Aig_Obj_t * pObjSavePi; - Aig_Obj_t *pObj, *pMatch; - Aig_Obj_t *pObjSavedLoAndEquality; - Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc, *pObjAndAccDummy; - Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate; - Aig_Obj_t *pObjSafetyPropertyOutput; - Aig_Obj_t *pDriverImage; - Aig_Obj_t *pObjCorrespondingLi; - Aig_Obj_t *pArgument; - Aig_Obj_t *collectiveAssertSafety, *collectiveAssumeSafety; - - char *nodeName; - int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, piVecIndex = 0; - - if( Aig_ManRegNum( p ) == 0 ) - { - printf("The input AIG contains no register, returning the original AIG as it is\n"); - return p; - } - - vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); - vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); - - vecLos = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); - vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); - - //**************************************************************** - // Step1: create the new manager - // Note: The new manager is created with "2 * Aig_ManObjNumMax(p)" - // nodes, but this selection is arbitrary - need to be justified - //**************************************************************** - pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( "live2safe" ); - pNew->pSpec = NULL; - - //**************************************************************** - // Step 2: map constant nodes - //**************************************************************** - pObj = Aig_ManConst1( p ); - pObj->pData = Aig_ManConst1( pNew ); - - //**************************************************************** - // Step 3: create true PIs - //**************************************************************** - Saig_ManForEachPi( p, pObj, i ) - { - piCopied++; - pObj->pData = Aig_ObjCreatePi(pNew); - Vec_PtrPush( vecPis, pObj->pData ); - nodeName = Aig_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) )); - Vec_PtrPush( vecPiNames, nodeName ); - } - - //**************************************************************** - // Step 4: create the special Pi corresponding to SAVE - //**************************************************************** - if( mode == FULL_BIERE_ONE_LOOP_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE ) - { - pObjSavePi = Aig_ObjCreatePi( pNew ); - nodeName = "SAVE_BIERE", - Vec_PtrPush( vecPiNames, nodeName ); - } - - //**************************************************************** - // Step 5: create register outputs - //**************************************************************** - Saig_ManForEachLo( p, pObj, i ) - { - loCopied++; - pObj->pData = Aig_ObjCreatePi(pNew); - Vec_PtrPush( vecLos, pObj->pData ); - nodeName = Aig_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) )); - Vec_PtrPush( vecLoNames, nodeName ); - } - - //**************************************************************** - // Step 6: create "saved" register output - //**************************************************************** - -#if 0 - loCreated++; - pObjSavedLo = Aig_ObjCreatePi( pNew ); - Vec_PtrPush( vecLos, pObjSavedLo ); - nodeName = "SAVED_LO"; - Vec_PtrPush( vecLoNames, nodeName ); -#endif - - //**************************************************************** - // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi - //**************************************************************** -#if 0 - pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo ); - pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) ); -#endif - - //******************************************************************** - // Step 8: create internal nodes - //******************************************************************** - Aig_ManForEachNode( p, pObj, i ) - { - pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - } - -#if 0 - //******************************************************************** - // Step 8.x : create PO for each safety assertions - //******************************************************************** - Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) - { - pObj->pData = Aig_ObjCreatePo( pNew, Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ) ); - } -#endif - - if( mode == FULL_BIERE_ONE_LOOP_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) - { - if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) == 0 ) - { - pObjAndAcc = NULL; - Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) - { - //pObj->pData = Aig_ObjCreatePo( pNew, Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ) ); - pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); - if( pObjAndAcc == NULL ) - pObjAndAcc = pArgument; - else - { - pObjAndAccDummy = pObjAndAcc; - pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAccDummy ); - } - } - Aig_ObjCreatePo( pNew, Aig_Not(pObjAndAcc) ); - } - else if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) != 0 ) - { - pObjAndAcc = NULL; - Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) - { - //pObj->pData = Aig_ObjCreatePo( pNew, Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ) ); - pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); - if( pObjAndAcc == NULL ) - pObjAndAcc = pArgument; - else - { - pObjAndAccDummy = pObjAndAcc; - pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAccDummy ); - } - } - collectiveAssertSafety = pObjAndAcc; - pObjAndAcc = NULL; - Vec_PtrForEachEntry( Aig_Obj_t *, vAssumeSafety, pObj, i ) - { - //pObj->pData = Aig_ObjCreatePo( pNew, Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ) ); - pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); - if( pObjAndAcc == NULL ) - pObjAndAcc = pArgument; - else - { - pObjAndAccDummy = pObjAndAcc; - pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAccDummy ); - } - } - collectiveAssumeSafety = pObjAndAcc; - Aig_ObjCreatePo( pNew, Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ) ); - } - else - printf("No safety property is specified, hence no safety gate is created\n"); - } - - //******************************************************************** - // Step 9: create the safety property output gate - // create the safety property output gate, this will be the sole true PO - // of the whole circuit, discuss with Sat/Alan for an alternative implementation - //******************************************************************** - - if( mode == FULL_BIERE_ONE_LOOP_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE ) - { - pObjSafetyPropertyOutput = Aig_ObjCreatePo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData ); - } - - // create register inputs for the original registers - nRegCount = 0; - - Saig_ManForEachLo( p, pObj, i ) - { - pMatch = Saig_ObjLoToLi( p, pObj ); - //Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pMatch) ); - Aig_ObjCreatePo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) ); - nRegCount++; - liCopied++; - } - -#if 0 - // create register input corresponding to the register "saved" - pObjSavedLi = Aig_ObjCreatePo( pNew, pObjSaveOrSaved ); - nRegCount++; - liCreated++;7 -#endif - - pObjAndAcc = NULL; - - //**************************************************************************************************** - //For detection of loop of length 1 we do not need any shadow register, we only need equality detector - //between Lo_j and Li_j and then a cascade of AND gates - //**************************************************************************************************** - - if( mode == FULL_BIERE_ONE_LOOP_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE ) - { - Saig_ManForEachLo( p, pObj, i ) - { - pObjCorrespondingLi = Saig_ObjLoToLi( p, pObj ); - - pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0( pObjCorrespondingLi )->pData, Aig_ObjFaninC0( pObjCorrespondingLi ) ) ); - pObjXnor = Aig_Not( pObjXor ); - - if( pObjAndAcc == NULL ) - pObjAndAcc = pObjXnor; - else - { - pObjAndAccDummy = pObjAndAcc; - pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAccDummy ); - } - } - - // create the AND gate whose output will be the signal "looped" - pObjSavedLoAndEquality = Aig_And( pNew, pObjSavePi, pObjAndAcc ); - - // create the master AND gate and corresponding AND and OR logic for the liveness properties - pObjAndAcc = NULL; - if( vLive == NULL || Vec_PtrSize( vLive ) == 0 ) - printf("Circuit without any liveness property\n"); - else - { - Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i ) - { - pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); - if( pObjAndAcc == NULL ) - pObjAndAcc = pDriverImage; - else - { - pObjAndAccDummy = pObjAndAcc; - pObjAndAcc = Aig_And( pNew, pDriverImage, pObjAndAccDummy ); - } - } - } - - if( pObjAndAcc != NULL ) - pObjLive = pObjAndAcc; - else - pObjLive = Aig_ManConst1( pNew ); - - // create the master AND gate and corresponding AND and OR logic for the fairness properties - pObjAndAcc = NULL; - if( vFair == NULL || Vec_PtrSize( vFair ) == 0 ) - printf("Circuit without any fairness property\n"); - else - { - Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i ) - { - pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); - if( pObjAndAcc == NULL ) - pObjAndAcc = pDriverImage; - else - { - pObjAndAccDummy = pObjAndAcc; - pObjAndAcc = Aig_And( pNew, pDriverImage, pObjAndAccDummy ); - } - } - } - - if( pObjAndAcc != NULL ) - pObjFair = pObjAndAcc; - else - pObjFair = Aig_ManConst1( pNew ); - - pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ); - - Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate ); - } - - Aig_ManSetRegNum( pNew, nRegCount ); - - //printf("\nSaig_ManPiNum = %d, Reg Num = %d, before everything, before Pi cleanup\n", Vec_PtrSize( pNew->vPis ), pNew->nRegs ); - - Aig_ManPiCleanupBiere( pNew ); - Aig_ManPoCleanupBiere( pNew ); - - Aig_ManCleanup( pNew ); - - assert( Aig_ManCheck( pNew ) ); - - return pNew; -} - - - -Vec_Ptr_t * populateLivenessVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig ) -{ - Abc_Obj_t * pNode; - int i, liveCounter = 0; - Vec_Ptr_t * vLive; - - vLive = Vec_PtrAlloc( 100 ); - Abc_NtkForEachPo( pNtk, pNode, i ) - //if( strstr( Abc_ObjName( pNode ), "assert_fair") != NULL ) - if( nodeName_starts_with( pNode, "assert_fair" ) ) - { - Vec_PtrPush( vLive, Aig_ManPo( pAig, i ) ); - liveCounter++; - } - printf("Number of liveness property found = %d\n", liveCounter); - return vLive; -} - -Vec_Ptr_t * populateFairnessVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig ) -{ - Abc_Obj_t * pNode; - int i, fairCounter = 0; - Vec_Ptr_t * vFair; - - vFair = Vec_PtrAlloc( 100 ); - Abc_NtkForEachPo( pNtk, pNode, i ) - //if( strstr( Abc_ObjName( pNode ), "assume_fair") != NULL ) - if( nodeName_starts_with( pNode, "assume_fair" ) ) - { - Vec_PtrPush( vFair, Aig_ManPo( pAig, i ) ); - fairCounter++; - } - printf("Number of fairness property found = %d\n", fairCounter); - return vFair; -} - -Vec_Ptr_t * populateSafetyAssertionVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig ) -{ - Abc_Obj_t * pNode; - int i, assertSafetyCounter = 0; - Vec_Ptr_t * vAssertSafety; - - vAssertSafety = Vec_PtrAlloc( 100 ); - Abc_NtkForEachPo( pNtk, pNode, i ) - //if( strstr( Abc_ObjName( pNode ), "Assert") != NULL ) - if( nodeName_starts_with( pNode, "assert_safety" ) || nodeName_starts_with( pNode, "Assert" )) - { - Vec_PtrPush( vAssertSafety, Aig_ManPo( pAig, i ) ); - assertSafetyCounter++; - } - printf("Number of safety property found = %d\n", assertSafetyCounter); - return vAssertSafety; -} - -Vec_Ptr_t * populateSafetyAssumptionVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig ) -{ - Abc_Obj_t * pNode; - int i, assumeSafetyCounter = 0; - Vec_Ptr_t * vAssumeSafety; - - vAssumeSafety = Vec_PtrAlloc( 100 ); - Abc_NtkForEachPo( pNtk, pNode, i ) - //if( strstr( Abc_ObjName( pNode ), "Assert") != NULL ) - if( nodeName_starts_with( pNode, "assume_safety" ) || nodeName_starts_with( pNode, "Assume" )) - { - Vec_PtrPush( vAssumeSafety, Aig_ManPo( pAig, i ) ); - assumeSafetyCounter++; - } - printf("Number of assume_safety property found = %d\n", assumeSafetyCounter); - return vAssumeSafety; -} - -void updateNewNetworkNameManager( Abc_Ntk_t *pNtk, Aig_Man_t *pAig, Vec_Ptr_t *vPiNames, Vec_Ptr_t *vLoNames ) -{ - Aig_Obj_t *pObj; - Abc_Obj_t *pNode; - int i, ntkObjId; - - pNtk->pManName = Nm_ManCreate( Abc_NtkCiNum( pNtk ) ); - - if( vPiNames ) - { - Saig_ManForEachPi( pAig, pObj, i ) - { - ntkObjId = Abc_NtkCi( pNtk, i )->Id; - //printf("Pi %d, Saved Name = %s, id = %d\n", i, Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), Vec_PtrEntry(vPiNames, i), NULL ), ntkObjId); - Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), (char *)Vec_PtrEntry(vPiNames, i), NULL ); - } - } - if( vLoNames ) - { - Saig_ManForEachLo( pAig, pObj, i ) - { - ntkObjId = Abc_NtkCi( pNtk, Saig_ManPiNum( pAig ) + i )->Id; - //printf("Lo %d, Saved name = %s, id = %d\n", i, Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), Vec_PtrEntry(vLoNames, i), NULL ), ntkObjId); - Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), (char *)Vec_PtrEntry(vLoNames, i), NULL ); - } - } - - Abc_NtkForEachPo(pNtk, pNode, i) - { - Abc_ObjAssignName(pNode, "assert_safety_", Abc_ObjName(pNode) ); - } - - // assign latch input names - Abc_NtkForEachLatch(pNtk, pNode, i) - if ( Nm_ManFindNameById(pNtk->pManName, Abc_ObjFanin0(pNode)->Id) == NULL ) - Abc_ObjAssignName( Abc_ObjFanin0(pNode), Abc_ObjName(Abc_ObjFanin0(pNode)), NULL ); -} - - -int Abc_CommandAbcLivenessToSafety( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkTemp, *pNtkNew, *pNtkOld; - Aig_Man_t * pAig, *pAigNew; - int c; - Vec_Ptr_t * vLive, * vFair, *vAssertSafety, *vAssumeSafety; - int directive = -1; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - if( argc == 1 ) - { - assert( directive == -1 ); - directive = FULL_BIERE_MODE; - } - else - { - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "1slh" ) ) != EOF ) - { - switch( c ) - { - case '1': - if( directive == -1 ) - directive = FULL_BIERE_ONE_LOOP_MODE; - else - { - assert( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE || directive == IGNORE_SAFETY_KEEP_LIVENESS_MODE ); - if( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) - directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE; - else - directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE; - } - break; - case 's': - if( directive == -1 ) - directive = IGNORE_SAFETY_KEEP_LIVENESS_MODE; - else - { - if( directive != FULL_BIERE_ONE_LOOP_MODE ) - goto usage; - assert(directive == FULL_BIERE_ONE_LOOP_MODE); - directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE; - } - break; - case 'l': - if( directive == -1 ) - directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE; - else - { - if( directive != FULL_BIERE_ONE_LOOP_MODE ) - goto usage; - assert(directive == FULL_BIERE_ONE_LOOP_MODE); - directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE; - } - break; - case 'h': - goto usage; - default: - goto usage; - } - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if( !Abc_NtkIsStrash( pNtk ) ) - { - printf("The input network was not strashed, strashing....\n"); - pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); - pNtkOld = pNtkTemp; - pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); - vLive = populateLivenessVector( pNtk, pAig ); - vFair = populateFairnessVector( pNtk, pAig ); - vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); - vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); - } - else - { - pAig = Abc_NtkToDar( pNtk, 0, 1 ); - pNtkOld = pNtk; - vLive = populateLivenessVector( pNtk, pAig ); - vFair = populateFairnessVector( pNtk, pAig ); - vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); - vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); - } - - switch( directive ) - { - case FULL_BIERE_MODE: - //if( Vec_PtrSize(vLive) == 0 && Vec_PtrSize(vAssertSafety) == 0 ) - //{ - // printf("Input circuit has NO safety and NO liveness property, original network is not disturbed\n"); - // return 1; - //} - //else - //{ - pAigNew = LivenessToSafetyTransformation( FULL_BIERE_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); - if( Aig_ManRegNum(pAigNew) != 0 ) - printf("A new circuit is produced with\n\t2 POs - one for safety and one for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n"); - break; - //} - case FULL_BIERE_ONE_LOOP_MODE: - //if( Vec_PtrSize(vLive) == 0 && Vec_PtrSize(vAssertSafety) == 0 ) - //{ - // printf("Input circuit has NO safety and NO liveness property, original network is not disturbed\n"); - // return 1; - //} - //else - //{ - pAigNew = LivenessToSafetyTransformationOneStepLoop( FULL_BIERE_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); - if( Aig_ManRegNum(pAigNew) != 0 ) - printf("A new circuit is produced with\n\t2 POs - one for safety and one for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n"); - break; - //} - case IGNORE_LIVENESS_KEEP_SAFETY_MODE: - //if( Vec_PtrSize(vAssertSafety) == 0 ) - //{ - // printf("Input circuit has NO safety property, original network is not disturbed\n"); - // return 1; - //} - //else - //{ - pAigNew = LivenessToSafetyTransformation( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); - if( Aig_ManRegNum(pAigNew) != 0 ) - printf("A new circuit is produced with\n\t1 PO - only for safety property; liveness properties are ignored, if any.\n\tno additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n"); - break; - //} - case IGNORE_SAFETY_KEEP_LIVENESS_MODE: - //if( Vec_PtrSize(vLive) == 0 ) - //{ - // printf("Input circuit has NO liveness property, original network is not disturbed\n"); - // return 1; - //} - //else - //{ - pAigNew = LivenessToSafetyTransformation( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); - if( Aig_ManRegNum(pAigNew) != 0 ) - printf("A new circuit is produced with\n\t1 PO - only for liveness property; safety properties are ignored, if any.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n"); - break; - //} - case IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE: - //if( Vec_PtrSize(vLive) == 0 ) - //{ - // printf("Input circuit has NO liveness property, original network is not disturbed\n"); - // return 1; - //} - //else - //{ - pAigNew = LivenessToSafetyTransformationOneStepLoop( IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); - if( Aig_ManRegNum(pAigNew) != 0 ) - printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nShadow registers are not created\n"); - break; - //} - } - -#if 0 - if( argc == 1 ) - { - pAigNew = LivenessToSafetyTransformation( FULL_BIERE_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); - if( Aig_ManRegNum(pAigNew) != 0 ) - printf("New circuit is produced considering all safety, liveness and fairness outputs.\nBiere's logic is created\n"); - } - else - { - Extra_UtilGetoptReset(); - c = Extra_UtilGetopt( argc, argv, "1lsh" ); - if( c == '1' ) - { - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if( !Abc_NtkIsStrash( pNtk ) ) - { - printf("The input network was not strashed, strashing....\n"); - pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); - pNtkOld = pNtkTemp; - pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); - vLive = populateLivenessVector( pNtk, pAig ); - vFair = populateFairnessVector( pNtk, pAig ); - vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); - vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); - } - else - { - pAig = Abc_NtkToDar( pNtk, 0, 1 ); - pNtkOld = pNtk; - vLive = populateLivenessVector( pNtk, pAig ); - vFair = populateFairnessVector( pNtk, pAig ); - vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); - vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); - } - pAigNew = LivenessToSafetyTransformationOneStepLoop( pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); - } - else if( c == 'l' ) - { - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if( !Abc_NtkIsStrash( pNtk ) ) - { - printf("The input network was not strashed, strashing....\n"); - pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); - pNtkOld = pNtkTemp; - pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); - vLive = populateLivenessVector( pNtk, pAig ); - vFair = populateFairnessVector( pNtk, pAig ); - vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); - vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); - } - else - { - pAig = Abc_NtkToDar( pNtk, 0, 1 ); - pNtkOld = pNtk; - vLive = populateLivenessVector( pNtk, pAig ); - vFair = populateFairnessVector( pNtk, pAig ); - vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); - vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); - } - pAigNew = LivenessToSafetyTransformation( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); - if( Aig_ManRegNum(pAigNew) != 0 ) - printf("New circuit is produced ignoring liveness outputs!\nOnly safety outputs are kept.\nBiere's logic is not created\n"); - } - else if( c == 's' ) - { - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if( !Abc_NtkIsStrash( pNtk ) ) - { - printf("The input network was not strashed, strashing....\n"); - pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); - pNtkOld = pNtkTemp; - pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); - vLive = populateLivenessVector( pNtk, pAig ); - vFair = populateFairnessVector( pNtk, pAig ); - vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); - vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); - } - else - { - pAig = Abc_NtkToDar( pNtk, 0, 1 ); - pNtkOld = pNtk; - vLive = populateLivenessVector( pNtk, pAig ); - vFair = populateFairnessVector( pNtk, pAig ); - vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); - vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); - } - pAigNew = LivenessToSafetyTransformation( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); - if( Aig_ManRegNum(pAigNew) != 0 ) - printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nBiere's logic is created\n"); - } - else if( c == 'h' ) - goto usage; - else - goto usage; - } -#endif - -#if 0 - Aig_ManPrintStats( pAigNew ); - printf("\nDetail statistics*************************************\n"); - printf("Number of true primary inputs = %d\n", Saig_ManPiNum( pAigNew )); - printf("Number of true primary outputs = %d\n", Saig_ManPoNum( pAigNew )); - printf("Number of true latch outputs = %d\n", Saig_ManCiNum( pAigNew ) - Saig_ManPiNum( pAigNew )); - printf("Number of true latch inputs = %d\n", Saig_ManCoNum( pAigNew ) - Saig_ManPoNum( pAigNew )); - printf("Numer of registers = %d\n", Saig_ManRegNum( pAigNew ) ); - printf("\n*******************************************************\n"); -#endif - - pNtkNew = Abc_NtkFromAigPhase( pAigNew ); - pNtkNew->pName = Aig_UtilStrsav( pAigNew->pName ); - - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" ); - - updateNewNetworkNameManager( pNtkNew, pAigNew, vecPiNames, vecLoNames ); - Abc_FrameSetCurrentNetwork( pAbc, pNtkNew ); - -#if 0 -#ifndef DUPLICATE_CKT_DEBUG - Saig_ManForEachPi( pAigNew, pObj, i ) - assert( strcmp( (char *)Vec_PtrEntry(vecPiNames, i), retrieveTruePiName( pNtk, pAig, pAigNew, pObj ) ) == 0 ); - //printf("Name of %d-th Pi = %s, %s\n", i, retrieveTruePiName( pNtk, pAig, pAigNew, pObj ), (char *)Vec_PtrEntry(vecPiNames, i) ); - - Saig_ManForEachLo( pAigNew, pObj, i ) - assert( strcmp( (char *)Vec_PtrEntry(vecLoNames, i), retrieveLOName( pNtk, pAig, pAigNew, pObj, vLive, vFair ) ) == 0 ); -#endif -#endif - - return 0; - -usage: - fprintf( stdout, "usage: l2s [-1lsh]\n" ); - fprintf( stdout, "\t performs Armin Biere's live-to-safe transformation\n" ); - fprintf( stdout, "\t-1 : no shadow logic, presume all loops are self loops\n"); - fprintf( stdout, "\t-l : ignore liveness and fairness outputs\n"); - fprintf( stdout, "\t-s : ignore safety assertions and assumptions\n"); - fprintf( stdout, "\t-h : print command usage\n"); - return 1; -} - -Vec_Int_t * prepareFlopVector( Aig_Man_t * pAig, int vectorLength ) -{ - Vec_Int_t *vFlops; - int i; - - vFlops = Vec_IntAlloc( vectorLength ); - - for( i=0; ipName = Aig_UtilStrsav( pAigNew->pName ); - - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" ); - - updateNewNetworkNameManager( pNtkNew, pAigNew, vecPiNames,vecLoNames ); - Abc_FrameSetCurrentNetwork( pAbc, pNtkNew ); - -#if 0 -#ifndef DUPLICATE_CKT_DEBUG - Saig_ManForEachPi( pAigNew, pObj, i ) - assert( strcmp( (char *)Vec_PtrEntry(vecPiNames, i), retrieveTruePiName( pNtk, pAig, pAigNew, pObj ) ) == 0 ); - //printf("Name of %d-th Pi = %s, %s\n", i, retrieveTruePiName( pNtk, pAig, pAigNew, pObj ), (char *)Vec_PtrEntry(vecPiNames, i) ); - - Saig_ManForEachLo( pAigNew, pObj, i ) - assert( strcmp( (char *)Vec_PtrEntry(vecLoNames, i), retrieveLOName( pNtk, pAig, pAigNew, pObj, vLive, vFair ) ) == 0 ); -#endif -#endif - - return 0; - -usage: - fprintf( stdout, "usage: l2s [-1lsh]\n" ); - fprintf( stdout, "\t performs Armin Biere's live-to-safe transformation\n" ); - fprintf( stdout, "\t-1 : no shadow logic, presume all loops are self loops\n"); - fprintf( stdout, "\t-l : ignore liveness and fairness outputs\n"); - fprintf( stdout, "\t-s : ignore safety assertions and assumptions\n"); - fprintf( stdout, "\t-h : print command usage\n"); - return 1; -} - -Aig_Man_t * LivenessToSafetyTransformationWithLTL( int mode, Abc_Ntk_t * pNtk, Aig_Man_t * p, - Vec_Ptr_t *vLive, Vec_Ptr_t *vFair, Vec_Ptr_t *vAssertSafety, Vec_Ptr_t *vAssumeSafety, - int *numLtlProcessed, Vec_Ptr_t *ltlBuffer ) -{ - Aig_Man_t * pNew; - int i, ii, iii, nRegCount; - Aig_Obj_t * pObjSavePi; - Aig_Obj_t *pObjSavedLo, *pObjSavedLi; - Aig_Obj_t *pObj, *pMatch; - Aig_Obj_t *pObjSaveOrSaved, *pObjSaveAndNotSaved, *pObjSavedLoAndEquality; - Aig_Obj_t *pObjShadowLo, *pObjShadowLi, *pObjShadowLiDriver; - Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc; - Aig_Obj_t *pObjLive, *pObjSafetyGate; - Aig_Obj_t *pObjSafetyPropertyOutput; - Aig_Obj_t *pObjOriginalSafetyPropertyOutput; - Aig_Obj_t *pDriverImage, *pArgument, *collectiveAssertSafety, *collectiveAssumeSafety; - Aig_Obj_t *pNegatedSafetyConjunction = NULL; - Aig_Obj_t *pObjSafetyAndLiveToSafety; - char *nodeName, *pFormula; - int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, piVecIndex = 0, liveLatch = 0, fairLatch = 0; - Vec_Ptr_t *vSignal, *vTopASTNodeArray; - ltlNode *pEnrtyGLOBALLY; - ltlNode *topNodeOfAST, *tempTopASTNode; - Vec_Vec_t *vAigGFMap; - Vec_Ptr_t *vSignalMemory, *vGFFlopMemory, *vPoForLtlProps; - Vec_Ptr_t *vecInputLtlFormulae; - - vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); - vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); - - vecLos = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); - vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); - - //**************************************************************** - //step0: Parsing the LTL formula - //**************************************************************** - //Vec_PtrForEachEntry( char *, pNtk->vLtlProperties, pFormula, i ) - // printf("\ninput LTL formula [%d] = %s\n", i, pFormula ); - - -#ifdef MULTIPLE_LTL_FORMULA - - - //*************************************************************************** - //Reading input LTL formulae from Ntk data-structure and creating - //AST for them, Steps involved: - // parsing -> AST creation -> well-formedness check -> signal name check - //*************************************************************************** - - //resetting numLtlProcessed - *numLtlProcessed = 0; - - if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) - { - //if( ltlBuffer ) - vecInputLtlFormulae = ltlBuffer; - //vecInputLtlFormulae = pNtk->vLtlProperties; - if( vecInputLtlFormulae ) - { - vTopASTNodeArray = Vec_PtrAlloc( Vec_PtrSize( vecInputLtlFormulae ) ); - printf("\n"); - Vec_PtrForEachEntry( char *, vecInputLtlFormulae, pFormula, i ) - { - tempTopASTNode = parseFormulaCreateAST( pFormula ); - //traverseAbstractSyntaxTree_postFix( tempTopASTNode ); - if( tempTopASTNode ) - { - printf("Formula %d: AST is created, ", i+1); - if( isWellFormed( tempTopASTNode ) ) - printf("Well-formedness check PASSED, "); - else - { - printf("Well-formedness check FAILED!!\n"); - printf("AST will be ignored for formula %d, no extra logic will be added for this formula\n", i+1 ); - //do memory management to free the created AST - continue; - } - if( checkSignalNameExistence( pNtk, tempTopASTNode ) ) - printf("Signal check PASSED\n"); - else - { - printf("Signal check FAILED!!"); - printf("AST will be ignored for formula %d, no extra logic will be added for this formula\n", i+1 ); - //do memory management to free the created AST - continue; - } - Vec_PtrPush( vTopASTNodeArray, tempTopASTNode ); - (*numLtlProcessed)++; - } - else - printf("\nNo AST has been created for formula %d, no extra logic will be added\n", i+1 ); - } - } - printf("\n"); - if( Vec_PtrSize( vTopASTNodeArray ) == 0 ) - { - //printf("\nNo AST has been created for any formula; hence the circuit is left untouched\n"); - printf("\nCurrently aborting, need to take care when Vec_PtrSize( vTopASTNodeArray ) == 0\n"); - exit(0); - } - } - - //**************************************************************** - // Step1: create the new manager - // Note: The new manager is created with "2 * Aig_ManObjNumMax(p)" - // nodes, but this selection is arbitrary - need to be justified - //**************************************************************** - pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) ); - pNew->pName = (char *)malloc( strlen( pNtk->pName ) + strlen("_l3s") + 1 ); - sprintf(pNew->pName, "%s_%s", pNtk->pName, "l3s"); - pNew->pSpec = NULL; - - //**************************************************************** - // Step 2: map constant nodes - //**************************************************************** - pObj = Aig_ManConst1( p ); - pObj->pData = Aig_ManConst1( pNew ); - - //**************************************************************** - // Step 3: create true PIs - //**************************************************************** - Saig_ManForEachPi( p, pObj, i ) - { - piCopied++; - pObj->pData = Aig_ObjCreatePi(pNew); - Vec_PtrPush( vecPis, pObj->pData ); - nodeName = Aig_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) )); - Vec_PtrPush( vecPiNames, nodeName ); - } - - //**************************************************************** - // Step 4: create the special Pi corresponding to SAVE - //**************************************************************** - if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) - { - pObjSavePi = Aig_ObjCreatePi( pNew ); - nodeName = "SAVE_BIERE", - Vec_PtrPush( vecPiNames, nodeName ); - } - - //**************************************************************** - // Step 5: create register outputs - //**************************************************************** - Saig_ManForEachLo( p, pObj, i ) - { - loCopied++; - pObj->pData = Aig_ObjCreatePi(pNew); - Vec_PtrPush( vecLos, pObj->pData ); - nodeName = Aig_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) )); - Vec_PtrPush( vecLoNames, nodeName ); - } - - //**************************************************************** - // Step 6: create "saved" register output - //**************************************************************** - if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) - { - loCreated++; - pObjSavedLo = Aig_ObjCreatePi( pNew ); - Vec_PtrPush( vecLos, pObjSavedLo ); - nodeName = "SAVED_LO"; - Vec_PtrPush( vecLoNames, nodeName ); - } - - //**************************************************************** - // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi - //**************************************************************** - if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) - { - pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo ); - pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) ); - } - - //******************************************************************** - // Step 8: create internal nodes - //******************************************************************** - Aig_ManForEachNode( p, pObj, i ) - { - pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - } - - - //******************************************************************** - // Step 8.x : create PO for each safety assertions - // NOTE : Here the output is purposely inverted as it will be thrown to - // dprove - //******************************************************************** - assert( pNegatedSafetyConjunction == NULL ); - if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE) - { - if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) == 0 ) - { - pObjAndAcc = Aig_ManConst1( pNew ); - Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) - { - pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); - pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); - } - pNegatedSafetyConjunction = Aig_Not(pObjAndAcc); - if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) - pObjOriginalSafetyPropertyOutput = Aig_ObjCreatePo( pNew, Aig_Not(pObjAndAcc) ); - } - else if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) != 0 ) - { - pObjAndAcc = Aig_ManConst1( pNew ); - Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) - { - pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); - pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); - } - collectiveAssertSafety = pObjAndAcc; - - pObjAndAcc = Aig_ManConst1( pNew ); - Vec_PtrForEachEntry( Aig_Obj_t *, vAssumeSafety, pObj, i ) - { - pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); - pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); - } - collectiveAssumeSafety = pObjAndAcc; - pNegatedSafetyConjunction = Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ); - if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) - pObjOriginalSafetyPropertyOutput = Aig_ObjCreatePo( pNew, Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ) ); - } - else - { - printf("WARNING!! No safety property is found, a new (negated) constant 1 output is created\n"); - pNegatedSafetyConjunction = Aig_Not( Aig_ManConst1(pNew) ); - if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) - pObjOriginalSafetyPropertyOutput = Aig_ObjCreatePo( pNew, Aig_Not( Aig_ManConst1(pNew) ) ); - } - } - assert( pNegatedSafetyConjunction != NULL ); - - //******************************************************************** - // Step 9: create the safety property output gate for the liveness properties - // discuss with Sat/Alan for an alternative implementation - //******************************************************************** - if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) - { - vPoForLtlProps = Vec_PtrAlloc( Vec_PtrSize( vTopASTNodeArray ) ); - if( Vec_PtrSize( vTopASTNodeArray ) ) - { - //no effective AST for any input LTL property - //must do something graceful - } - for( i=0; ipData ); - Vec_PtrPush( vPoForLtlProps, pObjSafetyPropertyOutput ); - } - } - - //************************************************************************************* - // Step 10: Placeholder PO's were created for Liveness property outputs in the - // last step. FYI, # of new liveness property outputs = # of LTL properties in the circuit - // It is time for creation of loop LI's and other stuff - // Now creating register inputs for the original flops - //************************************************************************************* - nRegCount = 0; - - Saig_ManForEachLo( p, pObj, i ) - { - pMatch = Saig_ObjLoToLi( p, pObj ); - Aig_ObjCreatePo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) ); - nRegCount++; - liCopied++; - } - - //************************************************************************************* - // Step 11: create register input corresponding to the register "saved" - //************************************************************************************* - if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) - { - #ifndef DUPLICATE_CKT_DEBUG - pObjSavedLi = Aig_ObjCreatePo( pNew, pObjSaveOrSaved ); - nRegCount++; - liCreated++; - - pObjAndAcc = Aig_ManConst1( pNew ); - - //************************************************************************************* - // Step 11: create the family of shadow registers, then create the cascade of Xnor - // and And gates for the comparator - //************************************************************************************* - Saig_ManForEachLo( p, pObj, i ) - { - //printf("\nKEMON RENDY = %s", Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i )) ); - //top|route0_target0_queue_with_credit0_queue0 - //top|route0_master0_queue2 - // if( strcmp( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "top|route0_queue1_num[0]" ) == 0 - // || strcmp( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "top|route0_queue1_num[1]" ) == 0 || strcmp( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "top|route0_queue1_num[2]" ) == 0 ) - { - pObjShadowLo = Aig_ObjCreatePi( pNew ); - - #ifdef PROPAGATE_NAMES - Vec_PtrPush( vecLos, pObjShadowLo ); - nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ) ) + 10 ); - sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "SHADOW" ); - - Vec_PtrPush( vecLoNames, nodeName ); - #endif - - pObjShadowLiDriver = Aig_Mux( pNew, pObjSaveAndNotSaved, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); - pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver ); - nRegCount++; - loCreated++; liCreated++; - - pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); - pObjXnor = Aig_Not( pObjXor ); - - pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAcc ); - } - } - - // create the AND gate whose output will be the signal "looped" - pObjSavedLoAndEquality = Aig_And( pNew, pObjSavedLo, pObjAndAcc ); - - // create the master AND gate and corresponding AND and OR logic for the liveness properties - - //************************************************************************************* - // Step 11: logic for LTL properties:- (looped & ~theta) where theta is the input ltl - // property - // Description of some data-structure: - //------------------------------------------------------------------------------------- - // Name | Type | Purpose - //------------------------------------------------------------------------------------- - // vSignalMemory | Vec_Ptr_t * | A vector across all ASTs of the LTL properties - // | | It remembers if OR+Latch for GF node has already been - // | | created for a particular signal. - // | | - // vGFFlopMemory | Vec_Ptr_t * | A vector across all ASTs of the LTL properties - // | | remembers if OR+Latch of a GF node has already been created - // | | - // vSignal | Vec_Ptr_t * | vector for each AST; contains pointers from GF nodes - // | | to AIG signals - // | | - // vAigGFMap | Vec_Vec_t * | vAigGFMap[ index ] = vector of GF nodes pointing to - // | | the same AIG node; "index" is the index of that - // | | AIG node in the vector vSignal - //************************************************************************************* - - vSignalMemory = Vec_PtrAlloc(10); - vGFFlopMemory = Vec_PtrAlloc(10); - - Vec_PtrForEachEntry( ltlNode *, vTopASTNodeArray, topNodeOfAST, iii ) - { - vSignal = Vec_PtrAlloc( 10 ); - vAigGFMap = Vec_VecAlloc( 10 ); - - //************************************************************************************* - //Step 11a: for the current AST, find out the leaf level Boolean signal pointers from - // the NEW aig. - //************************************************************************************* - populateBoolWithAigNodePtr( pNtk, p, pNew, topNodeOfAST ); - assert( checkAllBoolHaveAIGPointer( topNodeOfAST ) ); - - //************************************************************************************* - //Step 11b: for each GF node, compute the pointer in AIG that it should point to - // In particular, if the subtree below GF is some Boolean crown (including the case - // of simple negation, create new logic and populate the AIG pointer in GF node - // accordingly - //************************************************************************************* - populateAigPointerUnitGF( pNew, topNodeOfAST, vSignal, vAigGFMap ); - - //************************************************************************************* - //Step 11c: everything below GF are computed. Now, it is time to create logic for individual - // GF nodes (i.e. the OR gate and the latch and the Boolean crown of the AST - //************************************************************************************* - Vec_PtrForEachEntry( Aig_Obj_t *, vSignal, pObj, i ) - { - //********************************************************* - // Step 11c.1: if the OR+Latch of the particular signal is - // not already created, create it. It may have already been - // created from another property, so check it before creation - //********************************************************* - if( Vec_PtrFind( vSignalMemory, pObj ) == -1 ) - { - liveLatch++; - - pDriverImage = pObj; - pObjShadowLo = Aig_ObjCreatePi( pNew ); - pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) ); - pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver ); - - nRegCount++; - loCreated++; liCreated++; - - Vec_PtrPush( vSignalMemory, pObj ); - Vec_PtrPush( vGFFlopMemory, pObjShadowLo ); - - #if 1 - #ifdef PROPAGATE_NAMES - Vec_PtrPush( vecLos, pObjShadowLo ); - //nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); - //sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "LIVENESS" ); - nodeName = (char *)malloc( 20 ); - sprintf( nodeName, "n%d__%s", Aig_ObjId(pObjShadowLo), "GF_flop" ); - Vec_PtrPush( vecLoNames, nodeName ); - #endif - #endif - } - else - pObjShadowLo = (Aig_Obj_t *)Vec_PtrEntry( vGFFlopMemory, Vec_PtrFind( vSignalMemory, pObj ) ); - - Vec_VecForEachEntryLevel( ltlNode *, vAigGFMap, pEnrtyGLOBALLY, ii, i ) - setAIGNodePtrOfGloballyNode( pEnrtyGLOBALLY, pObjShadowLo); - - - //#ifdef PROPAGATE_NAMES - // Vec_PtrPush( vecLos, pObjShadowLo ); - // nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); - // sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "LIVENESS" ); - // Vec_PtrPush( vecLoNames, nodeName ); - //#endif - - } - - //********************************************************* - //Step 11c.2: creating the Boolean crown - //********************************************************* - buildLogicFromLTLNode( pNew, topNodeOfAST ); - - //********************************************************* - //Step 11c.3: creating logic for (looped & ~theta) and patching - // it with the proper PO - //Note: if ALLOW_SAFETY_PROPERTIES is defined then the final AND - //gate is a conjunction of safety & liveness, i.e. SAFETY & (looped => theta) - //since ABC convention demands a NOT gate at the end, the property logic - //becomes !( SAFETY & (looped => theta) ) = !SAFETY + (looped & !theta) - //********************************************************* - pObjLive = retriveAIGPointerFromLTLNode( topNodeOfAST ); - pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_Not(pObjLive) ); - #ifdef ALLOW_SAFETY_PROPERTIES - printf("liveness output is conjoined with safety assertions\n"); - pObjSafetyAndLiveToSafety = Aig_Or( pNew, pObjSafetyGate, pNegatedSafetyConjunction ); - pObjSafetyPropertyOutput = (Aig_Obj_t *)Vec_PtrEntry( vPoForLtlProps, iii ); - Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyAndLiveToSafety ); - #else - pObjSafetyPropertyOutput = Vec_PtrEntry( vPoForLtlProps, iii ); - Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate ); - #endif - //refreshing vSignal and vAigGFMap arrays - Vec_PtrFree( vSignal ); - Vec_VecFree( vAigGFMap ); - } - - #endif - } -#endif - - Aig_ManSetRegNum( pNew, nRegCount ); - - Aig_ManPiCleanupBiere( pNew ); - Aig_ManPoCleanupBiere( pNew ); - - Aig_ManCleanup( pNew ); - - assert( Aig_ManCheck( pNew ) ); - - if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) - { - assert((Aig_Obj_t *)Vec_PtrEntry(pNew->vPos, Saig_ManPoNum(pNew)+Aig_ObjPioNum(pObjSavedLo)-Saig_ManPiNum(p)-1) == pObjSavedLi); - assert( Saig_ManPiNum( p ) + 1 == Saig_ManPiNum( pNew ) ); - //assert( Saig_ManRegNum( pNew ) == Saig_ManRegNum( p ) * 2 + 1 + liveLatch + fairLatch ); - } - - - return pNew; -} - -int Abc_CommandAbcLivenessToSafetyWithLTL( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkTemp, *pNtkNew, *pNtkOld; - Aig_Man_t * pAig, *pAigNew; - int c; - Vec_Ptr_t * vLive, * vFair, *vAssertSafety, *vAssumeSafety; - int directive = -1; - char *ltfFormulaString = NULL; - int LTL_FLAG = 0, numOfLtlPropOutput; - Vec_Ptr_t *ltlBuffer; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - if( argc == 1 ) - { - assert( directive == -1 ); - directive = FULL_BIERE_MODE; - } - else - { - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "1slhf" ) ) != EOF ) - { - switch( c ) - { - case '1': - if( directive == -1 ) - directive = FULL_BIERE_ONE_LOOP_MODE; - else - { - assert( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE || directive == IGNORE_SAFETY_KEEP_LIVENESS_MODE ); - if( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) - directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE; - else - directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE; - } - break; - case 's': - if( directive == -1 ) - directive = IGNORE_SAFETY_KEEP_LIVENESS_MODE; - else - { - if( directive != FULL_BIERE_ONE_LOOP_MODE ) - goto usage; - assert(directive == FULL_BIERE_ONE_LOOP_MODE); - directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE; - } - break; - case 'l': - if( directive == -1 ) - directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE; - else - { - if( directive != FULL_BIERE_ONE_LOOP_MODE ) - goto usage; - assert(directive == FULL_BIERE_ONE_LOOP_MODE); - directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE; - } - break; - case 'f': - //assert( argc >= 3 ); - //vecLtlFormula = Vec_PtrAlloc( argc - 2 ); - //if( argc >= 3 ) - //{ - // for( t=3; t<=argc; t++ ) - // { - // printf("argv[%d] = %s\n", t-1, argv[t-1]); - // Vec_PtrPush( vecLtlFormula, argv[t-1] ); - // } - //} - //printf("argv[argc] = %s\n", argv[argc-1]); - //ltfFormulaString = argv[2]; - - //LTL_FLAG = 1; - printf("\nILLEGAL FLAG: aborting....\n"); - exit(0); - break; - case 'h': - goto usage; - default: - goto usage; - } - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if( !Abc_NtkIsStrash( pNtk ) ) - { - printf("The input network was not strashed, strashing....\n"); - pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); - pNtkOld = pNtkTemp; - pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); - vLive = populateLivenessVector( pNtk, pAig ); - vFair = populateFairnessVector( pNtk, pAig ); - vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); - vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); - } - else - { - pAig = Abc_NtkToDar( pNtk, 0, 1 ); - pNtkOld = pNtk; - vLive = populateLivenessVector( pNtk, pAig ); - vFair = populateFairnessVector( pNtk, pAig ); - vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); - vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); - } - - if( pAbc->vLTLProperties_global != NULL ) - ltlBuffer = pAbc->vLTLProperties_global; - else - ltlBuffer = NULL; - - switch( directive ) - { - case FULL_BIERE_MODE: - pAigNew = LivenessToSafetyTransformationWithLTL( FULL_BIERE_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety, &numOfLtlPropOutput, ltlBuffer ); - if( Aig_ManRegNum(pAigNew) != 0 ) - printf("A new circuit is produced with\n\t%d POs - one for safety and %d for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n", numOfLtlPropOutput+1, numOfLtlPropOutput); - break; - - case FULL_BIERE_ONE_LOOP_MODE: - pAigNew = LivenessToSafetyTransformationOneStepLoop( FULL_BIERE_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); - if( Aig_ManRegNum(pAigNew) != 0 ) - printf("A new circuit is produced with\n\t2 POs - one for safety and one for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n"); - break; - - case IGNORE_LIVENESS_KEEP_SAFETY_MODE: - pAigNew = LivenessToSafetyTransformationWithLTL( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety, &numOfLtlPropOutput, ltlBuffer ); - assert( numOfLtlPropOutput == 0 ); - if( Aig_ManRegNum(pAigNew) != 0 ) - printf("A new circuit is produced with\n\t1 PO - only for safety property; liveness properties are ignored, if any.\n\tno additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n"); - break; - - case IGNORE_SAFETY_KEEP_LIVENESS_MODE: - pAigNew = LivenessToSafetyTransformationWithLTL( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety, &numOfLtlPropOutput, ltlBuffer ); - if( Aig_ManRegNum(pAigNew) != 0 ) - printf("A new circuit is produced with\n\t%d PO - only for liveness property; safety properties are ignored, if any.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n", numOfLtlPropOutput); - break; - - case IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE: - pAigNew = LivenessToSafetyTransformationOneStepLoop( IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); - if( Aig_ManRegNum(pAigNew) != 0 ) - printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nShadow registers are not created\n"); - break; - } - -#if 0 - if( argc == 1 ) - { - pAigNew = LivenessToSafetyTransformation( FULL_BIERE_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); - if( Aig_ManRegNum(pAigNew) != 0 ) - printf("New circuit is produced considering all safety, liveness and fairness outputs.\nBiere's logic is created\n"); - } - else - { - Extra_UtilGetoptReset(); - c = Extra_UtilGetopt( argc, argv, "1lsh" ); - if( c == '1' ) - { - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if( !Abc_NtkIsStrash( pNtk ) ) - { - printf("The input network was not strashed, strashing....\n"); - pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); - pNtkOld = pNtkTemp; - pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); - vLive = populateLivenessVector( pNtk, pAig ); - vFair = populateFairnessVector( pNtk, pAig ); - vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); - vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); - } - else - { - pAig = Abc_NtkToDar( pNtk, 0, 1 ); - pNtkOld = pNtk; - vLive = populateLivenessVector( pNtk, pAig ); - vFair = populateFairnessVector( pNtk, pAig ); - vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); - vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); - } - pAigNew = LivenessToSafetyTransformationOneStepLoop( pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); - } - else if( c == 'l' ) - { - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if( !Abc_NtkIsStrash( pNtk ) ) - { - printf("The input network was not strashed, strashing....\n"); - pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); - pNtkOld = pNtkTemp; - pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); - vLive = populateLivenessVector( pNtk, pAig ); - vFair = populateFairnessVector( pNtk, pAig ); - vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); - vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); - } - else - { - pAig = Abc_NtkToDar( pNtk, 0, 1 ); - pNtkOld = pNtk; - vLive = populateLivenessVector( pNtk, pAig ); - vFair = populateFairnessVector( pNtk, pAig ); - vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); - vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); - } - pAigNew = LivenessToSafetyTransformation( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); - if( Aig_ManRegNum(pAigNew) != 0 ) - printf("New circuit is produced ignoring liveness outputs!\nOnly safety outputs are kept.\nBiere's logic is not created\n"); - } - else if( c == 's' ) - { - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if( !Abc_NtkIsStrash( pNtk ) ) - { - printf("The input network was not strashed, strashing....\n"); - pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); - pNtkOld = pNtkTemp; - pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); - vLive = populateLivenessVector( pNtk, pAig ); - vFair = populateFairnessVector( pNtk, pAig ); - vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); - vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); - } - else - { - pAig = Abc_NtkToDar( pNtk, 0, 1 ); - pNtkOld = pNtk; - vLive = populateLivenessVector( pNtk, pAig ); - vFair = populateFairnessVector( pNtk, pAig ); - vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); - vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); - } - pAigNew = LivenessToSafetyTransformation( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); - if( Aig_ManRegNum(pAigNew) != 0 ) - printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nBiere's logic is created\n"); - } - else if( c == 'h' ) - goto usage; - else - goto usage; - } -#endif - -#if 0 - Aig_ManPrintStats( pAigNew ); - printf("\nDetail statistics*************************************\n"); - printf("Number of true primary inputs = %d\n", Saig_ManPiNum( pAigNew )); - printf("Number of true primary outputs = %d\n", Saig_ManPoNum( pAigNew )); - printf("Number of true latch outputs = %d\n", Saig_ManCiNum( pAigNew ) - Saig_ManPiNum( pAigNew )); - printf("Number of true latch inputs = %d\n", Saig_ManCoNum( pAigNew ) - Saig_ManPoNum( pAigNew )); - printf("Numer of registers = %d\n", Saig_ManRegNum( pAigNew ) ); - printf("\n*******************************************************\n"); -#endif - - pNtkNew = Abc_NtkFromAigPhase( pAigNew ); - pNtkNew->pName = Aig_UtilStrsav( pAigNew->pName ); - - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" ); - - updateNewNetworkNameManager( pNtkNew, pAigNew, vecPiNames, vecLoNames ); - Abc_FrameSetCurrentNetwork( pAbc, pNtkNew ); - -#if 0 -#ifndef DUPLICATE_CKT_DEBUG - Saig_ManForEachPi( pAigNew, pObj, i ) - assert( strcmp( (char *)Vec_PtrEntry(vecPiNames, i), retrieveTruePiName( pNtk, pAig, pAigNew, pObj ) ) == 0 ); - //printf("Name of %d-th Pi = %s, %s\n", i, retrieveTruePiName( pNtk, pAig, pAigNew, pObj ), (char *)Vec_PtrEntry(vecPiNames, i) ); - - Saig_ManForEachLo( pAigNew, pObj, i ) - assert( strcmp( (char *)Vec_PtrEntry(vecLoNames, i), retrieveLOName( pNtk, pAig, pAigNew, pObj, vLive, vFair ) ) == 0 ); -#endif -#endif - - return 0; - -usage: - fprintf( stdout, "usage: l3s [-1lsh]\n" ); - fprintf( stdout, "\t performs Armin Biere's live-to-safe transformation\n" ); - fprintf( stdout, "\t-1 : no shadow logic, presume all loops are self loops\n"); - fprintf( stdout, "\t-l : ignore liveness and fairness outputs\n"); - fprintf( stdout, "\t-s : ignore safety assertions and assumptions\n"); - fprintf( stdout, "\t-h : print command usage\n"); - return 1; -} - - -ABC_NAMESPACE_IMPL_END diff --git a/src/aig/live/liveness_sim.c b/src/aig/live/liveness_sim.c deleted file mode 100644 index 5e494b87..00000000 --- a/src/aig/live/liveness_sim.c +++ /dev/null @@ -1,848 +0,0 @@ -/**CFile**************************************************************** - - FileName [liveness_sim.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Liveness property checking.] - - Synopsis [Main implementation module.] - - Author [Sayak Ray] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 1, 2009.] - - Revision [$Id: liveness_sim.c,v 1.00 2009/01/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include -#include "main.h" -#include "aig.h" -#include "saig.h" -#include - -ABC_NAMESPACE_IMPL_START - - -#define PROPAGATE_NAMES -//#define DUPLICATE_CKT_DEBUG - -extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); -extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); -//char *strdup(const char *string); - - -/******************************************************************* -LAYOUT OF PI VECTOR: - -+------------------------------------------------------------------------------------------------------------------------------------+ -| TRUE ORIGINAL PI (n) | SAVE(PI) (1) | ORIGINAL LO (k) | SAVED(LO) (1) | SHADOW_ORIGINAL LO (k) | LIVENESS LO (l) | FAIRNESS LO (f) | -+------------------------------------------------------------------------------------------------------------------------------------+ -<------------True PI----------------->|<----------------------------LO---------------------------------------------------------------> - -LAYOUT OF PO VECTOR: - -+-----------------------------------------------------------------------------------------------------------+ -| SOLE PO (1) | ORIGINAL LI (k) | SAVED LI (1) | SHADOW_ORIGINAL LI (k) | LIVENESS LI (l) | FAIRNESS LI (f) | -+-----------------------------------------------------------------------------------------------------------+ -<--True PO--->|<--------------------------------------LI----------------------------------------------------> - -********************************************************************/ - -static void printVecPtrOfString( Vec_Ptr_t *vec ) -{ - int i; - - for( i=0; i< Vec_PtrSize( vec ); i++ ) - { - printf("vec[%d] = %s\n", i, (char *)Vec_PtrEntry(vec, i) ); - } -} - -static int getPoIndex( Aig_Man_t *pAig, Aig_Obj_t *pPivot ) -{ - int i; - Aig_Obj_t *pObj; - - Saig_ManForEachPo( pAig, pObj, i ) - { - if( pObj == pPivot ) - return i; - } - return -1; -} - -static char * retrieveTruePiName( Abc_Ntk_t *pNtkOld, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, Aig_Obj_t *pObjPivot ) -{ - Aig_Obj_t *pObjOld, *pObj; - Abc_Obj_t *pNode; - int index; - - assert( Saig_ObjIsPi( pAigNew, pObjPivot ) ); - Aig_ManForEachPi( pAigNew, pObj, index ) - if( pObj == pObjPivot ) - break; - assert( index < Aig_ManPiNum( pAigNew ) - Aig_ManRegNum( pAigNew ) ); - if( index == Saig_ManPiNum( pAigNew ) - 1 ) - return "SAVE_BIERE"; - else - { - pObjOld = Aig_ManPi( pAigOld, index ); - pNode = Abc_NtkPi( pNtkOld, index ); - assert( pObjOld->pData == pObjPivot ); - return Abc_ObjName( pNode ); - } -} - -static char * retrieveLOName( Abc_Ntk_t *pNtkOld, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, Aig_Obj_t *pObjPivot, Vec_Ptr_t *vLive, Vec_Ptr_t * vFair ) -{ - Aig_Obj_t *pObjOld, *pObj; - Abc_Obj_t *pNode; - int index, oldIndex, originalLatchNum = Saig_ManRegNum(pAigOld), strMatch, i; - char *dummyStr = (char *)malloc( sizeof(char) * 50 ); - - assert( Saig_ObjIsLo( pAigNew, pObjPivot ) ); - Saig_ManForEachLo( pAigNew, pObj, index ) - if( pObj == pObjPivot ) - break; - if( index < originalLatchNum ) - { - oldIndex = Saig_ManPiNum( pAigOld ) + index; - pObjOld = Aig_ManPi( pAigOld, oldIndex ); - pNode = Abc_NtkCi( pNtkOld, oldIndex ); - assert( pObjOld->pData == pObjPivot ); - return Abc_ObjName( pNode ); - } - else if( index == originalLatchNum ) - return "SAVED_LO"; - else if( index > originalLatchNum && index < 2 * originalLatchNum + 1 ) - { - oldIndex = Saig_ManPiNum( pAigOld ) + index - originalLatchNum - 1; - pObjOld = Aig_ManPi( pAigOld, oldIndex ); - pNode = Abc_NtkCi( pNtkOld, oldIndex ); - sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "SHADOW"); - return dummyStr; - } - else if( index >= 2 * originalLatchNum + 1 && index < 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) ) - { - oldIndex = index - 2 * originalLatchNum - 1; - strMatch = 0; - Saig_ManForEachPo( pAigOld, pObj, i ) - { - pNode = Abc_NtkPo( pNtkOld, i ); - if( strstr( Abc_ObjName( pNode ), "assert_fair" ) != NULL ) - { - if( strMatch == oldIndex ) - { - sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "LIVENESS"); - return dummyStr; - } - else - strMatch++; - } - } - } - else if( index >= 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) && index < 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ) - { - oldIndex = index - 2 * originalLatchNum - 1 - Vec_PtrSize( vLive ); - strMatch = 0; - Saig_ManForEachPo( pAigOld, pObj, i ) - { - pNode = Abc_NtkPo( pNtkOld, i ); - if( strstr( Abc_ObjName( pNode ), "assume_fair" ) != NULL ) - { - if( strMatch == oldIndex ) - { - sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "FAIRNESS"); - return dummyStr; - } - else - strMatch++; - } - } - } - else - return "UNKNOWN"; -} - -extern Vec_Ptr_t *vecPis, *vecPiNames; -extern Vec_Ptr_t *vecLos, *vecLoNames; - - -static int Aig_ManPiCleanupBiere( Aig_Man_t * p ) -{ - int k = 0, nPisOld = Aig_ManPiNum(p); - - p->nObjs[AIG_OBJ_PI] = Vec_PtrSize( p->vPis ); - if ( Aig_ManRegNum(p) ) - p->nTruePis = Aig_ManPiNum(p) - Aig_ManRegNum(p); - - return nPisOld - Aig_ManPiNum(p); -} - - -static int Aig_ManPoCleanupBiere( Aig_Man_t * p ) -{ - int k = 0, nPosOld = Aig_ManPoNum(p); - - p->nObjs[AIG_OBJ_PO] = Vec_PtrSize( p->vPos ); - if ( Aig_ManRegNum(p) ) - p->nTruePos = Aig_ManPoNum(p) - Aig_ManRegNum(p); - return nPosOld - Aig_ManPoNum(p); -} - -static Aig_Man_t * LivenessToSafetyTransformationSim( Abc_Ntk_t * pNtk, Aig_Man_t * p, Vec_Ptr_t *vLive, Vec_Ptr_t *vFair ) -{ - Aig_Man_t * pNew; - int i, nRegCount; - Aig_Obj_t * pObjSavePi; - Aig_Obj_t *pObjSavedLo, *pObjSavedLi; - Aig_Obj_t *pObj, *pMatch; - Aig_Obj_t *pObjSaveOrSaved, *pObjSavedLoAndEquality; - Aig_Obj_t *pObjShadowLo, *pObjShadowLi, *pObjShadowLiDriver; - Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc, *pObjAndAccDummy; - Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate; - Aig_Obj_t *pObjSafetyPropertyOutput; - Aig_Obj_t *pDriverImage; - char *nodeName; - int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, piVecIndex = 0, liveLatch = 0, fairLatch = 0; - - vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); - vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); - - vecLos = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); - vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); - -#ifdef DUPLICATE_CKT_DEBUG - printf("\nCode is compiled in DEBUG mode, the input-output behavior will be the same as the original circuit\n"); - printf("Press any key to continue..."); - scanf("%c", &c); -#endif - - //**************************************************************** - // Step1: create the new manager - // Note: The new manager is created with "2 * Aig_ManObjNumMax(p)" - // nodes, but this selection is arbitrary - need to be justified - //**************************************************************** - pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( "live2safe" ); - pNew->pSpec = NULL; - - //**************************************************************** - // Step 2: map constant nodes - //**************************************************************** - pObj = Aig_ManConst1( p ); - pObj->pData = Aig_ManConst1( pNew ); - - //**************************************************************** - // Step 3: create true PIs - //**************************************************************** - Saig_ManForEachPi( p, pObj, i ) - { - piCopied++; - pObj->pData = Aig_ObjCreatePi(pNew); - Vec_PtrPush( vecPis, pObj->pData ); - nodeName = Aig_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) )); - Vec_PtrPush( vecPiNames, nodeName ); - } - - //**************************************************************** - // Step 4: create the special Pi corresponding to SAVE - //**************************************************************** -#ifndef DUPLICATE_CKT_DEBUG - pObjSavePi = Aig_ObjCreatePi( pNew ); - nodeName = Aig_UtilStrsav("SAVE_BIERE"), - Vec_PtrPush( vecPiNames, nodeName ); -#endif - - //**************************************************************** - // Step 5: create register outputs - //**************************************************************** - Saig_ManForEachLo( p, pObj, i ) - { - loCopied++; - pObj->pData = Aig_ObjCreatePi(pNew); - Vec_PtrPush( vecLos, pObj->pData ); - nodeName = Aig_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) )); - Vec_PtrPush( vecLoNames, nodeName ); - } - - //**************************************************************** - // Step 6: create "saved" register output - //**************************************************************** -#ifndef DUPLICATE_CKT_DEBUG - loCreated++; - pObjSavedLo = Aig_ObjCreatePi( pNew ); - Vec_PtrPush( vecLos, pObjSavedLo ); - nodeName = Aig_UtilStrsav("SAVED_LO"); - Vec_PtrPush( vecLoNames, nodeName ); -#endif - - //**************************************************************** - // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi - //**************************************************************** -#ifndef DUPLICATE_CKT_DEBUG - pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo ); - //pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) ); -#endif - - //******************************************************************** - // Step 8: create internal nodes - //******************************************************************** - Aig_ManForEachNode( p, pObj, i ) - { - pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - } - - //******************************************************************** - // Step 9: create the safety property output gate - // create the safety property output gate, this will be the sole true PO - // of the whole circuit, discuss with Sat/Alan for an alternative implementation - //******************************************************************** -#ifndef DUPLICATE_CKT_DEBUG - pObjSafetyPropertyOutput = Aig_ObjCreatePo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData ); -#endif - - //******************************************************************** - // DEBUG: To recreate the same circuit, at least from the input and output - // behavior, we need to copy the original PO - //******************************************************************** -#ifdef DUPLICATE_CKT_DEBUG - Saig_ManForEachPo( p, pObj, i ) - { - Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); - } -#endif - - // create register inputs for the original registers - nRegCount = 0; - - Saig_ManForEachLo( p, pObj, i ) - { - pMatch = Saig_ObjLoToLi( p, pObj ); - //Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pMatch) ); - Aig_ObjCreatePo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) ); - nRegCount++; - liCopied++; - } - - // create register input corresponding to the register "saved" -#ifndef DUPLICATE_CKT_DEBUG - pObjSavedLi = Aig_ObjCreatePo( pNew, pObjSaveOrSaved ); - nRegCount++; - liCreated++; - - pObjAndAcc = NULL; - - // create the family of shadow registers, then create the cascade of Xnor and And gates for the comparator - Saig_ManForEachLo( p, pObj, i ) - { - pObjShadowLo = Aig_ObjCreatePi( pNew ); - -#ifdef PROPAGATE_NAMES - Vec_PtrPush( vecLos, pObjShadowLo ); - nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ) ) + 10 ); - sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "SHADOW" ); - Vec_PtrPush( vecLoNames, nodeName ); -#endif - - pObjShadowLiDriver = Aig_Mux( pNew, pObjSavePi, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); - pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver ); - nRegCount++; - loCreated++; liCreated++; - - pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); - pObjXnor = Aig_Not( pObjXor ); - if( pObjAndAcc == NULL ) - pObjAndAcc = pObjXnor; - else - { - pObjAndAccDummy = pObjAndAcc; - pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAccDummy ); - } - } - - // create the AND gate whose output will be the signal "looped" - pObjSavedLoAndEquality = Aig_And( pNew, pObjSavedLo, pObjAndAcc ); - - // create the master AND gate and corresponding AND and OR logic for the liveness properties - pObjAndAcc = NULL; - if( vLive == NULL || Vec_PtrSize( vLive ) == 0 ) - printf("\nCircuit without any liveness property\n"); - else - { - Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i ) - { - //assert( Aig_ObjIsNode( Aig_ObjChild0( pObj ) ) ); - //Aig_ObjPrint( pNew, pObj ); - liveLatch++; - pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); - pObjShadowLo = Aig_ObjCreatePi( pNew ); - -#ifdef PROPAGATE_NAMES - Vec_PtrPush( vecLos, pObjShadowLo ); - nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); - sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "LIVENESS" ); - Vec_PtrPush( vecLoNames, nodeName ); -#endif - - pObjShadowLiDriver = Aig_Or( pNew, Aig_Mux(pNew, pObjSavePi, Aig_Not(Aig_ManConst1(pNew)), pObjShadowLo), - Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) ); - pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver ); - nRegCount++; - loCreated++; liCreated++; - - if( pObjAndAcc == NULL ) - pObjAndAcc = pObjShadowLo; - else - { - pObjAndAccDummy = pObjAndAcc; - pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAccDummy ); - } - } - } - - if( pObjAndAcc != NULL ) - pObjLive = pObjAndAcc; - else - pObjLive = Aig_ManConst1( pNew ); - - // create the master AND gate and corresponding AND and OR logic for the fairness properties - pObjAndAcc = NULL; - if( vFair == NULL || Vec_PtrSize( vFair ) == 0 ) - printf("\nCircuit without any fairness property\n"); - else - { - Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i ) - { - fairLatch++; - //assert( Aig_ObjIsNode( Aig_ObjChild0( pObj ) ) ); - pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); - pObjShadowLo = Aig_ObjCreatePi( pNew ); - -#ifdef PROPAGATE_NAMES - Vec_PtrPush( vecLos, pObjShadowLo ); - nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); - sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "FAIRNESS" ); - Vec_PtrPush( vecLoNames, nodeName ); -#endif - - pObjShadowLiDriver = Aig_Or( pNew, Aig_Mux(pNew, pObjSavePi, Aig_Not(Aig_ManConst1(pNew)), pObjShadowLo), - Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) ); - pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver ); - nRegCount++; - loCreated++; liCreated++; - - if( pObjAndAcc == NULL ) - pObjAndAcc = pObjShadowLo; - else - { - pObjAndAccDummy = pObjAndAcc; - pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAccDummy ); - } - } - } - - if( pObjAndAcc != NULL ) - pObjFair = pObjAndAcc; - else - pObjFair = Aig_ManConst1( pNew ); - - //pObjSafetyGate = Aig_Exor( pNew, Aig_Not(Aig_ManConst1( pNew )), Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ) ); - pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ); - - Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate ); -#endif - - Aig_ManSetRegNum( pNew, nRegCount ); - - Aig_ManPiCleanupBiere( pNew ); - Aig_ManPoCleanupBiere( pNew ); - - Aig_ManCleanup( pNew ); - assert( Aig_ManCheck( pNew ) ); - -#ifndef DUPLICATE_CKT_DEBUG - assert((Aig_Obj_t *)Vec_PtrEntry(pNew->vPos, Saig_ManPoNum(pNew)+Aig_ObjPioNum(pObjSavedLo)-Saig_ManPiNum(p)-1) == pObjSavedLi); - assert( Saig_ManPoNum( pNew ) == 1 ); - assert( Saig_ManPiNum( p ) + 1 == Saig_ManPiNum( pNew ) ); - assert( Saig_ManRegNum( pNew ) == Saig_ManRegNum( p ) * 2 + 1 + liveLatch + fairLatch ); -#endif - - return pNew; -} - - -static Aig_Man_t * LivenessToSafetyTransformationOneStepLoopSim( Abc_Ntk_t * pNtk, Aig_Man_t * p, Vec_Ptr_t *vLive, Vec_Ptr_t *vFair ) -{ - Aig_Man_t * pNew; - int i, nRegCount; - Aig_Obj_t * pObjSavePi; - Aig_Obj_t *pObj, *pMatch; - Aig_Obj_t *pObjSavedLoAndEquality; - Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc, *pObjAndAccDummy; - Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate; - Aig_Obj_t *pObjSafetyPropertyOutput; - Aig_Obj_t *pDriverImage; - Aig_Obj_t *pObjCorrespondingLi; - - - char *nodeName; - int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, piVecIndex = 0; - - vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); - vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); - - vecLos = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); - vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); - - //**************************************************************** - // Step1: create the new manager - // Note: The new manager is created with "2 * Aig_ManObjNumMax(p)" - // nodes, but this selection is arbitrary - need to be justified - //**************************************************************** - pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( "live2safe" ); - pNew->pSpec = NULL; - - //**************************************************************** - // Step 2: map constant nodes - //**************************************************************** - pObj = Aig_ManConst1( p ); - pObj->pData = Aig_ManConst1( pNew ); - - //**************************************************************** - // Step 3: create true PIs - //**************************************************************** - Saig_ManForEachPi( p, pObj, i ) - { - piCopied++; - pObj->pData = Aig_ObjCreatePi(pNew); - Vec_PtrPush( vecPis, pObj->pData ); - nodeName = Aig_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) )); - Vec_PtrPush( vecPiNames, nodeName ); - } - - //**************************************************************** - // Step 4: create the special Pi corresponding to SAVE - //**************************************************************** - pObjSavePi = Aig_ObjCreatePi( pNew ); - nodeName = "SAVE_BIERE", - Vec_PtrPush( vecPiNames, nodeName ); - - //**************************************************************** - // Step 5: create register outputs - //**************************************************************** - Saig_ManForEachLo( p, pObj, i ) - { - loCopied++; - pObj->pData = Aig_ObjCreatePi(pNew); - Vec_PtrPush( vecLos, pObj->pData ); - nodeName = Aig_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) )); - Vec_PtrPush( vecLoNames, nodeName ); - } - - //**************************************************************** - // Step 6: create "saved" register output - //**************************************************************** - -#if 0 - loCreated++; - pObjSavedLo = Aig_ObjCreatePi( pNew ); - Vec_PtrPush( vecLos, pObjSavedLo ); - nodeName = "SAVED_LO"; - Vec_PtrPush( vecLoNames, nodeName ); -#endif - - //**************************************************************** - // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi - //**************************************************************** -#if 0 - pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo ); - pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) ); -#endif - - //******************************************************************** - // Step 8: create internal nodes - //******************************************************************** - Aig_ManForEachNode( p, pObj, i ) - { - pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - } - - //******************************************************************** - // Step 9: create the safety property output gate - // create the safety property output gate, this will be the sole true PO - // of the whole circuit, discuss with Sat/Alan for an alternative implementation - //******************************************************************** - - pObjSafetyPropertyOutput = Aig_ObjCreatePo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData ); - - // create register inputs for the original registers - nRegCount = 0; - - Saig_ManForEachLo( p, pObj, i ) - { - pMatch = Saig_ObjLoToLi( p, pObj ); - //Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pMatch) ); - Aig_ObjCreatePo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) ); - nRegCount++; - liCopied++; - } - -#if 0 - // create register input corresponding to the register "saved" - pObjSavedLi = Aig_ObjCreatePo( pNew, pObjSaveOrSaved ); - nRegCount++; - liCreated++; -#endif - - pObjAndAcc = NULL; - - //**************************************************************************************************** - //For detection of loop of length 1 we do not need any shadow register, we only need equality detector - //between Lo_j and Li_j and then a cascade of AND gates - //**************************************************************************************************** - - Saig_ManForEachLo( p, pObj, i ) - { - pObjCorrespondingLi = Saig_ObjLoToLi( p, pObj ); - - pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0( pObjCorrespondingLi )->pData, Aig_ObjFaninC0( pObjCorrespondingLi ) ) ); - pObjXnor = Aig_Not( pObjXor ); - - if( pObjAndAcc == NULL ) - pObjAndAcc = pObjXnor; - else - { - pObjAndAccDummy = pObjAndAcc; - pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAccDummy ); - } - } - - // create the AND gate whose output will be the signal "looped" - pObjSavedLoAndEquality = Aig_And( pNew, pObjSavePi, pObjAndAcc ); - - // create the master AND gate and corresponding AND and OR logic for the liveness properties - pObjAndAcc = NULL; - if( vLive == NULL || Vec_PtrSize( vLive ) == 0 ) - printf("\nCircuit without any liveness property\n"); - else - { - Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i ) - { - pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); - if( pObjAndAcc == NULL ) - pObjAndAcc = pDriverImage; - else - { - pObjAndAccDummy = pObjAndAcc; - pObjAndAcc = Aig_And( pNew, pDriverImage, pObjAndAccDummy ); - } - } - } - - if( pObjAndAcc != NULL ) - pObjLive = pObjAndAcc; - else - pObjLive = Aig_ManConst1( pNew ); - - // create the master AND gate and corresponding AND and OR logic for the fairness properties - pObjAndAcc = NULL; - if( vFair == NULL || Vec_PtrSize( vFair ) == 0 ) - printf("\nCircuit without any fairness property\n"); - else - { - Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i ) - { - pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); - if( pObjAndAcc == NULL ) - pObjAndAcc = pDriverImage; - else - { - pObjAndAccDummy = pObjAndAcc; - pObjAndAcc = Aig_And( pNew, pDriverImage, pObjAndAccDummy ); - } - } - } - - if( pObjAndAcc != NULL ) - pObjFair = pObjAndAcc; - else - pObjFair = Aig_ManConst1( pNew ); - - pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ); - - Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate ); - - Aig_ManSetRegNum( pNew, nRegCount ); - - printf("\nSaig_ManPiNum = %d, Reg Num = %d, before everything, before Pi cleanup\n", Vec_PtrSize( pNew->vPis ), pNew->nRegs ); - - Aig_ManPiCleanupBiere( pNew ); - Aig_ManPoCleanupBiere( pNew ); - - Aig_ManCleanup( pNew ); - - assert( Aig_ManCheck( pNew ) ); - - return pNew; -} - - - -static Vec_Ptr_t * populateLivenessVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig ) -{ - Abc_Obj_t * pNode; - int i, liveCounter = 0; - Vec_Ptr_t * vLive; - - vLive = Vec_PtrAlloc( 100 ); - Abc_NtkForEachPo( pNtk, pNode, i ) - if( strstr( Abc_ObjName( pNode ), "assert_fair") != NULL ) - { - Vec_PtrPush( vLive, Aig_ManPo( pAig, i ) ); - liveCounter++; - } - printf("\nNumber of liveness property found = %d\n", liveCounter); - return vLive; -} - -static Vec_Ptr_t * populateFairnessVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig ) -{ - Abc_Obj_t * pNode; - int i, fairCounter = 0; - Vec_Ptr_t * vFair; - - vFair = Vec_PtrAlloc( 100 ); - Abc_NtkForEachPo( pNtk, pNode, i ) - if( strstr( Abc_ObjName( pNode ), "assume_fair") != NULL ) - { - Vec_PtrPush( vFair, Aig_ManPo( pAig, i ) ); - fairCounter++; - } - printf("\nNumber of fairness property found = %d\n", fairCounter); - return vFair; -} - -static void updateNewNetworkNameManager( Abc_Ntk_t *pNtk, Aig_Man_t *pAig, Vec_Ptr_t *vPiNames, Vec_Ptr_t *vLoNames ) -{ - Aig_Obj_t *pObj; - int i, ntkObjId; - - pNtk->pManName = Nm_ManCreate( Abc_NtkCiNum( pNtk ) ); - - Saig_ManForEachPi( pAig, pObj, i ) - { - ntkObjId = Abc_NtkCi( pNtk, i )->Id; - //printf("Pi %d, Saved Name = %s, id = %d\n", i, Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), Vec_PtrEntry(vPiNames, i), NULL ), ntkObjId); - Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), (char *)Vec_PtrEntry(vPiNames, i), NULL ); - } - Saig_ManForEachLo( pAig, pObj, i ) - { - ntkObjId = Abc_NtkCi( pNtk, Saig_ManPiNum( pAig ) + i )->Id; - //printf("Lo %d, Saved name = %s, id = %d\n", i, Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), Vec_PtrEntry(vLoNames, i), NULL ), ntkObjId); - Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), (char *)Vec_PtrEntry(vLoNames, i), NULL ); - } -} - - -int Abc_CommandAbcLivenessToSafetySim( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkTemp, *pNtkNew, *pNtkOld; - Aig_Man_t * pAig, *pAigNew; - int c; - Vec_Ptr_t * vLive, * vFair; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if( !Abc_NtkIsStrash( pNtk ) ) - { - printf("\nThe input network was not strashed, strashing....\n"); - pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); - pNtkOld = pNtkTemp; - pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); - vLive = populateLivenessVector( pNtk, pAig ); - vFair = populateFairnessVector( pNtk, pAig ); - } - else - { - pAig = Abc_NtkToDar( pNtk, 0, 1 ); - pNtkOld = pNtk; - vLive = populateLivenessVector( pNtk, pAig ); - vFair = populateFairnessVector( pNtk, pAig ); - } - -#if 0 - Aig_ManPrintStats( pAig ); - printf("\nDetail statistics*************************************\n"); - printf("Number of true primary inputs = %d\n", Saig_ManPiNum( pAig )); - printf("Number of true primary outputs = %d\n", Saig_ManPoNum( pAig )); - printf("Number of true latch outputs = %d\n", Saig_ManCiNum( pAig ) - Saig_ManPiNum( pAig )); - printf("Number of true latch inputs = %d\n", Saig_ManCoNum( pAig ) - Saig_ManPoNum( pAig )); - printf("Numer of registers = %d\n", Saig_ManRegNum( pAig ) ); - printf("\n*******************************************************\n"); -#endif - - c = Extra_UtilGetopt( argc, argv, "1" ); - if( c == '1' ) - pAigNew = LivenessToSafetyTransformationOneStepLoopSim( pNtk, pAig, vLive, vFair ); - else - pAigNew = LivenessToSafetyTransformationSim( pNtk, pAig, vLive, vFair ); - -#if 0 - Aig_ManPrintStats( pAigNew ); - printf("\nDetail statistics*************************************\n"); - printf("Number of true primary inputs = %d\n", Saig_ManPiNum( pAigNew )); - printf("Number of true primary outputs = %d\n", Saig_ManPoNum( pAigNew )); - printf("Number of true latch outputs = %d\n", Saig_ManCiNum( pAigNew ) - Saig_ManPiNum( pAigNew )); - printf("Number of true latch inputs = %d\n", Saig_ManCoNum( pAigNew ) - Saig_ManPoNum( pAigNew )); - printf("Numer of registers = %d\n", Saig_ManRegNum( pAigNew ) ); - printf("\n*******************************************************\n"); -#endif - - pNtkNew = Abc_NtkFromAigPhase( pAigNew ); - - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" ); - - updateNewNetworkNameManager( pNtkNew, pAigNew, vecPiNames,vecLoNames ); - Abc_FrameSetCurrentNetwork( pAbc, pNtkNew ); - - //Saig_ManForEachPi( pAigNew, pObj, i ) - // printf("Name of %d-th Pi = %s\n", i, retrieveTruePiName( pNtk, pAig, pAigNew, pObj ) ); - - //Saig_ManForEachLo( pAigNew, pObj, i ) - // printf("Name of %d-th Lo = %s\n", i, retrieveLOName( pNtk, pAig, pAigNew, pObj, vLive, vFair ) ); - - //printVecPtrOfString( vecPiNames ); - //printVecPtrOfString( vecLoNames ); - -#if 0 -#ifndef DUPLICATE_CKT_DEBUG - Saig_ManForEachPi( pAigNew, pObj, i ) - assert( strcmp( (char *)Vec_PtrEntry(vecPiNames, i), retrieveTruePiName( pNtk, pAig, pAigNew, pObj ) ) == 0 ); - //printf("Name of %d-th Pi = %s, %s\n", i, retrieveTruePiName( pNtk, pAig, pAigNew, pObj ), (char *)Vec_PtrEntry(vecPiNames, i) ); - - Saig_ManForEachLo( pAigNew, pObj, i ) - assert( strcmp( (char *)Vec_PtrEntry(vecLoNames, i), retrieveLOName( pNtk, pAig, pAigNew, pObj, vLive, vFair ) ) == 0 ); -#endif -#endif - - return 0; - -} -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/live/ltl_parser.c b/src/aig/live/ltl_parser.c deleted file mode 100644 index de113ba7..00000000 --- a/src/aig/live/ltl_parser.c +++ /dev/null @@ -1,839 +0,0 @@ -/**CFile**************************************************************** - - FileName [ltl_parser.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Liveness property checking.] - - Synopsis [LTL checker.] - - Author [Sayak Ray] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 1, 2009.] - - Revision [$Id: ltl_parser.c,v 1.00 2009/01/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include -#include -#include -#include -#include "aig.h" -#include "abc.h" -#include "mainInt.h" - -ABC_NAMESPACE_IMPL_START - - -enum ltlToken { AND, OR, NOT, IMPLY, GLOBALLY, EVENTUALLY, NEXT, UNTIL, BOOL }; -enum ltlGrammerToken { OPERAND, LTL, BINOP, UOP }; -typedef enum ltlToken tokenType; -typedef enum ltlGrammerToken ltlGrammerTokenType; - -struct ltlNode_t -{ - tokenType type; - char *name; - Aig_Obj_t *pObj; - struct ltlNode_t *left; - struct ltlNode_t *right; -}; - -typedef struct ltlNode_t ltlNode; - -ltlNode *generateTypedNode( tokenType new_type ) -//void generateTypedNode( ltlNode *new_node, tokenType new_type ) -{ - ltlNode *new_node; - - new_node = (ltlNode *)malloc( sizeof(ltlNode) ); - if( new_node ) - { - new_node->type = new_type; - new_node->pObj = NULL; - new_node->name = NULL; - new_node->left = NULL; - new_node->right = NULL; - } - - return new_node; -} - -Aig_Obj_t *buildLogicFromLTLNode_combinationalOnly( Aig_Man_t *pAig, ltlNode *pLtlNode ); - -static inline int isNotVarNameSymbol( char c ) -{ - return ( c == ' ' || c == '\t' || c == '\n' || c == ':' || c == '\0' ); -} - -void Abc_FrameCopyLTLDataBase( Abc_Frame_t *pAbc, Abc_Ntk_t * pNtk ) -{ - char *pLtlFormula, *tempFormula; - int i; - - if( pAbc->vLTLProperties_global != NULL ) - { -// printf("Deleting exisitng LTL database from the frame\n"); - Vec_PtrFree( pAbc->vLTLProperties_global ); - pAbc->vLTLProperties_global = NULL; - } - pAbc->vLTLProperties_global = Vec_PtrAlloc(Vec_PtrSize(pNtk->vLtlProperties)); - Vec_PtrForEachEntry( char *, pNtk->vLtlProperties, pLtlFormula, i ) - { - tempFormula = (char *)malloc( sizeof(char)*(strlen(pLtlFormula)+1) ); - sprintf( tempFormula, "%s", pLtlFormula ); - Vec_PtrPush( pAbc->vLTLProperties_global, tempFormula ); - } -} - -char *getVarName( char *suffixFormula, int startLoc, int *endLocation ) -{ - int i = startLoc, length; - char *name; - - if( isNotVarNameSymbol( suffixFormula[startLoc] ) ) - return NULL; - - while( !isNotVarNameSymbol( suffixFormula[i] ) ) - i++; - *endLocation = i; - length = i - startLoc; - name = (char *)malloc( sizeof(char) * (length + 1)); - for( i=0; i= (int)strlen( formula ) ) - { - printf("\nInvalid LTL formula: unexpected end of string..." ); - return 1; - } - return 0; -} - -int isTemporalOperator( char *formula, int index ) -{ - if( !(isUnexpectedEOS( formula, index ) || formula[ index ] == 'G' || formula[ index ] == 'F' || formula[ index ] == 'U' || formula[ index ] == 'X') ) - { - printf("\nInvalid LTL formula: expecting temporal operator at the position %d....\n", index); - return 0; - } - return 1; -} - -ltlNode *readLtlFormula( char *formula ) -{ - char ch; - char *varName; - int formulaLength, rememberEnd; - int i = startOfSuffixString; - ltlNode *curr_node, *temp_node_left, *temp_node_right; - char prevChar; - - formulaLength = strlen( formula ); - if( isUnexpectedEOS( formula, startOfSuffixString ) ) - { - printf("\nFAULTING POINT: formula = %s\nstartOfSuffixString = %d, formula[%d] = %c\n\n", formula, startOfSuffixString, startOfSuffixString - 1, formula[startOfSuffixString-1]); - return NULL; - } - - while( i < formulaLength ) - { - ch = formula[i]; - - switch(ch){ - case ' ': - case '\n': - case '\r': - case '\t': - case '\v': - case '\f': - i++; - startOfSuffixString = i; - break; - case ':': - i++; - if( !isTemporalOperator( formula, i ) ) - return NULL; - startOfSuffixString = i; - break; - case 'G': - prevChar = formula[i-1]; - if( prevChar == ':' ) //i.e. 'G' is a temporal operator - { - i++; - startOfSuffixString = i; - temp_node_left = readLtlFormula( formula ); - if( temp_node_left == NULL ) - return NULL; - else - { - curr_node = generateTypedNode(GLOBALLY); - curr_node->left = temp_node_left; - return curr_node; - } - } - else //i.e. 'G' must be starting a variable name - { - varName = getVarName( formula, i, &rememberEnd ); - if( !varName ) - { - printf("\nInvalid LTL formula: expecting valid variable name token...aborting" ); - return NULL; - } - curr_node = generateTypedNode(BOOL); - curr_node->name = varName; - i = rememberEnd; - startOfSuffixString = i; - return curr_node; - } - case 'F': - prevChar = formula[i-1]; - if( prevChar == ':' ) //i.e. 'F' is a temporal operator - { - i++; - startOfSuffixString = i; - temp_node_left = readLtlFormula( formula ); - if( temp_node_left == NULL ) - return NULL; - else - { - curr_node = generateTypedNode(EVENTUALLY); - curr_node->left = temp_node_left; - return curr_node; - } - } - else //i.e. 'F' must be starting a variable name - { - varName = getVarName( formula, i, &rememberEnd ); - if( !varName ) - { - printf("\nInvalid LTL formula: expecting valid variable name token...aborting" ); - return NULL; - } - curr_node = generateTypedNode(BOOL); - curr_node->name = varName; - i = rememberEnd; - startOfSuffixString = i; - return curr_node; - } - case 'X': - prevChar = formula[i-1]; - if( prevChar == ':' ) //i.e. 'X' is a temporal operator - { - i++; - startOfSuffixString = i; - temp_node_left = readLtlFormula( formula ); - if( temp_node_left == NULL ) - return NULL; - else - { - curr_node = generateTypedNode(NEXT); - curr_node->left = temp_node_left; - return curr_node; - } - } - else //i.e. 'X' must be starting a variable name - { - varName = getVarName( formula, i, &rememberEnd ); - if( !varName ) - { - printf("\nInvalid LTL formula: expecting valid variable name token...aborting" ); - return NULL; - } - curr_node = generateTypedNode(BOOL); - curr_node->name = varName; - i = rememberEnd; - startOfSuffixString = i; - return curr_node; - } - case 'U': - prevChar = formula[i-1]; - if( prevChar == ':' ) //i.e. 'X' is a temporal operator - { - i++; - startOfSuffixString = i; - temp_node_left = readLtlFormula( formula ); - if( temp_node_left == NULL ) - return NULL; - temp_node_right = readLtlFormula( formula ); - if( temp_node_right == NULL ) - { - //need to do memory management: if right subtree is NULL then left - //subtree must be freed. - return NULL; - } - curr_node = generateTypedNode(UNTIL); - curr_node->left = temp_node_left; - curr_node->right = temp_node_right; - return curr_node; - } - else //i.e. 'U' must be starting a variable name - { - varName = getVarName( formula, i, &rememberEnd ); - if( !varName ) - { - printf("\nInvalid LTL formula: expecting valid variable name token...aborting" ); - return NULL; - } - curr_node = generateTypedNode(BOOL); - curr_node->name = varName; - i = rememberEnd; - startOfSuffixString = i; - return curr_node; - } - case '+': - i++; - startOfSuffixString = i; - temp_node_left = readLtlFormula( formula ); - if( temp_node_left == NULL ) - return NULL; - temp_node_right = readLtlFormula( formula ); - if( temp_node_right == NULL ) - { - //need to do memory management: if right subtree is NULL then left - //subtree must be freed. - return NULL; - } - curr_node = generateTypedNode(OR); - curr_node->left = temp_node_left; - curr_node->right = temp_node_right; - return curr_node; - case '&': - i++; - startOfSuffixString = i; - temp_node_left = readLtlFormula( formula ); - if( temp_node_left == NULL ) - return NULL; - temp_node_right = readLtlFormula( formula ); - if( temp_node_right == NULL ) - { - //need to do memory management: if right subtree is NULL then left - //subtree must be freed. - return NULL; - } - curr_node = generateTypedNode(AND); - curr_node->left = temp_node_left; - curr_node->right = temp_node_right; - return curr_node; - case '!': - i++; - startOfSuffixString = i; - temp_node_left = readLtlFormula( formula ); - if( temp_node_left == NULL ) - return NULL; - else - { - curr_node = generateTypedNode(NOT); - curr_node->left = temp_node_left; - return curr_node; - } - default: - varName = getVarName( formula, i, &rememberEnd ); - if( !varName ) - { - printf("\nInvalid LTL formula: expecting valid variable name token...aborting" ); - return NULL; - } - curr_node = generateTypedNode(BOOL); - curr_node->name = varName; - i = rememberEnd; - startOfSuffixString = i; - return curr_node; - } - } - return NULL; -} - -void resetGlobalVar() -{ - startOfSuffixString = 0; -} - -ltlNode *parseFormulaCreateAST( char *inputFormula ) -{ - ltlNode *temp; - - temp = readLtlFormula( inputFormula ); - //if( temp == NULL ) - // printf("\nAST creation failed for formula %s", inputFormula ); - resetGlobalVar(); - return temp; -} - -void traverseAbstractSyntaxTree( ltlNode *node ) -{ - switch(node->type){ - case( AND ): - printf("& "); - assert( node->left != NULL ); - assert( node->right != NULL ); - traverseAbstractSyntaxTree( node->left ); - traverseAbstractSyntaxTree( node->right ); - return; - case( OR ): - printf("+ "); - assert( node->left != NULL ); - assert( node->right != NULL ); - traverseAbstractSyntaxTree( node->left ); - traverseAbstractSyntaxTree( node->right ); - return; - case( NOT ): - printf("~ "); - assert( node->left != NULL ); - traverseAbstractSyntaxTree( node->left ); - assert( node->right == NULL ); - return; - case( GLOBALLY ): - printf("G "); - assert( node->left != NULL ); - traverseAbstractSyntaxTree( node->left ); - assert( node->right == NULL ); - return; - case( EVENTUALLY ): - printf("F "); - assert( node->left != NULL ); - traverseAbstractSyntaxTree( node->left ); - assert( node->right == NULL ); - return; - case( NEXT ): - printf("X "); - assert( node->left != NULL ); - traverseAbstractSyntaxTree( node->left ); - assert( node->right == NULL ); - return; - case( UNTIL ): - printf("U "); - assert( node->left != NULL ); - assert( node->right != NULL ); - traverseAbstractSyntaxTree( node->left ); - traverseAbstractSyntaxTree( node->right ); - return; - case( BOOL ): - printf("%s ", node->name); - assert( node->left == NULL ); - assert( node->right == NULL ); - return; - default: - printf("\nUnsupported token type: Exiting execution\n"); - exit(0); - } -} - -void traverseAbstractSyntaxTree_postFix( ltlNode *node ) -{ - switch(node->type){ - case( AND ): - printf("( "); - assert( node->left != NULL ); - assert( node->right != NULL ); - traverseAbstractSyntaxTree_postFix( node->left ); - printf("& "); - traverseAbstractSyntaxTree_postFix( node->right ); - printf(") "); - return; - case( OR ): - printf("( "); - assert( node->left != NULL ); - assert( node->right != NULL ); - traverseAbstractSyntaxTree_postFix( node->left ); - printf("+ "); - traverseAbstractSyntaxTree_postFix( node->right ); - printf(") "); - return; - case( NOT ): - printf("~ "); - assert( node->left != NULL ); - traverseAbstractSyntaxTree_postFix( node->left ); - assert( node->right == NULL ); - return; - case( GLOBALLY ): - printf("G "); - //printf("( "); - assert( node->left != NULL ); - traverseAbstractSyntaxTree_postFix( node->left ); - assert( node->right == NULL ); - //printf(") "); - return; - case( EVENTUALLY ): - printf("F "); - //printf("( "); - assert( node->left != NULL ); - traverseAbstractSyntaxTree_postFix( node->left ); - assert( node->right == NULL ); - //printf(") "); - return; - case( NEXT ): - printf("X "); - assert( node->left != NULL ); - traverseAbstractSyntaxTree_postFix( node->left ); - assert( node->right == NULL ); - return; - case( UNTIL ): - printf("( "); - assert( node->left != NULL ); - assert( node->right != NULL ); - traverseAbstractSyntaxTree_postFix( node->left ); - printf("U "); - traverseAbstractSyntaxTree_postFix( node->right ); - printf(") "); - return; - case( BOOL ): - printf("%s ", node->name); - assert( node->left == NULL ); - assert( node->right == NULL ); - return; - default: - printf("\nUnsupported token type: Exiting execution\n"); - exit(0); - } -} - -void populateAigPointerUnitGF( Aig_Man_t *pAigNew, ltlNode *topASTNode, Vec_Ptr_t *vSignal, Vec_Vec_t *vAigGFMap ) -{ - ltlNode *nextNode, *nextToNextNode; - int serialNumSignal; - - switch( topASTNode->type ){ - case AND: - case OR: - case IMPLY: - populateAigPointerUnitGF( pAigNew, topASTNode->left, vSignal, vAigGFMap ); - populateAigPointerUnitGF( pAigNew, topASTNode->right, vSignal, vAigGFMap ); - return; - case NOT: - populateAigPointerUnitGF( pAigNew, topASTNode->left, vSignal, vAigGFMap ); - return; - case GLOBALLY: - nextNode = topASTNode->left; - assert( nextNode->type = EVENTUALLY ); - nextToNextNode = nextNode->left; - if( nextToNextNode->type == BOOL ) - { - assert( nextToNextNode->pObj ); - serialNumSignal = Vec_PtrFind( vSignal, nextToNextNode->pObj ); - if( serialNumSignal == -1 ) - { - Vec_PtrPush( vSignal, nextToNextNode->pObj ); - serialNumSignal = Vec_PtrFind( vSignal, nextToNextNode->pObj ); - } - //Vec_PtrPush( vGLOBALLY, topASTNode ); - Vec_VecPush( vAigGFMap, serialNumSignal, topASTNode ); - } - else - { - assert( nextToNextNode->pObj == NULL ); - buildLogicFromLTLNode_combinationalOnly( pAigNew, nextToNextNode ); - serialNumSignal = Vec_PtrFind( vSignal, nextToNextNode->pObj ); - if( serialNumSignal == -1 ) - { - Vec_PtrPush( vSignal, nextToNextNode->pObj ); - serialNumSignal = Vec_PtrFind( vSignal, nextToNextNode->pObj ); - } - //Vec_PtrPush( vGLOBALLY, topASTNode ); - Vec_VecPush( vAigGFMap, serialNumSignal, topASTNode ); - } - return; - case BOOL: - return; - default: - printf("\nINVALID situation: aborting...\n"); - exit(0); - } -} - -Aig_Obj_t *buildLogicFromLTLNode_combinationalOnly( Aig_Man_t *pAigNew, ltlNode *pLtlNode ) -{ - Aig_Obj_t *leftAigObj, *rightAigObj; - - if( pLtlNode->pObj != NULL ) - return pLtlNode->pObj; - else - { - assert( pLtlNode->type != BOOL ); - switch( pLtlNode->type ){ - case AND: - assert( pLtlNode->left ); assert( pLtlNode->right ); - leftAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->left ); - rightAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->right ); - assert( leftAigObj ); assert( rightAigObj ); - pLtlNode->pObj = Aig_And( pAigNew, leftAigObj, rightAigObj ); - return pLtlNode->pObj; - case OR: - assert( pLtlNode->left ); assert( pLtlNode->right ); - leftAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->left ); - rightAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->right ); - assert( leftAigObj ); assert( rightAigObj ); - pLtlNode->pObj = Aig_Or( pAigNew, leftAigObj, rightAigObj ); - return pLtlNode->pObj; - case NOT: - assert( pLtlNode->left ); assert( pLtlNode->right == NULL ); - leftAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->left ); - assert( leftAigObj ); - pLtlNode->pObj = Aig_Not( leftAigObj ); - return pLtlNode->pObj; - case GLOBALLY: - case EVENTUALLY: - case NEXT: - case UNTIL: - printf("FORBIDDEN node: ABORTING!!\n"); - exit(0); - default: - printf("\nSerious ERROR: attempting to create AIG node from a temporal node\n"); - exit(0); - } - } -} - -Aig_Obj_t *buildLogicFromLTLNode( Aig_Man_t *pAig, ltlNode *pLtlNode ) -{ - Aig_Obj_t *leftAigObj, *rightAigObj; - - if( pLtlNode->pObj != NULL ) - return pLtlNode->pObj; - else - { - assert( pLtlNode->type != BOOL ); - switch( pLtlNode->type ){ - case AND: - assert( pLtlNode->left ); assert( pLtlNode->right ); - leftAigObj = buildLogicFromLTLNode( pAig, pLtlNode->left ); - rightAigObj = buildLogicFromLTLNode( pAig, pLtlNode->right ); - assert( leftAigObj ); assert( rightAigObj ); - pLtlNode->pObj = Aig_And( pAig, leftAigObj, rightAigObj ); - return pLtlNode->pObj; - case OR: - assert( pLtlNode->left ); assert( pLtlNode->right ); - leftAigObj = buildLogicFromLTLNode( pAig, pLtlNode->left ); - rightAigObj = buildLogicFromLTLNode( pAig, pLtlNode->right ); - assert( leftAigObj ); assert( rightAigObj ); - pLtlNode->pObj = Aig_Or( pAig, leftAigObj, rightAigObj ); - return pLtlNode->pObj; - case NOT: - assert( pLtlNode->left ); assert( pLtlNode->right == NULL ); - leftAigObj = buildLogicFromLTLNode( pAig, pLtlNode->left ); - assert( leftAigObj ); - pLtlNode->pObj = Aig_Not( leftAigObj ); - return pLtlNode->pObj; - case GLOBALLY: - case EVENTUALLY: - case NEXT: - case UNTIL: - printf("\nAttempting to create circuit with missing AIG pointer in a TEMPORAL node: ABORTING!!\n"); - exit(0); - default: - printf("\nSerious ERROR: attempting to create AIG node from a temporal node\n"); - exit(0); - } - } -} - -int isNonTemporalSubformula( ltlNode *topNode ) -{ - switch( topNode->type ){ - case AND: - case OR: - case IMPLY: - return isNonTemporalSubformula( topNode->left) && isNonTemporalSubformula( topNode->right ) ; - case NOT: - assert( topNode->right == NULL ); - return isNonTemporalSubformula( topNode->left ); - case BOOL: - return 1; - default: - return 0; - } -} - -int isWellFormed( ltlNode *topNode ) -{ - ltlNode *nextNode; - - switch( topNode->type ){ - case AND: - case OR: - case IMPLY: - return isWellFormed( topNode->left) && isWellFormed( topNode->right ) ; - case NOT: - assert( topNode->right == NULL ); - return isWellFormed( topNode->left ); - case BOOL: - return 1; - case GLOBALLY: - nextNode = topNode->left; - assert( topNode->right == NULL ); - if( nextNode->type != EVENTUALLY ) - return 0; - else - { - assert( nextNode->right == NULL ); - return isNonTemporalSubformula( nextNode->left ); - } - default: - return 0; - } -} - -int checkBooleanConstant( char *targetName ) -{ - if( strcmp( targetName, "true" ) == 0 ) - return 1; - if( strcmp( targetName, "false" ) == 0 ) - return 0; - return -1; -} - -int checkSignalNameExistence( Abc_Ntk_t *pNtk, ltlNode *topASTNode ) -{ - char *targetName; - Abc_Obj_t * pNode; - int i; - - switch( topASTNode->type ){ - case BOOL: - targetName = topASTNode->name; - //printf("\nTrying to match name %s\n", targetName); - if( checkBooleanConstant( targetName ) != -1 ) - return 1; - Abc_NtkForEachPo( pNtk, pNode, i ) - { - if( strcmp( Abc_ObjName( pNode ), targetName ) == 0 ) - { - //printf("\nVariable name \"%s\" MATCHED\n", targetName); - return 1; - } - } - printf("\nVariable name \"%s\" not found in the PO name list\n", targetName); - return 0; - case AND: - case OR: - case IMPLY: - case UNTIL: - assert( topASTNode->left != NULL ); - assert( topASTNode->right != NULL ); - return checkSignalNameExistence( pNtk, topASTNode->left ) && checkSignalNameExistence( pNtk, topASTNode->right ); - - case NOT: - case NEXT: - case GLOBALLY: - case EVENTUALLY: - assert( topASTNode->left != NULL ); - assert( topASTNode->right == NULL ); - return checkSignalNameExistence( pNtk, topASTNode->left ); - default: - printf("\nUNSUPPORTED LTL NODE TYPE:: Aborting execution\n"); - exit(0); - } -} - -void populateBoolWithAigNodePtr( Abc_Ntk_t *pNtk, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, ltlNode *topASTNode ) -{ - char *targetName; - Abc_Obj_t * pNode; - int i; - Aig_Obj_t *pObj, *pDriverImage; - - switch( topASTNode->type ){ - case BOOL: - targetName = topASTNode->name; - if( checkBooleanConstant( targetName ) == 1 ) - { - topASTNode->pObj = Aig_ManConst1( pAigNew ); - return; - } - if( checkBooleanConstant( targetName ) == 0 ) - { - topASTNode->pObj = Aig_Not(topASTNode->pObj = Aig_ManConst1( pAigNew )); - return; - } - Abc_NtkForEachPo( pNtk, pNode, i ) - if( strcmp( Abc_ObjName( pNode ), targetName ) == 0 ) - { - pObj = Aig_ManPo( pAigOld, i ); - assert( Aig_ObjIsPo( pObj )); - pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); - topASTNode->pObj = pDriverImage; - return; - } - assert(0); - case AND: - case OR: - case IMPLY: - case UNTIL: - assert( topASTNode->left != NULL ); - assert( topASTNode->right != NULL ); - populateBoolWithAigNodePtr( pNtk, pAigOld, pAigNew, topASTNode->left ); - populateBoolWithAigNodePtr( pNtk, pAigOld, pAigNew, topASTNode->right ); - return; - case NOT: - case NEXT: - case GLOBALLY: - case EVENTUALLY: - assert( topASTNode->left != NULL ); - assert( topASTNode->right == NULL ); - populateBoolWithAigNodePtr( pNtk, pAigOld, pAigNew, topASTNode->left ); - return; - default: - printf("\nUNSUPPORTED LTL NODE TYPE:: Aborting execution\n"); - exit(0); - } -} - -int checkAllBoolHaveAIGPointer( ltlNode *topASTNode ) -{ - - switch( topASTNode->type ){ - case BOOL: - if( topASTNode->pObj != NULL ) - return 1; - else - { - printf("\nfaulting PODMANDYO topASTNode->name = %s\n", topASTNode->name); - return 0; - } - case AND: - case OR: - case IMPLY: - case UNTIL: - assert( topASTNode->left != NULL ); - assert( topASTNode->right != NULL ); - return checkAllBoolHaveAIGPointer( topASTNode->left ) && checkAllBoolHaveAIGPointer( topASTNode->right ); - - case NOT: - case NEXT: - case GLOBALLY: - case EVENTUALLY: - assert( topASTNode->left != NULL ); - assert( topASTNode->right == NULL ); - return checkAllBoolHaveAIGPointer( topASTNode->left ); - default: - printf("\nUNSUPPORTED LTL NODE TYPE:: Aborting execution\n"); - exit(0); - } -} - -void setAIGNodePtrOfGloballyNode( ltlNode *astNode, Aig_Obj_t *pObjLo ) -{ - astNode->pObj = pObjLo; -} - -Aig_Obj_t *retriveAIGPointerFromLTLNode( ltlNode *astNode ) -{ - return astNode->pObj; -} - - -ABC_NAMESPACE_IMPL_END diff --git a/src/aig/live/module.make b/src/aig/live/module.make deleted file mode 100644 index 46a9ed3c..00000000 --- a/src/aig/live/module.make +++ /dev/null @@ -1,3 +0,0 @@ -SRC += src/aig/live/liveness.c \ - src/aig/live/liveness_sim.c \ - src/aig/live/ltl_parser.c diff --git a/src/aig/llb/llb.c b/src/aig/llb/llb.c deleted file mode 100644 index 348c0622..00000000 --- a/src/aig/llb/llb.c +++ /dev/null @@ -1,52 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llb.h b/src/aig/llb/llb.h deleted file mode 100644 index e5fa6956..00000000 --- a/src/aig/llb/llb.h +++ /dev/null @@ -1,96 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD-based reachability.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 8, 2010.] - - Revision [$Id: llb.h,v 1.00 2010/05/08 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __LLB_H__ -#define __LLB_H__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Gia_ParLlb_t_ Gia_ParLlb_t; -struct Gia_ParLlb_t_ -{ - int nBddMax; // maximum BDD size - int nIterMax; // maximum iteration count - int nClusterMax; // maximum cluster size - int nHintDepth; // the number of times to cofactor - int HintFirst; // the number of first hint to use - int fUseFlow; // use flow computation - int nVolumeMax; // the largest volume - int nVolumeMin; // the smallest volume - int nPartValue; // partitioning value - int fBackward; // enable backward reachability - int fReorder; // enable dynamic variable reordering - int fIndConstr; // extract inductive constraints - int fUsePivots; // use internal pivot variables - int fCluster; // use partition clustering - int fSchedule; // use cluster scheduling - int fDumpReached; // dump reached states into a file - int fVerbose; // print verbose information - int fVeryVerbose; // print dependency matrices - int fSilent; // do not print any infomation - int fSkipReach; // skip reachability (preparation phase only) - int fSkipOutCheck; // does not check the property output - int TimeLimit; // time limit for one reachability run - int TimeLimitGlo; // time limit for all reachability runs - // internal parameters - int TimeTarget; // the time to stop - int iFrame; // explored up to this frame -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== llbCore.c ==========================================================*/ -extern void Llb_ManSetDefaultParams( Gia_ParLlb_t * pPars ); -/*=== llb4Nonlin.c ==========================================================*/ -extern int Llb_Nonlin4CoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/llb/llb1Cluster.c b/src/aig/llb/llb1Cluster.c deleted file mode 100644 index 758994b5..00000000 --- a/src/aig/llb/llb1Cluster.c +++ /dev/null @@ -1,357 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb1Cluster.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Clustering algorithm.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb1Cluster.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" -#include "extra.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManComputeCommonQuant( Llb_Mtr_t * p, int iCol1, int iCol2 ) -{ - int iVar, Weight = 0; - for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ ) - { - // count each removed variable as 2 - if ( p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 1 && p->pRowSums[iVar] == 2 ) - Weight += 2; - // count each added variale as -1 - else if ( (p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 0) || - (p->pMatrix[iCol1][iVar] == 0 && p->pMatrix[iCol2][iVar] == 1) ) - Weight--; - } - return Weight; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManComputeBestQuant( Llb_Mtr_t * p ) -{ - int i, k, WeightBest = -100000, WeightCur, RetValue = -1; - for ( i = 1; i < p->nCols-1; i++ ) - for ( k = i+1; k < p->nCols-1; k++ ) - { - if ( p->pColSums[i] == 0 || p->pColSums[i] > p->pMan->pPars->nClusterMax ) - continue; - if ( p->pColSums[k] == 0 || p->pColSums[k] > p->pMan->pPars->nClusterMax ) - continue; - - WeightCur = Llb_ManComputeCommonQuant( p, i, k ); - if ( WeightCur <= 0 ) - continue; - if ( WeightBest < WeightCur ) - { - WeightBest = WeightCur; - RetValue = (i << 16) | k; - } - } -// printf( "Choosing best quant Weight %4d\n", WeightCur ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float ** Llb_ManComputeQuant( Llb_Mtr_t * p ) -{ - float ** pCosts; - int i, k; - // alloc and clean - pCosts = (float **)Extra_ArrayAlloc( p->nCols, p->nCols, sizeof(float) ); - for ( i = 0; i < p->nCols; i++ ) - for ( k = 0; k < p->nCols; k++ ) - pCosts[i][i] = 0.0; - // fill up - for ( i = 1; i < p->nCols-1; i++ ) - for ( k = i+1; k < p->nCols-1; k++ ) - pCosts[i][k] = pCosts[k][i] = Llb_ManComputeCommonQuant( p, i, k ); - return pCosts; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Llb_ManComputeCommonAttr( Llb_Mtr_t * p, int iCol1, int iCol2 ) -{ - int iVar, CountComm = 0, CountDiff = 0; - for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ ) - { - if ( p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 1 ) - CountComm++; - else if ( p->pMatrix[iCol1][iVar] == 1 || p->pMatrix[iCol2][iVar] == 1 ) - CountDiff++; - } -/* - printf( "Attr cost for %4d and %4d: %4d %4d (%5.2f)\n", - iCol1, iCol2, - CountDiff, CountComm, - -1.0 * CountDiff / ( CountComm + CountDiff ) ); -*/ - return -1.0 * CountDiff / ( CountComm + CountDiff ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManComputeBestAttr( Llb_Mtr_t * p ) -{ - float WeightBest = -100000, WeightCur; - int i, k, RetValue = -1; - for ( i = 1; i < p->nCols-1; i++ ) - for ( k = i+1; k < p->nCols-1; k++ ) - { - if ( p->pColSums[i] == 0 || p->pColSums[i] > p->pMan->pPars->nClusterMax ) - continue; - if ( p->pColSums[k] == 0 || p->pColSums[k] > p->pMan->pPars->nClusterMax ) - continue; - WeightCur = Llb_ManComputeCommonAttr( p, i, k ); - if ( WeightBest < WeightCur ) - { - WeightBest = WeightCur; - RetValue = (i << 16) | k; - } - } - return RetValue; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float ** Llb_ManComputeAttr( Llb_Mtr_t * p ) -{ - float ** pCosts; - int i, k; - // alloc and clean - pCosts = (float **)Extra_ArrayAlloc( p->nCols, p->nCols, sizeof(float) ); - for ( i = 0; i < p->nCols; i++ ) - for ( k = 0; k < p->nCols; k++ ) - pCosts[i][i] = 0.0; - // fill up - for ( i = 1; i < p->nCols-1; i++ ) - for ( k = i+1; k < p->nCols-1; k++ ) - pCosts[i][k] = pCosts[k][i] = Llb_ManComputeCommonAttr( p, i, k ); - return pCosts; -} - - -/**Function************************************************************* - - Synopsis [Returns the number of variables that will be saved.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrCombineSelectedColumns( Llb_Mtr_t * p, int iGrp1, int iGrp2 ) -{ - int iVar; - assert( iGrp1 >= 1 && iGrp1 < p->nCols - 1 ); - assert( iGrp2 >= 1 && iGrp2 < p->nCols - 1 ); - assert( p->pColGrps[iGrp1] != NULL ); - assert( p->pColGrps[iGrp2] != NULL ); - for ( iVar = 0; iVar < p->nRows; iVar++ ) - { - if ( p->pMatrix[iGrp1][iVar] == 1 && p->pMatrix[iGrp2][iVar] == 1 ) - p->pRowSums[iVar]--; - if ( p->pMatrix[iGrp1][iVar] == 0 && p->pMatrix[iGrp2][iVar] == 1 ) - { - p->pMatrix[iGrp1][iVar] = 1; - p->pColSums[iGrp1]++; - } - if ( p->pMatrix[iGrp2][iVar] == 1 ) - p->pMatrix[iGrp2][iVar] = 0; - } - p->pColSums[iGrp2] = 0; -} - - -/**Function************************************************************* - - Synopsis [Combines one pair of columns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManClusterOne( Llb_Mtr_t * p, int iCol1, int iCol2 ) -{ - int fVerbose = 0; - Llb_Grp_t * pGrp; - int iVar; - - if ( fVerbose ) - { - printf( "Combining %d and %d\n", iCol1, iCol2 ); - for ( iVar = 0; iVar < p->nRows; iVar++ ) - { - if ( p->pMatrix[iCol1][iVar] == 0 && p->pMatrix[iCol2][iVar] == 0 ) - continue; - printf( "%3d : %c%c\n", iVar, - p->pMatrix[iCol1][iVar]? '*':' ', - p->pMatrix[iCol2][iVar]? '*':' ' ); - } - } - pGrp = Llb_ManGroupsCombine( p->pColGrps[iCol1], p->pColGrps[iCol2] ); - Llb_MtrCombineSelectedColumns( p, iCol1, iCol2 ); - p->pColGrps[iCol1] = pGrp; - p->pColGrps[iCol2] = NULL; -} - -/**Function************************************************************* - - Synopsis [Removes empty columns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManClusterCompress( Llb_Mtr_t * p ) -{ - int i, k = 0; - for ( i = 0; i < p->nCols; i++ ) - { - if ( p->pColGrps[i] == NULL ) - { - assert( p->pColSums[i] == 0 ); - assert( p->pMatrix[i] != NULL ); - ABC_FREE( p->pMatrix[i] ); - continue; - } - p->pMatrix[k] = p->pMatrix[i]; - p->pColGrps[k] = p->pColGrps[i]; - p->pColSums[k] = p->pColSums[i]; - k++; - } - p->nCols = k; -} - -/**Function************************************************************* - - Synopsis [Combines one pair of columns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManCluster( Llb_Mtr_t * p ) -{ - int RetValue; - do - { - do { - RetValue = Llb_ManComputeBestQuant( p ); - if ( RetValue > 0 ) - Llb_ManClusterOne( p, RetValue >> 16, RetValue & 0xffff ); - } - while ( RetValue > 0 ); - - RetValue = Llb_ManComputeBestAttr( p ); - if ( RetValue > 0 ) - Llb_ManClusterOne( p, RetValue >> 16, RetValue & 0xffff ); - - Llb_MtrVerifyMatrix( p ); - } - while ( RetValue > 0 ); - - Llb_ManClusterCompress( p ); - - Llb_MtrVerifyMatrix( p ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llb1Constr.c b/src/aig/llb/llb1Constr.c deleted file mode 100644 index 67fb30ba..00000000 --- a/src/aig/llb/llb1Constr.c +++ /dev/null @@ -1,313 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb1Constr.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Computing inductive constraints.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb1Constr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns the array of constraint candidates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManCountEntries( Vec_Int_t * vCands ) -{ - int i, Entry, Counter = 0; - Vec_IntForEachEntry( vCands, Entry, i ) - Counter += ((Entry == 0) || (Entry == 1)); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Returns the array of constraint candidates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManPrintEntries( Aig_Man_t * p, Vec_Int_t * vCands ) -{ - int i, Entry; - if ( vCands == NULL ) - { - printf( "There is no hints.\n" ); - return; - } - Entry = Llb_ManCountEntries(vCands); - printf( "\n*** Using %d hint%s:\n", Entry, (Entry != 1 ? "s":"") ); - Vec_IntForEachEntry( vCands, Entry, i ) - { - if ( Entry != 0 && Entry != 1 ) - continue; - printf( "%c", Entry ? '+' : '-' ); - printf( "%-6d : ", i ); - Aig_ObjPrint( p, Aig_ManObj(p, i) ); - printf( "\n" ); - } -} - -/**Function************************************************************* - - Synopsis [Dereference BDD nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManDerefenceBdds( Aig_Man_t * p, DdManager * dd ) -{ - Aig_Obj_t * pObj; - int i; - Aig_ManForEachObj( p, pObj, i ) - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); -} - -/**Function************************************************************* - - Synopsis [Returns the array of constraint candidates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ManComputeIndCase_rec( Aig_Man_t * p, Aig_Obj_t * pObj, DdManager * dd, Vec_Ptr_t * vBdds ) -{ - DdNode * bBdd0, * bBdd1; - DdNode * bFunc = (DdNode *)Vec_PtrEntry( vBdds, Aig_ObjId(pObj) ); - if ( bFunc != NULL ) - return bFunc; - assert( Aig_ObjIsNode(pObj) ); - bBdd0 = Llb_ManComputeIndCase_rec( p, Aig_ObjFanin0(pObj), dd, vBdds ); - bBdd1 = Llb_ManComputeIndCase_rec( p, Aig_ObjFanin1(pObj), dd, vBdds ); - bBdd0 = Cudd_NotCond( bBdd0, Aig_ObjFaninC0(pObj) ); - bBdd1 = Cudd_NotCond( bBdd1, Aig_ObjFaninC1(pObj) ); - bFunc = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bFunc ); - Vec_PtrWriteEntry( vBdds, Aig_ObjId(pObj), bFunc ); - return bFunc; -} - -/**Function************************************************************* - - Synopsis [Returns the array of constraint candidates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManComputeIndCase( Aig_Man_t * p, DdManager * dd, Vec_Int_t * vNodes ) -{ - Vec_Ptr_t * vBdds; - Aig_Obj_t * pObj; - DdNode * bFunc; - int i, Entry; - vBdds = Vec_PtrStart( Aig_ManObjNumMax(p) ); - bFunc = Cudd_ReadOne(dd); Cudd_Ref( bFunc ); - Vec_PtrWriteEntry( vBdds, Aig_ObjId(Aig_ManConst1(p)), bFunc ); - Saig_ManForEachPi( p, pObj, i ) - { - bFunc = Cudd_bddIthVar( dd, Aig_ManPiNum(p) + i ); Cudd_Ref( bFunc ); - Vec_PtrWriteEntry( vBdds, Aig_ObjId(pObj), bFunc ); - } - Saig_ManForEachLi( p, pObj, i ) - { - bFunc = (DdNode *)pObj->pData; Cudd_Ref( bFunc ); - Vec_PtrWriteEntry( vBdds, Aig_ObjId(Saig_ObjLiToLo(p, pObj)), bFunc ); - } - Vec_IntForEachEntry( vNodes, Entry, i ) - { - if ( Entry != 0 && Entry != 1 ) - continue; - pObj = Aig_ManObj( p, i ); - bFunc = Llb_ManComputeIndCase_rec( p, pObj, dd, vBdds ); - if ( Entry == 0 ) - { -// Extra_bddPrint( dd, Cudd_Not(pObj->pData) ); printf( "\n" ); -// Extra_bddPrint( dd, Cudd_Not(bFunc) ); printf( "\n" ); - if ( !Cudd_bddLeq( dd, Cudd_Not(pObj->pData), Cudd_Not(bFunc) ) ) - Vec_IntWriteEntry( vNodes, i, -1 ); - } - else if ( Entry == 1 ) - { -// Extra_bddPrint( dd, pObj->pData ); printf( "\n" ); -// Extra_bddPrint( dd, bFunc ); printf( "\n" ); - if ( !Cudd_bddLeq( dd, (DdNode *)pObj->pData, bFunc ) ) - Vec_IntWriteEntry( vNodes, i, -1 ); - } - } - Vec_PtrForEachEntry( DdNode *, vBdds, bFunc, i ) - if ( bFunc ) - Cudd_RecursiveDeref( dd, bFunc ); - Vec_PtrFree( vBdds ); -} - -/**Function************************************************************* - - Synopsis [Returns the array of constraint candidates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_ManComputeBaseCase( Aig_Man_t * p, DdManager * dd ) -{ - Vec_Int_t * vNodes; - Aig_Obj_t * pObj, * pRoot; - int i; - pRoot = Aig_ManPo( p, 0 ); - vNodes = Vec_IntStartFull( Aig_ManObjNumMax(p) ); - Aig_ManForEachObj( p, pObj, i ) - { - if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) ) - continue; - if ( Cudd_bddLeq( dd, (DdNode *)pObj->pData, Cudd_Not(pRoot->pData) ) ) - Vec_IntWriteEntry( vNodes, i, 1 ); - else if ( Cudd_bddLeq( dd, Cudd_Not((DdNode *)pObj->pData), Cudd_Not(pRoot->pData) ) ) - Vec_IntWriteEntry( vNodes, i, 0 ); - } - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Constructs global BDDs for each object in the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdManager * Llb_ManConstructGlobalBdds( Aig_Man_t * p ) -{ - DdManager * dd; - DdNode * bBdd0, * bBdd1; - Aig_Obj_t * pObj; - int i; - dd = Cudd_Init( Aig_ManPiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - pObj = Aig_ManConst1(p); - pObj->pData = Cudd_ReadOne(dd); Cudd_Ref( (DdNode *)pObj->pData ); - Aig_ManForEachPi( p, pObj, i ) - { - pObj->pData = Cudd_bddIthVar(dd, i); Cudd_Ref( (DdNode *)pObj->pData ); - } - Aig_ManForEachNode( p, pObj, i ) - { - bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); - pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData ); - } - Aig_ManForEachPo( p, pObj, i ) - { - pObj->pData = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); Cudd_Ref( (DdNode *)pObj->pData ); - } - return dd; -} - -/**Function************************************************************* - - Synopsis [Derives inductive constraints.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_ManDeriveConstraints( Aig_Man_t * p ) -{ - DdManager * dd; - Vec_Int_t * vNodes; - if ( Saig_ManPoNum(p) != 1 ) - { - printf( "The AIG has %d property outputs.\n", Saig_ManPoNum(p) ); - return NULL; - } - assert( Saig_ManPoNum(p) == 1 ); - dd = Llb_ManConstructGlobalBdds( p ); - vNodes = Llb_ManComputeBaseCase( p, dd ); - if ( Llb_ManCountEntries(vNodes) > 0 ) - Llb_ManComputeIndCase( p, dd, vNodes ); - if ( Llb_ManCountEntries(vNodes) == 0 ) - Vec_IntFreeP( &vNodes ); - Llb_ManDerefenceBdds( p, dd ); - Extra_StopManager( dd ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Tests derived constraints.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManConstrTest( Aig_Man_t * p ) -{ - Vec_Int_t * vNodes; - vNodes = Llb_ManDeriveConstraints( p ); - Llb_ManPrintEntries( p, vNodes ); - Vec_IntFreeP( &vNodes ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llb1Core.c b/src/aig/llb/llb1Core.c deleted file mode 100644 index ad2c5934..00000000 --- a/src/aig/llb/llb1Core.c +++ /dev/null @@ -1,222 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb1Core.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Top-level procedure.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb1Core.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" -#include "gia.h" -#include "giaAig.h" - -ABC_NAMESPACE_IMPL_START - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManSetDefaultParams( Gia_ParLlb_t * p ) -{ - memset( p, 0, sizeof(Gia_ParLlb_t) ); - p->nBddMax = 10000000; - p->nIterMax = 10000000; - p->nClusterMax = 20; - p->nHintDepth = 0; - p->HintFirst = 0; - p->fUseFlow = 0; // use flow - p->nVolumeMax = 100; // max volume - p->nVolumeMin = 30; // min volume - p->nPartValue = 5; // partitioning value - p->fBackward = 0; // forward by default - p->fReorder = 1; - p->fIndConstr = 0; - p->fUsePivots = 0; - p->fCluster = 0; - p->fSchedule = 0; - p->fDumpReached = 0; - p->fVerbose = 0; - p->fVeryVerbose = 0; - p->fSilent = 0; - p->TimeLimit = 0; -// p->TimeLimit = 0; - p->TimeLimitGlo = 0; - p->TimeTarget = 0; - p->iFrame = -1; -} - - -/**Function************************************************************* - - Synopsis [Prints statistics about MFFCs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManPrintAig( Llb_Man_t * p ) -{ - Abc_Print( 1, "pi =%3d ", Saig_ManPiNum(p->pAig) ); - Abc_Print( 1, "po =%3d ", Saig_ManPoNum(p->pAig) ); - Abc_Print( 1, "ff =%3d ", Saig_ManRegNum(p->pAig) ); - Abc_Print( 1, "int =%5d ", Vec_IntSize(p->vVar2Obj)-Aig_ManPiNum(p->pAig)-Saig_ManRegNum(p->pAig) ); - Abc_Print( 1, "var =%5d ", Vec_IntSize(p->vVar2Obj) ); - Abc_Print( 1, "part =%5d ", Vec_PtrSize(p->vGroups)-2 ); - Abc_Print( 1, "and =%5d ", Aig_ManNodeNum(p->pAig) ); - Abc_Print( 1, "lev =%4d ", Aig_ManLevelNum(p->pAig) ); -// Abc_Print( 1, "cut =%4d ", Llb_ManCrossCut(p->pAig) ); - Abc_Print( 1, "\n" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManModelCheckAig( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars, Vec_Int_t * vHints, DdManager ** pddGlo ) -{ - Llb_Man_t * p = NULL; - Aig_Man_t * pAig; - int RetValue = -1; - int clk = clock(); - - if ( pPars->fIndConstr ) - { - assert( vHints == NULL ); - vHints = Llb_ManDeriveConstraints( pAigGlo ); - } - - // derive AIG for hints - if ( vHints == NULL ) - pAig = Aig_ManDupSimple( pAigGlo ); - else - { - if ( pPars->fVerbose ) - Llb_ManPrintEntries( pAigGlo, vHints ); - pAig = Aig_ManDupSimpleWithHints( pAigGlo, vHints ); - } - - - if ( pPars->fUseFlow ) - { -// p = Llb_ManStartFlow( pAigGlo, pAig, pPars ); - } - else - { - p = Llb_ManStart( pAigGlo, pAig, pPars ); - if ( pPars->fVerbose ) - { - Llb_ManPrintAig( p ); - printf( "Original matrix: " ); - Llb_MtrPrintMatrixStats( p->pMatrix ); - if ( pPars->fVeryVerbose ) - Llb_MtrPrint( p->pMatrix, 1 ); - } - if ( pPars->fCluster ) - { - Llb_ManCluster( p->pMatrix ); - if ( pPars->fVerbose ) - { - printf( "Matrix after clustering: " ); - Llb_MtrPrintMatrixStats( p->pMatrix ); - if ( pPars->fVeryVerbose ) - Llb_MtrPrint( p->pMatrix, 1 ); - } - } - if ( pPars->fSchedule ) - { - Llb_MtrSchedule( p->pMatrix ); - if ( pPars->fVerbose ) - { - printf( "Matrix after scheduling: " ); - Llb_MtrPrintMatrixStats( p->pMatrix ); - if ( pPars->fVeryVerbose ) - Llb_MtrPrint( p->pMatrix, 1 ); - } - } - } - - if ( !p->pPars->fSkipReach ) - RetValue = Llb_ManReachability( p, vHints, pddGlo ); - Llb_ManStop( p ); - - Abc_PrintTime( 1, "Time", clock() - clk ); - - if ( pPars->fIndConstr ) - Vec_IntFreeP( &vHints ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManModelCheckGia( Gia_Man_t * pGia, Gia_ParLlb_t * pPars ) -{ - Gia_Man_t * pGia2; - Aig_Man_t * pAig; - int RetValue = -1; - pGia2 = Gia_ManDupDfs( pGia ); - pAig = Gia_ManToAigSimple( pGia2 ); - Gia_ManStop( pGia2 ); -//Aig_ManShow( pAig, 0, NULL ); - - if ( pPars->nHintDepth == 0 ) - RetValue = Llb_ManModelCheckAig( pAig, pPars, NULL, NULL ); - else - RetValue = Llb_ManModelCheckAigWithHints( pAig, pPars ); - pGia->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL; - Aig_ManStop( pAig ); - return RetValue; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llb1Group.c b/src/aig/llb/llb1Group.c deleted file mode 100644 index d865c239..00000000 --- a/src/aig/llb/llb1Group.c +++ /dev/null @@ -1,474 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb1Group.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Initial partition computation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb1Group.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Grp_t * Llb_ManGroupAlloc( Llb_Man_t * pMan ) -{ - Llb_Grp_t * p; - p = ABC_CALLOC( Llb_Grp_t, 1 ); - p->pMan = pMan; - p->vIns = Vec_PtrAlloc( 8 ); - p->vOuts = Vec_PtrAlloc( 8 ); - p->Id = Vec_PtrSize( pMan->vGroups ); - Vec_PtrPush( pMan->vGroups, p ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManGroupStop( Llb_Grp_t * p ) -{ - if ( p == NULL ) - return; - Vec_PtrWriteEntry( p->pMan->vGroups, p->Id, NULL ); - Vec_PtrFreeP( &p->vIns ); - Vec_PtrFreeP( &p->vOuts ); - Vec_PtrFreeP( &p->vNodes ); - ABC_FREE( p ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManGroupCollect_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) -{ - if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) - return; - Aig_ObjSetTravIdCurrent(pAig, pObj); - if ( Aig_ObjIsConst1(pObj) ) - return; - if ( Aig_ObjIsPo(pObj) ) - { - Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin0(pObj), vNodes ); - return; - } - assert( Aig_ObjIsAnd(pObj) ); - Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin0(pObj), vNodes ); - Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin1(pObj), vNodes ); - Vec_PtrPush( vNodes, pObj ); -} - -/**Function************************************************************* - - Synopsis [Collects the support of MFFC.] - - Description [Returns the number of internal nodes in the MFFC.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ManGroupCollect( Llb_Grp_t * pGroup ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i; - vNodes = Vec_PtrAlloc( 100 ); - Aig_ManIncrementTravId( pGroup->pMan->pAig ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) - Aig_ObjSetTravIdCurrent( pGroup->pMan->pAig, pObj ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) - Aig_ObjSetTravIdPrevious( pGroup->pMan->pAig, pObj ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) - Llb_ManGroupCollect_rec( pGroup->pMan->pAig, pObj, vNodes ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManGroupCreate_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vSupp ) -{ - if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) - return; - Aig_ObjSetTravIdCurrent(pAig, pObj); - if ( Aig_ObjIsConst1(pObj) ) - return; - if ( pObj->fMarkA ) - { - Vec_PtrPush( vSupp, pObj ); - return; - } - assert( Aig_ObjIsAnd(pObj) ); - Llb_ManGroupCreate_rec( pAig, Aig_ObjFanin0(pObj), vSupp ); - Llb_ManGroupCreate_rec( pAig, Aig_ObjFanin1(pObj), vSupp ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Grp_t * Llb_ManGroupCreate( Llb_Man_t * pMan, Aig_Obj_t * pObj ) -{ - Llb_Grp_t * p; - assert( pObj->fMarkA == 1 ); - // derive group - p = Llb_ManGroupAlloc( pMan ); - Vec_PtrPush( p->vOuts, pObj ); - Aig_ManIncrementTravId( pMan->pAig ); - if ( Aig_ObjIsPo(pObj) ) - Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin0(pObj), p->vIns ); - else - { - Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin0(pObj), p->vIns ); - Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin1(pObj), p->vIns ); - } - // derive internal objects - assert( p->vNodes == NULL ); - p->vNodes = Llb_ManGroupCollect( p ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Grp_t * Llb_ManGroupCreateFirst( Llb_Man_t * pMan ) -{ - Llb_Grp_t * p; - Aig_Obj_t * pObj; - int i; - p = Llb_ManGroupAlloc( pMan ); - Saig_ManForEachLo( pMan->pAig, pObj, i ) - Vec_PtrPush( p->vOuts, pObj ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Grp_t * Llb_ManGroupCreateLast( Llb_Man_t * pMan ) -{ - Llb_Grp_t * p; - Aig_Obj_t * pObj; - int i; - p = Llb_ManGroupAlloc( pMan ); - Saig_ManForEachLi( pMan->pAig, pObj, i ) - Vec_PtrPush( p->vIns, pObj ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Grp_t * Llb_ManGroupsCombine( Llb_Grp_t * p1, Llb_Grp_t * p2 ) -{ - Llb_Grp_t * p; - Aig_Obj_t * pObj; - int i; - p = Llb_ManGroupAlloc( p1->pMan ); - // create inputs - Vec_PtrForEachEntry( Aig_Obj_t *, p1->vIns, pObj, i ) - Vec_PtrPush( p->vIns, pObj ); - Vec_PtrForEachEntry( Aig_Obj_t *, p2->vIns, pObj, i ) - Vec_PtrPushUnique( p->vIns, pObj ); - // create outputs - Vec_PtrForEachEntry( Aig_Obj_t *, p1->vOuts, pObj, i ) - Vec_PtrPush( p->vOuts, pObj ); - Vec_PtrForEachEntry( Aig_Obj_t *, p2->vOuts, pObj, i ) - Vec_PtrPushUnique( p->vOuts, pObj ); - - // derive internal objects - assert( p->vNodes == NULL ); - p->vNodes = Llb_ManGroupCollect( p ); - return p; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManGroupMarkNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - return; - if ( Aig_ObjIsTravIdPrevious(p, pObj) ) - { - Aig_ObjSetTravIdCurrent(p, pObj); - return; - } - Aig_ObjSetTravIdCurrent(p, pObj); - assert( Aig_ObjIsNode(pObj) ); - Llb_ManGroupMarkNodes_rec( p, Aig_ObjFanin0(pObj) ); - Llb_ManGroupMarkNodes_rec( p, Aig_ObjFanin1(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Creates group from two cuts derived by the flow computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Grp_t * Llb_ManGroupCreateFromCuts( Llb_Man_t * pMan, Vec_Int_t * vCut1, Vec_Int_t * vCut2 ) -{ - Llb_Grp_t * p; - Aig_Obj_t * pObj; - int i; - p = Llb_ManGroupAlloc( pMan ); - - // mark Cut1 - Aig_ManIncrementTravId( pMan->pAig ); - Aig_ManForEachObjVec( vCut1, pMan->pAig, pObj, i ) - Aig_ObjSetTravIdCurrent( pMan->pAig, pObj ); - // collect unmarked Cut2 - Aig_ManForEachObjVec( vCut2, pMan->pAig, pObj, i ) - if ( !Aig_ObjIsTravIdCurrent( pMan->pAig, pObj ) ) - Vec_PtrPush( p->vOuts, pObj ); - - // mark nodes reachable from Cut2 - Aig_ManIncrementTravId( pMan->pAig ); - Aig_ManForEachObjVec( vCut2, pMan->pAig, pObj, i ) - Llb_ManGroupMarkNodes_rec( pMan->pAig, pObj ); - // collect marked Cut1 - Aig_ManForEachObjVec( vCut1, pMan->pAig, pObj, i ) - if ( Aig_ObjIsTravIdCurrent( pMan->pAig, pObj ) ) - Vec_PtrPush( p->vIns, pObj ); - - // derive internal objects - assert( p->vNodes == NULL ); - p->vNodes = Llb_ManGroupCollect( p ); - return p; -} - - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManPrepareGroups( Llb_Man_t * pMan ) -{ - Aig_Obj_t * pObj; - int i; - assert( pMan->vGroups == NULL ); - pMan->vGroups = Vec_PtrAlloc( 1000 ); - Llb_ManGroupCreateFirst( pMan ); - Aig_ManForEachNode( pMan->pAig, pObj, i ) - { - if ( pObj->fMarkA ) - Llb_ManGroupCreate( pMan, pObj ); - } - Saig_ManForEachLi( pMan->pAig, pObj, i ) - { - if ( pObj->fMarkA ) - Llb_ManGroupCreate( pMan, pObj ); - } - Llb_ManGroupCreateLast( pMan ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManPrintSpan( Llb_Man_t * p ) -{ - Llb_Grp_t * pGroup; - Aig_Obj_t * pVar; - int i, k, Span = 0, SpanMax = 0; - Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGroup, i ) - { - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) - if ( Vec_IntEntry(p->vVarBegs, pVar->Id) == i ) - Span++; - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) - if ( Vec_IntEntry(p->vVarBegs, pVar->Id) == i ) - Span++; - - SpanMax = ABC_MAX( SpanMax, Span ); -printf( "%d ", Span ); - - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) - if ( Vec_IntEntry(p->vVarEnds, pVar->Id) == i ) - Span--; - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) - if ( Vec_IntEntry(p->vVarEnds, pVar->Id) == i ) - Span--; - } -printf( "\n" ); -printf( "Max = %d\n", SpanMax ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManGroupHasVar( Llb_Man_t * p, int iGroup, int iVar ) -{ - Llb_Grp_t * pGroup = (Llb_Grp_t *)Vec_PtrEntry( p->vGroups, iGroup ); - Aig_Obj_t * pObj; - int i; - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) - if ( pObj->Id == iVar ) - return 1; - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) - if ( pObj->Id == iVar ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManPrintHisto( Llb_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i, k; - Aig_ManForEachObj( p->pAig, pObj, i ) - { - if ( Vec_IntEntry(p->vObj2Var, i) < 0 ) - continue; - printf( "%3d :", i ); - for ( k = 0; k < Vec_IntEntry(p->vVarBegs, i); k++ ) - printf( " " ); - for ( ; k <= Vec_IntEntry(p->vVarEnds, i); k++ ) - printf( "%c", Llb_ManGroupHasVar(p, k, i)? '*':'-' ); - printf( "\n" ); - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llb1Hint.c b/src/aig/llb/llb1Hint.c deleted file mode 100644 index d8ffecd3..00000000 --- a/src/aig/llb/llb1Hint.c +++ /dev/null @@ -1,226 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb1Hint.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Cofactors the circuit w.r.t. the high-fanout variables.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb1Hint.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns CI index with the largest number of fanouts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManMaxFanoutCi( Aig_Man_t * pAig ) -{ - Aig_Obj_t * pObj; - int i, WeightMax = -ABC_INFINITY, iInput = -1; - Aig_ManForEachPi( pAig, pObj, i ) - if ( WeightMax < Aig_ObjRefs(pObj) ) - { - WeightMax = Aig_ObjRefs(pObj); - iInput = i; - } - assert( iInput >= 0 ); - return iInput; -} - -/**Function************************************************************* - - Synopsis [Derives AIG whose PI is substituted by a constant.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Llb_ManPerformHints( Aig_Man_t * pAig, int nHintDepth ) -{ - Aig_Man_t * pNew, * pTemp; - int i, iInput; - pNew = Aig_ManDupDfs( pAig ); - for ( i = 0; i < nHintDepth; i++ ) - { - iInput = Llb_ManMaxFanoutCi( pNew ); - Abc_Print( 1, "%d %3d\n", i, iInput ); - pNew = Aig_ManDupCof( pTemp = pNew, iInput, 1 ); - Aig_ManStop( pTemp ); - } - return pNew; -} - -/**Function************************************************************* - - Synopsis [Returns CI index with the largest number of fanouts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_ManCollectHighFanoutObjects( Aig_Man_t * pAig, int nCandMax, int fCisOnly ) -{ - Vec_Int_t * vFanouts, * vResult; - Aig_Obj_t * pObj; - int i, fChanges, PivotValue; -// int Entry; - // collect fanout counts - vFanouts = Vec_IntAlloc( 100 ); - Aig_ManForEachObj( pAig, pObj, i ) - { -// if ( !Aig_ObjIsPi(pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) - if ( !Saig_ObjIsLo(pAig,pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) - continue; - Vec_IntPush( vFanouts, Aig_ObjRefs(pObj) ); - } - Vec_IntSort( vFanouts, 1 ); - // pick the separator - nCandMax = ABC_MIN( nCandMax, Vec_IntSize(vFanouts) - 1 ); - PivotValue = Vec_IntEntry( vFanouts, nCandMax ); - Vec_IntFree( vFanouts ); - // collect obj satisfying the constraints - vResult = Vec_IntAlloc( 100 ); - Aig_ManForEachObj( pAig, pObj, i ) - { -// if ( !Aig_ObjIsPi(pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) - if ( !Saig_ObjIsLo(pAig,pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) - continue; - if ( Aig_ObjRefs(pObj) < PivotValue ) - continue; - Vec_IntPush( vResult, Aig_ObjId(pObj) ); - } - assert( Vec_IntSize(vResult) >= nCandMax ); - // order in the decreasing order of fanouts - do - { - fChanges = 0; - for ( i = 0; i < Vec_IntSize(vResult) - 1; i++ ) - if ( Aig_ObjRefs(Aig_ManObj(pAig, Vec_IntEntry(vResult, i))) < - Aig_ObjRefs(Aig_ManObj(pAig, Vec_IntEntry(vResult, i+1))) ) - { - int Temp = Vec_IntEntry( vResult, i ); - Vec_IntWriteEntry( vResult, i, Vec_IntEntry(vResult, i+1) ); - Vec_IntWriteEntry( vResult, i+1, Temp ); - fChanges = 1; - } - } - while ( fChanges ); -/* - Vec_IntForEachEntry( vResult, Entry, i ) - printf( "%d ", Aig_ObjRefs(Aig_ManObj(pAig, Entry)) ); -printf( "\n" ); -*/ - return vResult; -} - -/**Function************************************************************* - - Synopsis [Derives AIG whose PI is substituted by a constant.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManModelCheckAigWithHints( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars ) -{ - DdManager * ddGlo = NULL; - Vec_Int_t * vHints; - Vec_Int_t * vHFCands; - int i, Entry, RetValue = -1; - int clk = clock(); - assert( pPars->nHintDepth > 0 ); -/* - // perform reachability without hints - RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, NULL, NULL ); - if ( RetValue >= 0 ) - return RetValue; -*/ - // create hints representation - vHFCands = Llb_ManCollectHighFanoutObjects( pAigGlo, pPars->nHintDepth+pPars->HintFirst, 1 ); - vHints = Vec_IntStartFull( Aig_ManObjNumMax(pAigGlo) ); - // add one hint at a time till the problem is solved - Vec_IntForEachEntryStart( vHFCands, Entry, i, pPars->HintFirst ) - { - Vec_IntWriteEntry( vHints, Entry, 1 ); // change to 1 to start from zero cof!!! - // solve under hints - RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, vHints, &ddGlo ); - if ( RetValue == 0 ) - goto Finish; - if ( RetValue == 1 ) - break; - } - if ( RetValue == -1 ) - goto Finish; - // undo the hints one at a time - for ( ; i >= pPars->HintFirst; i-- ) - { - Entry = Vec_IntEntry( vHFCands, i ); - Vec_IntWriteEntry( vHints, Entry, -1 ); - // solve under relaxed hints - RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, vHints, &ddGlo ); - if ( RetValue == 0 ) - goto Finish; - if ( RetValue == 1 ) - continue; - break; - } -Finish: - if ( ddGlo ) - { - if ( ddGlo->bFunc ) - Cudd_RecursiveDeref( ddGlo, ddGlo->bFunc ); - Extra_StopManager( ddGlo ); - } - Vec_IntFreeP( &vHFCands ); - Vec_IntFreeP( &vHints ); - if ( pPars->fVerbose ) - Abc_PrintTime( 1, "Total runtime", clock() - clk ); - return RetValue; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llb1Man.c b/src/aig/llb/llb1Man.c deleted file mode 100644 index f5de25e0..00000000 --- a/src/aig/llb/llb1Man.c +++ /dev/null @@ -1,218 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb1Man.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Reachability manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb1Man.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManPrepareVarMap( Llb_Man_t * p ) -{ - Aig_Obj_t * pObjLi, * pObjLo; - int i, iVarLi, iVarLo; - assert( p->vNs2Glo == NULL ); - assert( p->vCs2Glo == NULL ); - assert( p->vGlo2Cs == NULL ); - assert( p->vGlo2Ns == NULL ); - p->vNs2Glo = Vec_IntStartFull( Vec_IntSize(p->vVar2Obj) ); - p->vCs2Glo = Vec_IntStartFull( Vec_IntSize(p->vVar2Obj) ); - p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); - p->vGlo2Ns = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); - Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) - { - iVarLi = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLi)); - iVarLo = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLo)); - assert( iVarLi >= 0 && iVarLi < Vec_IntSize(p->vVar2Obj) ); - assert( iVarLo >= 0 && iVarLo < Vec_IntSize(p->vVar2Obj) ); - Vec_IntWriteEntry( p->vNs2Glo, iVarLi, i ); - Vec_IntWriteEntry( p->vCs2Glo, iVarLo, i ); - Vec_IntWriteEntry( p->vGlo2Cs, i, iVarLo ); - Vec_IntWriteEntry( p->vGlo2Ns, i, iVarLi ); - } - // add mapping of the PIs - Saig_ManForEachPi( p->pAig, pObjLo, i ) - { - iVarLo = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLo)); - Vec_IntWriteEntry( p->vCs2Glo, iVarLo, Aig_ManRegNum(p->pAig)+i ); - Vec_IntWriteEntry( p->vNs2Glo, iVarLo, Aig_ManRegNum(p->pAig)+i ); - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManPrepareVarLimits( Llb_Man_t * p ) -{ - Llb_Grp_t * pGroup; - Aig_Obj_t * pVar; - int i, k; - assert( p->vVarBegs == NULL ); - assert( p->vVarEnds == NULL ); - p->vVarEnds = Vec_IntStart( Aig_ManObjNumMax(p->pAig) ); - p->vVarBegs = Vec_IntStart( Aig_ManObjNumMax(p->pAig) ); - Vec_IntFill( p->vVarBegs, Aig_ManObjNumMax(p->pAig), p->pMatrix->nCols ); - - for ( i = 0; i < p->pMatrix->nCols; i++ ) - { - pGroup = p->pMatrix->pColGrps[i]; - - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) - if ( Vec_IntEntry(p->vVarBegs, pVar->Id) > i ) - Vec_IntWriteEntry( p->vVarBegs, pVar->Id, i ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) - if ( Vec_IntEntry(p->vVarBegs, pVar->Id) > i ) - Vec_IntWriteEntry( p->vVarBegs, pVar->Id, i ); - - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) - if ( Vec_IntEntry(p->vVarEnds, pVar->Id) < i ) - Vec_IntWriteEntry( p->vVarEnds, pVar->Id, i ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) - if ( Vec_IntEntry(p->vVarEnds, pVar->Id) < i ) - Vec_IntWriteEntry( p->vVarEnds, pVar->Id, i ); - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManStop( Llb_Man_t * p ) -{ - Llb_Grp_t * pGrp; - DdNode * bTemp; - int i; - -// Vec_IntFreeP( &p->vMem ); -// Vec_PtrFreeP( &p->vTops ); -// Vec_PtrFreeP( &p->vBots ); -// Vec_VecFreeP( (Vec_Vec_t **)&p->vCuts ); - - if ( p->pMatrix ) - Llb_MtrFree( p->pMatrix ); - Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGrp, i ) - Llb_ManGroupStop( pGrp ); - if ( p->dd ) - { -// printf( "Manager dd\n" ); - Extra_StopManager( p->dd ); - } - if ( p->ddG ) - { -// printf( "Manager ddG\n" ); - if ( p->ddG->bFunc ) - Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc ); - Extra_StopManager( p->ddG ); - } - if ( p->ddR ) - { -// printf( "Manager ddR\n" ); - if ( p->ddR->bFunc ) - Cudd_RecursiveDeref( p->ddR, p->ddR->bFunc ); - Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i ) - Cudd_RecursiveDeref( p->ddR, bTemp ); - Extra_StopManager( p->ddR ); - } - Aig_ManStop( p->pAig ); - Vec_PtrFreeP( &p->vGroups ); - Vec_IntFreeP( &p->vVar2Obj ); - Vec_IntFreeP( &p->vObj2Var ); - Vec_IntFreeP( &p->vVarBegs ); - Vec_IntFreeP( &p->vVarEnds ); - Vec_PtrFreeP( &p->vRings ); - Vec_IntFreeP( &p->vNs2Glo ); - Vec_IntFreeP( &p->vCs2Glo ); - Vec_IntFreeP( &p->vGlo2Cs ); - Vec_IntFreeP( &p->vGlo2Ns ); -// Vec_IntFreeP( &p->vHints ); - ABC_FREE( p ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Man_t * Llb_ManStart( Aig_Man_t * pAigGlo, Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) -{ - Llb_Man_t * p; - Aig_ManCleanMarkA( pAig ); - p = ABC_CALLOC( Llb_Man_t, 1 ); - p->pAigGlo = pAigGlo; - p->pPars = pPars; - p->pAig = pAig; - p->vVar2Obj = Llb_ManMarkPivotNodes( p->pAig, pPars->fUsePivots ); - p->vObj2Var = Vec_IntInvert( p->vVar2Obj, -1 ); - p->vRings = Vec_PtrAlloc( 100 ); - Llb_ManPrepareVarMap( p ); - Llb_ManPrepareGroups( p ); - Aig_ManCleanMarkA( pAig ); - p->pMatrix = Llb_MtrCreate( p ); - p->pMatrix->pMan = p; - return p; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llb1Matrix.c b/src/aig/llb/llb1Matrix.c deleted file mode 100644 index 7aa9c744..00000000 --- a/src/aig/llb/llb1Matrix.c +++ /dev/null @@ -1,430 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb1Matrix.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Partition clustering as a matrix problem.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb1Matrix.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// 0123 nCols -// +---------------------> -// pi 0 | 111 row0 pRowSums[0] -// pi 1 | 1 11 row1 pRowSums[1] -// pi 2 | 1 11 row2 pRowSums[2] -// CS |1 1 -// CS |1 111 -// CS |111 111 -// int | 11111 -// int | 111 -// int | 111 -// int | 111 -// NS | 11 11 -// NS | 11 1 -// NS | 111 -// nRows | -// v -// cccc pColSums[0] -// oooo pColSums[1] -// llll pColSums[2] -// 0123 pColSums[3] - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Verify columns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrVerifyRowsAll( Llb_Mtr_t * p ) -{ - int iRow, iCol, Counter; - for ( iCol = 0; iCol < p->nCols; iCol++ ) - { - Counter = 0; - for ( iRow = 0; iRow < p->nRows; iRow++ ) - if ( p->pMatrix[iCol][iRow] == 1 ) - Counter++; - assert( Counter == p->pColSums[iCol] ); - } -} - -/**Function************************************************************* - - Synopsis [Verify columns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrVerifyColumnsAll( Llb_Mtr_t * p ) -{ - int iRow, iCol, Counter; - for ( iRow = 0; iRow < p->nRows; iRow++ ) - { - Counter = 0; - for ( iCol = 0; iCol < p->nCols; iCol++ ) - if ( p->pMatrix[iCol][iRow] == 1 ) - Counter++; - assert( Counter == p->pRowSums[iRow] ); - } -} - -/**Function************************************************************* - - Synopsis [Verify columns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrVerifyMatrix( Llb_Mtr_t * p ) -{ - Llb_MtrVerifyRowsAll( p ); - Llb_MtrVerifyColumnsAll( p ); -} - -/**Function************************************************************* - - Synopsis [Sort variables in the order of removal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int * Llb_MtrFindVarOrder( Llb_Mtr_t * p ) -{ - int * pOrder, * pLast; - int i, k, fChanges, Temp; - pOrder = ABC_CALLOC( int, p->nRows ); - pLast = ABC_CALLOC( int, p->nRows ); - for ( i = 0; i < p->nRows; i++ ) - { - pOrder[i] = i; - for ( k = p->nCols - 1; k >= 0; k-- ) - if ( p->pMatrix[k][i] ) - { - pLast[i] = k; - break; - } - } - do - { - fChanges = 0; - for ( i = 0; i < p->nRows - 1; i++ ) - if ( pLast[i] > pLast[i+1] ) - { - Temp = pOrder[i]; - pOrder[i] = pOrder[i+1]; - pOrder[i+1] = Temp; - - Temp = pLast[i]; - pLast[i] = pLast[i+1]; - pLast[i+1] = Temp; - - fChanges = 1; - } - } - while ( fChanges ); - ABC_FREE( pLast ); - return pOrder; -} - -/**Function************************************************************* - - Synopsis [Returns type of a variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Llb_MtrVarName( Llb_Mtr_t * p, int iVar ) -{ - static char Buffer[10]; - if ( iVar < p->nPis ) - strcpy( Buffer, "pi" ); - else if ( iVar < p->nPis + p->nFfs ) - strcpy( Buffer, "CS" ); - else if ( iVar >= p->nRows - p->nFfs ) - strcpy( Buffer, "NS" ); - else - strcpy( Buffer, "int" ); - return Buffer; -} - -/**Function************************************************************* - - Synopsis [Creates one column with vars in the array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrPrint( Llb_Mtr_t * p, int fOrder ) -{ - int * pOrder = NULL; - int i, iRow, iCol; - if ( fOrder ) - pOrder = Llb_MtrFindVarOrder( p ); - for ( i = 0; i < p->nRows; i++ ) - { - iRow = pOrder ? pOrder[i] : i; - printf( "%3d : ", iRow ); - printf( "%3d ", p->pRowSums[iRow] ); - printf( "%3s ", Llb_MtrVarName(p, iRow) ); - for ( iCol = 0; iCol < p->nCols; iCol++ ) - printf( "%c", p->pMatrix[iCol][iRow] ? '*' : ' ' ); - printf( "\n" ); - } - ABC_FREE( pOrder ); -} - -/**Function************************************************************* - - Synopsis [Verify columns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrPrintMatrixStats( Llb_Mtr_t * p ) -{ - int iVar, iGrp, iGrp1, iGrp2, Span = 0, nCutSize = 0, nCutSizeMax = 0; - int * pGrp1 = ABC_CALLOC( int, p->nRows ); - int * pGrp2 = ABC_CALLOC( int, p->nRows ); - for ( iVar = 0; iVar < p->nRows; iVar++ ) - { - if ( p->pRowSums[iVar] == 0 ) - continue; - for ( iGrp1 = 0; iGrp1 < p->nCols; iGrp1++ ) - if ( p->pMatrix[iGrp1][iVar] == 1 ) - break; - for ( iGrp2 = p->nCols - 1; iGrp2 >= 0; iGrp2-- ) - if ( p->pMatrix[iGrp2][iVar] == 1 ) - break; - assert( iGrp1 <= iGrp2 ); - pGrp1[iVar] = iGrp1; - pGrp2[iVar] = iGrp2; - Span += iGrp2 - iGrp1; - } - // compute span - for ( iGrp = 0; iGrp < p->nCols; iGrp++ ) - { - for ( iVar = 0; iVar < p->nRows; iVar++ ) - if ( pGrp1[iVar] == iGrp ) - nCutSize++; - if ( nCutSizeMax < nCutSize ) - nCutSizeMax = nCutSize; - for ( iVar = 0; iVar < p->nRows; iVar++ ) - if ( pGrp2[iVar] == iGrp ) - nCutSize--; - } - ABC_FREE( pGrp1 ); - ABC_FREE( pGrp2 ); - printf( "[%4d x %4d] Life-span =%6.2f Max-cut =%5d\n", - p->nCols, p->nRows, 1.0*Span/p->nRows, nCutSizeMax ); - if ( nCutSize ) - Abc_Print( -1, "Cut size is not zero (%d).\n", nCutSize ); -} - - - -/**Function************************************************************* - - Synopsis [Starts the matrix representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Mtr_t * Llb_MtrAlloc( int nPis, int nFfs, int nCols, int nRows ) -{ - Llb_Mtr_t * p; - int i; - p = ABC_CALLOC( Llb_Mtr_t, 1 ); - p->nPis = nPis; - p->nFfs = nFfs; - p->nRows = nRows; - p->nCols = nCols; - p->pRowSums = ABC_CALLOC( int, nRows ); - p->pColSums = ABC_CALLOC( int, nCols ); - p->pColGrps = ABC_CALLOC( Llb_Grp_t *, nCols ); - p->pMatrix = ABC_CALLOC( char *, nCols ); - for ( i = 0; i < nCols; i++ ) - p->pMatrix[i] = ABC_CALLOC( char, nRows ); - // partial product - p->pProdVars = ABC_CALLOC( char, nRows ); // variables in the partial product - p->pProdNums = ABC_CALLOC( int, nRows ); // var counts in the remaining partitions - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the matrix representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrFree( Llb_Mtr_t * p ) -{ - int i; - ABC_FREE( p->pProdVars ); - ABC_FREE( p->pProdNums ); - for ( i = 0; i < p->nCols; i++ ) - ABC_FREE( p->pMatrix[i] ); - ABC_FREE( p->pRowSums ); - ABC_FREE( p->pColSums ); - ABC_FREE( p->pMatrix ); - ABC_FREE( p->pColGrps ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Creates one column with vars in the array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrAddColumn( Llb_Mtr_t * p, Llb_Grp_t * pGrp ) -{ - Aig_Obj_t * pVar; - int i, iRow, iCol = pGrp->Id; - assert( iCol >= 0 && iCol < p->nCols ); - p->pColGrps[iCol] = pGrp; - Vec_PtrForEachEntry( Aig_Obj_t *, pGrp->vIns, pVar, i ) - { - iRow = Vec_IntEntry( pGrp->pMan->vObj2Var, Aig_ObjId(pVar) ); - assert( iRow >= 0 && iRow < p->nRows ); - p->pMatrix[iCol][iRow] = 1; - p->pColSums[iCol]++; - p->pRowSums[iRow]++; - } - Vec_PtrForEachEntry( Aig_Obj_t *, pGrp->vOuts, pVar, i ) - { - iRow = Vec_IntEntry( pGrp->pMan->vObj2Var, Aig_ObjId(pVar) ); - assert( iRow >= 0 && iRow < p->nRows ); - p->pMatrix[iCol][iRow] = 1; - p->pColSums[iCol]++; - p->pRowSums[iRow]++; - } -} - -/**Function************************************************************* - - Synopsis [Matrix reduce.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrRemoveSingletonRows( Llb_Mtr_t * p ) -{ - int i, k; - for ( i = 0; i < p->nRows; i++ ) - if ( p->pRowSums[i] < 2 ) - { - p->pRowSums[i] = 0; - for ( k = 0; k < p->nCols; k++ ) - { - if ( p->pMatrix[k][i] == 1 ) - { - p->pMatrix[k][i] = 0; - p->pColSums[k]--; - } - } - } -} - -/**Function************************************************************* - - Synopsis [Matrix reduce.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Mtr_t * Llb_MtrCreate( Llb_Man_t * p ) -{ - Llb_Mtr_t * pMatrix; - Llb_Grp_t * pGroup; - int i; - pMatrix = Llb_MtrAlloc( Saig_ManPiNum(p->pAig), Saig_ManRegNum(p->pAig), - Vec_PtrSize(p->vGroups), Vec_IntSize(p->vVar2Obj) ); - Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGroup, i ) - Llb_MtrAddColumn( pMatrix, pGroup ); -// Llb_MtrRemoveSingletonRows( pMatrix ); - return pMatrix; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llb1Pivot.c b/src/aig/llb/llb1Pivot.c deleted file mode 100644 index d42bf659..00000000 --- a/src/aig/llb/llb1Pivot.c +++ /dev/null @@ -1,254 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb1Pivot.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Determining pivot variables.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb1Pivot.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManTracePaths_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pPivot ) -{ - Aig_Obj_t * pFanout; - int k, iFan; - if ( Aig_ObjIsTravIdPrevious(p, pObj) ) - return 0; - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - return 1; - if ( Saig_ObjIsLi(p, pObj) ) - return 0; - if ( Saig_ObjIsPo(p, pObj) ) - return 0; - if ( pObj == pPivot ) - return 1; - assert( Aig_ObjIsCand(pObj) ); - Aig_ObjForEachFanout( p, pObj, pFanout, iFan, k ) - if ( !Llb_ManTracePaths_rec( p, pFanout, pPivot ) ) - { - Aig_ObjSetTravIdPrevious(p, pObj); - return 0; - } - Aig_ObjSetTravIdCurrent(p, pObj); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManTracePaths( Aig_Man_t * p, Aig_Obj_t * pPivot ) -{ - Aig_Obj_t * pObj; - int i, Counter = 0; - Aig_ManIncrementTravId( p ); // prev = visited with path to LI (value 0) - Aig_ManIncrementTravId( p ); // cur = visited w/o path to LI (value 1) - Saig_ManForEachLo( p, pObj, i ) - Counter += Llb_ManTracePaths_rec( p, pObj, pPivot ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManTestCuts( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i, Count; - Aig_ManFanoutStart( p ); - Aig_ManForEachNode( p, pObj, i ) - { - if ( Aig_ObjRefs(pObj) <= 1 ) - continue; - Count = Llb_ManTracePaths( p, pObj ); - printf( "Obj =%5d. Lev =%3d. Fanout =%5d. Count = %3d.\n", - i, Aig_ObjLevel(pObj), Aig_ObjRefs(pObj), Count ); - } - Aig_ManFanoutStop( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManLabelLiCones_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - if ( pObj->fMarkB ) - return; - pObj->fMarkB = 1; - assert( Aig_ObjIsNode(pObj) ); - Llb_ManLabelLiCones_rec( p, Aig_ObjFanin0(pObj) ); - Llb_ManLabelLiCones_rec( p, Aig_ObjFanin1(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Determine starting cut-points.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManLabelLiCones( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i; - // mark const and PIs - Aig_ManConst1(p)->fMarkB = 1; - Aig_ManForEachPi( p, pObj, i ) - pObj->fMarkB = 1; - // mark cones - Saig_ManForEachLi( p, pObj, i ) - Llb_ManLabelLiCones_rec( p, Aig_ObjFanin0(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Determine starting cut-points.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManMarkInternalPivots( Aig_Man_t * p ) -{ - Vec_Ptr_t * vMuxes; - Aig_Obj_t * pObj; - int i, Counter = 0; - - // remove refs due to MUXes - vMuxes = Aig_ManMuxesCollect( p ); - Aig_ManMuxesDeref( p, vMuxes ); - - // mark nodes feeding into LIs - Aig_ManCleanMarkB( p ); - Llb_ManLabelLiCones( p ); - - // mark internal nodes - Aig_ManFanoutStart( p ); - Aig_ManForEachNode( p, pObj, i ) - if ( pObj->fMarkB && pObj->nRefs > 1 ) - { - if ( Llb_ManTracePaths(p, pObj) > 0 ) - pObj->fMarkA = 1; - Counter++; - } - Aig_ManFanoutStop( p ); -// printf( "TracePath tried = %d.\n", Counter ); - - // mark nodes feeding into LIs - Aig_ManCleanMarkB( p ); - - // add refs due to MUXes - Aig_ManMuxesRef( p, vMuxes ); - Vec_PtrFree( vMuxes ); -} - -/**Function************************************************************* - - Synopsis [Determine starting cut-points.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_ManMarkPivotNodes( Aig_Man_t * p, int fUseInternal ) -{ - Vec_Int_t * vVar2Obj; - Aig_Obj_t * pObj; - int i; - // mark inputs/outputs - Aig_ManForEachPi( p, pObj, i ) - pObj->fMarkA = 1; - Saig_ManForEachLi( p, pObj, i ) - pObj->fMarkA = 1; - - // mark internal pivot nodes - if ( fUseInternal ) - Llb_ManMarkInternalPivots( p ); - - // assign variable numbers - Aig_ManConst1(p)->fMarkA = 0; - vVar2Obj = Vec_IntAlloc( 100 ); - Aig_ManForEachPi( p, pObj, i ) - Vec_IntPush( vVar2Obj, Aig_ObjId(pObj) ); - Aig_ManForEachNode( p, pObj, i ) - if ( pObj->fMarkA ) - Vec_IntPush( vVar2Obj, Aig_ObjId(pObj) ); - Saig_ManForEachLi( p, pObj, i ) - Vec_IntPush( vVar2Obj, Aig_ObjId(pObj) ); - return vVar2Obj; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llb1Reach.c b/src/aig/llb/llb1Reach.c deleted file mode 100644 index e427eb24..00000000 --- a/src/aig/llb/llb1Reach.c +++ /dev/null @@ -1,899 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb1Reach.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Reachability analysis.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb1Reach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" -#include "extra.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Derives global BDD for the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ManConstructOutBdd( Aig_Man_t * pAig, Aig_Obj_t * pNode, DdManager * dd ) -{ - DdNode * bBdd0, * bBdd1, * bFunc; - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i, TimeStop; - if ( Aig_ObjFanin0(pNode) == Aig_ManConst1(pAig) ) - return Cudd_NotCond( Cudd_ReadOne(dd), Aig_ObjFaninC0(pNode) ); - TimeStop = dd->TimeStop; dd->TimeStop = 0; - vNodes = Aig_ManDfsNodes( pAig, &pNode, 1 ); - assert( Vec_PtrSize(vNodes) > 0 ); - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) - { - if ( !Aig_ObjIsNode(pObj) ) - continue; - bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bBdd1 = Cudd_NotCond( Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); - pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData ); - } - bFunc = (DdNode *)pObj->pData; Cudd_Ref( bFunc ); - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) - { - if ( !Aig_ObjIsNode(pObj) ) - continue; - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); - } - Vec_PtrFree( vNodes ); - if ( Aig_ObjIsPo(pNode) ) - bFunc = Cudd_NotCond( bFunc, Aig_ObjFaninC0(pNode) ); - Cudd_Deref( bFunc ); - dd->TimeStop = TimeStop; - return bFunc; -} - -/**Function************************************************************* - - Synopsis [Derives BDD for the group.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ManConstructGroupBdd( Llb_Man_t * p, Llb_Grp_t * pGroup ) -{ - Aig_Obj_t * pObj; - DdNode * bBdd0, * bBdd1, * bRes, * bXor, * bTemp; - int i, k; - Aig_ManConst1(p->pAig)->pData = Cudd_ReadOne( p->dd ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) - pObj->pData = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vNodes, pObj, i ) - { - bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bBdd1 = Cudd_NotCond( Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); -// pObj->pData = Extra_bddAndTime( p->dd, bBdd0, bBdd1, p->pPars->TimeTarget ); - pObj->pData = Cudd_bddAnd( p->dd, bBdd0, bBdd1 ); - if ( pObj->pData == NULL ) - { - Vec_PtrForEachEntryStop( Aig_Obj_t *, pGroup->vNodes, pObj, k, i ) - if ( pObj->pData ) - Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData ); - return NULL; - } - Cudd_Ref( (DdNode *)pObj->pData ); - } - bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) - { - if ( Aig_ObjIsPo(pObj) ) - bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - else - bBdd0 = (DdNode *)pObj->pData; - bBdd1 = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); - bXor = Cudd_bddXor( p->dd, bBdd0, bBdd1 ); Cudd_Ref( bXor ); -// bRes = Extra_bddAndTime( p->dd, bTemp = bRes, Cudd_Not(bXor), p->pPars->TimeTarget ); - bRes = Cudd_bddAnd( p->dd, bTemp = bRes, Cudd_Not(bXor) ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bXor ); - Vec_PtrForEachEntryStop( Aig_Obj_t *, pGroup->vNodes, pObj, k, i ) - if ( pObj->pData ) - Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData ); - return NULL; - } - Cudd_Ref( bRes ); - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bXor ); - } - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vNodes, pObj, i ) - Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData ); - Cudd_Deref( bRes ); - return bRes; -} - -/**Function************************************************************* - - Synopsis [Derives quantification cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ManConstructQuantCubeIntern( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace, int fBackward ) -{ - Aig_Obj_t * pObj; - DdNode * bRes, * bTemp, * bVar; - int i, iGroupFirst, iGroupLast; - int TimeStop; - TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; - bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) - { - if ( fBackward && Saig_ObjIsPi(p->pAig, pObj) ) - continue; - iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj)); - iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); - assert( iGroupFirst <= iGroupLast ); - if ( iGroupFirst < iGroupLast ) - continue; - bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); - bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) - { - if ( fBackward && Saig_ObjIsPi(p->pAig, pObj) ) - continue; - iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj)); - iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); - assert( iGroupFirst <= iGroupLast ); - if ( iGroupFirst < iGroupLast ) - continue; - bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); - bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - Cudd_Deref( bRes ); - p->dd->TimeStop = TimeStop; - return bRes; -} - -/**Function************************************************************* - - Synopsis [Derives quantification cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ManConstructQuantCubeFwd( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace ) -{ - Aig_Obj_t * pObj; - DdNode * bRes, * bTemp, * bVar; - int i, iGroupLast, TimeStop; - TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; - bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) - { - iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); - assert( iGroupLast >= iGrpPlace ); - if ( iGroupLast > iGrpPlace ) - continue; - bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); - bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) - { - iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); - assert( iGroupLast >= iGrpPlace ); - if ( iGroupLast > iGrpPlace ) - continue; - bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); - bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - Cudd_Deref( bRes ); - p->dd->TimeStop = TimeStop; - return bRes; -} - -/**Function************************************************************* - - Synopsis [Derives quantification cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ManConstructQuantCubeBwd( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace ) -{ - Aig_Obj_t * pObj; - DdNode * bRes, * bTemp, * bVar; - int i, iGroupFirst, TimeStop; - TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; - bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) - { - if ( Saig_ObjIsPi(p->pAig, pObj) ) - continue; - iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj)); - assert( iGroupFirst <= iGrpPlace ); - if ( iGroupFirst < iGrpPlace ) - continue; - bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); - bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) - { - if ( Saig_ObjIsPi(p->pAig, pObj) ) - continue; - iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj)); - assert( iGroupFirst <= iGrpPlace ); - if ( iGroupFirst < iGrpPlace ) - continue; - bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); - bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - Cudd_Deref( bRes ); - p->dd->TimeStop = TimeStop; - return bRes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ManComputeInitState( Llb_Man_t * p, DdManager * dd ) -{ - Aig_Obj_t * pObj; - DdNode * bRes, * bVar, * bTemp; - int i, iVar, TimeStop; - TimeStop = dd->TimeStop; dd->TimeStop = 0; - bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); - Saig_ManForEachLo( p->pAig, pObj, i ) - { - iVar = (dd == p->ddG) ? i : Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)); - bVar = Cudd_bddIthVar( dd, iVar ); - bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bRes ); - dd->TimeStop = TimeStop; - return bRes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ManComputeImage( Llb_Man_t * p, DdNode * bInit, int fBackward ) -{ - int fCheckSupport = 0; - Llb_Grp_t * pGroup; - DdNode * bImage, * bGroup, * bCube, * bTemp; - int k, Index; - bImage = bInit; Cudd_Ref( bImage ); - for ( k = 1; k < p->pMatrix->nCols-1; k++ ) - { - if ( fBackward ) - Index = p->pMatrix->nCols - 1 - k; - else - Index = k; - - // compute group BDD - pGroup = p->pMatrix->pColGrps[Index]; - bGroup = Llb_ManConstructGroupBdd( p, pGroup ); - if ( bGroup == NULL ) - { - Cudd_RecursiveDeref( p->dd, bImage ); - return NULL; - } - Cudd_Ref( bGroup ); - // quantify variables appearing only in this group - bCube = Llb_ManConstructQuantCubeIntern( p, pGroup, Index, fBackward ); Cudd_Ref( bCube ); - bGroup = Cudd_bddExistAbstract( p->dd, bTemp = bGroup, bCube ); - if ( bGroup == NULL ) - { - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bCube ); - return NULL; - } - Cudd_Ref( bGroup ); - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bCube ); - // perform partial product - if ( fBackward ) - bCube = Llb_ManConstructQuantCubeBwd( p, pGroup, Index ); - else - bCube = Llb_ManConstructQuantCubeFwd( p, pGroup, Index ); - Cudd_Ref( bCube ); -// bImage = Extra_bddAndAbstractTime( p->dd, bTemp = bImage, bGroup, bCube, p->pPars->TimeTarget ); - bImage = Cudd_bddAndAbstract( p->dd, bTemp = bImage, bGroup, bCube ); - if ( bImage == NULL ) - { - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bGroup ); - Cudd_RecursiveDeref( p->dd, bCube ); - return NULL; - } - Cudd_Ref( bImage ); - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bGroup ); - Cudd_RecursiveDeref( p->dd, bCube ); - } - - // make sure image depends on next state vars - if ( fCheckSupport ) - { - bCube = Cudd_Support( p->dd, bImage ); Cudd_Ref( bCube ); - for ( bTemp = bCube; bTemp != p->dd->one; bTemp = cuddT(bTemp) ) - { - int ObjId = Vec_IntEntry( p->vVar2Obj, bTemp->index ); - Aig_Obj_t * pObj = Aig_ManObj( p->pAig, ObjId ); - if ( !Saig_ObjIsLi(p->pAig, pObj) ) - printf( "Var %d assigned to obj %d that is not LI\n", bTemp->index, ObjId ); - } - Cudd_RecursiveDeref( p->dd, bCube ); - } - Cudd_Deref( bImage ); - return bImage; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ManCreateConstraints( Llb_Man_t * p, Vec_Int_t * vHints, int fUseNsVars ) -{ - DdNode * bConstr, * bFunc, * bTemp; - Aig_Obj_t * pObj; - int i, Entry, TimeStop; - if ( vHints == NULL ) - return Cudd_ReadOne( p->dd ); - TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; - assert( Aig_ManPiNum(p->pAig) == Aig_ManPiNum(p->pAigGlo) ); - // assign const and PI nodes to the original AIG - Aig_ManCleanData( p->pAig ); - Aig_ManConst1( p->pAig )->pData = Cudd_ReadOne( p->dd ); - Saig_ManForEachPi( p->pAig, pObj, i ) - pObj->pData = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var,Aig_ObjId(pObj)) ); - Saig_ManForEachLo( p->pAig, pObj, i ) - { - if ( fUseNsVars ) - Entry = Vec_IntEntry( p->vObj2Var, Aig_ObjId(Saig_ObjLoToLi(p->pAig, pObj)) ); - else - Entry = Vec_IntEntry( p->vObj2Var, Aig_ObjId(pObj) ); - pObj->pData = Cudd_bddIthVar( p->dd, Entry ); - } - // transfer them to the global AIG - Aig_ManCleanData( p->pAigGlo ); - Aig_ManConst1( p->pAigGlo )->pData = Cudd_ReadOne( p->dd ); - Aig_ManForEachPi( p->pAigGlo, pObj, i ) - pObj->pData = Aig_ManPi(p->pAig, i)->pData; - // derive consraints - bConstr = Cudd_ReadOne( p->dd ); Cudd_Ref( bConstr ); - Vec_IntForEachEntry( vHints, Entry, i ) - { - if ( Entry != 0 && Entry != 1 ) - continue; - bFunc = Llb_ManConstructOutBdd( p->pAigGlo, Aig_ManObj(p->pAigGlo, i), p->dd ); Cudd_Ref( bFunc ); - bFunc = Cudd_NotCond( bFunc, Entry ); // restrict to not constraint - // make the product - bConstr = Cudd_bddAnd( p->dd, bTemp = bConstr, bFunc ); Cudd_Ref( bConstr ); - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bFunc ); - } - Cudd_Deref( bConstr ); - p->dd->TimeStop = TimeStop; - return bConstr; -} - -/**Function************************************************************* - - Synopsis [Perform reachability with hints and returns reached states in ppGlo.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Cex_t * Llb_ManReachDeriveCex( Llb_Man_t * p ) -{ - Abc_Cex_t * pCex; - Aig_Obj_t * pObj; - DdNode * bState, * bImage, * bOneCube, * bTemp, * bRing; - int i, v, RetValue, nPiOffset; - char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) ); - assert( Vec_PtrSize(p->vRings) > 0 ); - - p->dd->TimeStop = 0; - p->ddR->TimeStop = 0; - -/* - Saig_ManForEachLo( p->pAig, pObj, i ) - printf( "%d ", pObj->Id ); - printf( "\n" ); - Saig_ManForEachLi( p->pAig, pObj, i ) - printf( "%d(%d) ", pObj->Id, Aig_ObjFaninId0(pObj) ); - printf( "\n" ); -*/ - // allocate room for the counter-example - pCex = Abc_CexAlloc( Saig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Vec_PtrSize(p->vRings) ); - pCex->iFrame = Vec_PtrSize(p->vRings) - 1; - pCex->iPo = -1; - - // get the last cube - bOneCube = Cudd_bddIntersect( p->ddR, (DdNode *)Vec_PtrEntryLast(p->vRings), p->ddR->bFunc ); Cudd_Ref( bOneCube ); - RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); - Cudd_RecursiveDeref( p->ddR, bOneCube ); - assert( RetValue ); - - // write PIs of counter-example - nPiOffset = Saig_ManRegNum(p->pAig) + Saig_ManPiNum(p->pAig) * (Vec_PtrSize(p->vRings) - 1); - Saig_ManForEachPi( p->pAig, pObj, i ) - if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) - Aig_InfoSetBit( pCex->pData, nPiOffset + i ); - - // write state in terms of NS variables - if ( Vec_PtrSize(p->vRings) > 1 ) - { - bState = Llb_CoreComputeCube( p->dd, p->vGlo2Ns, 1, pValues ); Cudd_Ref( bState ); - } - // perform backward analysis - Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v ) - { - if ( v == Vec_PtrSize(p->vRings) - 1 ) - continue; -//Extra_bddPrintSupport( p->dd, bState ); printf( "\n" ); -//Extra_bddPrintSupport( p->dd, bRing ); printf( "\n" ); - // compute the next states - bImage = Llb_ManComputeImage( p, bState, 1 ); - assert( bImage != NULL ); - Cudd_Ref( bImage ); - Cudd_RecursiveDeref( p->dd, bState ); -//Extra_bddPrintSupport( p->dd, bImage ); printf( "\n" ); - - // move reached states into ring manager - bImage = Extra_TransferPermute( p->dd, p->ddR, bTemp = bImage, Vec_IntArray(p->vCs2Glo) ); Cudd_Ref( bImage ); - Cudd_RecursiveDeref( p->dd, bTemp ); -//Extra_bddPrintSupport( p->ddR, bImage ); printf( "\n" ); - - // intersect with the previous set - bOneCube = Cudd_bddIntersect( p->ddR, bImage, bRing ); Cudd_Ref( bOneCube ); - Cudd_RecursiveDeref( p->ddR, bImage ); - - // find any assignment of the BDD - RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); - Cudd_RecursiveDeref( p->ddR, bOneCube ); - assert( RetValue ); -/* - for ( i = 0; i < p->ddR->size; i++ ) - printf( "%d ", pValues[i] ); - printf( "\n" ); -*/ - // write PIs of counter-example - nPiOffset -= Saig_ManPiNum(p->pAig); - Saig_ManForEachPi( p->pAig, pObj, i ) - if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) - Aig_InfoSetBit( pCex->pData, nPiOffset + i ); - - // check that we get the init state - if ( v == 0 ) - { - Saig_ManForEachLo( p->pAig, pObj, i ) - assert( pValues[i] == 0 ); - break; - } - - // write state in terms of NS variables - bState = Llb_CoreComputeCube( p->dd, p->vGlo2Ns, 1, pValues ); Cudd_Ref( bState ); - } - assert( nPiOffset == Saig_ManRegNum(p->pAig) ); - // update the output number -//Abc_CexPrint( pCex ); - RetValue = Saig_ManFindFailedPoCex( p->pAigGlo, pCex ); - assert( RetValue >= 0 && RetValue < Saig_ManPoNum(p->pAigGlo) ); // invalid CEX!!! - pCex->iPo = RetValue; - // cleanup - ABC_FREE( pValues ); - return pCex; -} - -/**Function************************************************************* - - Synopsis [Perform reachability with hints and returns reached states in ppGlo.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManReachability( Llb_Man_t * p, Vec_Int_t * vHints, DdManager ** pddGlo ) -{ - int * pNs2Glo = Vec_IntArray( p->vNs2Glo ); - int * pCs2Glo = Vec_IntArray( p->vCs2Glo ); - int * pGlo2Cs = Vec_IntArray( p->vGlo2Cs ); - DdNode * bCurrent, * bReached, * bNext, * bTemp, * bCube; - DdNode * bConstrCs, * bConstrNs; - int clk2, clk = clock(), nIters, nBddSize = 0; - int nThreshold = 10000; - - // compute time to stop - p->pPars->TimeTarget = p->pPars->TimeLimit ? time(NULL) + p->pPars->TimeLimit : 0; - - // define variable limits - Llb_ManPrepareVarLimits( p ); - - // start the managers - assert( p->dd == NULL ); - assert( p->ddG == NULL ); - assert( p->ddR == NULL ); - p->dd = Cudd_Init( Vec_IntSize(p->vVar2Obj), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - p->ddR = Cudd_Init( Aig_ManPiNum(p->pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - if ( pddGlo && *pddGlo ) - p->ddG = *pddGlo, *pddGlo = NULL; - else - p->ddG = Cudd_Init( Aig_ManRegNum(p->pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - - if ( p->pPars->fReorder ) - { - Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); - Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT ); - Cudd_AutodynEnable( p->ddR, CUDD_REORDER_SYMM_SIFT ); - } - else - { - Cudd_AutodynDisable( p->dd ); - Cudd_AutodynDisable( p->ddG ); - Cudd_AutodynDisable( p->ddR ); - } - - // set the stop time parameter - p->dd->TimeStop = p->pPars->TimeTarget; - p->ddG->TimeStop = p->pPars->TimeTarget; - p->ddR->TimeStop = p->pPars->TimeTarget; - - // create bad state in the ring manager - p->ddR->bFunc = Llb_BddComputeBad( p->pAigGlo, p->ddR, p->pPars->TimeTarget ); - if ( p->ddR->bFunc == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = -1; - return -1; - } - Cudd_Ref( p->ddR->bFunc ); - - // derive constraints - bConstrCs = Llb_ManCreateConstraints( p, vHints, 0 ); Cudd_Ref( bConstrCs ); - bConstrNs = Llb_ManCreateConstraints( p, vHints, 1 ); Cudd_Ref( bConstrNs ); -//Extra_bddPrint( p->dd, bConstrCs ); printf( "\n" ); -//Extra_bddPrint( p->dd, bConstrNs ); printf( "\n" ); - - // perform reachability analysis - // compute the starting set of states - if ( p->ddG->bFunc ) - { - bReached = p->ddG->bFunc; p->ddG->bFunc = NULL; - bCurrent = Extra_TransferPermute( p->ddG, p->dd, bReached, pGlo2Cs ); Cudd_Ref( bCurrent ); - } - else - { - bReached = Llb_ManComputeInitState( p, p->ddG ); Cudd_Ref( bReached ); - bCurrent = Llb_ManComputeInitState( p, p->dd ); Cudd_Ref( bCurrent ); - } -//Extra_bddPrintSupport( p->ddG, bReached ); printf( "\n" ); -//Extra_bddPrintSupport( p->dd, bCurrent ); printf( "\n" ); - -//Extra_bddPrintSupport( p->dd, bCurrent ); printf( "\n" ); - for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ ) - { - clk2 = clock(); - // check the runtime limit - if ( p->pPars->TimeLimit && time(NULL) > p->pPars->TimeTarget ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout during image computation (%d seconds).\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; - Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; - Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - return -1; - } - - // save the onion ring - bTemp = Extra_TransferPermute( p->dd, p->ddR, bCurrent, pCs2Glo ); - if ( bTemp == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during ring transfer.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; - Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; - Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - return -1; - } - Cudd_Ref( bTemp ); - Vec_PtrPush( p->vRings, bTemp ); - - // check it for bad states - if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->ddR, bTemp, Cudd_Not(p->ddR->bFunc) ) ) - { - assert( p->pAigGlo->pSeqModel == NULL ); - if ( !p->pPars->fBackward ) - p->pAigGlo->pSeqModel = Llb_ManReachDeriveCex( p ); - if ( !p->pPars->fSilent ) - { - if ( !p->pPars->fBackward ) - printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump a witness). ", p->pAigGlo->pSeqModel->iPo, nIters ); - else - printf( "Output ??? was asserted in frame %d (counter-example is not produced). ", nIters ); - Abc_PrintTime( 1, "Time", clock() - clk ); - } - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; - Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; - Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - return 0; - } - - // restrict reachable states using constraints - if ( vHints ) - { - bCurrent = Cudd_bddAnd( p->dd, bTemp = bCurrent, bConstrCs ); Cudd_Ref( bCurrent ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - - // quantify variables appearing only in the init state - bCube = Llb_ManConstructQuantCubeIntern( p, (Llb_Grp_t *)Vec_PtrEntry(p->vGroups,0), 0, 0 ); Cudd_Ref( bCube ); - bCurrent = Cudd_bddExistAbstract( p->dd, bTemp = bCurrent, bCube ); Cudd_Ref( bCurrent ); - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bCube ); - - // compute the next states - bNext = Llb_ManComputeImage( p, bCurrent, 0 ); - if ( bNext == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; - Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; - Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - return -1; - } - Cudd_Ref( bNext ); - Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; - - // restrict reachable states using constraints - if ( vHints ) - { - bNext = Cudd_bddAnd( p->dd, bTemp = bNext, bConstrNs ); Cudd_Ref( bNext ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } -//Extra_bddPrintSupport( p->dd, bNext ); printf( "\n" ); - - // remap these states into the current state vars -// bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pNs2Glo ); Cudd_Ref( bNext ); -// Cudd_RecursiveDeref( p->dd, bTemp ); -// bNext = Extra_TransferPermuteTime( p->dd, p->ddG, bTemp = bNext, pNs2Glo, p->pPars->TimeTarget ); - bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pNs2Glo ); - if ( bNext == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; - Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - return -1; - } - Cudd_Ref( bNext ); - Cudd_RecursiveDeref( p->dd, bTemp ); - - - // check if there are any new states - if ( Cudd_bddLeq( p->ddG, bNext, bReached ) ) // implication = no new states - { - Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; - break; - } - - // check the BDD size - nBddSize = Cudd_DagSize(bNext); - if ( nBddSize > p->pPars->nBddMax ) - { - Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; - break; - } - - // get the new states - bCurrent = Cudd_bddAnd( p->ddG, bNext, Cudd_Not(bReached) ); - if ( bCurrent == NULL ) - { - Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - break; - } - Cudd_Ref( bCurrent ); - // minimize the new states with the reached states -// bCurrent = Cudd_bddConstrain( p->ddG, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); -// bCurrent = Cudd_bddRestrict( p->ddG, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); -// Cudd_RecursiveDeref( p->ddG, bTemp ); -//printf( "Initial BDD =%7d. Constrained BDD =%7d.\n", Cudd_DagSize(bTemp), Cudd_DagSize(bCurrent) ); - - // remap these states into the current state vars -// bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs ); Cudd_Ref( bCurrent ); -// Cudd_RecursiveDeref( p->ddG, bTemp ); -// bCurrent = Extra_TransferPermuteTime( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs, p->pPars->TimeTarget ); - bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs ); - if ( bCurrent == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->ddG, bTemp ); - Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; - Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - return -1; - } - Cudd_Ref( bCurrent ); - Cudd_RecursiveDeref( p->ddG, bTemp ); - - - // add to the reached states - bReached = Cudd_bddOr( p->ddG, bTemp = bReached, bNext ); - if ( bReached == NULL ) - { - Cudd_RecursiveDeref( p->ddG, bTemp ); bTemp = NULL; - Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; - break; - } - Cudd_Ref( bReached ); - Cudd_RecursiveDeref( p->ddG, bTemp ); - Cudd_RecursiveDeref( p->ddG, bNext ); - bNext = NULL; - - if ( p->pPars->fVerbose ) - { - fprintf( stdout, "F =%5d : ", nIters ); - fprintf( stdout, "Im =%6d ", nBddSize ); - fprintf( stdout, "(%4d %3d) ", Cudd_ReadReorderings(p->dd), Cudd_ReadGarbageCollections(p->dd) ); - fprintf( stdout, "Rea =%6d ", Cudd_DagSize(bReached) ); - fprintf( stdout, "(%4d%4d) ", Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) ); - Abc_PrintTime( 1, "Time", clock() - clk2 ); - } -/* - if ( p->pPars->fVerbose ) - { - double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) ); -// Extra_bddPrint( p->ddG, bReached );printf( "\n" ); - fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); - fflush( stdout ); - } -*/ - } - Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; - Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; - if ( bReached == NULL ) - { - p->pPars->iFrame = nIters - 1; - return 0; // reachable - } -// assert( bCurrent == NULL ); - if ( bCurrent ) - Cudd_RecursiveDeref( p->dd, bCurrent ); - // report the stats - if ( p->pPars->fVerbose ) - { - double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) ); - if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax ) - fprintf( stdout, "Reachability analysis is stopped after %d frames.\n", nIters ); - else - fprintf( stdout, "Reachability analysis completed after %d frames.\n", nIters ); - fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); - fflush( stdout ); - } - if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax ) - { - if ( !p->pPars->fSilent ) - printf( "Verified only for states reachable in %d frames. ", nIters ); - p->pPars->iFrame = p->pPars->nIterMax; - Cudd_RecursiveDeref( p->ddG, bReached ); - return -1; // undecided - } - if ( pddGlo ) - { - assert( p->ddG->bFunc == NULL ); - p->ddG->bFunc = bReached; bReached = NULL; - assert( *pddGlo == NULL ); - *pddGlo = p->ddG; p->ddG = NULL; - } - else - Cudd_RecursiveDeref( p->ddG, bReached ); - if ( !p->pPars->fSilent ) - printf( "The miter is proved unreachable after %d iterations. ", nIters ); - p->pPars->iFrame = nIters - 1; - return 1; // unreachable -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llb1Sched.c b/src/aig/llb/llb1Sched.c deleted file mode 100644 index 6bdae42e..00000000 --- a/src/aig/llb/llb1Sched.c +++ /dev/null @@ -1,257 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb1Sched.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Partition scheduling algorithm.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb1Sched.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Swaps two rows.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrSwapColumns( Llb_Mtr_t * p, int iCol1, int iCol2 ) -{ - Llb_Grp_t * pGemp; - char * pTemp; - int iTemp; - assert( iCol1 >= 0 && iCol1 < p->nCols ); - assert( iCol2 >= 0 && iCol2 < p->nCols ); - if ( iCol1 == iCol2 ) - return; - assert( iCol1 != iCol2 ); - // swap col groups - pGemp = p->pColGrps[iCol1]; - p->pColGrps[iCol1] = p->pColGrps[iCol2]; - p->pColGrps[iCol2] = pGemp; - // swap col vectors - pTemp = p->pMatrix[iCol1]; - p->pMatrix[iCol1] = p->pMatrix[iCol2]; - p->pMatrix[iCol2] = pTemp; - // swap col sums - iTemp = p->pColSums[iCol1]; - p->pColSums[iCol1] = p->pColSums[iCol2]; - p->pColSums[iCol2] = iTemp; -} - -/**Function************************************************************* - - Synopsis [Find columns which brings as few vars as possible.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_MtrFindBestColumn( Llb_Mtr_t * p, int iGrpStart ) -{ - int Cost, Cost2, CostBest = ABC_INFINITY, Cost2Best = ABC_INFINITY; - int WeightCur, WeightBest = -ABC_INFINITY, iGrp, iGrpBest = -1; - int k, c, iVar, Counter; - // find partition that reduces partial product as much as possible - for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ ) - { - if ( p->pRowSums[iVar] < 2 ) - continue; - // look at present variables that can be quantified - if ( !(p->pProdVars[iVar] == 1 && p->pProdNums[iVar] == 1) ) - continue; - // check that it appears in one partition only - Counter = 0; - for ( c = iGrpStart; c < p->nCols-1; c++ ) - if ( p->pMatrix[c][iVar] == 1 ) - { - iGrp = c; - Counter++; - } - assert( Counter == 1 ); - if ( Counter != 1 ) - Abc_Print( -1, "Llb_MtrFindBestColumn() Internal error!\n" ); - // find weight of this column - WeightCur = 0; - for ( k = 0; k < p->nRows; k++ ) - { - // increase weight if variable k will be quantified from partial product - if ( p->pProdVars[k] == 1 && p->pMatrix[iGrp][k] == 1 && p->pProdNums[k] == 1 ) - WeightCur += 2; - // decrease weight if variable k will be added to partial product - if ( p->pProdVars[k] == 0 && p->pMatrix[iGrp][k] == 1 ) - WeightCur--; - } - if ( WeightCur > 0 && WeightBest < WeightCur ) - { - WeightBest = WeightCur; - iGrpBest = iGrp; - } - } - if ( iGrpBest >= 0 ) - return iGrpBest; - // could not find the group with any vars to quantify - // select the group that contains as few extra variables as possible - // if there is a tie, select variables that appear in less groups than others - for ( iGrp = iGrpStart; iGrp < p->nCols-1; iGrp++ ) - { - Cost = Cost2 = 0; - for ( k = 0; k < p->nRows; k++ ) - if ( p->pProdVars[k] == 0 && p->pMatrix[iGrp][k] == 1 ) - { - Cost++; - Cost2 += p->pProdNums[k]; - } - if ( CostBest > Cost || - (CostBest == Cost && Cost2 > Cost2Best) ) - { - CostBest = Cost; - Cost2Best = Cost2; - iGrpBest = iGrp; - } - } - return iGrpBest; -} - -/**Function************************************************************* - - Synopsis [Returns the number of variables that will be saved.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrUseSelectedColumn( Llb_Mtr_t * p, int iCol ) -{ - int iVar; - assert( iCol >= 1 && iCol < p->nCols - 1 ); - for ( iVar = 0; iVar < p->nRows; iVar++ ) - { - if ( p->pMatrix[iCol][iVar] == 0 ) - continue; - if ( p->pProdVars[iVar] == 1 && p->pProdNums[iVar] == 1 ) - { - p->pProdVars[iVar] = 0; - p->pProdNums[iVar] = 0; - continue; - } - if ( p->pProdVars[iVar] == 0 ) - { - p->pProdVars[iVar] = 1; - p->pProdNums[iVar] = p->pRowSums[iVar]; - } - p->pProdNums[iVar]--; - assert( p->pProdNums[iVar] >= 0 ); - if ( p->pProdNums[iVar] < 0 ) - Abc_Print( -1, "Llb_MtrUseSelectedColumn() Internal error!\n" ); - } -} - -/**Function************************************************************* - - Synopsis [Verify columns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrVerifyColumns( Llb_Mtr_t * p, int iGrpStart ) -{ - int iVar, iGrp, Counter; - for ( iVar = 0; iVar < p->nRows; iVar++ ) - { - if ( p->pProdVars[iVar] == 0 ) - continue; - Counter = 0; - for ( iGrp = iGrpStart; iGrp < p->nCols; iGrp++ ) - if ( p->pMatrix[iGrp][iVar] == 1 ) - Counter++; - assert( Counter == p->pProdNums[iVar] ); - if ( Counter != p->pProdNums[iVar] ) - Abc_Print( -1, "Llb_MtrVerifyColumns(): Internal error.\n" ); - } -} - -/**Function************************************************************* - - Synopsis [Matrix reduce.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrSchedule( Llb_Mtr_t * p ) -{ - int iGrp, iGrpBest, i; - // start partial product - for ( i = 0; i < p->nRows; i++ ) - { - if ( i >= p->nPis && i < p->nPis + p->nFfs ) - { - p->pProdVars[i] = 1; - p->pProdNums[i] = p->pRowSums[i] - 1; - } - else - { - p->pProdVars[i] = 0; - p->pProdNums[i] = p->pRowSums[i]; - } - } - // order the partitions - Llb_MtrVerifyMatrix( p ); - for ( iGrp = 1; iGrp < p->nCols-1; iGrp++ ) - { - Llb_MtrVerifyColumns( p, iGrp ); - iGrpBest = Llb_MtrFindBestColumn( p, iGrp ); - Llb_MtrUseSelectedColumn( p, iGrpBest ); - Llb_MtrSwapColumns( p, iGrp, iGrpBest ); - } - Llb_MtrVerifyMatrix( p ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llb2Bad.c b/src/aig/llb/llb2Bad.c deleted file mode 100644 index 9aecb9ff..00000000 --- a/src/aig/llb/llb2Bad.c +++ /dev/null @@ -1,137 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb2Bad.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Computing bad states.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb2Bad.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes bad in working manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_BddComputeBad( Aig_Man_t * pInit, DdManager * dd, int TimeOut ) -{ - Vec_Ptr_t * vNodes; - DdNode * bBdd0, * bBdd1, * bTemp, * bResult; - Aig_Obj_t * pObj; - int i, k; - assert( Cudd_ReadSize(dd) == Aig_ManPiNum(pInit) ); - // initialize elementary variables - Aig_ManConst1(pInit)->pData = Cudd_ReadOne( dd ); - Saig_ManForEachLo( pInit, pObj, i ) - pObj->pData = Cudd_bddIthVar( dd, i ); - Saig_ManForEachPi( pInit, pObj, i ) - pObj->pData = Cudd_bddIthVar( dd, Aig_ManRegNum(pInit) + i ); - // compute internal nodes - vNodes = Aig_ManDfsNodes( pInit, (Aig_Obj_t **)Vec_PtrArray(pInit->vPos), Saig_ManPoNum(pInit) ); - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) - { - if ( !Aig_ObjIsNode(pObj) ) - continue; - bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); -// pObj->pData = Extra_bddAndTime( dd, bBdd0, bBdd1, TimeOut ); - pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); - if ( pObj->pData == NULL ) - { - Vec_PtrForEachEntryStop( Aig_Obj_t *, vNodes, pObj, k, i ) - if ( pObj->pData ) - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); - Vec_PtrFree( vNodes ); - return NULL; - } - Cudd_Ref( (DdNode *)pObj->pData ); - } - // quantify PIs of each PO - bResult = Cudd_ReadLogicZero( dd ); Cudd_Ref( bResult ); - Saig_ManForEachPo( pInit, pObj, i ) - { - bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bResult = Cudd_bddOr( dd, bTemp = bResult, bBdd0 ); Cudd_Ref( bResult ); - Cudd_RecursiveDeref( dd, bTemp ); - } - // deref - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) - { - if ( !Aig_ObjIsNode(pObj) ) - continue; - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); - } - Vec_PtrFree( vNodes ); - Cudd_Deref( bResult ); - return bResult; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_BddQuantifyPis( Aig_Man_t * pInit, DdManager * dd, DdNode * bFunc ) -{ - DdNode * bVar, * bCube, * bTemp; - Aig_Obj_t * pObj; - int i, TimeStop; - assert( Cudd_ReadSize(dd) == Aig_ManPiNum(pInit) ); - TimeStop = dd->TimeStop; dd->TimeStop = 0; - // create PI cube - bCube = Cudd_ReadOne( dd ); Cudd_Ref( bCube ); - Saig_ManForEachPi( pInit, pObj, i ) { - bVar = Cudd_bddIthVar( dd, Aig_ManRegNum(pInit) + i ); - bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube ); - Cudd_RecursiveDeref( dd, bTemp ); - } - // quantify PI cube - bFunc = Cudd_bddExistAbstract( dd, bFunc, bCube ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( dd, bCube ); - Cudd_Deref( bFunc ); - dd->TimeStop = TimeStop; - return bFunc; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llb2Core.c b/src/aig/llb/llb2Core.c deleted file mode 100644 index 4ecd1cdf..00000000 --- a/src/aig/llb/llb2Core.c +++ /dev/null @@ -1,775 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb2Core.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Core procedure.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb2Core.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Llb_Img_t_ Llb_Img_t; -struct Llb_Img_t_ -{ - Aig_Man_t * pInit; // AIG manager - Aig_Man_t * pAig; // AIG manager - Gia_ParLlb_t * pPars; // parameters - - DdManager * dd; // BDD manager - DdManager * ddG; // BDD manager - DdManager * ddR; // BDD manager - Vec_Ptr_t * vDdMans; // BDD managers for each partition - Vec_Ptr_t * vRings; // onion rings in ddR - - Vec_Int_t * vDriRefs; // driver references - Vec_Int_t * vVarsCs; // cur state variables - Vec_Int_t * vVarsNs; // next state variables - - Vec_Int_t * vCs2Glo; // cur state variables into global variables - Vec_Int_t * vNs2Glo; // next state variables into global variables - Vec_Int_t * vGlo2Cs; // global variables into cur state variables - Vec_Int_t * vGlo2Ns; // global variables into next state variables -}; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes cube composed of given variables with given values.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_CoreComputeCube( DdManager * dd, Vec_Int_t * vVars, int fUseVarIndex, char * pValues ) -{ - DdNode * bRes, * bVar, * bTemp; - int i, iVar, Index, TimeStop; - TimeStop = dd->TimeStop; dd->TimeStop = 0; - bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); - Vec_IntForEachEntry( vVars, Index, i ) - { - iVar = fUseVarIndex ? Index : i; - bVar = Cudd_NotCond( Cudd_bddIthVar(dd, iVar), (int)(pValues == NULL || pValues[i] != 1) ); - bRes = Cudd_bddAnd( dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bRes ); - dd->TimeStop = TimeStop; - return bRes; -} - -/**Function************************************************************* - - Synopsis [Derives counter-example by backward reachability.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Cex_t * Llb_CoreDeriveCex( Llb_Img_t * p ) -{ - Abc_Cex_t * pCex; - Aig_Obj_t * pObj; - Vec_Ptr_t * vSupps, * vQuant0, * vQuant1; - DdNode * bState, * bImage, * bOneCube, * bTemp, * bRing; - int i, v, RetValue, nPiOffset; - char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) ); - assert( Vec_PtrSize(p->vRings) > 0 ); - - p->dd->TimeStop = 0; - p->ddR->TimeStop = 0; - - // get supports and quantified variables - Vec_PtrReverseOrder( p->vDdMans ); - vSupps = Llb_ImgSupports( p->pAig, p->vDdMans, p->vVarsNs, p->vVarsCs, 1, 0 ); - Llb_ImgSchedule( vSupps, &vQuant0, &vQuant1, 0 ); - Vec_VecFree( (Vec_Vec_t *)vSupps ); - Llb_ImgQuantifyReset( p->vDdMans ); -// Llb_ImgQuantifyFirst( p->pAig, p->vDdMans, vQuant0 ); - - // allocate room for the counter-example - pCex = Abc_CexAlloc( Saig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Vec_PtrSize(p->vRings) ); - pCex->iFrame = Vec_PtrSize(p->vRings) - 1; - pCex->iPo = -1; - - // get the last cube - bOneCube = Cudd_bddIntersect( p->ddR, (DdNode *)Vec_PtrEntryLast(p->vRings), p->ddR->bFunc ); Cudd_Ref( bOneCube ); - RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); - Cudd_RecursiveDeref( p->ddR, bOneCube ); - assert( RetValue ); - - // write PIs of counter-example - nPiOffset = Saig_ManRegNum(p->pAig) + Saig_ManPiNum(p->pAig) * (Vec_PtrSize(p->vRings) - 1); - Saig_ManForEachPi( p->pAig, pObj, i ) - if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) - Aig_InfoSetBit( pCex->pData, nPiOffset + i ); - - // write state in terms of NS variables - if ( Vec_PtrSize(p->vRings) > 1 ) - { - bState = Llb_CoreComputeCube( p->dd, p->vVarsNs, 1, pValues ); Cudd_Ref( bState ); - } - // perform backward analysis - Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v ) - { - if ( v == Vec_PtrSize(p->vRings) - 1 ) - continue; - // compute the next states - bImage = Llb_ImgComputeImage( p->pAig, p->vDdMans, p->dd, bState, - vQuant0, vQuant1, p->vDriRefs, p->pPars->TimeTarget, 1, 0, 0 ); - assert( bImage != NULL ); - Cudd_Ref( bImage ); - Cudd_RecursiveDeref( p->dd, bState ); -//Extra_bddPrintSupport( p->dd, bImage ); printf( "\n" ); - - // move reached states into ring manager - bImage = Extra_TransferPermute( p->dd, p->ddR, bTemp = bImage, Vec_IntArray(p->vCs2Glo) ); Cudd_Ref( bImage ); - Cudd_RecursiveDeref( p->dd, bTemp ); - - // intersect with the previous set - bOneCube = Cudd_bddIntersect( p->ddR, bImage, bRing ); Cudd_Ref( bOneCube ); - Cudd_RecursiveDeref( p->ddR, bImage ); - - // find any assignment of the BDD - RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); - Cudd_RecursiveDeref( p->ddR, bOneCube ); - assert( RetValue ); - - // write PIs of counter-example - nPiOffset -= Saig_ManPiNum(p->pAig); - Saig_ManForEachPi( p->pAig, pObj, i ) - if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) - Aig_InfoSetBit( pCex->pData, nPiOffset + i ); - - // check that we get the init state - if ( v == 0 ) - { - Saig_ManForEachLo( p->pAig, pObj, i ) - assert( pValues[i] == 0 ); - break; - } - - // write state in terms of NS variables - bState = Llb_CoreComputeCube( p->dd, p->vVarsNs, 1, pValues ); Cudd_Ref( bState ); - } - assert( nPiOffset == Saig_ManRegNum(p->pAig) ); - // update the output number - RetValue = Saig_ManFindFailedPoCex( p->pInit, pCex ); - assert( RetValue >= 0 && RetValue < Saig_ManPoNum(p->pInit) ); // invalid CEX!!! - pCex->iPo = RetValue; - // cleanup - ABC_FREE( pValues ); - Vec_VecFree( (Vec_Vec_t *)vQuant0 ); - Vec_VecFree( (Vec_Vec_t *)vQuant1 ); - return pCex; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_CoreReachability_int( Llb_Img_t * p, Vec_Ptr_t * vQuant0, Vec_Ptr_t * vQuant1 ) -{ - int * pLoc2Glo = p->pPars->fBackward? Vec_IntArray( p->vCs2Glo ) : Vec_IntArray( p->vNs2Glo ); - int * pLoc2GloR = p->pPars->fBackward? Vec_IntArray( p->vNs2Glo ) : Vec_IntArray( p->vCs2Glo ); - int * pGlo2Loc = p->pPars->fBackward? Vec_IntArray( p->vGlo2Ns ) : Vec_IntArray( p->vGlo2Cs ); - DdNode * bCurrent, * bReached, * bNext, * bTemp; - int clk2, clk = clock(), nIters, nBddSize, iOutFail = -1; -/* - // compute time to stop - if ( p->pPars->TimeLimit ) - p->pPars->TimeTarget = clock() + p->pPars->TimeLimit * CLOCKS_PER_SEC; - else - p->pPars->TimeTarget = 0; -*/ - - if ( time(NULL) > p->pPars->TimeTarget ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) before image computation.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = -1; - return -1; - } - - // set the stop time parameter - p->dd->TimeStop = p->pPars->TimeTarget; - p->ddG->TimeStop = p->pPars->TimeTarget; - p->ddR->TimeStop = p->pPars->TimeTarget; - - // compute initial states - if ( p->pPars->fBackward ) - { - // create init state in the global manager - bTemp = Llb_BddComputeBad( p->pInit, p->ddR, p->pPars->TimeTarget ); - if ( bTemp == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) while computing bad states.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = -1; - return -1; - } - Cudd_Ref( bTemp ); - // create bad state in the ring manager - p->ddR->bFunc = Llb_CoreComputeCube( p->ddR, p->vVarsCs, 0, NULL ); Cudd_Ref( p->ddR->bFunc ); - bCurrent = Llb_BddQuantifyPis( p->pInit, p->ddR, bTemp ); Cudd_Ref( bCurrent ); - Cudd_RecursiveDeref( p->ddR, bTemp ); - bReached = Cudd_bddTransfer( p->ddR, p->ddG, bCurrent ); Cudd_Ref( bReached ); - Cudd_RecursiveDeref( p->ddR, bCurrent ); - // move init state to the working manager - bCurrent = Extra_TransferPermute( p->ddG, p->dd, bReached, pGlo2Loc ); - if ( bCurrent == NULL ) - { - Cudd_RecursiveDeref( p->ddG, bReached ); - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during transfer 0.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = -1; - return -1; - } - Cudd_Ref( bCurrent ); - } - else - { - // create bad state in the ring manager - p->ddR->bFunc = Llb_BddComputeBad( p->pInit, p->ddR, p->pPars->TimeTarget ); - if ( p->ddR->bFunc == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) while computing bad states.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = -1; - return -1; - } - Cudd_Ref( p->ddR->bFunc ); - // create init state in the working and global manager - bCurrent = Llb_CoreComputeCube( p->dd, p->vVarsCs, 1, NULL ); Cudd_Ref( bCurrent ); - bReached = Llb_CoreComputeCube( p->ddG, p->vVarsCs, 0, NULL ); Cudd_Ref( bReached ); -//Extra_bddPrint( p->dd, bCurrent ); printf( "\n" ); -//Extra_bddPrint( p->ddG, bReached ); printf( "\n" ); - } - - // compute onion rings - for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ ) - { - clk2 = clock(); - // check the runtime limit - if ( p->pPars->TimeLimit && time(NULL) > p->pPars->TimeTarget ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - return -1; - } - - // save the onion ring - bTemp = Extra_TransferPermute( p->dd, p->ddR, bCurrent, pLoc2GloR ); - if ( bTemp == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - return -1; - } - Cudd_Ref( bTemp ); - Vec_PtrPush( p->vRings, bTemp ); - - // check it for bad states - if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->ddR, bTemp, Cudd_Not(p->ddR->bFunc) ) ) - { - assert( p->pInit->pSeqModel == NULL ); - if ( !p->pPars->fBackward ) - p->pInit->pSeqModel = Llb_CoreDeriveCex( p ); - Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - if ( !p->pPars->fSilent ) - { - if ( !p->pPars->fBackward ) - printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump a witness). ", p->pInit->pSeqModel->iPo, nIters ); - else - printf( "Output ??? was asserted in frame %d (counter-example is not produced). ", nIters ); - Abc_PrintTime( 1, "Time", clock() - clk ); - } - p->pPars->iFrame = nIters - 1; - return 0; - } - - // compute the next states - bNext = Llb_ImgComputeImage( p->pAig, p->vDdMans, p->dd, bCurrent, - vQuant0, vQuant1, p->vDriRefs, p->pPars->TimeTarget, - p->pPars->fBackward, p->pPars->fReorder, p->pPars->fVeryVerbose ); - if ( bNext == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - return -1; - } - Cudd_Ref( bNext ); - Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; -//Extra_bddPrintSupport( p->dd, bNext ); printf( "\n" ); - - // remap these states into the global manager -// bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pLoc2Glo ); Cudd_Ref( bNext ); -// Cudd_RecursiveDeref( p->dd, bTemp ); - -// bNext = Extra_TransferPermuteTime( p->dd, p->ddG, bTemp = bNext, pLoc2Glo, p->pPars->TimeTarget ); - bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pLoc2Glo ); - if ( bNext == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - return -1; - } - Cudd_Ref( bNext ); - Cudd_RecursiveDeref( p->dd, bTemp ); - - nBddSize = Cudd_DagSize(bNext); - // check if there are any new states - if ( Cudd_bddLeq( p->ddG, bNext, bReached ) ) // implication = no new states - { - Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; - break; - } - - // get the new states - bCurrent = Cudd_bddAnd( p->ddG, bNext, Cudd_Not(bReached) ); - if ( bCurrent == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->ddG, bNext ); - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - return -1; - } - Cudd_Ref( bCurrent ); - - // remap these states into the current state vars -// bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Loc ); Cudd_Ref( bCurrent ); -// Cudd_RecursiveDeref( p->ddG, bTemp ); - -// bCurrent = Extra_TransferPermuteTime( p->ddG, p->dd, bTemp = bCurrent, pGlo2Loc, p->pPars->TimeTarget ); - bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Loc ); - if ( bCurrent == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->ddG, bTemp ); - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - return -1; - } - Cudd_Ref( bCurrent ); - Cudd_RecursiveDeref( p->ddG, bTemp ); - - // add to the reached states - bReached = Cudd_bddOr( p->ddG, bTemp = bReached, bNext ); Cudd_Ref( bReached ); - Cudd_RecursiveDeref( p->ddG, bTemp ); - Cudd_RecursiveDeref( p->ddG, bNext ); - bNext = NULL; - - if ( p->pPars->fVeryVerbose ) - { - double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) ); -// Extra_bddPrint( p->ddG, bReached );printf( "\n" ); - fprintf( stdout, " Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); - fflush( stdout ); - } - if ( p->pPars->fVerbose ) - { - fprintf( stdout, "F =%3d : ", nIters ); - fprintf( stdout, "Image =%6d ", nBddSize ); - fprintf( stdout, "(%4d%4d) ", - Cudd_ReadReorderings(p->dd), Cudd_ReadGarbageCollections(p->dd) ); - fprintf( stdout, "Reach =%6d ", Cudd_DagSize(bReached) ); - fprintf( stdout, "(%4d%4d) ", - Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) ); - Abc_PrintTime( 1, "Time", clock() - clk2 ); - } - - // check timeframe limit - if ( nIters == p->pPars->nIterMax - 1 ) - { - if ( !p->pPars->fSilent ) - printf( "Reached limit on the number of timeframes (%d).\n", p->pPars->nIterMax ); - p->pPars->iFrame = nIters; - Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - return -1; - } - } - if ( bReached == NULL ) - { - p->pPars->iFrame = nIters - 1; - return 0; // reachable - } - if ( bCurrent ) - Cudd_RecursiveDeref( p->dd, bCurrent ); - // report the stats - if ( p->pPars->fVerbose ) - { - double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) ); - if ( nIters >= p->pPars->nIterMax ) - fprintf( stdout, "Reachability analysis is stopped after %d frames.\n", nIters ); - else - fprintf( stdout, "Reachability analysis completed after %d frames.\n", nIters ); - fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); - fflush( stdout ); - } - if ( p->pPars->fDumpReached ) - { - Llb_ManDumpReached( p->ddG, bReached, p->pAig->pName, "reached.blif" ); - printf( "Reached states with %d BDD nodes are dumpted into file \"reached.blif\".\n", Cudd_DagSize(bReached) ); - } - Cudd_RecursiveDeref( p->ddG, bReached ); - if ( nIters >= p->pPars->nIterMax ) - { - if ( !p->pPars->fSilent ) - { - printf( "Verified only for states reachable in %d frames. ", nIters ); - Abc_PrintTime( 1, "Time", clock() - clk ); - } - p->pPars->iFrame = p->pPars->nIterMax; - return -1; // undecided - } - if ( !p->pPars->fSilent ) - { - printf( "The miter is proved unreachable after %d iterations. ", nIters ); - Abc_PrintTime( 1, "Time", clock() - clk ); - } - p->pPars->iFrame = nIters - 1; - return 1; // unreachable -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_CoreReachability( Llb_Img_t * p ) -{ - Vec_Ptr_t * vSupps, * vQuant0, * vQuant1; - int RetValue; - // get supports and quantified variables - if ( p->pPars->fBackward ) - { - Vec_PtrReverseOrder( p->vDdMans ); - vSupps = Llb_ImgSupports( p->pAig, p->vDdMans, p->vVarsNs, p->vVarsCs, 0, p->pPars->fVeryVerbose ); - } - else - vSupps = Llb_ImgSupports( p->pAig, p->vDdMans, p->vVarsCs, p->vVarsNs, 0, p->pPars->fVeryVerbose ); - Llb_ImgSchedule( vSupps, &vQuant0, &vQuant1, p->pPars->fVeryVerbose ); - Vec_VecFree( (Vec_Vec_t *)vSupps ); - // remove variables - Llb_ImgQuantifyFirst( p->pAig, p->vDdMans, vQuant0, p->pPars->fVeryVerbose ); - // perform reachability - RetValue = Llb_CoreReachability_int( p, vQuant0, vQuant1 ); - Vec_VecFree( (Vec_Vec_t *)vQuant0 ); - Vec_VecFree( (Vec_Vec_t *)vQuant1 ); - return RetValue; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_CoreConstructAll( Aig_Man_t * p, Vec_Ptr_t * vResult, Vec_Int_t * vVarsNs, int TimeTarget ) -{ - DdManager * dd; - Vec_Ptr_t * vDdMans; - Vec_Ptr_t * vLower, * vUpper; - int i; - vDdMans = Vec_PtrStart( Vec_PtrSize(vResult) ); - Vec_PtrForEachEntryReverse( Vec_Ptr_t *, vResult, vLower, i ) - { - if ( i < Vec_PtrSize(vResult) - 1 ) - dd = Llb_ImgPartition( p, vLower, vUpper, TimeTarget ); - else - dd = Llb_DriverLastPartition( p, vVarsNs, TimeTarget ); - if ( dd == NULL ) - { - Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i ) - { - if ( dd == NULL ) - continue; - if ( dd->bFunc ) - Cudd_RecursiveDeref( dd, dd->bFunc ); - Extra_StopManager( dd ); - } - Vec_PtrFree( vDdMans ); - return NULL; - } - Vec_PtrWriteEntry( vDdMans, i, dd ); - vUpper = vLower; - } - return vDdMans; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_CoreSetVarMaps( Llb_Img_t * p ) -{ - Aig_Obj_t * pObj; - int i, iVarCs, iVarNs; - assert( p->vVarsCs != NULL ); - assert( p->vVarsNs != NULL ); - assert( p->vCs2Glo == NULL ); - assert( p->vNs2Glo == NULL ); - assert( p->vGlo2Cs == NULL ); - assert( p->vGlo2Ns == NULL ); - p->vCs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) ); - p->vNs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) ); - p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); - p->vGlo2Ns = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); - for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ ) - { - iVarCs = Vec_IntEntry( p->vVarsCs, i ); - iVarNs = Vec_IntEntry( p->vVarsNs, i ); - assert( iVarCs >= 0 && iVarCs < Aig_ManObjNumMax(p->pAig) ); - assert( iVarNs >= 0 && iVarNs < Aig_ManObjNumMax(p->pAig) ); - Vec_IntWriteEntry( p->vCs2Glo, iVarCs, i ); - Vec_IntWriteEntry( p->vNs2Glo, iVarNs, i ); - Vec_IntWriteEntry( p->vGlo2Cs, i, iVarCs ); - Vec_IntWriteEntry( p->vGlo2Ns, i, iVarNs ); - } - // add mapping of the PIs - Saig_ManForEachPi( p->pAig, pObj, i ) - Vec_IntWriteEntry( p->vCs2Glo, Aig_ObjId(pObj), Aig_ManRegNum(p->pAig)+i ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Img_t * Llb_CoreStart( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) -{ - Llb_Img_t * p; - p = ABC_CALLOC( Llb_Img_t, 1 ); - p->pInit = pInit; - p->pAig = pAig; - p->pPars = pPars; - p->dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - p->ddG = Cudd_Init( Aig_ManRegNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - p->ddR = Cudd_Init( Aig_ManPiNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); - Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT ); - Cudd_AutodynEnable( p->ddR, CUDD_REORDER_SYMM_SIFT ); - p->vRings = Vec_PtrAlloc( 100 ); - p->vDriRefs = Llb_DriverCountRefs( pAig ); - p->vVarsCs = Llb_DriverCollectCs( pAig ); - p->vVarsNs = Llb_DriverCollectNs( pAig, p->vDriRefs ); - Llb_CoreSetVarMaps( p ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_CoreStop( Llb_Img_t * p ) -{ - DdManager * dd; - DdNode * bTemp; - int i; - if ( p->vDdMans ) - Vec_PtrForEachEntry( DdManager *, p->vDdMans, dd, i ) - { - if ( dd->bFunc ) - Cudd_RecursiveDeref( dd, dd->bFunc ); - if ( dd->bFunc2 ) - Cudd_RecursiveDeref( dd, dd->bFunc2 ); - Extra_StopManager( dd ); - } - Vec_PtrFreeP( &p->vDdMans ); - if ( p->ddR->bFunc ) - Cudd_RecursiveDeref( p->ddR, p->ddR->bFunc ); - Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i ) - Cudd_RecursiveDeref( p->ddR, bTemp ); - Vec_PtrFree( p->vRings ); - Extra_StopManager( p->dd ); - Extra_StopManager( p->ddG ); - Extra_StopManager( p->ddR ); - Vec_IntFreeP( &p->vDriRefs ); - Vec_IntFreeP( &p->vVarsCs ); - Vec_IntFreeP( &p->vVarsNs ); - Vec_IntFreeP( &p->vCs2Glo ); - Vec_IntFreeP( &p->vNs2Glo ); - Vec_IntFreeP( &p->vGlo2Cs ); - Vec_IntFreeP( &p->vGlo2Ns ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_CoreExperiment( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars, Vec_Ptr_t * vResult, int TimeTarget ) -{ - int RetValue; - Llb_Img_t * p; -// printf( "\n" ); -// pPars->fVerbose = 1; - p = Llb_CoreStart( pInit, pAig, pPars ); - p->vDdMans = Llb_CoreConstructAll( pAig, vResult, p->vVarsNs, TimeTarget ); - if ( p->vDdMans == NULL ) - { - if ( !pPars->fSilent ) - printf( "Reached timeout (%d seconds) while deriving the partitions.\n", pPars->TimeLimit ); - Llb_CoreStop( p ); - return -1; - } - RetValue = Llb_CoreReachability( p ); - Llb_CoreStop( p ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Finds balanced cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManReachMinCut( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) -{ - extern Vec_Ptr_t * Llb_ManComputeCuts( Aig_Man_t * p, int Num, int fVerbose, int fVeryVerbose ); - Vec_Ptr_t * vResult; - Aig_Man_t * p; - int RetValue = -1; - int clk = clock(); - - // compute time to stop - pPars->TimeTarget = pPars->TimeLimit ? time(NULL) + pPars->TimeLimit : 0; - - p = Aig_ManDupFlopsOnly( pAig ); -//Aig_ManShow( p, 0, NULL ); - if ( pPars->fVerbose ) - Aig_ManPrintStats( pAig ); - if ( pPars->fVerbose ) - Aig_ManPrintStats( p ); - Aig_ManFanoutStart( p ); - - vResult = Llb_ManComputeCuts( p, pPars->nPartValue, pPars->fVerbose, pPars->fVeryVerbose ); - - if ( pPars->TimeLimit && time(NULL) > pPars->TimeTarget ) - { - if ( !pPars->fSilent ) - printf( "Reached timeout (%d seconds) after partitioning.\n", pPars->TimeLimit ); - - Vec_VecFree( (Vec_Vec_t *)vResult ); - Aig_ManFanoutStop( p ); - Aig_ManCleanMarkAB( p ); - Aig_ManStop( p ); - return RetValue; - } - - if ( !pPars->fSkipReach ) - RetValue = Llb_CoreExperiment( pAig, p, pPars, vResult, pPars->TimeTarget ); - - Vec_VecFree( (Vec_Vec_t *)vResult ); - Aig_ManFanoutStop( p ); - Aig_ManCleanMarkAB( p ); - Aig_ManStop( p ); - - if ( RetValue == -1 ) - Abc_PrintTime( 1, "Total runtime of the min-cut-based reachability engine", clock() - clk ); - return RetValue; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llb2Driver.c b/src/aig/llb/llb2Driver.c deleted file mode 100644 index 041a39d5..00000000 --- a/src/aig/llb/llb2Driver.c +++ /dev/null @@ -1,221 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb2Driver.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Procedures working with flop drivers.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb2Driver.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// driver issue:arises when creating -// - driver ref-counter array -// - Ns2Glo maps -// - final partition -// - change-phase cube - -// LI variable is used when -// - driver drives more than one LI -// - driver is a PI -// - driver is a constant - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns the array of times each flop driver is referenced.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_DriverCountRefs( Aig_Man_t * p ) -{ - Vec_Int_t * vCounts; - Aig_Obj_t * pObj; - int i; - vCounts = Vec_IntStart( Aig_ManObjNumMax(p) ); - Saig_ManForEachLi( p, pObj, i ) - Vec_IntAddToEntry( vCounts, Aig_ObjFaninId0(pObj), 1 ); - return vCounts; -} - -/**Function************************************************************* - - Synopsis [Returns array of NS variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_DriverCollectNs( Aig_Man_t * pAig, Vec_Int_t * vDriRefs ) -{ - Vec_Int_t * vVars; - Aig_Obj_t * pObj, * pDri; - int i; - vVars = Vec_IntAlloc( Aig_ManRegNum(pAig) ); - Saig_ManForEachLi( pAig, pObj, i ) - { - pDri = Aig_ObjFanin0(pObj); - if ( Vec_IntEntry( vDriRefs, Aig_ObjId(pDri) ) != 1 || Saig_ObjIsPi(pAig, pDri) || Aig_ObjIsConst1(pDri) ) - Vec_IntPush( vVars, Aig_ObjId(pObj) ); - else - Vec_IntPush( vVars, Aig_ObjId(pDri) ); - } - return vVars; -} - -/**Function************************************************************* - - Synopsis [Returns array of CS variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_DriverCollectCs( Aig_Man_t * pAig ) -{ - Vec_Int_t * vVars; - Aig_Obj_t * pObj; - int i; - vVars = Vec_IntAlloc( Aig_ManRegNum(pAig) ); - Saig_ManForEachLo( pAig, pObj, i ) - Vec_IntPush( vVars, Aig_ObjId(pObj) ); - return vVars; -} - -/**Function************************************************************* - - Synopsis [Create cube for phase swapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_DriverPhaseCube( Aig_Man_t * pAig, Vec_Int_t * vDriRefs, DdManager * dd ) -{ - DdNode * bCube, * bVar, * bTemp; - Aig_Obj_t * pObj; - int i, TimeStop; - TimeStop = dd->TimeStop; dd->TimeStop = 0; - bCube = Cudd_ReadOne( dd ); Cudd_Ref( bCube ); - Saig_ManForEachLi( pAig, pObj, i ) - { - assert( Vec_IntEntry( vDriRefs, Aig_ObjFaninId0(pObj) ) >= 1 ); - if ( Vec_IntEntry( vDriRefs, Aig_ObjFaninId0(pObj) ) != 1 ) - continue; - if ( !Aig_ObjFaninC0(pObj) ) - continue; - bVar = Cudd_bddIthVar( dd, Aig_ObjFaninId0(pObj) ); - bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bCube ); - dd->TimeStop = TimeStop; - return bCube; -} - -/**Function************************************************************* - - Synopsis [Compute the last partition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdManager * Llb_DriverLastPartition( Aig_Man_t * p, Vec_Int_t * vVarsNs, int TimeTarget ) -{ - int fVerbose = 1; - DdManager * dd; - DdNode * bVar1, * bVar2, * bProd, * bRes, * bTemp; - Aig_Obj_t * pObj; - int i; - dd = Cudd_Init( Aig_ManObjNumMax(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - dd->TimeStop = TimeTarget; - bRes = Cudd_ReadOne(dd); Cudd_Ref( bRes ); - - // mark the duplicated flop inputs - Aig_ManForEachObjVec( vVarsNs, p, pObj, i ) - { - if ( !Saig_ObjIsLi(p, pObj) ) - continue; - bVar1 = Cudd_bddIthVar( dd, Aig_ObjId(pObj) ); - bVar2 = Cudd_bddIthVar( dd, Aig_ObjFaninId0(pObj) ); - if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) - bVar2 = Cudd_ReadOne(dd); - bVar2 = Cudd_NotCond( bVar2, Aig_ObjFaninC0(pObj) ); - bProd = Cudd_bddXnor( dd, bVar1, bVar2 ); Cudd_Ref( bProd ); -// bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd ); Cudd_Ref( bRes ); -// bRes = Extra_bddAndTime( dd, bTemp = bRes, bProd, TimeTarget ); - bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bProd ); - return NULL; - } - Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bProd ); - } - -/* - Saig_ManForEachLi( p, pObj, i ) - printf( "%d ", Aig_ObjId(pObj) ); - printf( "\n" ); - Saig_ManForEachLi( p, pObj, i ) - printf( "%c%d ", Aig_ObjFaninC0(pObj)? '-':'+', Aig_ObjFaninId0(pObj) ); - printf( "\n" ); -*/ - Cudd_AutodynDisable( dd ); -// Cudd_RecursiveDeref( dd, bRes ); -// Extra_StopManager( dd ); - dd->bFunc = bRes; - dd->TimeStop = 0; - return dd; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llb2Dump.c b/src/aig/llb/llb2Dump.c deleted file mode 100644 index 3e1dd8c5..00000000 --- a/src/aig/llb/llb2Dump.c +++ /dev/null @@ -1,104 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb2Dump.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Dumps the BDD of reached states into a file.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb2Dump.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns a dummy name.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Llb_ManGetDummyName( char * pPrefix, int Num, int nDigits ) -{ - static char Buffer[2000]; - sprintf( Buffer, "%s%0*d", pPrefix, nDigits, Num ); - return Buffer; -} - -/**Function************************************************************* - - Synopsis [Writes reached state BDD into a BLIF file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManDumpReached( DdManager * ddG, DdNode * bReached, char * pModel, char * pFileName ) -{ - FILE * pFile; - Vec_Ptr_t * vNamesIn, * vNamesOut; - char * pName; - int i, nDigits; - // reorder the BDD - Cudd_ReduceHeap( ddG, CUDD_REORDER_SYMM_SIFT, 1 ); - - // create input names - nDigits = Extra_Base10Log( Cudd_ReadSize(ddG) ); - vNamesIn = Vec_PtrAlloc( Cudd_ReadSize(ddG) ); - for ( i = 0; i < Cudd_ReadSize(ddG); i++ ) - { - pName = Llb_ManGetDummyName( "ff", i, nDigits ); - Vec_PtrPush( vNamesIn, Extra_UtilStrsav(pName) ); - } - // create output names - vNamesOut = Vec_PtrAlloc( 1 ); - Vec_PtrPush( vNamesOut, Extra_UtilStrsav("Reached") ); - - // write the file - pFile = fopen( pFileName, "wb" ); - Cudd_DumpBlif( ddG, 1, &bReached, (char **)Vec_PtrArray(vNamesIn), (char **)Vec_PtrArray(vNamesOut), pModel, pFile, 0 ); - fclose( pFile ); - - // cleanup - Vec_PtrForEachEntry( char *, vNamesIn, pName, i ) - ABC_FREE( pName ); - Vec_PtrForEachEntry( char *, vNamesOut, pName, i ) - ABC_FREE( pName ); - Vec_PtrFree( vNamesIn ); - Vec_PtrFree( vNamesOut ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llb2Flow.c b/src/aig/llb/llb2Flow.c deleted file mode 100644 index 1b177807..00000000 --- a/src/aig/llb/llb2Flow.c +++ /dev/null @@ -1,1374 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb2Flow.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Flow computation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb2Flow.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline int Llb_ObjSetPath( Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { pObj->pData = (void *)pNext; return 1; } -static inline Aig_Obj_t * Llb_ObjGetPath( Aig_Obj_t * pObj ) { return (Aig_Obj_t *)pObj->pData; } -static inline Aig_Obj_t * Llb_ObjGetFanoutPath( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - Aig_Obj_t * pFanout; - int i, iFanout; - assert( Llb_ObjGetPath(pObj) ); - Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) - if ( Llb_ObjGetPath(pFanout) == pObj ) - return pFanout; - return NULL; -} - -extern Vec_Ptr_t * Llb_ManCutSupp( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - - -/**Function************************************************************* - - Synopsis [For each cut, returns PIs that can be quantified.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ManCutSupps( Aig_Man_t * p, Vec_Ptr_t * vResult ) -{ - Vec_Ptr_t * vSupps, * vOne, * vLower, * vUpper; - int i; - vSupps = Vec_PtrAlloc( 100 ); - Vec_PtrPush( vSupps, Vec_PtrAlloc(0) ); - vLower = (Vec_Ptr_t *)Vec_PtrEntry( vResult, 0 ); - Vec_PtrForEachEntryStart( Vec_Ptr_t *, vResult, vUpper, i, 1 ) - { - vOne = Llb_ManCutSupp( p, vLower, vUpper ); - Vec_PtrPush( vSupps, vOne ); - vLower = vUpper; - } - assert( Vec_PtrSize(vSupps) == Vec_PtrSize(vResult) ); - return vSupps; -} - -/**Function************************************************************* - - Synopsis [For each cut, returns PIs that can be quantified.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ManCutMap( Aig_Man_t * p, Vec_Ptr_t * vResult, Vec_Ptr_t * vSupps ) -{ - int fShowMatrix = 1; - Vec_Ptr_t * vMaps, * vOne; - Vec_Int_t * vMap, * vPrev, * vNext; - Aig_Obj_t * pObj; - int * piFirst, * piLast; - int i, k, CounterPlus, CounterMinus, Counter; - - vMaps = Vec_PtrAlloc( 100 ); - Vec_PtrForEachEntry( Vec_Ptr_t *, vResult, vOne, i ) - { - vMap = Vec_IntStart( Aig_ManObjNumMax(p) ); - Vec_PtrForEachEntry( Aig_Obj_t *, vOne, pObj, k ) - { - if ( !Saig_ObjIsPi(p, pObj) ) - Vec_IntWriteEntry( vMap, pObj->Id, 1 ); -// else -//printf( "*" ); -//printf( "%d ", pObj->Id ); - } - Vec_PtrPush( vMaps, vMap ); -//printf( "\n" ); - } - Vec_PtrPush( vMaps, Vec_IntStart( Aig_ManObjNumMax(p) ) ); - assert( Vec_PtrSize(vMaps) == Vec_PtrSize(vResult)+1 ); - - // collect the first and last PIs - piFirst = ABC_ALLOC( int, Saig_ManPiNum(p) ); - piLast = ABC_ALLOC( int, Saig_ManPiNum(p) ); - Saig_ManForEachPi( p, pObj, i ) - piFirst[i] = piLast[i] = -1; - Vec_PtrForEachEntry( Vec_Ptr_t *, vSupps, vOne, i ) - { - Vec_PtrForEachEntry( Aig_Obj_t *, vOne, pObj, k ) - { - if ( !Saig_ObjIsPi(p, pObj) ) - continue; - if ( piFirst[Aig_ObjPioNum(pObj)] == -1 ) - piFirst[Aig_ObjPioNum(pObj)] = i; - piLast[Aig_ObjPioNum(pObj)] = i; - } - } - // PIs feeding into the flops should be extended to the last frame - Saig_ManForEachLi( p, pObj, i ) - { - if ( !Saig_ObjIsPi(p, Aig_ObjFanin0(pObj)) ) - continue; - piLast[Aig_ObjPioNum(Aig_ObjFanin0(pObj))] = Vec_PtrSize(vMaps)-1; - } - - // set the PI map - Saig_ManForEachPi( p, pObj, i ) - { - if ( piFirst[i] == -1 ) - continue; - if ( piFirst[i] == piLast[i] ) - { - vMap = (Vec_Int_t *)Vec_PtrEntry( vMaps, piFirst[i] ); - Vec_IntWriteEntry( vMap, pObj->Id, 2 ); - continue; - } - - // set support for all in between - for ( k = piFirst[i]; k <= piLast[i]; k++ ) - { - vMap = (Vec_Int_t *)Vec_PtrEntry( vMaps, k ); - Vec_IntWriteEntry( vMap, pObj->Id, 1 ); - } - } - ABC_FREE( piFirst ); - ABC_FREE( piLast ); - - - // find all that will appear here - Counter = Aig_ManRegNum(p); - printf( "%d ", Counter ); - Vec_PtrForEachEntryStart( Vec_Int_t *, vMaps, vMap, i, 1 ) - { - vPrev = (Vec_Int_t *)Vec_PtrEntry( vMaps, i-1 ); - vNext = (i == Vec_PtrSize(vMaps)-1)? NULL: (Vec_Int_t *)Vec_PtrEntry( vMaps, i+1 ); - - CounterPlus = CounterMinus = 0; - Aig_ManForEachObj( p, pObj, k ) - { - if ( Saig_ObjIsPi(p, pObj) ) - { - if ( Vec_IntEntry(vPrev, k) == 0 && Vec_IntEntry(vMap, k) == 1 ) - CounterPlus++; - if ( Vec_IntEntry(vMap, k) == 1 && (vNext == NULL || Vec_IntEntry(vNext, k) == 0) ) - CounterMinus++; - } - else - { - if ( Vec_IntEntry(vPrev, k) == 0 && Vec_IntEntry(vMap, k) == 1 ) - CounterPlus++; - if ( Vec_IntEntry(vPrev, k) == 1 && Vec_IntEntry(vMap, k) == 0 ) - CounterMinus++; - } - } - Counter = Counter + CounterPlus - CounterMinus; - printf( "%d=%d ", i, Counter ); - } - printf( "\n" ); - - if ( fShowMatrix ) - Aig_ManForEachObj( p, pObj, i ) - { - if ( !Aig_ObjIsPi(pObj) && !Aig_ObjIsNode(pObj) ) - continue; - Vec_PtrForEachEntry( Vec_Int_t *, vMaps, vMap, k ) - if ( Vec_IntEntry(vMap, i) ) - break; - if ( k == Vec_PtrSize(vMaps) ) - continue; - printf( "Obj = %4d : ", i ); - if ( Saig_ObjIsPi(p,pObj) ) - printf( "pi " ); - else if ( Saig_ObjIsLo(p,pObj) ) - printf( "lo " ); - else if ( Aig_ObjIsNode(pObj) ) - printf( "and " ); - - Vec_PtrForEachEntry( Vec_Int_t *, vMaps, vMap, k ) - printf( "%d", Vec_IntEntry(vMap, i) ); - printf( "\n" ); - } - return vMaps; -} - -/**Function************************************************************* - - Synopsis [Counts the number of PIs in the cut] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManCutPiNum( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) -{ - Aig_Obj_t * pObj; - int i, Counter = 0; - Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) - if ( Saig_ObjIsPi(p,pObj) ) - Counter++; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts the number of LOs in the cut] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManCutLoNum( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) -{ - Aig_Obj_t * pObj; - int i, Counter = 0; - Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) - if ( Saig_ObjIsLo(p,pObj) ) - Counter++; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts the number of LIs in the cut] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManCutLiNum( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) -{ - Aig_Obj_t * pFanout; - Aig_Obj_t * pObj; - int i, k, iFanout, Counter = 0; - Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) - { - if ( Aig_ObjIsPi(pObj) ) - continue; - Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, k ) - { - if ( Saig_ObjIsLi(p, pFanout) ) - { - Counter++; - break; - } - } - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Computes volume of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManCutVolume_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - return 0; - Aig_ObjSetTravIdCurrent(p, pObj); - assert( Aig_ObjIsNode(pObj) ); - return 1 + Llb_ManCutVolume_rec(p, Aig_ObjFanin0(pObj)) + - Llb_ManCutVolume_rec(p, Aig_ObjFanin1(pObj)); -} - -/**Function************************************************************* - - Synopsis [Computes volume of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManCutVolume( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) -{ - Aig_Obj_t * pObj; - int i, Counter = 0; - // mark the lower cut with the traversal ID - Aig_ManIncrementTravId(p); - Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) - Aig_ObjSetTravIdCurrent( p, pObj ); - // count the upper cut - Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) - Counter += Llb_ManCutVolume_rec( p, pObj ); - return Counter; -} - - -/**Function************************************************************* - - Synopsis [Computes volume of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManCutNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) -{ - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - return; - Aig_ObjSetTravIdCurrent(p, pObj); - assert( Aig_ObjIsNode(pObj) ); - Llb_ManCutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); - Llb_ManCutNodes_rec(p, Aig_ObjFanin1(pObj), vNodes); - Vec_PtrPush( vNodes, pObj ); -} - -/**Function************************************************************* - - Synopsis [Computes volume of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ManCutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i; - // mark the lower cut with the traversal ID - Aig_ManIncrementTravId(p); - Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) - Aig_ObjSetTravIdCurrent( p, pObj ); - // count the upper cut - vNodes = Vec_PtrAlloc( 100 ); - Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) - Llb_ManCutNodes_rec( p, pObj, vNodes ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Computes volume of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ManCutSupp( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) -{ - Vec_Ptr_t * vNodes, * vSupp; - Aig_Obj_t * pObj; - int i; - vNodes = Llb_ManCutNodes( p, vLower, vUpper ); - // mark support of the nodes - Aig_ManIncrementTravId(p); - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) - { - assert( Aig_ObjIsNode(pObj) ); - Aig_ObjSetTravIdCurrent( p, Aig_ObjFanin0(pObj) ); - Aig_ObjSetTravIdCurrent( p, Aig_ObjFanin1(pObj) ); - } - Vec_PtrFree( vNodes ); - // collect the support nodes - vSupp = Vec_PtrAlloc( 100 ); - Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - Vec_PtrPush( vSupp, pObj ); - return vSupp; - -} - -/**Function************************************************************* - - Synopsis [Computes volume of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ManCutRange( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) -{ - Vec_Ptr_t * vRange; - Aig_Obj_t * pObj; - int i; - // mark the lower cut with the traversal ID - Aig_ManIncrementTravId(p); - Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) - Aig_ObjSetTravIdCurrent( p, pObj ); - // collect the upper ones that are not marked - vRange = Vec_PtrAlloc( 100 ); - Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) - if ( !Aig_ObjIsTravIdCurrent(p, pObj) ) - Vec_PtrPush( vRange, pObj ); - return vRange; -} - - - - -/**Function************************************************************* - - Synopsis [Prints the given cluster.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManCutPrint( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) -{ - Vec_Ptr_t * vSupp, * vRange; - int Pis, Ffs, And; - - Pis = Llb_ManCutPiNum(p, vLower); - Ffs = Llb_ManCutLoNum(p, vLower); - And = Vec_PtrSize(vLower) - Pis - Ffs; - printf( "Leaf: %3d=%3d+%3d+%3d ", Vec_PtrSize(vLower), Pis, Ffs, And ); - - Pis = Llb_ManCutPiNum(p, vUpper); - Ffs = Llb_ManCutLiNum(p, vUpper); - And = Vec_PtrSize(vUpper) - Pis - Ffs; - printf( "Root: %3d=%3d+%3d+%3d ", Vec_PtrSize(vUpper), Pis, Ffs, And ); - - vSupp = Llb_ManCutSupp( p, vLower, vUpper ); - Pis = Llb_ManCutPiNum(p, vSupp); - Ffs = Llb_ManCutLoNum(p, vSupp); - And = Vec_PtrSize(vSupp) - Pis - Ffs; - printf( "Supp: %3d=%3d+%3d+%3d ", Vec_PtrSize(vSupp), Pis, Ffs, And ); - - vRange = Llb_ManCutRange( p, vLower, vUpper ); - Pis = Llb_ManCutPiNum(p, vRange); - Ffs = Llb_ManCutLiNum(p, vRange); - And = Vec_PtrSize(vRange) - Pis - Ffs; - printf( "Range: %3d=%3d+%3d+%3d ", Vec_PtrSize(vRange), Pis, Ffs, And ); - - printf( "S =%3d. V =%3d.\n", - Vec_PtrSize(vSupp)+Vec_PtrSize(vRange), Llb_ManCutVolume(p, vLower, vUpper) ); - Vec_PtrFree( vSupp ); - Vec_PtrFree( vRange ); -/* - { - Aig_Obj_t * pObj; - int i; - printf( "Lower: " ); - Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) - printf( " %d", pObj->Id ); - printf( " " ); - printf( "Upper: " ); - Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) - printf( " %d", pObj->Id ); - printf( "\n" ); - } -*/ -} - -/**Function************************************************************* - - Synopsis [Prints the given cluster.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManResultPrint( Aig_Man_t * p, Vec_Ptr_t * vResult ) -{ - Vec_Ptr_t * vLower, * vUpper; - int i; - Vec_PtrForEachEntryReverse( Vec_Ptr_t *, vResult, vLower, i ) - { - if ( i < Vec_PtrSize(vResult) - 1 ) - Llb_ManCutPrint( p, vLower, vUpper ); - vUpper = vLower; - } -} - -/**Function************************************************************* - - Synopsis [Tries to find an augmenting path originating in this node.] - - Description [This procedure works for directed graphs only!] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManFlowBwdPath2_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - Aig_Obj_t * pFanout; - assert( Aig_ObjIsNode(pObj) || Aig_ObjIsPi(pObj) || Aig_ObjIsConst1(pObj) ); - // skip visited nodes - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - return 0; - Aig_ObjSetTravIdCurrent(p, pObj); - // process node without flow - if ( !Llb_ObjGetPath(pObj) ) - { - // start the path if we reached a terminal node - if ( pObj->fMarkA ) - return Llb_ObjSetPath( pObj, (Aig_Obj_t *)1 ); - // explore the fanins -// Abc_ObjForEachFanin( pObj, pFanin, i ) -// if ( Abc_NtkMaxFlowBwdPath2_rec(pFanin) ) -// return Abc_ObjSetPath( pObj, pFanin ); - if ( Aig_ObjIsNode(pObj) ) - { - if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ) ) - return Llb_ObjSetPath( pObj, Aig_ObjFanin0(pObj) ); - if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ) ) - return Llb_ObjSetPath( pObj, Aig_ObjFanin1(pObj) ); - } - return 0; - } - // pObj has flow - find the fanout with flow - pFanout = Llb_ObjGetFanoutPath( p, 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 ); - assert( Aig_ObjIsNode(pFanout) ); - if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pFanout) ) ) - return Llb_ObjSetPath( pFanout, Aig_ObjFanin0(pFanout) ); - if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pFanout) ) ) - return Llb_ObjSetPath( pFanout, Aig_ObjFanin1(pFanout) ); - // try the fanout - if ( Llb_ManFlowBwdPath2_rec( p, pFanout ) ) - return Llb_ObjSetPath( pFanout, NULL ); - return 0; -} - - -/**Function************************************************************* - - Synopsis [Cleans markB.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManFlowLabelTfi_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - return; - Aig_ObjSetTravIdCurrent(p, pObj); - if ( Aig_ObjIsPi(pObj) || Aig_ObjIsConst1(pObj) ) - return; - assert( Aig_ObjIsNode(pObj) ); - Llb_ManFlowLabelTfi_rec( p, Aig_ObjFanin0(pObj) ); - Llb_ManFlowLabelTfi_rec( p, Aig_ObjFanin1(pObj) ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManFlowUpdateCut( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) -{ - Aig_Obj_t * pObj; - int i; - // label the TFI of the cut nodes - Aig_ManIncrementTravId(p); - Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) - Llb_ManFlowLabelTfi_rec( p, pObj ); - // collect labeled fanins of non-labeled nodes - Vec_PtrClear( vMinCut ); - Aig_ManIncrementTravId(p); - Aig_ManForEachObj( p, pObj, i ) - { - if ( !Aig_ObjIsPo(pObj) && !Aig_ObjIsNode(pObj) ) - continue; - if ( Aig_ObjIsTravIdCurrent(p, pObj) || Aig_ObjIsTravIdPrevious(p, pObj) ) - continue; - if ( Aig_ObjIsTravIdPrevious(p, Aig_ObjFanin0(pObj)) ) - { - Aig_ObjSetTravIdCurrent(p, Aig_ObjFanin0(pObj)); - Vec_PtrPush( vMinCut, Aig_ObjFanin0(pObj) ); - } - if ( Aig_ObjIsNode(pObj) && Aig_ObjIsTravIdPrevious(p, Aig_ObjFanin1(pObj)) ) - { - Aig_ObjSetTravIdCurrent(p, Aig_ObjFanin1(pObj)); - Vec_PtrPush( vMinCut, Aig_ObjFanin1(pObj) ); - } - } -} - -/**Function************************************************************* - - Synopsis [Find minimum-volume minumum cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ManFlowMinCut( Aig_Man_t * p ) -{ - Vec_Ptr_t * vMinCut; - Aig_Obj_t * pObj; - int i; - // collect the cut nodes - vMinCut = Vec_PtrAlloc( Aig_ManRegNum(p) ); - Aig_ManForEachObj( p, pObj, i ) - { - // node without flow is not a cut node - if ( !Llb_ObjGetPath(pObj) ) - continue; - // unvisited node is below the cut - if ( !Aig_ObjIsTravIdCurrent(p, pObj) ) - continue; - // add terminal with flow or node whose path is not visited - if ( pObj->fMarkA || !Aig_ObjIsTravIdCurrent( p, Llb_ObjGetPath(pObj) ) ) - Vec_PtrPush( vMinCut, pObj ); - } - return vMinCut; -} - -/**Function************************************************************* - - Synopsis [Verifies the min-cut is indeed a cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManFlowVerifyCut_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - // skip visited nodes - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - return 1; - Aig_ObjSetTravIdCurrent(p, pObj); - // visit the node - if ( Aig_ObjIsConst1(pObj) ) - return 1; - if ( Aig_ObjIsPi(pObj) ) - return 0; - // explore the fanins - assert( Aig_ObjIsNode(pObj) ); - if ( !Llb_ManFlowVerifyCut_rec(p, Aig_ObjFanin0(pObj)) ) - return 0; - if ( !Llb_ManFlowVerifyCut_rec(p, Aig_ObjFanin1(pObj)) ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Verifies the min-cut is indeed a cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManFlowVerifyCut( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) -{ - Aig_Obj_t * pObj; - int i; - // mark the cut with the current traversal ID - Aig_ManIncrementTravId(p); - Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) - Aig_ObjSetTravIdCurrent( p, pObj ); - // search from the latches for a path to the COs/CIs - Saig_ManForEachLi( p, pObj, i ) - { - if ( !Llb_ManFlowVerifyCut_rec( p, Aig_ObjFanin0(pObj) ) ) - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Implementation of max-flow/min-cut computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ManFlow( Aig_Man_t * p, Vec_Ptr_t * vSources, int * pnFlow ) -{ - Vec_Ptr_t * vMinCut; - Aig_Obj_t * pObj; - int Flow, FlowCur, RetValue, i; - // find the max-flow - Flow = 0; - Aig_ManCleanData( p ); - Aig_ManIncrementTravId(p); - Vec_PtrForEachEntry( Aig_Obj_t *, vSources, pObj, i ) - { - assert( !pObj->fMarkA && pObj->fMarkB ); - if ( !Aig_ObjFanin0(pObj)->fMarkB ) - { - FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ); - Flow += FlowCur; - if ( FlowCur ) - Aig_ManIncrementTravId(p); - } - if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB ) - { - FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ); - Flow += FlowCur; - if ( FlowCur ) - Aig_ManIncrementTravId(p); - } - } - if ( pnFlow ) - *pnFlow = Flow; - - // mark the nodes reachable from the latches - Aig_ManIncrementTravId(p); - Vec_PtrForEachEntry( Aig_Obj_t *, vSources, pObj, i ) - { - assert( !pObj->fMarkA && pObj->fMarkB ); - if ( !Aig_ObjFanin0(pObj)->fMarkB ) - { - RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ); - assert( RetValue == 0 ); - } - if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB ) - { - RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ); - assert( RetValue == 0 ); - } - } - - // find the min-cut with the smallest volume - vMinCut = Llb_ManFlowMinCut( p ); - assert( Vec_PtrSize(vMinCut) == Flow ); - // verify the cut - if ( !Llb_ManFlowVerifyCut(p, vMinCut) ) - printf( "Llb_ManFlow() error! The computed min-cut is not a cut!\n" ); -// Llb_ManFlowPrintCut( p, vMinCut ); - return vMinCut; -} - -/**Function************************************************************* - - Synopsis [Implementation of max-flow/min-cut computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ManFlowCompute( Aig_Man_t * p ) -{ - Vec_Ptr_t * vMinCut; - Aig_Obj_t * pObj; - int Flow, FlowCur, RetValue, i; - // find the max-flow - Flow = 0; - Aig_ManCleanData( p ); - Aig_ManIncrementTravId(p); - Aig_ManForEachObj( p, pObj, i ) - { - if ( !pObj->fMarkB ) - continue; - assert( !pObj->fMarkA ); - if ( !Aig_ObjFanin0(pObj)->fMarkB ) - { -//printf( "%d ", Aig_ObjFanin0(pObj)->Id ); - FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ); - Flow += FlowCur; - if ( FlowCur ) - Aig_ManIncrementTravId(p); - } - if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB ) - { -//printf( "%d ", Aig_ObjFanin1(pObj)->Id ); - FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ); - Flow += FlowCur; - if ( FlowCur ) - Aig_ManIncrementTravId(p); - } - } -//printf( "\n" ); - - // mark the nodes reachable from the latches - Aig_ManIncrementTravId(p); - Aig_ManForEachObj( p, pObj, i ) - { - if ( !pObj->fMarkB ) - continue; - assert( !pObj->fMarkA ); - if ( !Aig_ObjFanin0(pObj)->fMarkB ) - { - RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ); - assert( RetValue == 0 ); - } - if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB ) - { - RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ); - assert( RetValue == 0 ); - } - } - // find the min-cut with the smallest volume - vMinCut = Llb_ManFlowMinCut( p ); - assert( Vec_PtrSize(vMinCut) == Flow ); -//printf( "%d ", Vec_PtrSize(vMinCut) ); - Llb_ManFlowUpdateCut( p, vMinCut ); -//printf( "%d ", Vec_PtrSize(vMinCut) ); - // verify the cut - if ( !Llb_ManFlowVerifyCut(p, vMinCut) ) - printf( "Llb_ManFlow() error! The computed min-cut is not a cut!\n" ); -// Llb_ManFlowPrintCut( p, vMinCut ); - return vMinCut; -} - - - - -/**Function************************************************************* - - Synopsis [Cleans markB.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManFlowCleanMarkB_rec( Aig_Obj_t * pObj ) -{ - if ( pObj->fMarkB == 0 ) - return; - pObj->fMarkB = 0; - assert( Aig_ObjIsNode(pObj) ); - Llb_ManFlowCleanMarkB_rec( Aig_ObjFanin0(pObj) ); - Llb_ManFlowCleanMarkB_rec( Aig_ObjFanin1(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Cleans markB.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManFlowSetMarkA_rec( Aig_Obj_t * pObj ) -{ - if ( pObj->fMarkA ) - return; - pObj->fMarkA = 1; - if ( Aig_ObjIsPi(pObj) || Aig_ObjIsConst1(pObj) ) - return; - assert( Aig_ObjIsNode(pObj) ); - Llb_ManFlowSetMarkA_rec( Aig_ObjFanin0(pObj) ); - Llb_ManFlowSetMarkA_rec( Aig_ObjFanin1(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Prepares flow computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManFlowPrepareCut( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) -{ - Aig_Obj_t * pObj; - int i; - // reset marks - Aig_ManForEachObj( p, pObj, i ) - { - pObj->fMarkA = 0; - pObj->fMarkB = 1; - } - // clean PIs and const - Aig_ManConst1(p)->fMarkB = 0; - Aig_ManForEachPi( p, pObj, i ) - pObj->fMarkB = 0; - // clean upper cut -//printf( "Upper: "); - Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) - { - Llb_ManFlowCleanMarkB_rec( pObj ); -//printf( "%d ", pObj->Id ); - } -//printf( "\n" ); - // set lower cut -//printf( "Lower: "); - Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) - { -//printf( "%d ", pObj->Id ); - assert( pObj->fMarkB == 0 ); - Llb_ManFlowSetMarkA_rec( pObj ); - } -//printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Prepares flow computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManFlowUnmarkCone( Aig_Man_t * p, Vec_Ptr_t * vCone ) -{ - Aig_Obj_t * pObj; - int i; - Vec_PtrForEachEntry( Aig_Obj_t *, vCone, pObj, i ) - { - assert( Aig_ObjIsNode(pObj) ); - assert( pObj->fMarkB == 1 ); - pObj->fMarkB = 0; - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManFlowCollectAndMarkCone_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vCone ) -{ - Aig_Obj_t * pFanout; - int i, iFanout; - if ( Saig_ObjIsLi(p, pObj) ) - return; - if ( pObj->fMarkB ) - return; - if ( pObj->fMarkA == 0 ) - { - assert( Aig_ObjIsNode(pObj) ); - pObj->fMarkB = 1; - if ( Aig_ObjIsNode(pObj) ) - Vec_PtrPush( vCone, pObj ); - } - Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) - Llb_ManFlowCollectAndMarkCone_rec( p, pFanout, vCone ); -} - -/**Function************************************************************* - - Synopsis [Collects the cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManFlowCollectAndMarkCone( Aig_Man_t * p, Vec_Ptr_t * vStarts, Vec_Ptr_t * vCone ) -{ - Aig_Obj_t * pObj; - int i; - Vec_PtrClear( vCone ); - Vec_PtrForEachEntry( Aig_Obj_t *, vStarts, pObj, i ) - { - assert( pObj->fMarkA && !pObj->fMarkB ); - Llb_ManFlowCollectAndMarkCone_rec( p, pObj, vCone ); - } -} - - - - -/**Function************************************************************* - - Synopsis [Finds balanced cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ManComputeCutLo( Aig_Man_t * p ) -{ - Vec_Ptr_t * vMinCut; - Aig_Obj_t * pObj; - int i; - vMinCut = Vec_PtrAlloc( 100 ); - Aig_ManForEachPi( p, pObj, i ) - Vec_PtrPush( vMinCut, pObj ); - return vMinCut; -} - -/**Function************************************************************* - - Synopsis [Finds balanced cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ManComputeCutLi( Aig_Man_t * p ) -{ - Vec_Ptr_t * vMinCut; - Aig_Obj_t * pObj; - int i; - assert( Saig_ManPoNum(p) == 0 ); - vMinCut = Vec_PtrAlloc( 100 ); - Aig_ManIncrementTravId(p); - Saig_ManForEachLi( p, pObj, i ) - { - pObj = Aig_ObjFanin0(pObj); - if ( Aig_ObjIsConst1(pObj) ) - continue; - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - continue; - Aig_ObjSetTravIdCurrent(p, pObj); - Vec_PtrPush( vMinCut, pObj ); - } - return vMinCut; -} - - - -/**Function************************************************************* - - Synopsis [Finds balanced cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManFlowGetObjSet( Aig_Man_t * p, Vec_Ptr_t * vLower, int iStart, int nSize, Vec_Ptr_t * vSet ) -{ - Aig_Obj_t * pObj; - int i; - Vec_PtrClear( vSet ); - for ( i = 0; i < nSize; i++ ) - { - pObj = (Aig_Obj_t *)Vec_PtrEntry( vLower, (iStart + i) % Vec_PtrSize(vLower) ); - Vec_PtrPush( vSet, pObj ); - } -} - -/**Function************************************************************* - - Synopsis [Finds balanced cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ManFlowFindBestCut( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, int Num ) -{ - int nVolMin = Aig_ManNodeNum(p) / Num / 2; - Vec_Ptr_t * vMinCut; - Vec_Ptr_t * vCone, * vSet; - Aig_Obj_t * pObj; - int i, s, Vol, VolLower, VolUpper, VolCmp; - int iBest = -1, iMinCut = ABC_INFINITY, iVolBest = 0; - - Vol = Llb_ManCutVolume( p, vLower, vUpper ); - assert( Vol > nVolMin ); - VolCmp = ABC_MIN( nVolMin, Vol - nVolMin ); - vCone = Vec_PtrAlloc( 100 ); - vSet = Vec_PtrAlloc( 100 ); - Llb_ManFlowPrepareCut( p, vLower, vUpper ); - for ( s = 1; s < Aig_ManRegNum(p); s += 5 ) - { - Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) - { - Llb_ManFlowGetObjSet( p, vLower, i, s, vSet ); - Llb_ManFlowCollectAndMarkCone( p, vSet, vCone ); - if ( Vec_PtrSize(vCone) == 0 ) - continue; - vMinCut = Llb_ManFlowCompute( p ); - Llb_ManFlowUnmarkCone( p, vCone ); - - VolLower = Llb_ManCutVolume( p, vLower, vMinCut ); - VolUpper = Llb_ManCutVolume( p, vMinCut, vUpper ); - Vol = ABC_MIN( VolLower, VolUpper ); - if ( Vol >= VolCmp && (iMinCut == -1 || - iMinCut > Vec_PtrSize(vMinCut) || - (iMinCut == Vec_PtrSize(vMinCut) && iVolBest < Vol)) ) - { - iBest = i; - iMinCut = Vec_PtrSize(vMinCut); - iVolBest = Vol; - } - Vec_PtrFree( vMinCut ); - } - if ( iBest >= 0 ) - break; - } - if ( iBest == -1 ) - { - // cleanup - Vec_PtrFree( vCone ); - Vec_PtrFree( vSet ); - return NULL; - } - // get the best cut - assert( iBest >= 0 ); - Llb_ManFlowGetObjSet( p, vLower, iBest, s, vSet ); - Llb_ManFlowCollectAndMarkCone( p, vSet, vCone ); - vMinCut = Llb_ManFlowCompute( p ); - Llb_ManFlowUnmarkCone( p, vCone ); - // cleanup - Vec_PtrFree( vCone ); - Vec_PtrFree( vSet ); - return vMinCut; -} - -/**Function************************************************************* - - Synopsis [Finds balanced cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ManComputeCuts( Aig_Man_t * p, int Num, int fVerbose, int fVeryVerbose ) -{ - int nVolMax = Aig_ManNodeNum(p) / Num; - Vec_Ptr_t * vResult, * vMinCut, * vLower, * vUpper; - int i, k, nVol, clk = clock(); - vResult = Vec_PtrAlloc( 100 ); - Vec_PtrPush( vResult, Llb_ManComputeCutLo(p) ); - Vec_PtrPush( vResult, Llb_ManComputeCutLi(p) ); - while ( 1 ) - { - // find a place to insert new cut - vLower = (Vec_Ptr_t *)Vec_PtrEntry( vResult, 0 ); - Vec_PtrForEachEntryStart( Vec_Ptr_t *, vResult, vUpper, i, 1 ) - { - nVol = Llb_ManCutVolume( p, vLower, vUpper ); - if ( nVol <= nVolMax ) - { - vLower = vUpper; - continue; - } - - if ( fVeryVerbose ) - Llb_ManCutPrint( p, vLower, vUpper ); - vMinCut = Llb_ManFlowFindBestCut( p, vLower, vUpper, Num ); - if ( vMinCut == NULL ) - { - if ( fVeryVerbose ) - printf( "Could not break the cut.\n" ); - if ( fVeryVerbose ) - printf( "\n" ); - vLower = vUpper; - continue; - } - - if ( fVeryVerbose ) - Llb_ManCutPrint( p, vMinCut, vUpper ); - if ( fVeryVerbose ) - Llb_ManCutPrint( p, vLower, vMinCut ); - if ( fVeryVerbose ) - printf( "\n" ); - - break; - } - if ( i == Vec_PtrSize(vResult) ) - break; - // insert vMinCut before vUpper - Vec_PtrPush( vResult, NULL ); - for ( k = Vec_PtrSize(vResult) - 1; k > i; k-- ) - Vec_PtrWriteEntry( vResult, k, Vec_PtrEntry(vResult, k-1) ); - Vec_PtrWriteEntry( vResult, i, vMinCut ); - } - if ( fVerbose ) - { - printf( "Finished computing %d partitions. ", Vec_PtrSize(vResult) - 1 ); - Abc_PrintTime( 1, "Time", clock() - clk ); - Llb_ManResultPrint( p, vResult ); - } - return vResult; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_BddSetDefaultParams( Gia_ParLlb_t * p ) -{ - memset( p, 0, sizeof(Gia_ParLlb_t) ); - p->nBddMax = 1000000; - p->nIterMax = 10000000; - p->nClusterMax = 20; - p->nHintDepth = 0; - p->HintFirst = 0; - p->fUseFlow = 0; // use flow - p->nVolumeMax = 100; // max volume - p->nVolumeMin = 30; // min volume - p->fReorder = 1; - p->fIndConstr = 0; - p->fUsePivots = 0; - p->fCluster = 0; - p->fSchedule = 0; - p->fVerbose = 0; - p->fVeryVerbose = 0; - p->fSilent = 0; - p->TimeLimit = 0; -// p->TimeLimit = 0; - p->TimeLimitGlo = 0; - p->TimeTarget = 0; - p->iFrame = -1; -} - -/**Function************************************************************* - - Synopsis [Finds balanced cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManMinCutTest( Aig_Man_t * pAig, int Num ) -{ - extern void Llb_BddConstructTest( Aig_Man_t * p, Vec_Ptr_t * vResult ); - extern void Llb_BddExperiment( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars, Vec_Ptr_t * vResult, Vec_Ptr_t * vMaps ); - - - int fVerbose = 1; - Gia_ParLlb_t Pars, * pPars = &Pars; - Vec_Ptr_t * vResult;//, * vSupps, * vMaps; - Aig_Man_t * p; - - Llb_BddSetDefaultParams( pPars ); - - p = Aig_ManDupFlopsOnly( pAig ); -//Aig_ManShow( p, 0, NULL ); - Aig_ManPrintStats( pAig ); - Aig_ManPrintStats( p ); - Aig_ManFanoutStart( p ); - - vResult = Llb_ManComputeCuts( p, Num, 1, 0 ); -// vSupps = Llb_ManCutSupps( p, vResult ); -// vMaps = Llb_ManCutMap( p, vResult, vSupps ); - -// Llb_BddExperiment( pAig, p, pPars, vResult, vMaps ); - Llb_CoreExperiment( pAig, p, pPars, vResult, 0 ); - -// Vec_VecFree( (Vec_Vec_t *)vMaps ); -// Vec_VecFree( (Vec_Vec_t *)vSupps ); - Vec_VecFree( (Vec_Vec_t *)vResult ); - - Aig_ManFanoutStop( p ); - Aig_ManCleanMarkAB( p ); - Aig_ManStop( p ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llb2Image.c b/src/aig/llb/llb2Image.c deleted file mode 100644 index 5baa5c57..00000000 --- a/src/aig/llb/llb2Image.c +++ /dev/null @@ -1,478 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb2Image.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Computes image using partitioned structure.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb2Image.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -extern Vec_Ptr_t * Llb_ManCutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ); -extern Vec_Ptr_t * Llb_ManCutRange( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes supports of the partitions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ImgSupports( Aig_Man_t * p, Vec_Ptr_t * vDdMans, Vec_Int_t * vStart, Vec_Int_t * vStop, int fAddPis, int fVerbose ) -{ - Vec_Ptr_t * vSupps; - Vec_Int_t * vOne; - Aig_Obj_t * pObj; - DdManager * dd; - DdNode * bSupp, * bTemp; - int i, Entry, nSize; - nSize = Cudd_ReadSize( (DdManager *)Vec_PtrEntry( vDdMans, 0 ) ); - vSupps = Vec_PtrAlloc( 100 ); - // create initial - vOne = Vec_IntStart( nSize ); - Vec_IntForEachEntry( vStart, Entry, i ) - Vec_IntWriteEntry( vOne, Entry, 1 ); - Vec_PtrPush( vSupps, vOne ); - // create intermediate - Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i ) - { - vOne = Vec_IntStart( nSize ); - bSupp = Cudd_Support( dd, dd->bFunc ); Cudd_Ref( bSupp ); - for ( bTemp = bSupp; bTemp != Cudd_ReadOne(dd); bTemp = cuddT(bTemp) ) - Vec_IntWriteEntry( vOne, bTemp->index, 1 ); - Cudd_RecursiveDeref( dd, bSupp ); - Vec_PtrPush( vSupps, vOne ); - } - // create final - vOne = Vec_IntStart( nSize ); - Vec_IntForEachEntry( vStop, Entry, i ) - Vec_IntWriteEntry( vOne, Entry, 1 ); - if ( fAddPis ) - Saig_ManForEachPi( p, pObj, i ) - Vec_IntWriteEntry( vOne, Aig_ObjId(pObj), 1 ); - Vec_PtrPush( vSupps, vOne ); - - // print supports - assert( nSize == Aig_ManObjNumMax(p) ); - if ( fVerbose ) - Aig_ManForEachObj( p, pObj, i ) - { - int k, Counter = 0; - Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k ) - Counter += Vec_IntEntry(vOne, i); - if ( Counter == 0 ) - continue; - printf( "Obj = %4d : ", i ); - if ( Saig_ObjIsPi(p,pObj) ) - printf( "pi " ); - else if ( Saig_ObjIsLo(p,pObj) ) - printf( "lo " ); - else if ( Saig_ObjIsLi(p,pObj) ) - printf( "li " ); - else if ( Aig_ObjIsNode(pObj) ) - printf( "and " ); - Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k ) - printf( "%d", Vec_IntEntry(vOne, i) ); - printf( "\n" ); - } - return vSupps; -} - -/**Function************************************************************* - - Synopsis [Computes quantification schedule.] - - Description [Input array contains supports: 0=starting, ... intermediate... - N-1=final. Output arrays contain immediately quantifiable vars (vQuant0) - and vars that should be quantified after conjunction (vQuant1).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ImgSchedule( Vec_Ptr_t * vSupps, Vec_Ptr_t ** pvQuant0, Vec_Ptr_t ** pvQuant1, int fVerbose ) -{ - Vec_Int_t * vOne; - int nVarsAll, Counter, iSupp, Entry, i, k; - // start quantification arrays - *pvQuant0 = Vec_PtrAlloc( Vec_PtrSize(vSupps) ); - *pvQuant1 = Vec_PtrAlloc( Vec_PtrSize(vSupps) ); - Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k ) - { - Vec_PtrPush( *pvQuant0, Vec_IntAlloc(16) ); - Vec_PtrPush( *pvQuant1, Vec_IntAlloc(16) ); - } - // count how many times each var appears - nVarsAll = Vec_IntSize( (Vec_Int_t *)Vec_PtrEntry(vSupps, 0) ); - for ( i = 0; i < nVarsAll; i++ ) - { - Counter = 0; - Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k ) - if ( Vec_IntEntry(vOne, i) ) - { - iSupp = k; - Counter++; - } - if ( Counter == 0 ) - continue; - if ( Counter == 1 ) - Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(*pvQuant0, iSupp), i ); - else // if ( Counter > 1 ) - Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(*pvQuant1, iSupp), i ); - } - - if ( fVerbose ) - for ( i = 0; i < Vec_PtrSize(vSupps); i++ ) - { - printf( "%2d : Quant0 = ", i ); - Vec_IntForEachEntry( (Vec_Int_t *)Vec_PtrEntry(*pvQuant0, i), Entry, k ) - printf( "%d ", Entry ); - printf( "\n" ); - } - - if ( fVerbose ) - for ( i = 0; i < Vec_PtrSize(vSupps); i++ ) - { - printf( "%2d : Quant1 = ", i ); - Vec_IntForEachEntry( (Vec_Int_t *)Vec_PtrEntry(*pvQuant1, i), Entry, k ) - printf( "%d ", Entry ); - printf( "\n" ); - } -} - -/**Function************************************************************* - - Synopsis [Computes one partition in a separate BDD manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdManager * Llb_ImgPartition( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, int TimeTarget ) -{ - Vec_Ptr_t * vNodes, * vRange; - Aig_Obj_t * pObj; - DdManager * dd; - DdNode * bBdd0, * bBdd1, * bProd, * bRes, * bTemp; - int i; - - dd = Cudd_Init( Aig_ManObjNumMax(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - dd->TimeStop = TimeTarget; - - Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) - pObj->pData = Cudd_bddIthVar( dd, Aig_ObjId(pObj) ); - - vNodes = Llb_ManCutNodes( p, vLower, vUpper ); - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) - { - bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); -// pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData ); -// pObj->pData = Extra_bddAndTime( dd, bBdd0, bBdd1, TimeTarget ); - pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); - if ( pObj->pData == NULL ) - { - Cudd_Quit( dd ); - Vec_PtrFree( vNodes ); - return NULL; - } - Cudd_Ref( (DdNode *)pObj->pData ); - } - - vRange = Llb_ManCutRange( p, vLower, vUpper ); - bRes = Cudd_ReadOne(dd); Cudd_Ref( bRes ); - Vec_PtrForEachEntry( Aig_Obj_t *, vRange, pObj, i ) - { - assert( Aig_ObjIsNode(pObj) ); - bProd = Cudd_bddXnor( dd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)), (DdNode *)pObj->pData ); Cudd_Ref( bProd ); -// bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd ); Cudd_Ref( bRes ); -// bRes = Extra_bddAndTime( dd, bTemp = bRes, bProd, TimeTarget ); - bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd ); - if ( bRes == NULL ) - { - Cudd_Quit( dd ); - Vec_PtrFree( vRange ); - Vec_PtrFree( vNodes ); - return NULL; - } - Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bProd ); - } - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); - - Vec_PtrFree( vRange ); - Vec_PtrFree( vNodes ); - Cudd_AutodynDisable( dd ); -// Cudd_RecursiveDeref( dd, bRes ); -// Extra_StopManager( dd ); - dd->bFunc = bRes; - dd->TimeStop = 0; - return dd; -} - -/**Function************************************************************* - - Synopsis [Derives positive cube composed of nodes IDs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ImgComputeCube( Aig_Man_t * pAig, Vec_Int_t * vNodeIds, DdManager * dd ) -{ - DdNode * bProd, * bTemp; - Aig_Obj_t * pObj; - int i, TimeStop; - TimeStop = dd->TimeStop; dd->TimeStop = 0; - bProd = Cudd_ReadOne(dd); Cudd_Ref( bProd ); - Aig_ManForEachObjVec( vNodeIds, pAig, pObj, i ) - { - bProd = Cudd_bddAnd( dd, bTemp = bProd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)) ); Cudd_Ref( bProd ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bProd ); - dd->TimeStop = TimeStop; - return bProd; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ImgQuantifyFirst( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, Vec_Ptr_t * vQuant0, int fVerbose ) -{ - DdManager * dd; - DdNode * bProd, * bRes, * bTemp; - int i, clk = clock(); - Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i ) - { - // remember unquantified ones - assert( dd->bFunc2 == NULL ); - dd->bFunc2 = dd->bFunc; Cudd_Ref( dd->bFunc2 ); - - Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - - bRes = dd->bFunc; - if ( fVerbose ) - Abc_Print( 1, "Part %2d : Init =%5d. ", i, Cudd_DagSize(bRes) ); - bProd = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant0, i+1), dd ); Cudd_Ref( bProd ); - bRes = Cudd_bddExistAbstract( dd, bTemp = bRes, bProd ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bProd ); - dd->bFunc = bRes; - - Cudd_AutodynDisable( dd ); - - if ( fVerbose ) - Abc_Print( 1, "Quant =%5d. ", Cudd_DagSize(bRes) ); - Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); - if ( fVerbose ) - Abc_Print( 1, "Reo = %5d. ", Cudd_DagSize(bRes) ); - Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); - if ( fVerbose ) - Abc_Print( 1, "Reo = %5d. ", Cudd_DagSize(bRes) ); - if ( fVerbose ) - Abc_Print( 1, "Supp = %3d. ", Cudd_SupportSize(dd, bRes) ); - if ( fVerbose ) - Abc_PrintTime( 1, "Time", clock() - clk ); - - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ImgQuantifyReset( Vec_Ptr_t * vDdMans ) -{ - DdManager * dd; - int i; - Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i ) - { - assert( dd->bFunc2 != NULL ); - Cudd_RecursiveDeref( dd, dd->bFunc ); - dd->bFunc = dd->bFunc2; - dd->bFunc2 = NULL; - } -} - -/**Function************************************************************* - - Synopsis [Computes image of the initial set of states.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ImgComputeImage( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, DdManager * dd, DdNode * bInit, - Vec_Ptr_t * vQuant0, Vec_Ptr_t * vQuant1, Vec_Int_t * vDriRefs, - int TimeTarget, int fBackward, int fReorder, int fVerbose ) -{ - int fCheckSupport = 0; - DdManager * ddPart; - DdNode * bImage, * bGroup, * bCube, * bTemp; - int i, clk, clk0 = clock(); - - bImage = bInit; Cudd_Ref( bImage ); - if ( fBackward ) - { - // change polarity - bCube = Llb_DriverPhaseCube( pAig, vDriRefs, dd ); Cudd_Ref( bCube ); - bImage = Extra_bddChangePolarity( dd, bTemp = bImage, bCube ); Cudd_Ref( bImage ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bCube ); - } - else - { - // quantify unique vriables - bCube = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant0, 0), dd ); Cudd_Ref( bCube ); - bImage = Cudd_bddExistAbstract( dd, bTemp = bImage, bCube ); - if ( bImage == NULL ) - { - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bCube ); - return NULL; - } - Cudd_Ref( bImage ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bCube ); - } - // perform image computation - Vec_PtrForEachEntry( DdManager *, vDdMans, ddPart, i ) - { - clk = clock(); -if ( fVerbose ) -printf( " %2d : ", i ); - // transfer the BDD from the group manager to the main manager - bGroup = Cudd_bddTransfer( ddPart, dd, ddPart->bFunc ); - if ( bGroup == NULL ) - return NULL; - Cudd_Ref( bGroup ); -if ( fVerbose ) -printf( "Pt0 =%6d. Pt1 =%6d. ", Cudd_DagSize(ddPart->bFunc), Cudd_DagSize(bGroup) ); - // perform partial product - bCube = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant1, i+1), dd ); Cudd_Ref( bCube ); -// bImage = Cudd_bddAndAbstract( dd, bTemp = bImage, bGroup, bCube ); -// bImage = Extra_bddAndAbstractTime( dd, bTemp = bImage, bGroup, bCube, TimeTarget ); - bImage = Cudd_bddAndAbstract( dd, bTemp = bImage, bGroup, bCube ); - if ( bImage == NULL ) - { - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bCube ); - Cudd_RecursiveDeref( dd, bGroup ); - return NULL; - } - Cudd_Ref( bImage ); - -if ( fVerbose ) -printf( "Im0 =%6d. Im1 =%6d. ", Cudd_DagSize(bTemp), Cudd_DagSize(bImage) ); -//printf("\n"); Extra_bddPrintSupport(dd, bImage); printf("\n"); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bCube ); - Cudd_RecursiveDeref( dd, bGroup ); - -// Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); -// Abc_Print( 1, "Reo =%6d. ", Cudd_DagSize(bImage) ); - -if ( fVerbose ) -printf( "Supp =%3d. ", Cudd_SupportSize(dd, bImage) ); -if ( fVerbose ) -Abc_PrintTime( 1, "T", clock() - clk ); - } - - if ( !fBackward ) - { - // change polarity - bCube = Llb_DriverPhaseCube( pAig, vDriRefs, dd ); Cudd_Ref( bCube ); - bImage = Extra_bddChangePolarity( dd, bTemp = bImage, bCube ); Cudd_Ref( bImage ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bCube ); - } - else - { - // quantify unique vriables - bCube = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant0, 0), dd ); Cudd_Ref( bCube ); - bImage = Cudd_bddExistAbstract( dd, bTemp = bImage, bCube ); Cudd_Ref( bImage ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bCube ); - } - - if ( fReorder ) - { - if ( fVerbose ) - Abc_Print( 1, " Reordering... Before =%5d. ", Cudd_DagSize(bImage) ); - Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); - if ( fVerbose ) - Abc_Print( 1, "After =%5d. ", Cudd_DagSize(bImage) ); -// Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); -// Abc_Print( 1, "After =%5d. ", Cudd_DagSize(bImage) ); - if ( fVerbose ) - Abc_PrintTime( 1, "Time", clock() - clk0 ); -// Abc_Print( 1, "\n" ); - } - - Cudd_Deref( bImage ); - return bImage; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llb3Image.c b/src/aig/llb/llb3Image.c deleted file mode 100644 index 09f2700c..00000000 --- a/src/aig/llb/llb3Image.c +++ /dev/null @@ -1,1093 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb3Image.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Computes image using partitioned structure.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb3Image.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Llb_Var_t_ Llb_Var_t; -struct Llb_Var_t_ -{ - int iVar; // variable number - int nScore; // variable score - Vec_Int_t * vParts; // partitions -}; - -typedef struct Llb_Prt_t_ Llb_Prt_t; -struct Llb_Prt_t_ -{ - int iPart; // partition number - int nSize; // the number of BDD nodes - DdNode * bFunc; // the partition - Vec_Int_t * vVars; // support -}; - -typedef struct Llb_Mgr_t_ Llb_Mgr_t; -struct Llb_Mgr_t_ -{ - Aig_Man_t * pAig; // AIG manager - Vec_Ptr_t * vLeaves; // leaves in the AIG manager - Vec_Ptr_t * vRoots; // roots in the AIG manager - DdManager * dd; // working BDD manager - int * pVars2Q; // variables to quantify - // internal - Llb_Prt_t ** pParts; // partitions - Llb_Var_t ** pVars; // variables - int iPartFree; // next free partition - int nVars; // the number of BDD variables - int nSuppMax; // maximum support size - // temporary - int * pSupp; // temporary support storage -}; - -static inline Llb_Var_t * Llb_MgrVar( Llb_Mgr_t * p, int i ) { return p->pVars[i]; } -static inline Llb_Prt_t * Llb_MgrPart( Llb_Mgr_t * p, int i ) { return p->pParts[i]; } - -// iterator over vars -#define Llb_MgrForEachVar( p, pVar, i ) \ - for ( i = 0; (i < p->nVars) && (((pVar) = Llb_MgrVar(p, i)), 1); i++ ) if ( pVar == NULL ) {} else -// iterator over parts -#define Llb_MgrForEachPart( p, pPart, i ) \ - for ( i = 0; (i < p->iPartFree) && (((pPart) = Llb_MgrPart(p, i)), 1); i++ ) if ( pPart == NULL ) {} else - -// iterator over vars of one partition -#define Llb_PartForEachVar( p, pPart, pVar, i ) \ - for ( i = 0; (i < Vec_IntSize(pPart->vVars)) && (((pVar) = Llb_MgrVar(p, Vec_IntEntry(pPart->vVars,i))), 1); i++ ) -// iterator over parts of one variable -#define Llb_VarForEachPart( p, pVar, pPart, i ) \ - for ( i = 0; (i < Vec_IntSize(pVar->vParts)) && (((pPart) = Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,i))), 1); i++ ) - -// statistics -int timeBuild, timeAndEx, timeOther; -int nSuppMax; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Removes one variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_NonlinRemoveVar( Llb_Mgr_t * p, Llb_Var_t * pVar ) -{ - assert( p->pVars[pVar->iVar] == pVar ); - p->pVars[pVar->iVar] = NULL; - Vec_IntFree( pVar->vParts ); - ABC_FREE( pVar ); -} - -/**Function************************************************************* - - Synopsis [Removes one partition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_NonlinRemovePart( Llb_Mgr_t * p, Llb_Prt_t * pPart ) -{ - assert( p->pParts[pPart->iPart] == pPart ); - p->pParts[pPart->iPart] = NULL; - Vec_IntFree( pPart->vVars ); - Cudd_RecursiveDeref( p->dd, pPart->bFunc ); - ABC_FREE( pPart ); -} - -/**Function************************************************************* - - Synopsis [Create cube with singleton variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_NonlinCreateCube1( Llb_Mgr_t * p, Llb_Prt_t * pPart ) -{ - DdNode * bCube, * bTemp; - Llb_Var_t * pVar; - int i, TimeStop; - TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; - bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube ); - Llb_PartForEachVar( p, pPart, pVar, i ) - { - assert( Vec_IntSize(pVar->vParts) > 0 ); - if ( Vec_IntSize(pVar->vParts) != 1 ) - continue; - assert( Vec_IntEntry(pVar->vParts, 0) == pPart->iPart ); - bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - Cudd_Deref( bCube ); - p->dd->TimeStop = TimeStop; - return bCube; -} - -/**Function************************************************************* - - Synopsis [Create cube of variables appearing only in two partitions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_NonlinCreateCube2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 ) -{ - DdNode * bCube, * bTemp; - Llb_Var_t * pVar; - int i, TimeStop; - TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; - bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube ); - Llb_PartForEachVar( p, pPart1, pVar, i ) - { - assert( Vec_IntSize(pVar->vParts) > 0 ); - if ( Vec_IntSize(pVar->vParts) != 2 ) - continue; - if ( (Vec_IntEntry(pVar->vParts, 0) == pPart1->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart2->iPart) || - (Vec_IntEntry(pVar->vParts, 0) == pPart2->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart1->iPart) ) - { - bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - } - Cudd_Deref( bCube ); - p->dd->TimeStop = TimeStop; - return bCube; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if partition has singleton variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_NonlinHasSingletonVars( Llb_Mgr_t * p, Llb_Prt_t * pPart ) -{ - Llb_Var_t * pVar; - int i; - Llb_PartForEachVar( p, pPart, pVar, i ) - if ( Vec_IntSize(pVar->vParts) == 1 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if partition has singleton variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_NonlinPrint( Llb_Mgr_t * p ) -{ - Llb_Prt_t * pPart; - Llb_Var_t * pVar; - int i, k; - printf( "\n" ); - Llb_MgrForEachVar( p, pVar, i ) - { - printf( "Var %3d : ", i ); - Llb_VarForEachPart( p, pVar, pPart, k ) - printf( "%d ", pPart->iPart ); - printf( "\n" ); - } - Llb_MgrForEachPart( p, pPart, i ) - { - printf( "Part %3d : ", i ); - Llb_PartForEachVar( p, pPart, pVar, k ) - printf( "%d ", pVar->iVar ); - printf( "\n" ); - } -} - -/**Function************************************************************* - - Synopsis [Quantifies singles belonging to one partition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_NonlinQuantify1( Llb_Mgr_t * p, Llb_Prt_t * pPart, int fSubset ) -{ - Llb_Var_t * pVar; - Llb_Prt_t * pTemp; - Vec_Ptr_t * vSingles; - DdNode * bCube, * bTemp; - int i, RetValue, nSizeNew; - if ( fSubset ) - { - int Length; -// int nSuppSize = Cudd_SupportSize( p->dd, pPart->bFunc ); -// pPart->bFunc = Cudd_SubsetHeavyBranch( p->dd, bTemp = pPart->bFunc, nSuppSize, 3*pPart->nSize/4 ); Cudd_Ref( pPart->bFunc ); - pPart->bFunc = Cudd_LargestCube( p->dd, bTemp = pPart->bFunc, &Length ); Cudd_Ref( pPart->bFunc ); - - printf( "Subsetting %3d : ", pPart->iPart ); - printf( "(Supp =%3d Node =%5d) -> ", Cudd_SupportSize(p->dd, bTemp), Cudd_DagSize(bTemp) ); - printf( "(Supp =%3d Node =%5d)\n", Cudd_SupportSize(p->dd, pPart->bFunc), Cudd_DagSize(pPart->bFunc) ); - - RetValue = (Cudd_DagSize(bTemp) == Cudd_DagSize(pPart->bFunc)); - - Cudd_RecursiveDeref( p->dd, bTemp ); - - if ( RetValue ) - return 1; - } - else - { - // create cube to be quantified - bCube = Llb_NonlinCreateCube1( p, pPart ); Cudd_Ref( bCube ); -// assert( !Cudd_IsConstant(bCube) ); - // derive new function - pPart->bFunc = Cudd_bddExistAbstract( p->dd, bTemp = pPart->bFunc, bCube ); Cudd_Ref( pPart->bFunc ); - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bCube ); - } - // get support - vSingles = Vec_PtrAlloc( 0 ); - nSizeNew = Cudd_DagSize(pPart->bFunc); - Extra_SupportArray( p->dd, pPart->bFunc, p->pSupp ); - Llb_PartForEachVar( p, pPart, pVar, i ) - if ( p->pSupp[pVar->iVar] ) - { - assert( Vec_IntSize(pVar->vParts) > 1 ); - pVar->nScore -= pPart->nSize - nSizeNew; - } - else - { - RetValue = Vec_IntRemove( pVar->vParts, pPart->iPart ); - assert( RetValue ); - pVar->nScore -= pPart->nSize; - if ( Vec_IntSize(pVar->vParts) == 0 ) - Llb_NonlinRemoveVar( p, pVar ); - else if ( Vec_IntSize(pVar->vParts) == 1 ) - Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); - } - - // update partition - pPart->nSize = nSizeNew; - Vec_IntClear( pPart->vVars ); - for ( i = 0; i < p->nVars; i++ ) - if ( p->pSupp[i] && p->pVars2Q[i] ) - Vec_IntPush( pPart->vVars, i ); - // remove other variables - Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i ) - Llb_NonlinQuantify1( p, pTemp, 0 ); - Vec_PtrFree( vSingles ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Quantifies singles belonging to one partition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_NonlinQuantify2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2, int Limit, int TimeOut ) -{ - int fVerbose = 0; - Llb_Var_t * pVar; - Llb_Prt_t * pTemp; - Vec_Ptr_t * vSingles; - DdNode * bCube, * bFunc; - int i, RetValue, nSuppSize; - int iPart1 = pPart1->iPart; - int iPart2 = pPart2->iPart; - - // create cube to be quantified - bCube = Llb_NonlinCreateCube2( p, pPart1, pPart2 ); Cudd_Ref( bCube ); -if ( fVerbose ) -{ -printf( "\n" ); -printf( "\n" ); -Llb_NonlinPrint( p ); -printf( "Conjoining partitions %d and %d.\n", pPart1->iPart, pPart2->iPart ); -Extra_bddPrintSupport( p->dd, bCube ); printf( "\n" ); -} - - // derive new function -// bFunc = Cudd_bddAndAbstract( p->dd, pPart1->bFunc, pPart2->bFunc, bCube ); Cudd_Ref( bFunc ); -/* - bFunc = Cudd_bddAndAbstractLimit( p->dd, pPart1->bFunc, pPart2->bFunc, bCube, Limit ); - if ( bFunc == NULL ) - { - int RetValue; - Cudd_RecursiveDeref( p->dd, bCube ); - if ( pPart1->nSize < pPart2->nSize ) - RetValue = Llb_NonlinQuantify1( p, pPart1, 1 ); - else - RetValue = Llb_NonlinQuantify1( p, pPart2, 1 ); - if ( RetValue ) - Limit = Limit + 1000; - Llb_NonlinQuantify2( p, pPart1, pPart2, Limit, TimeOut ); - return 0; - } - Cudd_Ref( bFunc ); -*/ - -// bFunc = Extra_bddAndAbstractTime( p->dd, pPart1->bFunc, pPart2->bFunc, bCube, TimeOut ); - bFunc = Cudd_bddAndAbstract( p->dd, pPart1->bFunc, pPart2->bFunc, bCube ); - if ( bFunc == NULL ) - { - Cudd_RecursiveDeref( p->dd, bCube ); - return 0; - } - Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( p->dd, bCube ); - - // create new partition - pTemp = p->pParts[p->iPartFree] = ABC_CALLOC( Llb_Prt_t, 1 ); - pTemp->iPart = p->iPartFree++; - pTemp->nSize = Cudd_DagSize(bFunc); - pTemp->bFunc = bFunc; - pTemp->vVars = Vec_IntAlloc( 8 ); - // update variables - Llb_PartForEachVar( p, pPart1, pVar, i ) - { - RetValue = Vec_IntRemove( pVar->vParts, pPart1->iPart ); - assert( RetValue ); - pVar->nScore -= pPart1->nSize; - } - // update variables - Llb_PartForEachVar( p, pPart2, pVar, i ) - { - RetValue = Vec_IntRemove( pVar->vParts, pPart2->iPart ); - assert( RetValue ); - pVar->nScore -= pPart2->nSize; - } - // add variables to the new partition - nSuppSize = 0; - Extra_SupportArray( p->dd, bFunc, p->pSupp ); - for ( i = 0; i < p->nVars; i++ ) - { - nSuppSize += p->pSupp[i]; - if ( p->pSupp[i] && p->pVars2Q[i] ) - { - pVar = Llb_MgrVar( p, i ); - pVar->nScore += pTemp->nSize; - Vec_IntPush( pVar->vParts, pTemp->iPart ); - Vec_IntPush( pTemp->vVars, i ); - } - } - p->nSuppMax = ABC_MAX( p->nSuppMax, nSuppSize ); - // remove variables and collect partitions with singleton variables - vSingles = Vec_PtrAlloc( 0 ); - Llb_PartForEachVar( p, pPart1, pVar, i ) - { - if ( Vec_IntSize(pVar->vParts) == 0 ) - Llb_NonlinRemoveVar( p, pVar ); - else if ( Vec_IntSize(pVar->vParts) == 1 ) - { - if ( fVerbose ) - printf( "Adding partition %d because of var %d.\n", - Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar ); - Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); - } - } - Llb_PartForEachVar( p, pPart2, pVar, i ) - { - if ( pVar == NULL ) - continue; - if ( Vec_IntSize(pVar->vParts) == 0 ) - Llb_NonlinRemoveVar( p, pVar ); - else if ( Vec_IntSize(pVar->vParts) == 1 ) - { - if ( fVerbose ) - printf( "Adding partition %d because of var %d.\n", - Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar ); - Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); - } - } - // remove partitions - Llb_NonlinRemovePart( p, pPart1 ); - Llb_NonlinRemovePart( p, pPart2 ); - // remove other variables -if ( fVerbose ) -Llb_NonlinPrint( p ); - Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i ) - { -if ( fVerbose ) -printf( "Updating partitiong %d with singlton vars.\n", pTemp->iPart ); - Llb_NonlinQuantify1( p, pTemp, 0 ); - } -if ( fVerbose ) -Llb_NonlinPrint( p ); - Vec_PtrFree( vSingles ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Computes volume of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_NonlinCutNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) -{ - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - return; - Aig_ObjSetTravIdCurrent(p, pObj); - if ( Saig_ObjIsLi(p, pObj) ) - { - Llb_NonlinCutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); - return; - } - if ( Aig_ObjIsConst1(pObj) ) - return; - assert( Aig_ObjIsNode(pObj) ); - Llb_NonlinCutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); - Llb_NonlinCutNodes_rec(p, Aig_ObjFanin1(pObj), vNodes); - Vec_PtrPush( vNodes, pObj ); -} - -/**Function************************************************************* - - Synopsis [Computes volume of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_NonlinCutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i; - // mark the lower cut with the traversal ID - Aig_ManIncrementTravId(p); - Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) - Aig_ObjSetTravIdCurrent( p, pObj ); - // count the upper cut - vNodes = Vec_PtrAlloc( 100 ); - Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) - Llb_NonlinCutNodes_rec( p, pObj, vNodes ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Returns array of BDDs for the roots in terms of the leaves.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_NonlinBuildBdds( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, DdManager * dd, int TimeOut ) -{ - Vec_Ptr_t * vNodes, * vResult; - Aig_Obj_t * pObj; - DdNode * bBdd0, * bBdd1, * bProd; - int i, k; - - Aig_ManConst1(p)->pData = Cudd_ReadOne( dd ); - Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) - pObj->pData = Cudd_bddIthVar( dd, Aig_ObjId(pObj) ); - - vNodes = Llb_NonlinCutNodes( p, vLower, vUpper ); - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) - { - bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); -// pObj->pData = Extra_bddAndTime( dd, bBdd0, bBdd1, TimeOut ); - pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); - if ( pObj->pData == NULL ) - { - Vec_PtrForEachEntryStop( Aig_Obj_t *, vNodes, pObj, k, i ) - if ( pObj->pData ) - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); - Vec_PtrFree( vNodes ); - return NULL; - } - Cudd_Ref( (DdNode *)pObj->pData ); - } - - vResult = Vec_PtrAlloc( 100 ); - Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) - { - if ( Aig_ObjIsNode(pObj) ) - { - bProd = Cudd_bddXnor( dd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)), (DdNode *)pObj->pData ); Cudd_Ref( bProd ); - } - else - { - assert( Saig_ObjIsLi(p, pObj) ); - bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bProd = Cudd_bddXnor( dd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)), bBdd0 ); Cudd_Ref( bProd ); - } - Vec_PtrPush( vResult, bProd ); - } - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); - - Vec_PtrFree( vNodes ); - return vResult; -} - -/**Function************************************************************* - - Synopsis [Starts non-linear quantification scheduling.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_NonlinAddPair( Llb_Mgr_t * p, DdNode * bFunc, int iPart, int iVar ) -{ - if ( p->pVars[iVar] == NULL ) - { - p->pVars[iVar] = ABC_CALLOC( Llb_Var_t, 1 ); - p->pVars[iVar]->iVar = iVar; - p->pVars[iVar]->nScore = 0; - p->pVars[iVar]->vParts = Vec_IntAlloc( 8 ); - } - Vec_IntPush( p->pVars[iVar]->vParts, iPart ); - Vec_IntPush( p->pParts[iPart]->vVars, iVar ); -} - -/**Function************************************************************* - - Synopsis [Starts non-linear quantification scheduling.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_NonlinAddPartition( Llb_Mgr_t * p, int i, DdNode * bFunc ) -{ - int k, nSuppSize; - assert( !Cudd_IsConstant(bFunc) ); - // create partition - p->pParts[i] = ABC_CALLOC( Llb_Prt_t, 1 ); - p->pParts[i]->iPart = i; - p->pParts[i]->bFunc = bFunc; - p->pParts[i]->vVars = Vec_IntAlloc( 8 ); - // add support dependencies - nSuppSize = 0; - Extra_SupportArray( p->dd, bFunc, p->pSupp ); - for ( k = 0; k < p->nVars; k++ ) - { - nSuppSize += p->pSupp[k]; - if ( p->pSupp[k] && p->pVars2Q[k] ) - Llb_NonlinAddPair( p, bFunc, i, k ); - } - p->nSuppMax = ABC_MAX( p->nSuppMax, nSuppSize ); -} - -/**Function************************************************************* - - Synopsis [Starts non-linear quantification scheduling.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_NonlinStart( Llb_Mgr_t * p, int TimeOut ) -{ - Vec_Ptr_t * vRootBdds; - DdNode * bFunc; - int i; - // create and collect BDDs - vRootBdds = Llb_NonlinBuildBdds( p->pAig, p->vLeaves, p->vRoots, p->dd, TimeOut ); // come referenced - if ( vRootBdds == NULL ) - return 0; - // add pairs (refs are consumed inside) - Vec_PtrForEachEntry( DdNode *, vRootBdds, bFunc, i ) - Llb_NonlinAddPartition( p, i, bFunc ); - Vec_PtrFree( vRootBdds ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Checks that each var appears in at least one partition.] - - Description [] - - SideEffects [] - - SeeAlso [] -**********************************************************************/ -void Llb_NonlinCheckVars( Llb_Mgr_t * p ) -{ - Llb_Var_t * pVar; - int i; - Llb_MgrForEachVar( p, pVar, i ) - assert( Vec_IntSize(pVar->vParts) > 1 ); -} - -/**Function************************************************************* - - Synopsis [Find next partition to quantify] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_NonlinNextPartitions( Llb_Mgr_t * p, Llb_Prt_t ** ppPart1, Llb_Prt_t ** ppPart2 ) -{ - Llb_Var_t * pVar, * pVarBest = NULL; - Llb_Prt_t * pPart, * pPart1Best = NULL, * pPart2Best = NULL; - int i; - Llb_NonlinCheckVars( p ); - // find variable with minimum score - Llb_MgrForEachVar( p, pVar, i ) - if ( pVarBest == NULL || pVarBest->nScore > pVar->nScore ) - pVarBest = pVar; - if ( pVarBest == NULL ) - return 0; - // find two partitions with minimum size - Llb_VarForEachPart( p, pVarBest, pPart, i ) - { - if ( pPart1Best == NULL ) - pPart1Best = pPart; - else if ( pPart2Best == NULL ) - pPart2Best = pPart; - else if ( pPart1Best->nSize > pPart->nSize || pPart2Best->nSize > pPart->nSize ) - { - if ( pPart1Best->nSize > pPart2Best->nSize ) - pPart1Best = pPart; - else - pPart2Best = pPart; - } - } - *ppPart1 = pPart1Best; - *ppPart2 = pPart2Best; - return 1; -} - -/**Function************************************************************* - - Synopsis [Reorders BDDs in the working manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_NonlinReorder( DdManager * dd, int fTwice, int fVerbose ) -{ - int clk = clock(); - if ( fVerbose ) - Abc_Print( 1, "Reordering... Before =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); - Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); - if ( fVerbose ) - Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); - if ( fTwice ) - { - Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); - if ( fVerbose ) - Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); - } - if ( fVerbose ) - Abc_PrintTime( 1, "Time", clock() - clk ); -} - -/**Function************************************************************* - - Synopsis [Recomputes scores after variable reordering.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_NonlinRecomputeScores( Llb_Mgr_t * p ) -{ - Llb_Prt_t * pPart; - Llb_Var_t * pVar; - int i, k; - Llb_MgrForEachPart( p, pPart, i ) - pPart->nSize = Cudd_DagSize(pPart->bFunc); - Llb_MgrForEachVar( p, pVar, i ) - { - pVar->nScore = 0; - Llb_VarForEachPart( p, pVar, pPart, k ) - pVar->nScore += pPart->nSize; - } -} - -/**Function************************************************************* - - Synopsis [Recomputes scores after variable reordering.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_NonlinVerifyScores( Llb_Mgr_t * p ) -{ - Llb_Prt_t * pPart; - Llb_Var_t * pVar; - int i, k, nScore; - Llb_MgrForEachPart( p, pPart, i ) - assert( pPart->nSize == Cudd_DagSize(pPart->bFunc) ); - Llb_MgrForEachVar( p, pVar, i ) - { - nScore = 0; - Llb_VarForEachPart( p, pVar, pPart, k ) - nScore += pPart->nSize; - assert( nScore == pVar->nScore ); - } -} - -/**Function************************************************************* - - Synopsis [Starts non-linear quantification scheduling.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Mgr_t * Llb_NonlinAlloc( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, DdManager * dd ) -{ - Llb_Mgr_t * p; - p = ABC_CALLOC( Llb_Mgr_t, 1 ); - p->pAig = pAig; - p->vLeaves = vLeaves; - p->vRoots = vRoots; - p->dd = dd; - p->pVars2Q = pVars2Q; - p->nVars = Cudd_ReadSize(dd); - p->iPartFree = Vec_PtrSize(vRoots); - p->pVars = ABC_CALLOC( Llb_Var_t *, p->nVars ); - p->pParts = ABC_CALLOC( Llb_Prt_t *, 2 * p->iPartFree + 2 ); - p->pSupp = ABC_ALLOC( int, Cudd_ReadSize(dd) ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops non-linear quantification scheduling.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_NonlinFree( Llb_Mgr_t * p ) -{ - Llb_Prt_t * pPart; - Llb_Var_t * pVar; - int i; - Llb_MgrForEachVar( p, pVar, i ) - Llb_NonlinRemoveVar( p, pVar ); - Llb_MgrForEachPart( p, pPart, i ) - Llb_NonlinRemovePart( p, pPart ); - ABC_FREE( p->pVars ); - ABC_FREE( p->pParts ); - ABC_FREE( p->pSupp ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Performs image computation.] - - Description [Computes image of BDDs (vFuncs).] - - SideEffects [BDDs in vFuncs are derefed inside. The result is refed.] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_NonlinImage( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, - DdManager * dd, DdNode * bCurrent, int fReorder, int fVerbose, int * pOrder, int Limit, int TimeOut ) -{ - Llb_Prt_t * pPart, * pPart1, * pPart2; - Llb_Mgr_t * p; - DdNode * bFunc, * bTemp; - int i, nReorders, timeInside; - int clk = clock(), clk2; - // start the manager - clk2 = clock(); - p = Llb_NonlinAlloc( pAig, vLeaves, vRoots, pVars2Q, dd ); - if ( !Llb_NonlinStart( p, TimeOut ) ) - { - Llb_NonlinFree( p ); - return NULL; - } - // add partition - Llb_NonlinAddPartition( p, p->iPartFree++, bCurrent ); - // remove singles - Llb_MgrForEachPart( p, pPart, i ) - if ( Llb_NonlinHasSingletonVars(p, pPart) ) - Llb_NonlinQuantify1( p, pPart, 0 ); - timeBuild += clock() - clk2; - timeInside = clock() - clk2; - // compute scores - Llb_NonlinRecomputeScores( p ); - // save permutation - if ( pOrder ) - memcpy( pOrder, dd->invperm, sizeof(int) * dd->size ); - // iteratively quantify variables - while ( Llb_NonlinNextPartitions(p, &pPart1, &pPart2) ) - { - clk2 = clock(); - nReorders = Cudd_ReadReorderings(dd); - if ( !Llb_NonlinQuantify2( p, pPart1, pPart2, Limit, TimeOut ) ) - { - Llb_NonlinFree( p ); - return NULL; - } - timeAndEx += clock() - clk2; - timeInside += clock() - clk2; - if ( nReorders < Cudd_ReadReorderings(dd) ) - Llb_NonlinRecomputeScores( p ); -// else -// Llb_NonlinVerifyScores( p ); - } - // load partitions - bFunc = Cudd_ReadOne(p->dd); Cudd_Ref( bFunc ); - Llb_MgrForEachPart( p, pPart, i ) - { - bFunc = Cudd_bddAnd( p->dd, bTemp = bFunc, pPart->bFunc ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - nSuppMax = p->nSuppMax; - Llb_NonlinFree( p ); - // reorder variables - if ( fReorder ) - Llb_NonlinReorder( dd, 0, fVerbose ); - timeOther += clock() - clk - timeInside; - // return - Cudd_Deref( bFunc ); - return bFunc; -} - - - -static Llb_Mgr_t * p = NULL; - -/**Function************************************************************* - - Synopsis [Starts image computation manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdManager * Llb_NonlinImageStart( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, int * pOrder, int fFirst, int TimeTarget ) -{ - DdManager * dd; - int clk = clock(); - assert( p == NULL ); - // start a new manager (disable reordering) - dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - dd->TimeStop = TimeTarget; - Cudd_ShuffleHeap( dd, pOrder ); -// if ( fFirst ) - Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - // start the manager - p = Llb_NonlinAlloc( pAig, vLeaves, vRoots, pVars2Q, dd ); - if ( !Llb_NonlinStart( p, 0 ) ) - { - Llb_NonlinFree( p ); - p = NULL; - return NULL; - } - timeBuild += clock() - clk; -// if ( !fFirst ) -// Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - return dd; -} - -/**Function************************************************************* - - Synopsis [Performs image computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_NonlinImageCompute( DdNode * bCurrent, int fReorder, int fDrop, int fVerbose, int * pOrder ) -{ - Llb_Prt_t * pPart, * pPart1, * pPart2; - DdNode * bFunc, * bTemp; - int i, nReorders, timeInside = 0; - int clk = clock(), clk2; - - // add partition - Llb_NonlinAddPartition( p, p->iPartFree++, bCurrent ); - // remove singles - Llb_MgrForEachPart( p, pPart, i ) - if ( Llb_NonlinHasSingletonVars(p, pPart) ) - Llb_NonlinQuantify1( p, pPart, 0 ); - // reorder - if ( fReorder ) - Llb_NonlinReorder( p->dd, 0, 0 ); - // save permutation - memcpy( pOrder, p->dd->invperm, sizeof(int) * p->dd->size ); - - // compute scores - Llb_NonlinRecomputeScores( p ); - // iteratively quantify variables - while ( Llb_NonlinNextPartitions(p, &pPart1, &pPart2) ) - { - clk2 = clock(); - nReorders = Cudd_ReadReorderings(p->dd); - if ( !Llb_NonlinQuantify2( p, pPart1, pPart2, 0, 0 ) ) - { - Llb_NonlinFree( p ); - return NULL; - } - timeAndEx += clock() - clk2; - timeInside += clock() - clk2; - if ( nReorders < Cudd_ReadReorderings(p->dd) ) - Llb_NonlinRecomputeScores( p ); -// else -// Llb_NonlinVerifyScores( p ); - } - // load partitions - bFunc = Cudd_ReadOne(p->dd); Cudd_Ref( bFunc ); - Llb_MgrForEachPart( p, pPart, i ) - { - bFunc = Cudd_bddAnd( p->dd, bTemp = bFunc, pPart->bFunc ); - if ( bFunc == NULL ) - { - Cudd_RecursiveDeref( p->dd, bTemp ); - Llb_NonlinFree( p ); - return NULL; - } - Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - nSuppMax = p->nSuppMax; - // reorder variables -// if ( fReorder ) -// Llb_NonlinReorder( p->dd, 0, fVerbose ); - // save permutation -// memcpy( pOrder, p->dd->invperm, sizeof(int) * Cudd_ReadSize(p->dd) ); - - timeOther += clock() - clk - timeInside; - // return - Cudd_Deref( bFunc ); - return bFunc; -} - -/**Function************************************************************* - - Synopsis [Quits image computation manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_NonlinImageQuit() -{ - DdManager * dd; - if ( p == NULL ) - return; - dd = p->dd; - Llb_NonlinFree( p ); - if ( dd->bFunc ) - Cudd_RecursiveDeref( dd, dd->bFunc ); - Extra_StopManager( dd ); -// Cudd_Quit ( dd ); - p = NULL; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llb3Nonlin.c b/src/aig/llb/llb3Nonlin.c deleted file mode 100644 index e20a1541..00000000 --- a/src/aig/llb/llb3Nonlin.c +++ /dev/null @@ -1,871 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb2Nonlin.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Non-linear quantification scheduling.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb2Nonlin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Llb_Mnn_t_ Llb_Mnn_t; -struct Llb_Mnn_t_ -{ - Aig_Man_t * pInit; // AIG manager - Aig_Man_t * pAig; // AIG manager - Gia_ParLlb_t * pPars; // parameters - - DdManager * dd; // BDD manager - DdManager * ddG; // BDD manager - DdManager * ddR; // BDD manager - Vec_Ptr_t * vRings; // onion rings in ddR - - Vec_Ptr_t * vLeaves; - Vec_Ptr_t * vRoots; - int * pVars2Q; - int * pOrderL; - int * pOrderL2; - int * pOrderG; - - Vec_Int_t * vCs2Glo; // cur state variables into global variables - Vec_Int_t * vNs2Glo; // next state variables into global variables - Vec_Int_t * vGlo2Cs; // global variables into cur state variables - Vec_Int_t * vGlo2Ns; // global variables into next state variables - - int ddLocReos; - int ddLocGrbs; - - int timeImage; - int timeTran1; - int timeTran2; - int timeGloba; - int timeOther; - int timeTotal; - int timeReo; - int timeReoG; - -}; - -extern int timeBuild, timeAndEx, timeOther; -extern int nSuppMax; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Finds variable whose 0-cofactor is the smallest.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_NonlinFindBestVar( DdManager * dd, DdNode * bFunc, Aig_Man_t * pAig ) -{ - int fVerbose = 0; - Aig_Obj_t * pObj; - DdNode * bCof, * bVar; - int i, iVar, iVarBest = -1, iValue, iValueBest = ABC_INFINITY, Size0Best = -1; - int Size, Size0, Size1; - int clk = clock(); - Size = Cudd_DagSize(bFunc); -// printf( "Original = %6d. SuppSize = %3d. Vars = %3d.\n", -// Size = Cudd_DagSize(bFunc), Cudd_SupportSize(dd, bFunc), Aig_ManRegNum(pAig) ); - Saig_ManForEachLo( pAig, pObj, i ) - { - iVar = Aig_ObjId(pObj); - -if ( fVerbose ) -printf( "Var =%3d : ", iVar ); - bVar = Cudd_bddIthVar(dd, iVar); - - bCof = Cudd_bddAnd( dd, bFunc, Cudd_Not(bVar) ); Cudd_Ref( bCof ); - Size0 = Cudd_DagSize(bCof); -if ( fVerbose ) -printf( "Supp0 =%3d ", Cudd_SupportSize(dd, bCof) ); -if ( fVerbose ) -printf( "Size0 =%6d ", Size0 ); - Cudd_RecursiveDeref( dd, bCof ); - - bCof = Cudd_bddAnd( dd, bFunc, bVar ); Cudd_Ref( bCof ); - Size1 = Cudd_DagSize(bCof); -if ( fVerbose ) -printf( "Supp1 =%3d ", Cudd_SupportSize(dd, bCof) ); -if ( fVerbose ) -printf( "Size1 =%6d ", Size1 ); - Cudd_RecursiveDeref( dd, bCof ); - - iValue = ABC_MAX(Size0, Size1) - ABC_MIN(Size0, Size1) + Size0 + Size1 - Size; -if ( fVerbose ) -printf( "D =%6d ", Size0 + Size1 - Size ); -if ( fVerbose ) -printf( "B =%6d ", ABC_MAX(Size0, Size1) - ABC_MIN(Size0, Size1) ); -if ( fVerbose ) -printf( "S =%6d\n", iValue ); - if ( Size0 > 1 && Size1 > 1 && iValueBest > iValue ) - { - iValueBest = iValue; - iVarBest = i; - Size0Best = Size0; - } - } - printf( "BestVar = %4d/%4d. Value =%6d. Orig =%6d. Size0 =%6d. ", - iVarBest, Aig_ObjId(Saig_ManLo(pAig,iVarBest)), iValueBest, Size, Size0Best ); - Abc_PrintTime( 1, "Time", clock() - clk ); - return iVarBest; -} - - -/**Function************************************************************* - - Synopsis [Finds variable whose 0-cofactor is the smallest.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_NonlinTrySubsetting( DdManager * dd, DdNode * bFunc ) -{ - DdNode * bNew; - printf( "Original = %6d. SuppSize = %3d. ", - Cudd_DagSize(bFunc), Cudd_SupportSize(dd, bFunc) ); - bNew = Cudd_SubsetHeavyBranch( dd, bFunc, Cudd_SupportSize(dd, bFunc), 1000 ); Cudd_Ref( bNew ); - printf( "Result = %6d. SuppSize = %3d.\n", - Cudd_DagSize(bNew), Cudd_SupportSize(dd, bNew) ); - Cudd_RecursiveDeref( dd, bNew ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_NonlinPrepareVarMap( Llb_Mnn_t * p ) -{ - Aig_Obj_t * pObjLi, * pObjLo, * pObj; - int i, iVarLi, iVarLo; - p->vCs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) ); - p->vNs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) ); - p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); - p->vGlo2Ns = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); - Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) - { - iVarLi = Aig_ObjId(pObjLi); - iVarLo = Aig_ObjId(pObjLo); - assert( iVarLi >= 0 && iVarLi < Aig_ManObjNumMax(p->pAig) ); - assert( iVarLo >= 0 && iVarLo < Aig_ManObjNumMax(p->pAig) ); - Vec_IntWriteEntry( p->vCs2Glo, iVarLo, i ); - Vec_IntWriteEntry( p->vNs2Glo, iVarLi, i ); - Vec_IntWriteEntry( p->vGlo2Cs, i, iVarLo ); - Vec_IntWriteEntry( p->vGlo2Ns, i, iVarLi ); - } - // add mapping of the PIs - Saig_ManForEachPi( p->pAig, pObj, i ) - { - Vec_IntWriteEntry( p->vCs2Glo, Aig_ObjId(pObj), Aig_ManRegNum(p->pAig)+i ); - Vec_IntWriteEntry( p->vNs2Glo, Aig_ObjId(pObj), Aig_ManRegNum(p->pAig)+i ); - } -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_NonlinComputeInitState( Aig_Man_t * pAig, DdManager * dd ) -{ - Aig_Obj_t * pObj; - DdNode * bRes, * bVar, * bTemp; - int i, iVar, TimeStop; - TimeStop = dd->TimeStop; dd->TimeStop = 0; - bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); - Saig_ManForEachLo( pAig, pObj, i ) - { - iVar = (Cudd_ReadSize(dd) == Aig_ManRegNum(pAig)) ? i : Aig_ObjId(pObj); - bVar = Cudd_bddIthVar( dd, iVar ); - bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bRes ); - dd->TimeStop = TimeStop; - return bRes; -} - - -/**Function************************************************************* - - Synopsis [Derives counter-example by backward reachability.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Cex_t * Llb_NonlinDeriveCex( Llb_Mnn_t * p ) -{ - Abc_Cex_t * pCex; - Aig_Obj_t * pObj; - Vec_Int_t * vVarsNs; - DdNode * bState, * bImage, * bOneCube, * bTemp, * bRing; - int i, v, RetValue, nPiOffset; - char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) ); - assert( Vec_PtrSize(p->vRings) > 0 ); - - p->dd->TimeStop = 0; - p->ddR->TimeStop = 0; - - // update quantifiable vars - memset( p->pVars2Q, 0, sizeof(int) * Cudd_ReadSize(p->dd) ); - vVarsNs = Vec_IntAlloc( Aig_ManRegNum(p->pAig) ); - Saig_ManForEachLi( p->pAig, pObj, i ) - { - p->pVars2Q[Aig_ObjId(pObj)] = 1; - Vec_IntPush( vVarsNs, Aig_ObjId(pObj) ); - } -/* - Saig_ManForEachLo( p->pAig, pObj, i ) - printf( "%d ", pObj->Id ); - printf( "\n" ); - Saig_ManForEachLi( p->pAig, pObj, i ) - printf( "%d(%d) ", pObj->Id, Aig_ObjFaninId0(pObj) ); - printf( "\n" ); -*/ - // allocate room for the counter-example - pCex = Abc_CexAlloc( Saig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Vec_PtrSize(p->vRings) ); - pCex->iFrame = Vec_PtrSize(p->vRings) - 1; - pCex->iPo = -1; - - // get the last cube - bOneCube = Cudd_bddIntersect( p->ddR, (DdNode *)Vec_PtrEntryLast(p->vRings), p->ddR->bFunc ); Cudd_Ref( bOneCube ); - RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); - Cudd_RecursiveDeref( p->ddR, bOneCube ); - assert( RetValue ); - - // write PIs of counter-example - nPiOffset = Saig_ManRegNum(p->pAig) + Saig_ManPiNum(p->pAig) * (Vec_PtrSize(p->vRings) - 1); - Saig_ManForEachPi( p->pAig, pObj, i ) - if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) - Aig_InfoSetBit( pCex->pData, nPiOffset + i ); - - // write state in terms of NS variables - if ( Vec_PtrSize(p->vRings) > 1 ) - { - bState = Llb_CoreComputeCube( p->dd, vVarsNs, 1, pValues ); Cudd_Ref( bState ); - } - // perform backward analysis - Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v ) - { - if ( v == Vec_PtrSize(p->vRings) - 1 ) - continue; -//Extra_bddPrintSupport( p->dd, bState ); printf( "\n" ); -//Extra_bddPrintSupport( p->dd, bRing ); printf( "\n" ); - // compute the next states - bImage = Llb_NonlinImage( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->dd, bState, - p->pPars->fReorder, p->pPars->fVeryVerbose, NULL, ABC_INFINITY, ABC_INFINITY ); // consumed reference - assert( bImage != NULL ); - Cudd_Ref( bImage ); -//Extra_bddPrintSupport( p->dd, bImage ); printf( "\n" ); - - // move reached states into ring manager - bImage = Extra_TransferPermute( p->dd, p->ddR, bTemp = bImage, Vec_IntArray(p->vCs2Glo) ); Cudd_Ref( bImage ); - Cudd_RecursiveDeref( p->dd, bTemp ); - - // intersect with the previous set - bOneCube = Cudd_bddIntersect( p->ddR, bImage, bRing ); Cudd_Ref( bOneCube ); - Cudd_RecursiveDeref( p->ddR, bImage ); - - // find any assignment of the BDD - RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); - Cudd_RecursiveDeref( p->ddR, bOneCube ); - assert( RetValue ); - - // write PIs of counter-example - nPiOffset -= Saig_ManPiNum(p->pAig); - Saig_ManForEachPi( p->pAig, pObj, i ) - if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) - Aig_InfoSetBit( pCex->pData, nPiOffset + i ); - - // check that we get the init state - if ( v == 0 ) - { - Saig_ManForEachLo( p->pAig, pObj, i ) - assert( pValues[i] == 0 ); - break; - } - - // write state in terms of NS variables - bState = Llb_CoreComputeCube( p->dd, vVarsNs, 1, pValues ); Cudd_Ref( bState ); - } - assert( nPiOffset == Saig_ManRegNum(p->pAig) ); - // update the output number -//Abc_CexPrint( pCex ); - RetValue = Saig_ManFindFailedPoCex( p->pInit, pCex ); - assert( RetValue >= 0 && RetValue < Saig_ManPoNum(p->pInit) ); // invalid CEX!!! - pCex->iPo = RetValue; - // cleanup - ABC_FREE( pValues ); - Vec_IntFree( vVarsNs ); - return pCex; -} - - -/**Function************************************************************* - - Synopsis [Perform reachability with hints.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_NonlinReoHook( DdManager * dd, char * Type, void * Method ) -{ - Aig_Man_t * pAig = (Aig_Man_t *)dd->bFunc; - Aig_Obj_t * pObj; - int i; - printf( "Order: " ); - for ( i = 0; i < Cudd_ReadSize(dd); i++ ) - { - pObj = Aig_ManObj( pAig, i ); - if ( pObj == NULL ) - continue; - if ( Saig_ObjIsPi(pAig, pObj) ) - printf( "pi" ); - else if ( Saig_ObjIsLo(pAig, pObj) ) - printf( "lo" ); - else if ( Saig_ObjIsPo(pAig, pObj) ) - printf( "po" ); - else if ( Saig_ObjIsLi(pAig, pObj) ) - printf( "li" ); - else continue; - printf( "%d=%d ", i, dd->perm[i] ); - } - printf( "\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Perform reachability with hints.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_NonlinCompPerms( DdManager * dd, int * pVar2Lev ) -{ - DdSubtable * pSubt; - int i, Sum = 0, Entry; - for ( i = 0; i < dd->size; i++ ) - { - pSubt = &(dd->subtables[dd->perm[i]]); - if ( pSubt->keys == pSubt->dead + 1 ) - continue; - Entry = ABC_MAX(dd->perm[i], pVar2Lev[i]) - ABC_MIN(dd->perm[i], pVar2Lev[i]); - Sum += Entry; -//printf( "%d-%d(%d) ", dd->perm[i], pV2L[i], Entry ); - } - return Sum; -} - -/**Function************************************************************* - - Synopsis [Perform reachability with hints.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_NonlinReachability( Llb_Mnn_t * p ) -{ - DdNode * bTemp, * bNext; - int nIters, nBddSize0, nBddSize, NumCmp, Limit = p->pPars->nBddMax; - int clk2, clk3, clk = clock(); - assert( Aig_ManRegNum(p->pAig) > 0 ); - - // compute time to stop - p->pPars->TimeTarget = p->pPars->TimeLimit ? time(NULL) + p->pPars->TimeLimit : 0; - - // set the stop time parameter - p->dd->TimeStop = p->pPars->TimeTarget; - p->ddG->TimeStop = p->pPars->TimeTarget; - p->ddR->TimeStop = p->pPars->TimeTarget; - - // set reordering hooks - assert( p->dd->bFunc == NULL ); -// p->dd->bFunc = (DdNode *)p->pAig; -// Cudd_AddHook( p->dd, Llb_NonlinReoHook, CUDD_POST_REORDERING_HOOK ); - - // create bad state in the ring manager - p->ddR->bFunc = Llb_BddComputeBad( p->pInit, p->ddR, p->pPars->TimeTarget ); - if ( p->ddR->bFunc == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = -1; - return -1; - } - Cudd_Ref( p->ddR->bFunc ); - // compute the starting set of states - Cudd_Quit( p->dd ); - p->dd = Llb_NonlinImageStart( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->pOrderL, 1, p->pPars->TimeTarget ); - if ( p->dd == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = -1; - return -1; - } - p->dd->bFunc = Llb_NonlinComputeInitState( p->pAig, p->dd ); Cudd_Ref( p->dd->bFunc ); // current - p->ddG->bFunc = Llb_NonlinComputeInitState( p->pAig, p->ddG ); Cudd_Ref( p->ddG->bFunc ); // reached - p->ddG->bFunc2 = Llb_NonlinComputeInitState( p->pAig, p->ddG ); Cudd_Ref( p->ddG->bFunc2 ); // frontier - for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ ) - { - // check the runtime limit - clk2 = clock(); - if ( p->pPars->TimeLimit && time(NULL) > p->pPars->TimeTarget ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Llb_NonlinImageQuit(); - return -1; - } - - // save the onion ring - bTemp = Extra_TransferPermute( p->dd, p->ddR, p->dd->bFunc, Vec_IntArray(p->vCs2Glo) ); - if ( bTemp == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during ring transfer.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Llb_NonlinImageQuit(); - return -1; - } - Cudd_Ref( bTemp ); - Vec_PtrPush( p->vRings, bTemp ); - - // check it for bad states - if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->ddR, bTemp, Cudd_Not(p->ddR->bFunc) ) ) - { - assert( p->pInit->pSeqModel == NULL ); - if ( !p->pPars->fBackward ) - p->pInit->pSeqModel = Llb_NonlinDeriveCex( p ); - if ( !p->pPars->fSilent ) - { - if ( !p->pPars->fBackward ) - printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump a witness). ", p->pInit->pSeqModel->iPo, nIters ); - else - printf( "Output ??? was asserted in frame %d (counter-example is not produced). ", nIters ); - Abc_PrintTime( 1, "Time", clock() - clk ); - } - p->pPars->iFrame = nIters - 1; - Llb_NonlinImageQuit(); - return 0; - } - - // compute the next states - clk3 = clock(); - nBddSize0 = Cudd_DagSize( p->dd->bFunc ); - bNext = Llb_NonlinImageCompute( p->dd->bFunc, p->pPars->fReorder, 0, 1, p->pOrderL ); // consumes ref -// bNext = Llb_NonlinImage( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->dd, bCurrent, -// p->pPars->fReorder, p->pPars->fVeryVerbose, NULL, ABC_INFINITY, p->pPars->TimeTarget ); - if ( bNext == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation in quantification.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Llb_NonlinImageQuit(); - return -1; - } - Cudd_Ref( bNext ); - nBddSize = Cudd_DagSize( bNext ); - p->timeImage += clock() - clk3; - - - // transfer to the state manager - clk3 = clock(); - Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc2 ); - p->ddG->bFunc2 = Extra_TransferPermute( p->dd, p->ddG, bNext, Vec_IntArray(p->vNs2Glo) ); -// p->ddG->bFunc2 = Extra_bddAndPermute( p->ddG, Cudd_Not(p->ddG->bFunc), p->dd, bNext, Vec_IntArray(p->vNs2Glo) ); - if ( p->ddG->bFunc2 == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->dd, bNext ); - Llb_NonlinImageQuit(); - return -1; - } - Cudd_Ref( p->ddG->bFunc2 ); - Cudd_RecursiveDeref( p->dd, bNext ); - p->timeTran1 += clock() - clk3; - - // save permutation - NumCmp = Llb_NonlinCompPerms( p->dd, p->pOrderL2 ); - // save order before image computation - memcpy( p->pOrderL2, p->dd->perm, sizeof(int) * p->dd->size ); - // update the image computation manager - p->timeReo += Cudd_ReadReorderingTime(p->dd); - p->ddLocReos += Cudd_ReadReorderings(p->dd); - p->ddLocGrbs += Cudd_ReadGarbageCollections(p->dd); - Llb_NonlinImageQuit(); - p->dd = Llb_NonlinImageStart( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->pOrderL, 0, p->pPars->TimeTarget ); - if ( p->dd == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - return -1; - } - //Extra_TestAndPerm( p->ddG, Cudd_Not(p->ddG->bFunc), p->ddG->bFunc2 ); - - // derive new states - clk3 = clock(); - p->ddG->bFunc2 = Cudd_bddAnd( p->ddG, bTemp = p->ddG->bFunc2, Cudd_Not(p->ddG->bFunc) ); - if ( p->ddG->bFunc2 == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->ddG, bTemp ); - Llb_NonlinImageQuit(); - return -1; - } - Cudd_Ref( p->ddG->bFunc2 ); - Cudd_RecursiveDeref( p->ddG, bTemp ); - p->timeGloba += clock() - clk3; - - if ( Cudd_IsConstant(p->ddG->bFunc2) ) - break; - // add to the reached set - clk3 = clock(); - p->ddG->bFunc = Cudd_bddOr( p->ddG, bTemp = p->ddG->bFunc, p->ddG->bFunc2 ); - if ( p->ddG->bFunc == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->ddG, bTemp ); - Llb_NonlinImageQuit(); - return -1; - } - Cudd_Ref( p->ddG->bFunc ); - Cudd_RecursiveDeref( p->ddG, bTemp ); - p->timeGloba += clock() - clk3; - - // reset permutation -// RetValue = Cudd_CheckZeroRef( dd ); -// assert( RetValue == 0 ); -// Cudd_ShuffleHeap( dd, pOrderG ); - - // move new states to the working manager - clk3 = clock(); - p->dd->bFunc = Extra_TransferPermute( p->ddG, p->dd, p->ddG->bFunc2, Vec_IntArray(p->vGlo2Cs) ); - if ( p->dd->bFunc == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Llb_NonlinImageQuit(); - return -1; - } - Cudd_Ref( p->dd->bFunc ); - p->timeTran2 += clock() - clk3; - - // report the results - if ( p->pPars->fVerbose ) - { - printf( "I =%3d : ", nIters ); - printf( "Fr =%7d ", nBddSize0 ); - printf( "Im =%7d ", nBddSize ); - printf( "(%4d %4d) ", p->ddLocReos, p->ddLocGrbs ); - printf( "Rea =%6d ", Cudd_DagSize(p->ddG->bFunc) ); - printf( "(%4d %4d) ", Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) ); - printf( "S =%4d ", nSuppMax ); - printf( "cL =%5d ", NumCmp ); - printf( "cG =%5d ", Llb_NonlinCompPerms( p->ddG, p->pOrderG ) ); - Abc_PrintTime( 1, "T", clock() - clk2 ); - memcpy( p->pOrderG, p->ddG->perm, sizeof(int) * p->ddG->size ); - } -/* - if ( pPars->fVerbose ) - { - double nMints = Cudd_CountMinterm(ddG, bReached, Saig_ManRegNum(pAig) ); -// Extra_bddPrint( ddG, bReached );printf( "\n" ); - printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(pAig)) ); - fflush( stdout ); - } -*/ - if ( nIters == p->pPars->nIterMax - 1 ) - { - if ( !p->pPars->fSilent ) - printf( "Reached limit on the number of timeframes (%d).\n", p->pPars->nIterMax ); - p->pPars->iFrame = nIters; - Llb_NonlinImageQuit(); - return -1; - } - } - Llb_NonlinImageQuit(); - - // report the stats - if ( p->pPars->fVerbose ) - { - double nMints = Cudd_CountMinterm(p->ddG, p->ddG->bFunc, Saig_ManRegNum(p->pAig) ); - if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax ) - printf( "Reachability analysis is stopped after %d frames.\n", nIters ); - else - printf( "Reachability analysis completed after %d frames.\n", nIters ); - printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); - fflush( stdout ); - } - if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax ) - { - if ( !p->pPars->fSilent ) - printf( "Verified only for states reachable in %d frames. ", nIters ); - p->pPars->iFrame = p->pPars->nIterMax; - return -1; // undecided - } - // report - if ( !p->pPars->fSilent ) - printf( "The miter is proved unreachable after %d iterations. ", nIters ); - p->pPars->iFrame = nIters - 1; - Abc_PrintTime( 1, "Time", clock() - clk ); - return 1; // unreachable -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Mnn_t * Llb_MnnStart( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) -{ - Llb_Mnn_t * p; - Aig_Obj_t * pObj; - int i; - p = ABC_CALLOC( Llb_Mnn_t, 1 ); - p->pInit = pInit; - p->pAig = pAig; - p->pPars = pPars; - p->dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - p->ddG = Cudd_Init( Aig_ManRegNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - p->ddR = Cudd_Init( Aig_ManPiNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); - Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT ); - Cudd_AutodynEnable( p->ddR, CUDD_REORDER_SYMM_SIFT ); - p->vRings = Vec_PtrAlloc( 100 ); - // create leaves - p->vLeaves = Vec_PtrAlloc( Aig_ManPiNum(pAig) ); - Aig_ManForEachPi( pAig, pObj, i ) - Vec_PtrPush( p->vLeaves, pObj ); - // create roots - p->vRoots = Vec_PtrAlloc( Aig_ManPoNum(pAig) ); - Saig_ManForEachLi( pAig, pObj, i ) - Vec_PtrPush( p->vRoots, pObj ); - // variables to quantify - p->pOrderL = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); - p->pOrderL2= ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); - p->pOrderG = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); - p->pVars2Q = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); - Aig_ManForEachPi( pAig, pObj, i ) - p->pVars2Q[Aig_ObjId(pObj)] = 1; - for ( i = 0; i < Aig_ManObjNumMax(pAig); i++ ) - p->pOrderL[i] = p->pOrderL2[i] = p->pOrderG[i] = i; - Llb_NonlinPrepareVarMap( p ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MnnStop( Llb_Mnn_t * p ) -{ - DdNode * bTemp; - int i; - if ( p->pPars->fVerbose ) - { - p->timeOther = p->timeTotal - p->timeImage - p->timeTran1 - p->timeTran2 - p->timeGloba; - p->timeReoG = Cudd_ReadReorderingTime(p->ddG); - ABC_PRTP( "Image ", p->timeImage, p->timeTotal ); - ABC_PRTP( " build ", timeBuild, p->timeTotal ); - ABC_PRTP( " and-ex ", timeAndEx, p->timeTotal ); - ABC_PRTP( " other ", timeOther, p->timeTotal ); - ABC_PRTP( "Transfer1", p->timeTran1, p->timeTotal ); - ABC_PRTP( "Transfer2", p->timeTran2, p->timeTotal ); - ABC_PRTP( "Global ", p->timeGloba, p->timeTotal ); - ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); - ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); - ABC_PRTP( " reo ", p->timeReo, p->timeTotal ); - ABC_PRTP( " reoG ", p->timeReoG, p->timeTotal ); - } - if ( p->ddR->bFunc ) - Cudd_RecursiveDeref( p->ddR, p->ddR->bFunc ); - Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i ) - Cudd_RecursiveDeref( p->ddR, bTemp ); - Vec_PtrFree( p->vRings ); - if ( p->ddG->bFunc ) - Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc ); - if ( p->ddG->bFunc2 ) - Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc2 ); -// printf( "manager1\n" ); -// Extra_StopManager( p->dd ); -// printf( "manager2\n" ); - Extra_StopManager( p->ddG ); -// printf( "manager3\n" ); - Extra_StopManager( p->ddR ); - Vec_IntFreeP( &p->vCs2Glo ); - Vec_IntFreeP( &p->vNs2Glo ); - Vec_IntFreeP( &p->vGlo2Cs ); - Vec_IntFreeP( &p->vGlo2Ns ); - Vec_PtrFree( p->vLeaves ); - Vec_PtrFree( p->vRoots ); - ABC_FREE( p->pVars2Q ); - ABC_FREE( p->pOrderL ); - ABC_FREE( p->pOrderL2 ); - ABC_FREE( p->pOrderG ); - ABC_FREE( p ); -} - - -/**Function************************************************************* - - Synopsis [Finds balanced cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_NonlinExperiment( Aig_Man_t * pAig, int Num ) -{ - Llb_Mnn_t * pMnn; - Gia_ParLlb_t Pars, * pPars = &Pars; - Aig_Man_t * p; - int clk = clock(); - - Llb_ManSetDefaultParams( pPars ); - pPars->fVerbose = 1; - - p = Aig_ManDupFlopsOnly( pAig ); -//Aig_ManShow( p, 0, NULL ); - Aig_ManPrintStats( pAig ); - Aig_ManPrintStats( p ); - - pMnn = Llb_MnnStart( pAig, p, pPars ); - Llb_NonlinReachability( pMnn ); - pMnn->timeTotal = clock() - clk; - Llb_MnnStop( pMnn ); - - Aig_ManStop( p ); -} - -/**Function************************************************************* - - Synopsis [Finds balanced cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_NonlinCoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) -{ - Llb_Mnn_t * pMnn; - Aig_Man_t * p; - int RetValue = -1; - - p = Aig_ManDupFlopsOnly( pAig ); -//Aig_ManShow( p, 0, NULL ); - if ( pPars->fVerbose ) - Aig_ManPrintStats( pAig ); - if ( pPars->fVerbose ) - Aig_ManPrintStats( p ); - - if ( !pPars->fSkipReach ) - { - int clk = clock(); - pMnn = Llb_MnnStart( pAig, p, pPars ); - RetValue = Llb_NonlinReachability( pMnn ); - pMnn->timeTotal = clock() - clk; - Llb_MnnStop( pMnn ); - } - - Aig_ManStop( p ); - return RetValue; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llb4Cex.c b/src/aig/llb/llb4Cex.c deleted file mode 100644 index 4f06b8c6..00000000 --- a/src/aig/llb/llb4Cex.c +++ /dev/null @@ -1,320 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb2Cex.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Non-linear quantification scheduling.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb2Cex.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" -#include "cnf.h" -#include "satSolver.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Translates a sequence of states into a counter-example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Cex_t * Llb4_Nonlin4TransformCex( Aig_Man_t * pAig, Vec_Ptr_t * vStates, int iCexPo, int fVerbose ) -{ - Abc_Cex_t * pCex; - Cnf_Dat_t * pCnf; - Vec_Int_t * vAssumps; - sat_solver * pSat; - Aig_Obj_t * pObj; - unsigned * pNext, * pThis; - int i, k, iBit, status, nRegs, clk = clock(); -/* - Vec_PtrForEachEntry( unsigned *, vStates, pNext, i ) - { - printf( "%4d : ", i ); - Extra_PrintBinary( stdout, pNext, Aig_ManRegNum(pAig) ); - printf( "\n" ); - } -*/ - // derive SAT solver - nRegs = Aig_ManRegNum(pAig); pAig->nRegs = 0; - pCnf = Cnf_Derive( pAig, Aig_ManPoNum(pAig) ); - pAig->nRegs = nRegs; -// Cnf_DataTranformPolarity( pCnf, 0 ); - // convert into SAT solver - pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); - if ( pSat == NULL ) - { - printf( "Llb4_Nonlin4TransformCex(): Counter-example generation has failed.\n" ); - Cnf_DataFree( pCnf ); - return NULL; - } - // simplify the problem - status = sat_solver_simplify(pSat); - if ( status == 0 ) - { - printf( "Llb4_Nonlin4TransformCex(): SAT solver is invalid.\n" ); - sat_solver_delete( pSat ); - Cnf_DataFree( pCnf ); - return NULL; - } - // start the counter-example - pCex = Abc_CexAlloc( Saig_ManRegNum(pAig), Saig_ManPiNum(pAig), Vec_PtrSize(vStates) ); - pCex->iFrame = Vec_PtrSize(vStates)-1; - pCex->iPo = -1; - - // solve each time frame - iBit = Saig_ManRegNum(pAig); - pThis = (unsigned *)Vec_PtrEntry( vStates, 0 ); - vAssumps = Vec_IntAlloc( 2 * Aig_ManRegNum(pAig) ); - Vec_PtrForEachEntryStart( unsigned *, vStates, pNext, i, 1 ) - { - // create assumptions - Vec_IntClear( vAssumps ); - Saig_ManForEachLo( pAig, pObj, k ) - Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !Aig_InfoHasBit(pThis,k) ) ); - Saig_ManForEachLi( pAig, pObj, k ) - Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !Aig_InfoHasBit(pNext,k) ) ); - // solve SAT problem - status = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), - (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); - // if the problem is SAT, get the counterexample - if ( status != l_True ) - { - printf( "Llb4_Nonlin4TransformCex(): There is no transition between state %d and %d.\n", i-1, i ); - Vec_IntFree( vAssumps ); - sat_solver_delete( pSat ); - Cnf_DataFree( pCnf ); - ABC_FREE( pCex ); - return NULL; - } - // get the assignment of PIs - Saig_ManForEachPi( pAig, pObj, k ) - if ( sat_solver_var_value(pSat, pCnf->pVarNums[Aig_ObjId(pObj)]) ) - Aig_InfoSetBit( pCex->pData, iBit + k ); - // update the counter - iBit += Saig_ManPiNum(pAig); - pThis = pNext; - } - - // add the last frame when the property fails - Vec_IntClear( vAssumps ); - if ( iCexPo >= 0 ) - { - Saig_ManForEachPo( pAig, pObj, k ) - if ( k == iCexPo ) - Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 ) ); - } - else - { - Saig_ManForEachPo( pAig, pObj, k ) - Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 ) ); - } - - // add clause - status = sat_solver_addclause( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps) ); - if ( status == 0 ) - { - printf( "Llb4_Nonlin4TransformCex(): The SAT solver is unsat after adding last clause.\n" ); - Vec_IntFree( vAssumps ); - sat_solver_delete( pSat ); - Cnf_DataFree( pCnf ); - ABC_FREE( pCex ); - return NULL; - } - // create assumptions - Vec_IntClear( vAssumps ); - Saig_ManForEachLo( pAig, pObj, k ) - Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !Aig_InfoHasBit(pThis,k) ) ); - // solve the last frame - status = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), - (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); - if ( status != l_True ) - { - printf( "Llb4_Nonlin4TransformCex(): There is no last transition that makes the property fail.\n" ); - Vec_IntFree( vAssumps ); - sat_solver_delete( pSat ); - Cnf_DataFree( pCnf ); - ABC_FREE( pCex ); - return NULL; - } - // get the assignment of PIs - Saig_ManForEachPi( pAig, pObj, k ) - if ( sat_solver_var_value(pSat, pCnf->pVarNums[Aig_ObjId(pObj)]) ) - Aig_InfoSetBit( pCex->pData, iBit + k ); - iBit += Saig_ManPiNum(pAig); - assert( iBit == pCex->nBits ); - - // free the sat_solver - Vec_IntFree( vAssumps ); - sat_solver_delete( pSat ); - Cnf_DataFree( pCnf ); - - // verify counter-example - status = Saig_ManFindFailedPoCex( pAig, pCex ); - if ( status >= 0 && status < Saig_ManPoNum(pAig) ) - pCex->iPo = status; - else - { - printf( "Llb4_Nonlin4TransformCex(): Counter-example verification has FAILED.\n" ); - ABC_FREE( pCex ); - return NULL; - } - // report the results -// if ( fVerbose ) -// Abc_PrintTime( 1, "SAT-based cex generation time", clock() - clk ); - return pCex; -} - - -/**Function************************************************************* - - Synopsis [Resimulates the counter-example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb4_Nonlin4VerifyCex( Aig_Man_t * pAig, Abc_Cex_t * p ) -{ - Vec_Ptr_t * vStates; - Aig_Obj_t * pObj, * pObjRi, * pObjRo; - int i, k, iBit = 0; - // create storage for states - vStates = Vec_PtrAllocSimInfo( p->iFrame+1, Aig_BitWordNum(Aig_ManRegNum(pAig)) ); - Vec_PtrCleanSimInfo( vStates, 0, Aig_BitWordNum(Aig_ManRegNum(pAig)) ); - // verify counter-example - Aig_ManCleanMarkB(pAig); - Aig_ManConst1(pAig)->fMarkB = 1; - Saig_ManForEachLo( pAig, pObj, i ) - pObj->fMarkB = 0; //Aig_InfoHasBit(p->pData, iBit++); - // do not require equal flop count in the AIG and in the CEX - iBit = p->nRegs; - for ( i = 0; i <= p->iFrame; i++ ) - { - // save current state - Saig_ManForEachLo( pAig, pObj, k ) - if ( pObj->fMarkB ) - Aig_InfoSetBit( (unsigned *)Vec_PtrEntry(vStates, i), k ); - // compute new state - Saig_ManForEachPi( pAig, pObj, k ) - pObj->fMarkB = Aig_InfoHasBit(p->pData, iBit++); - Aig_ManForEachNode( pAig, pObj, k ) - pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) & - (Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj)); - Aig_ManForEachPo( pAig, pObj, k ) - pObj->fMarkB = Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj); - if ( i == p->iFrame ) - break; - Saig_ManForEachLiLo( pAig, pObjRi, pObjRo, k ) - pObjRo->fMarkB = pObjRi->fMarkB; - } -/* - { - unsigned * pNext; - Vec_PtrForEachEntry( unsigned *, vStates, pNext, i ) - { - printf( "%4d : ", i ); - Extra_PrintBinary( stdout, pNext, Aig_ManRegNum(pAig) ); - printf( "\n" ); - } - } -*/ - assert( iBit == p->nBits ); -// if ( Aig_ManPo(pAig, p->iPo)->fMarkB == 0 ) -// Vec_PtrFreeP( &vStates ); - for ( i = Saig_ManPoNum(pAig) - 1; i >= 0; i-- ) - { - if ( Aig_ManPo(pAig, i)->fMarkB ) - { - p->iPo = i; - break; - } - } - if ( i == -1 ) - Vec_PtrFreeP( &vStates ); - Aig_ManCleanMarkB(pAig); - return vStates; -} - -/**Function************************************************************* - - Synopsis [Translates a sequence of states into a counter-example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Cex_t * Llb4_Nonlin4NormalizeCex( Aig_Man_t * pAigOrg, Aig_Man_t * pAigRpm, Abc_Cex_t * pCexRpm ) -{ - Abc_Cex_t * pCexOrg; - Vec_Ptr_t * vStates; - // check parameters of the AIG - if ( Saig_ManRegNum(pAigOrg) != Saig_ManRegNum(pAigRpm) ) - { - printf( "Llb4_Nonlin4NormalizeCex(): The number of flops in the original and reparametrized AIGs do not agree.\n" ); - return NULL; - } -/* - if ( Saig_ManRegNum(pAigRpm) != pCexRpm->nRegs ) - { - printf( "Llb4_Nonlin4NormalizeCex(): The number of flops in the reparametrized AIG and in the CEX do not agree.\n" ); - return NULL; - } -*/ - if ( Saig_ManPiNum(pAigRpm) != pCexRpm->nPis ) - { - printf( "Llb4_Nonlin4NormalizeCex(): The number of PIs in the reparametrized AIG and in the CEX do not agree.\n" ); - return NULL; - } - // get the sequence of states - vStates = Llb4_Nonlin4VerifyCex( pAigRpm, pCexRpm ); - if ( vStates == NULL ) - { - Abc_Print( 1, "Llb4_Nonlin4NormalizeCex(): The given CEX does not fail outputs of pAigRpm.\n" ); - return NULL; - } - // derive updated counter-example - pCexOrg = Llb4_Nonlin4TransformCex( pAigOrg, vStates, pCexRpm->iPo, 0 ); - Vec_PtrFree( vStates ); - return pCexOrg; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llb4Cluster.c b/src/aig/llb/llb4Cluster.c deleted file mode 100644 index 8d29eed4..00000000 --- a/src/aig/llb/llb4Cluster.c +++ /dev/null @@ -1,452 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb2Cluster.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Non-linear quantification scheduling.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb2Cluster.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Find good static variable ordering.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4FindOrder_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vOrder, int * pCounter ) -{ - Aig_Obj_t * pFanin0, * pFanin1; - if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) - return; - Aig_ObjSetTravIdCurrent( pAig, pObj ); - assert( Llb_ObjBddVar(vOrder, pObj) < 0 ); - if ( Aig_ObjIsPi(pObj) ) - { - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); - return; - } - // try fanins with higher level first - pFanin0 = Aig_ObjFanin0(pObj); - pFanin1 = Aig_ObjFanin1(pObj); -// if ( pFanin0->Level > pFanin1->Level || (pFanin0->Level == pFanin1->Level && pFanin0->Id < pFanin1->Id) ) - if ( pFanin0->Level > pFanin1->Level ) - { - Llb_Nonlin4FindOrder_rec( pAig, pFanin0, vOrder, pCounter ); - Llb_Nonlin4FindOrder_rec( pAig, pFanin1, vOrder, pCounter ); - } - else - { - Llb_Nonlin4FindOrder_rec( pAig, pFanin1, vOrder, pCounter ); - Llb_Nonlin4FindOrder_rec( pAig, pFanin0, vOrder, pCounter ); - } - if ( pObj->fMarkA ) - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); -} - -/**Function************************************************************* - - Synopsis [Find good static variable ordering.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_Nonlin4FindOrder( Aig_Man_t * pAig, int * pCounter ) -{ - Vec_Int_t * vNodes = NULL; - Vec_Int_t * vOrder; - Aig_Obj_t * pObj; - int i, Counter = 0; - // mark nodes to exclude: AND with low level and CO drivers - Aig_ManCleanMarkA( pAig ); - Aig_ManForEachNode( pAig, pObj, i ) - if ( Aig_ObjLevel(pObj) > 3 ) - pObj->fMarkA = 1; - Aig_ManForEachPo( pAig, pObj, i ) - Aig_ObjFanin0(pObj)->fMarkA = 0; - - // collect nodes in the order - vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) ); - Aig_ManIncrementTravId( pAig ); - Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) ); -// Aig_ManForEachPo( pAig, pObj, i ) - Saig_ManForEachLi( pAig, pObj, i ) - { - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); - Llb_Nonlin4FindOrder_rec( pAig, Aig_ObjFanin0(pObj), vOrder, &Counter ); - } - Aig_ManForEachPi( pAig, pObj, i ) - if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); - Aig_ManCleanMarkA( pAig ); - Vec_IntFreeP( &vNodes ); -// assert( Counter == Aig_ManObjNum(pAig) - 1 ); - -/* - Saig_ManForEachPi( pAig, pObj, i ) - printf( "pi%d ", Llb_ObjBddVar(vOrder, pObj) ); - printf( "\n" ); - Saig_ManForEachLo( pAig, pObj, i ) - printf( "lo%d ", Llb_ObjBddVar(vOrder, pObj) ); - printf( "\n" ); - Saig_ManForEachPo( pAig, pObj, i ) - printf( "po%d ", Llb_ObjBddVar(vOrder, pObj) ); - printf( "\n" ); - Saig_ManForEachLi( pAig, pObj, i ) - printf( "li%d ", Llb_ObjBddVar(vOrder, pObj) ); - printf( "\n" ); - Aig_ManForEachNode( pAig, pObj, i ) - printf( "n%d ", Llb_ObjBddVar(vOrder, pObj) ); - printf( "\n" ); -*/ - if ( pCounter ) - *pCounter = Counter; - return vOrder; -} - -/**Function************************************************************* - - Synopsis [Derives BDDs for the partitions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_Nonlin4FindPartitions_rec( DdManager * dd, Aig_Obj_t * pObj, Vec_Int_t * vOrder, Vec_Ptr_t * vRoots ) -{ - DdNode * bBdd, * bBdd0, * bBdd1, * bPart, * vVar; - if ( Aig_ObjIsConst1(pObj) ) - return Cudd_ReadOne(dd); - if ( Aig_ObjIsPi(pObj) ) - return Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); - if ( pObj->pData ) - return (DdNode *)pObj->pData; - if ( Aig_ObjIsPo(pObj) ) - { - bBdd0 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) ); - bPart = Cudd_bddXnor( dd, Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ), bBdd0 ); Cudd_Ref( bPart ); - Vec_PtrPush( vRoots, bPart ); - return NULL; - } - bBdd0 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) ); - bBdd1 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin1(pObj), vOrder, vRoots), Aig_ObjFaninC1(pObj) ); - bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bBdd ); - if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) - { - vVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); - bPart = Cudd_bddXnor( dd, vVar, bBdd ); Cudd_Ref( bPart ); - Vec_PtrPush( vRoots, bPart ); - Cudd_RecursiveDeref( dd, bBdd ); - bBdd = vVar; Cudd_Ref( vVar ); - } - pObj->pData = bBdd; - return bBdd; -} - -/**Function************************************************************* - - Synopsis [Derives BDDs for the partitions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_Nonlin4FindPartitions( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fOutputs ) -{ - Vec_Ptr_t * vRoots; - Aig_Obj_t * pObj; - int i; - Aig_ManCleanData( pAig ); - vRoots = Vec_PtrAlloc( 100 ); - if ( fOutputs ) - { - Saig_ManForEachPo( pAig, pObj, i ) - Llb_Nonlin4FindPartitions_rec( dd, pObj, vOrder, vRoots ); - } - else - { - Saig_ManForEachLi( pAig, pObj, i ) - Llb_Nonlin4FindPartitions_rec( dd, pObj, vOrder, vRoots ); - } - Aig_ManForEachNode( pAig, pObj, i ) - if ( pObj->pData ) - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); - return vRoots; -} - -/**Function************************************************************* - - Synopsis [Creates quantifiable variables for both types of traversal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_Nonlin4FindVars2Q( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder ) -{ - Vec_Int_t * vVars2Q; - Aig_Obj_t * pObj; - int i; - vVars2Q = Vec_IntAlloc( 0 ); - Vec_IntFill( vVars2Q, Cudd_ReadSize(dd), 1 ); - Saig_ManForEachLo( pAig, pObj, i ) - Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 ); -// Aig_ManForEachPo( pAig, pObj, i ) - Saig_ManForEachLi( pAig, pObj, i ) - Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 ); - return vVars2Q; -} - -/**Function************************************************************* - - Synopsis [Creates quantifiable variables for both types of traversal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_Nonlin4CountTerms( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, DdNode * bFunc, int fCo, int fFlop ) -{ - DdNode * bSupp; - Aig_Obj_t * pObj; - int i, Counter = 0; - bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); - if ( !fCo && !fFlop ) - { - Saig_ManForEachPi( pAig, pObj, i ) - if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) - Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) ); - } - else if ( fCo && !fFlop ) - { - Saig_ManForEachPo( pAig, pObj, i ) - if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) - Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) ); - } - else if ( !fCo && fFlop ) - { - Saig_ManForEachLo( pAig, pObj, i ) - if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) - Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) ); - } - else if ( fCo && fFlop ) - { - Saig_ManForEachLi( pAig, pObj, i ) - if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) - Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) ); - } - Cudd_RecursiveDeref( dd, bSupp ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Creates quantifiable variables for both types of traversal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4PrintGroups( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups ) -{ - DdNode * bTemp; - int i, nSuppAll, nSuppPi, nSuppPo, nSuppLi, nSuppLo, nSuppAnd; - Vec_PtrForEachEntry( DdNode *, vGroups, bTemp, i ) - { -//Extra_bddPrintSupport(dd, bTemp); printf("\n" ); - nSuppAll = Cudd_SupportSize(dd,bTemp); - nSuppPi = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 0, 0); - nSuppPo = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 1, 0); - nSuppLi = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 0, 1); - nSuppLo = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 1, 1); - nSuppAnd = nSuppAll - (nSuppPi+nSuppPo+nSuppLi+nSuppLo); - - if ( Cudd_DagSize(bTemp) <= 10 ) - continue; - - printf( "%4d : bdd =%6d supp =%3d ", i, Cudd_DagSize(bTemp), nSuppAll ); - printf( "pi =%3d ", nSuppPi ); - printf( "po =%3d ", nSuppPo ); - printf( "lo =%3d ", nSuppLo ); - printf( "li =%3d ", nSuppLi ); - printf( "and =%3d", nSuppAnd ); - printf( "\n" ); - } -} - -/**Function************************************************************* - - Synopsis [Creates quantifiable variables for both types of traversal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4PrintSuppProfile( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups ) -{ - Aig_Obj_t * pObj; - int i, * pSupp; - int nSuppAll = 0, nSuppPi = 0, nSuppPo = 0, nSuppLi = 0, nSuppLo = 0, nSuppAnd = 0; - - pSupp = ABC_CALLOC( int, Cudd_ReadSize(dd) ); - Extra_VectorSupportArray( dd, (DdNode **)Vec_PtrArray(vGroups), Vec_PtrSize(vGroups), pSupp ); - - Aig_ManForEachObj( pAig, pObj, i ) - { - if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) - continue; - // remove variables that do not participate - if ( pSupp[Llb_ObjBddVar(vOrder, pObj)] == 0 ) - { - if ( Aig_ObjIsNode(pObj) ) - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), -1 ); - continue; - } - nSuppAll++; - if ( Saig_ObjIsPi(pAig, pObj) ) - nSuppPi++; - else if ( Saig_ObjIsLo(pAig, pObj) ) - nSuppLo++; - else if ( Saig_ObjIsPo(pAig, pObj) ) - nSuppPo++; - else if ( Saig_ObjIsLi(pAig, pObj) ) - nSuppLi++; - else - nSuppAnd++; - } - ABC_FREE( pSupp ); - - printf( "Groups =%3d ", Vec_PtrSize(vGroups) ); - printf( "Variables: all =%4d ", nSuppAll ); - printf( "pi =%4d ", nSuppPi ); - printf( "po =%4d ", nSuppPo ); - printf( "lo =%4d ", nSuppLo ); - printf( "li =%4d ", nSuppLi ); - printf( "and =%4d", nSuppAnd ); - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4Cluster( Aig_Man_t * pAig, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int nBddMax, int fVerbose ) -{ - DdManager * dd; - Vec_Int_t * vOrder, * vVars2Q; - Vec_Ptr_t * vParts, * vGroups; - DdNode * bTemp; - int i, nVarNum; - - // create the BDD manager - vOrder = Llb_Nonlin4FindOrder( pAig, &nVarNum ); - dd = Cudd_Init( nVarNum, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); -// Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - - vVars2Q = Llb_Nonlin4FindVars2Q( dd, pAig, vOrder ); - vParts = Llb_Nonlin4FindPartitions( dd, pAig, vOrder, 0 ); - - vGroups = Llb_Nonlin4Group( dd, vParts, vVars2Q, nBddMax ); - Vec_IntFree( vVars2Q ); - - Vec_PtrForEachEntry( DdNode *, vParts, bTemp, i ) - Cudd_RecursiveDeref( dd, bTemp ); - Vec_PtrFree( vParts ); - - -// if ( fVerbose ) - Llb_Nonlin4PrintSuppProfile( dd, pAig, vOrder, vGroups ); - if ( fVerbose ) - printf( "Before reordering\n" ); - if ( fVerbose ) - Llb_Nonlin4PrintGroups( dd, pAig, vOrder, vGroups ); - -// Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 ); -// printf( "After reordering\n" ); -// Llb_Nonlin4PrintGroups( dd, pAig, vOrder, vGroups ); - - if ( pvOrder ) - *pvOrder = vOrder; - else - Vec_IntFree( vOrder ); - - if ( pvGroups ) - *pvGroups = vGroups; - else - { - Vec_PtrForEachEntry( DdNode *, vGroups, bTemp, i ) - Cudd_RecursiveDeref( dd, bTemp ); - Vec_PtrFree( vGroups ); - } - - if ( pdd ) - *pdd = dd; - else - Extra_StopManager( dd ); -// Cudd_Quit( dd ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llb4Image.c b/src/aig/llb/llb4Image.c deleted file mode 100644 index 031c8830..00000000 --- a/src/aig/llb/llb4Image.c +++ /dev/null @@ -1,861 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb3Image.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Computes image using partitioned structure.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb3Image.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Llb_Var_t_ Llb_Var_t; -struct Llb_Var_t_ -{ - int iVar; // variable number - int nScore; // variable score - Vec_Int_t * vParts; // partitions -}; - -typedef struct Llb_Prt_t_ Llb_Prt_t; -struct Llb_Prt_t_ -{ - int iPart; // partition number - int nSize; // the number of BDD nodes - DdNode * bFunc; // the partition - Vec_Int_t * vVars; // support -}; - -typedef struct Llb_Mgr_t_ Llb_Mgr_t; -struct Llb_Mgr_t_ -{ - DdManager * dd; // working BDD manager - Vec_Int_t * vVars2Q; // variables to quantify - int nSizeMax; // maximum size of the cluster - // internal - Llb_Prt_t ** pParts; // partitions - Llb_Var_t ** pVars; // variables - int iPartFree; // next free partition - int nVars; // the number of BDD variables - int nSuppMax; // maximum support size - // temporary - int * pSupp; // temporary support storage -}; - -static inline Llb_Var_t * Llb_MgrVar( Llb_Mgr_t * p, int i ) { return p->pVars[i]; } -static inline Llb_Prt_t * Llb_MgrPart( Llb_Mgr_t * p, int i ) { return p->pParts[i]; } - -// iterator over vars -#define Llb_MgrForEachVar( p, pVar, i ) \ - for ( i = 0; (i < p->nVars) && (((pVar) = Llb_MgrVar(p, i)), 1); i++ ) if ( pVar == NULL ) {} else -// iterator over parts -#define Llb_MgrForEachPart( p, pPart, i ) \ - for ( i = 0; (i < p->iPartFree) && (((pPart) = Llb_MgrPart(p, i)), 1); i++ ) if ( pPart == NULL ) {} else - -// iterator over vars of one partition -#define Llb_PartForEachVar( p, pPart, pVar, i ) \ - for ( i = 0; (i < Vec_IntSize(pPart->vVars)) && (((pVar) = Llb_MgrVar(p, Vec_IntEntry(pPart->vVars,i))), 1); i++ ) -// iterator over parts of one variable -#define Llb_VarForEachPart( p, pVar, pPart, i ) \ - for ( i = 0; (i < Vec_IntSize(pVar->vParts)) && (((pPart) = Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,i))), 1); i++ ) - -// statistics -//int timeBuild, timeAndEx, timeOther; -//int nSuppMax; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Removes one variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4RemoveVar( Llb_Mgr_t * p, Llb_Var_t * pVar ) -{ - assert( p->pVars[pVar->iVar] == pVar ); - p->pVars[pVar->iVar] = NULL; - Vec_IntFree( pVar->vParts ); - ABC_FREE( pVar ); -} - -/**Function************************************************************* - - Synopsis [Removes one partition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4RemovePart( Llb_Mgr_t * p, Llb_Prt_t * pPart ) -{ -//printf( "Removing %d\n", pPart->iPart ); - assert( p->pParts[pPart->iPart] == pPart ); - p->pParts[pPart->iPart] = NULL; - Vec_IntFree( pPart->vVars ); - Cudd_RecursiveDeref( p->dd, pPart->bFunc ); - ABC_FREE( pPart ); -} - -/**Function************************************************************* - - Synopsis [Create cube with singleton variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_Nonlin4CreateCube1( Llb_Mgr_t * p, Llb_Prt_t * pPart ) -{ - DdNode * bCube, * bTemp; - Llb_Var_t * pVar; - int i, TimeStop; - TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; - bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube ); - Llb_PartForEachVar( p, pPart, pVar, i ) - { - assert( Vec_IntSize(pVar->vParts) > 0 ); - if ( Vec_IntSize(pVar->vParts) != 1 ) - continue; - assert( Vec_IntEntry(pVar->vParts, 0) == pPart->iPart ); - bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - Cudd_Deref( bCube ); - p->dd->TimeStop = TimeStop; - return bCube; -} - -/**Function************************************************************* - - Synopsis [Create cube of variables appearing only in two partitions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_Nonlin4CreateCube2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 ) -{ - DdNode * bCube, * bTemp; - Llb_Var_t * pVar; - int i, TimeStop; - TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; - bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube ); - Llb_PartForEachVar( p, pPart1, pVar, i ) - { - assert( Vec_IntSize(pVar->vParts) > 0 ); - if ( Vec_IntSize(pVar->vParts) != 2 ) - continue; - if ( (Vec_IntEntry(pVar->vParts, 0) == pPart1->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart2->iPart) || - (Vec_IntEntry(pVar->vParts, 0) == pPart2->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart1->iPart) ) - { - bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - } - Cudd_Deref( bCube ); - p->dd->TimeStop = TimeStop; - return bCube; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if partition has singleton variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_Nonlin4HasSingletonVars( Llb_Mgr_t * p, Llb_Prt_t * pPart ) -{ - Llb_Var_t * pVar; - int i; - Llb_PartForEachVar( p, pPart, pVar, i ) - if ( Vec_IntSize(pVar->vParts) == 1 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if partition has singleton variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4Print( Llb_Mgr_t * p ) -{ - Llb_Prt_t * pPart; - Llb_Var_t * pVar; - int i, k; - printf( "\n" ); - Llb_MgrForEachVar( p, pVar, i ) - { - printf( "Var %3d : ", i ); - Llb_VarForEachPart( p, pVar, pPart, k ) - printf( "%d ", pPart->iPart ); - printf( "\n" ); - } - Llb_MgrForEachPart( p, pPart, i ) - { - printf( "Part %3d : ", i ); - Llb_PartForEachVar( p, pPart, pVar, k ) - printf( "%d ", pVar->iVar ); - printf( "\n" ); - } -} - -/**Function************************************************************* - - Synopsis [Quantifies singles belonging to one partition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_Nonlin4Quantify1( Llb_Mgr_t * p, Llb_Prt_t * pPart ) -{ - Llb_Var_t * pVar; - Llb_Prt_t * pTemp; - Vec_Ptr_t * vSingles; - DdNode * bCube, * bTemp; - int i, RetValue, nSizeNew; - // create cube to be quantified - bCube = Llb_Nonlin4CreateCube1( p, pPart ); Cudd_Ref( bCube ); -// assert( !Cudd_IsConstant(bCube) ); - // derive new function - pPart->bFunc = Cudd_bddExistAbstract( p->dd, bTemp = pPart->bFunc, bCube ); Cudd_Ref( pPart->bFunc ); - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bCube ); - // get support - vSingles = Vec_PtrAlloc( 0 ); - nSizeNew = Cudd_DagSize(pPart->bFunc); - Extra_SupportArray( p->dd, pPart->bFunc, p->pSupp ); - Llb_PartForEachVar( p, pPart, pVar, i ) - if ( p->pSupp[pVar->iVar] ) - { - assert( Vec_IntSize(pVar->vParts) > 1 ); - pVar->nScore -= pPart->nSize - nSizeNew; - } - else - { - RetValue = Vec_IntRemove( pVar->vParts, pPart->iPart ); - assert( RetValue ); - pVar->nScore -= pPart->nSize; - if ( Vec_IntSize(pVar->vParts) == 0 ) - Llb_Nonlin4RemoveVar( p, pVar ); - else if ( Vec_IntSize(pVar->vParts) == 1 ) - Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); - } - - // update partition - pPart->nSize = nSizeNew; - Vec_IntClear( pPart->vVars ); - for ( i = 0; i < p->nVars; i++ ) - if ( p->pSupp[i] && Vec_IntEntry(p->vVars2Q, i) ) - Vec_IntPush( pPart->vVars, i ); - // remove other variables - Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i ) - Llb_Nonlin4Quantify1( p, pTemp ); - Vec_PtrFree( vSingles ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Quantifies singles belonging to one partition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_Nonlin4Quantify2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 ) -{ - int fVerbose = 0; - Llb_Var_t * pVar; - Llb_Prt_t * pTemp; - Vec_Ptr_t * vSingles; - DdNode * bCube, * bFunc; - int i, RetValue, nSuppSize; - int iPart1 = pPart1->iPart; - int iPart2 = pPart2->iPart; - int liveBeg, liveEnd; - - // create cube to be quantified - bCube = Llb_Nonlin4CreateCube2( p, pPart1, pPart2 ); Cudd_Ref( bCube ); - -//printf( "Quantifying " ); Extra_bddPrintSupport( p->dd, bCube ); printf( "\n" ); - -if ( fVerbose ) -{ -printf( "\n" ); -printf( "\n" ); -Llb_Nonlin4Print( p ); -printf( "Conjoining partitions %d and %d.\n", pPart1->iPart, pPart2->iPart ); -Extra_bddPrintSupport( p->dd, bCube ); printf( "\n" ); -} -liveBeg = p->dd->keys - p->dd->dead; - bFunc = Cudd_bddAndAbstract( p->dd, pPart1->bFunc, pPart2->bFunc, bCube ); -liveEnd = p->dd->keys - p->dd->dead; -//printf( "%d ", liveEnd-liveBeg ); - - if ( bFunc == NULL ) - { - Cudd_RecursiveDeref( p->dd, bCube ); - return 0; - } - Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( p->dd, bCube ); - -//printf( "Creating part %d ", p->iPartFree ); Extra_bddPrintSupport( p->dd, bFunc ); printf( "\n" ); - -//printf( "Creating %d\n", p->iPartFree ); - - // create new partition - pTemp = p->pParts[p->iPartFree] = ABC_CALLOC( Llb_Prt_t, 1 ); - pTemp->iPart = p->iPartFree++; - pTemp->nSize = Cudd_DagSize(bFunc); - pTemp->bFunc = bFunc; - pTemp->vVars = Vec_IntAlloc( 8 ); - // update variables - Llb_PartForEachVar( p, pPart1, pVar, i ) - { - RetValue = Vec_IntRemove( pVar->vParts, pPart1->iPart ); - assert( RetValue ); - pVar->nScore -= pPart1->nSize; - } - // update variables - Llb_PartForEachVar( p, pPart2, pVar, i ) - { - RetValue = Vec_IntRemove( pVar->vParts, pPart2->iPart ); - assert( RetValue ); - pVar->nScore -= pPart2->nSize; - } - // add variables to the new partition - nSuppSize = 0; - Extra_SupportArray( p->dd, bFunc, p->pSupp ); - for ( i = 0; i < p->nVars; i++ ) - { - nSuppSize += p->pSupp[i]; - if ( p->pSupp[i] && Vec_IntEntry(p->vVars2Q, i) ) - { - pVar = Llb_MgrVar( p, i ); - pVar->nScore += pTemp->nSize; - Vec_IntPush( pVar->vParts, pTemp->iPart ); - Vec_IntPush( pTemp->vVars, i ); - } - } - p->nSuppMax = ABC_MAX( p->nSuppMax, nSuppSize ); - // remove variables and collect partitions with singleton variables - vSingles = Vec_PtrAlloc( 0 ); - Llb_PartForEachVar( p, pPart1, pVar, i ) - { - if ( Vec_IntSize(pVar->vParts) == 0 ) - Llb_Nonlin4RemoveVar( p, pVar ); - else if ( Vec_IntSize(pVar->vParts) == 1 ) - { - if ( fVerbose ) - printf( "Adding partition %d because of var %d.\n", - Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar ); - Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); - } - } - Llb_PartForEachVar( p, pPart2, pVar, i ) - { - if ( pVar == NULL ) - continue; - if ( Vec_IntSize(pVar->vParts) == 0 ) - Llb_Nonlin4RemoveVar( p, pVar ); - else if ( Vec_IntSize(pVar->vParts) == 1 ) - { - if ( fVerbose ) - printf( "Adding partition %d because of var %d.\n", - Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar ); - Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); - } - } - // remove partitions - Llb_Nonlin4RemovePart( p, pPart1 ); - Llb_Nonlin4RemovePart( p, pPart2 ); - // remove other variables -if ( fVerbose ) -Llb_Nonlin4Print( p ); - Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i ) - { -if ( fVerbose ) -printf( "Updating partitiong %d with singlton vars.\n", pTemp->iPart ); - Llb_Nonlin4Quantify1( p, pTemp ); - } -if ( fVerbose ) -Llb_Nonlin4Print( p ); - Vec_PtrFree( vSingles ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Computes volume of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4CutNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) -{ - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - return; - Aig_ObjSetTravIdCurrent(p, pObj); - if ( Saig_ObjIsLi(p, pObj) ) - { - Llb_Nonlin4CutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); - return; - } - if ( Aig_ObjIsConst1(pObj) ) - return; - assert( Aig_ObjIsNode(pObj) ); - Llb_Nonlin4CutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); - Llb_Nonlin4CutNodes_rec(p, Aig_ObjFanin1(pObj), vNodes); - Vec_PtrPush( vNodes, pObj ); -} - -/**Function************************************************************* - - Synopsis [Computes volume of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_Nonlin4CutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i; - // mark the lower cut with the traversal ID - Aig_ManIncrementTravId(p); - Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) - Aig_ObjSetTravIdCurrent( p, pObj ); - // count the upper cut - vNodes = Vec_PtrAlloc( 100 ); - Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) - Llb_Nonlin4CutNodes_rec( p, pObj, vNodes ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Starts non-linear quantification scheduling.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4AddPair( Llb_Mgr_t * p, int iPart, int iVar ) -{ - if ( p->pVars[iVar] == NULL ) - { - p->pVars[iVar] = ABC_CALLOC( Llb_Var_t, 1 ); - p->pVars[iVar]->iVar = iVar; - p->pVars[iVar]->nScore = 0; - p->pVars[iVar]->vParts = Vec_IntAlloc( 8 ); - } - Vec_IntPush( p->pVars[iVar]->vParts, iPart ); - Vec_IntPush( p->pParts[iPart]->vVars, iVar ); -} - -/**Function************************************************************* - - Synopsis [Starts non-linear quantification scheduling.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4AddPartition( Llb_Mgr_t * p, int i, DdNode * bFunc ) -{ - int k, nSuppSize; - assert( !Cudd_IsConstant(bFunc) ); -//printf( "Creating init %d\n", i ); - // create partition - p->pParts[i] = ABC_CALLOC( Llb_Prt_t, 1 ); - p->pParts[i]->iPart = i; - p->pParts[i]->bFunc = bFunc; Cudd_Ref( bFunc ); - p->pParts[i]->vVars = Vec_IntAlloc( 8 ); - // add support dependencies - nSuppSize = 0; - Extra_SupportArray( p->dd, bFunc, p->pSupp ); - for ( k = 0; k < p->nVars; k++ ) - { - nSuppSize += p->pSupp[k]; - if ( p->pSupp[k] && Vec_IntEntry(p->vVars2Q, k) ) - Llb_Nonlin4AddPair( p, i, k ); - } - p->nSuppMax = ABC_MAX( p->nSuppMax, nSuppSize ); -} - -/**Function************************************************************* - - Synopsis [Checks that each var appears in at least one partition.] - - Description [] - - SideEffects [] - - SeeAlso [] -**********************************************************************/ -void Llb_Nonlin4CheckVars( Llb_Mgr_t * p ) -{ - Llb_Var_t * pVar; - int i; - Llb_MgrForEachVar( p, pVar, i ) - assert( Vec_IntSize(pVar->vParts) > 1 ); -} - -/**Function************************************************************* - - Synopsis [Find next partition to quantify] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_Nonlin4NextPartitions( Llb_Mgr_t * p, Llb_Prt_t ** ppPart1, Llb_Prt_t ** ppPart2 ) -{ - Llb_Var_t * pVar, * pVarBest = NULL; - Llb_Prt_t * pPart, * pPart1Best = NULL, * pPart2Best = NULL; - int i; - Llb_Nonlin4CheckVars( p ); - // find variable with minimum score - Llb_MgrForEachVar( p, pVar, i ) - { - if ( p->nSizeMax && pVar->nScore > p->nSizeMax ) - continue; -// if ( pVarBest == NULL || Vec_IntSize(pVarBest->vParts) * pVarBest->nScore > Vec_IntSize(pVar->vParts) * pVar->nScore ) - if ( pVarBest == NULL || pVarBest->nScore > pVar->nScore ) - pVarBest = pVar; -// printf( "%d ", pVar->nScore ); - } -//printf( "\n" ); - if ( pVarBest == NULL ) - return 0; - // find two partitions with minimum size - Llb_VarForEachPart( p, pVarBest, pPart, i ) - { - if ( pPart1Best == NULL ) - pPart1Best = pPart; - else if ( pPart2Best == NULL ) - pPart2Best = pPart; - else if ( pPart1Best->nSize > pPart->nSize || pPart2Best->nSize > pPart->nSize ) - { - if ( pPart1Best->nSize > pPart2Best->nSize ) - pPart1Best = pPart; - else - pPart2Best = pPart; - } - } -//printf( "Selecting %d and parts %d and %d\n", pVarBest->iVar, pPart1Best->nSize, pPart2Best->nSize ); -//Extra_bddPrintSupport( p->dd, pPart1Best->bFunc ); printf( "\n" ); -//Extra_bddPrintSupport( p->dd, pPart2Best->bFunc ); printf( "\n" ); - - *ppPart1 = pPart1Best; - *ppPart2 = pPart2Best; - return 1; -} - -/**Function************************************************************* - - Synopsis [Recomputes scores after variable reordering.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4RecomputeScores( Llb_Mgr_t * p ) -{ - Llb_Prt_t * pPart; - Llb_Var_t * pVar; - int i, k; - Llb_MgrForEachPart( p, pPart, i ) - pPart->nSize = Cudd_DagSize(pPart->bFunc); - Llb_MgrForEachVar( p, pVar, i ) - { - pVar->nScore = 0; - Llb_VarForEachPart( p, pVar, pPart, k ) - pVar->nScore += pPart->nSize; - } -} - -/**Function************************************************************* - - Synopsis [Recomputes scores after variable reordering.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4VerifyScores( Llb_Mgr_t * p ) -{ - Llb_Prt_t * pPart; - Llb_Var_t * pVar; - int i, k, nScore; - Llb_MgrForEachPart( p, pPart, i ) - assert( pPart->nSize == Cudd_DagSize(pPart->bFunc) ); - Llb_MgrForEachVar( p, pVar, i ) - { - nScore = 0; - Llb_VarForEachPart( p, pVar, pPart, k ) - nScore += pPart->nSize; - assert( nScore == pVar->nScore ); - } -} - -/**Function************************************************************* - - Synopsis [Starts non-linear quantification scheduling.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Mgr_t * Llb_Nonlin4Alloc( DdManager * dd, Vec_Ptr_t * vParts, DdNode * bCurrent, Vec_Int_t * vVars2Q, int nSizeMax ) -{ - Llb_Mgr_t * p; - DdNode * bFunc; - int i; - p = ABC_CALLOC( Llb_Mgr_t, 1 ); - p->dd = dd; - p->nSizeMax = nSizeMax; - p->vVars2Q = vVars2Q; - p->nVars = Cudd_ReadSize(dd); - p->iPartFree = Vec_PtrSize(vParts); - p->pVars = ABC_CALLOC( Llb_Var_t *, p->nVars ); - p->pParts = ABC_CALLOC( Llb_Prt_t *, 2 * p->iPartFree + 2 ); - p->pSupp = ABC_ALLOC( int, Cudd_ReadSize(dd) ); - // add pairs (refs are consumed inside) - Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i ) - Llb_Nonlin4AddPartition( p, i, bFunc ); - // add partition - if ( bCurrent ) - Llb_Nonlin4AddPartition( p, p->iPartFree++, bCurrent ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops non-linear quantification scheduling.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4Free( Llb_Mgr_t * p ) -{ - Llb_Prt_t * pPart; - Llb_Var_t * pVar; - int i; - Llb_MgrForEachVar( p, pVar, i ) - Llb_Nonlin4RemoveVar( p, pVar ); - Llb_MgrForEachPart( p, pPart, i ) - Llb_Nonlin4RemovePart( p, pPart ); - ABC_FREE( p->pVars ); - ABC_FREE( p->pParts ); - ABC_FREE( p->pSupp ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_Nonlin4Image( DdManager * dd, Vec_Ptr_t * vParts, DdNode * bCurrent, Vec_Int_t * vVars2Q ) -{ - Llb_Prt_t * pPart, * pPart1, * pPart2; - Llb_Mgr_t * p; - DdNode * bFunc, * bTemp; - int i, nReorders; - // start the manager - p = Llb_Nonlin4Alloc( dd, vParts, bCurrent, vVars2Q, 0 ); - // remove singles - Llb_MgrForEachPart( p, pPart, i ) - if ( Llb_Nonlin4HasSingletonVars(p, pPart) ) - Llb_Nonlin4Quantify1( p, pPart ); - // compute scores - Llb_Nonlin4RecomputeScores( p ); - // iteratively quantify variables - while ( Llb_Nonlin4NextPartitions(p, &pPart1, &pPart2) ) - { - nReorders = Cudd_ReadReorderings(dd); - if ( !Llb_Nonlin4Quantify2( p, pPart1, pPart2 ) ) - { - Llb_Nonlin4Free( p ); - return NULL; - } - if ( nReorders < Cudd_ReadReorderings(dd) ) - Llb_Nonlin4RecomputeScores( p ); -// else -// Llb_Nonlin4VerifyScores( p ); - } - // load partitions - bFunc = Cudd_ReadOne(p->dd); Cudd_Ref( bFunc ); - Llb_MgrForEachPart( p, pPart, i ) - { - bFunc = Cudd_bddAnd( p->dd, bTemp = bFunc, pPart->bFunc ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } -// nSuppMax = p->nSuppMax; - Llb_Nonlin4Free( p ); -//printf( "\n" ); - // return - Cudd_Deref( bFunc ); - return bFunc; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_Nonlin4Group( DdManager * dd, Vec_Ptr_t * vParts, Vec_Int_t * vVars2Q, int nSizeMax ) -{ - Vec_Ptr_t * vGroups; - Llb_Prt_t * pPart, * pPart1, * pPart2; - Llb_Mgr_t * p; - int i, nReorders, clk = clock(); - // start the manager - p = Llb_Nonlin4Alloc( dd, vParts, NULL, vVars2Q, nSizeMax ); - // remove singles - Llb_MgrForEachPart( p, pPart, i ) - if ( Llb_Nonlin4HasSingletonVars(p, pPart) ) - Llb_Nonlin4Quantify1( p, pPart ); - // compute scores - Llb_Nonlin4RecomputeScores( p ); - // iteratively quantify variables - while ( Llb_Nonlin4NextPartitions(p, &pPart1, &pPart2) ) - { - nReorders = Cudd_ReadReorderings(dd); - if ( !Llb_Nonlin4Quantify2( p, pPart1, pPart2 ) ) - { - Llb_Nonlin4Free( p ); - return NULL; - } - if ( nReorders < Cudd_ReadReorderings(dd) ) - Llb_Nonlin4RecomputeScores( p ); -// else -// Llb_Nonlin4VerifyScores( p ); - } - // load partitions - vGroups = Vec_PtrAlloc( 1000 ); - Llb_MgrForEachPart( p, pPart, i ) - { -//printf( "Iteration %d ", pPart->iPart ); - if ( Cudd_IsConstant(pPart->bFunc) ) - { -//printf( "Constant\n" ); - assert( !Cudd_IsComplement(pPart->bFunc) ); - continue; - } -//printf( "\n" ); - Vec_PtrPush( vGroups, pPart->bFunc ); - Cudd_Ref( pPart->bFunc ); -//printf( "Part %d ", pPart->iPart ); -//Extra_bddPrintSupport( p->dd, pPart->bFunc ); printf( "\n" ); - } - Llb_Nonlin4Free( p ); -//Abc_PrintTime( 1, "Reparametrization time", clock() - clk ); - return vGroups; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llb4Map.c b/src/aig/llb/llb4Map.c deleted file mode 100644 index 9dabb19d..00000000 --- a/src/aig/llb/llb4Map.c +++ /dev/null @@ -1,123 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb2Map.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Non-linear quantification scheduling.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb2Map.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" -#include "abc.h" -#include "if.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns internal nodes used in the mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_AigMap( Aig_Man_t * pAig, int nLutSize, int nLutMin ) -{ - extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); - extern If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); - extern void Gia_ManSetIfParsDefault( If_Par_t * pPars ); - If_Par_t Pars, * pPars = &Pars; - If_Man_t * pIfMan; - If_Obj_t * pAnd; - Abc_Ntk_t * pNtk; - Abc_Obj_t * pNode; - Vec_Int_t * vNodes; - Aig_Obj_t * pObj; - int i; - - // create ABC network - pNtk = Abc_NtkFromAigPhase( pAig ); - assert( Abc_NtkIsStrash(pNtk) ); - - // derive mapping parameters - Gia_ManSetIfParsDefault( pPars ); - pPars->nLutSize = nLutSize; - - // get timing information - pPars->pTimesArr = Abc_NtkGetCiArrivalFloats(pNtk); - pPars->pTimesReq = NULL; - - // perform LUT mapping - pIfMan = Abc_NtkToIf( pNtk, pPars ); - if ( pIfMan == NULL ) - { - Abc_NtkDelete( pNtk ); - return NULL; - } - if ( !If_ManPerformMapping( pIfMan ) ) - { - Abc_NtkDelete( pNtk ); - If_ManStop( pIfMan ); - return NULL; - } - - // mark nodes in the AIG used in the mapping - Aig_ManCleanMarkA( pAig ); - Aig_ManForEachNode( pAig, pObj, i ) - { - pNode = (Abc_Obj_t *)pObj->pData; - if ( pNode == NULL ) - continue; - pAnd = (If_Obj_t *)pNode->pCopy; - if ( pAnd == NULL ) - continue; - if ( pAnd->nRefs > 0 && (int)If_ObjCutBest(pAnd)->nLeaves >= nLutMin ) - pObj->fMarkA = 1; - } - Abc_NtkDelete( pNtk ); - If_ManStop( pIfMan ); - - // unmark flop drivers - Saig_ManForEachLi( pAig, pObj, i ) - Aig_ObjFanin0(pObj)->fMarkA = 0; - - // collect mapping - vNodes = Vec_IntAlloc( 100 ); - Aig_ManForEachNode( pAig, pObj, i ) - if ( pObj->fMarkA ) - Vec_IntPush( vNodes, Aig_ObjId(pObj) ); - Aig_ManCleanMarkA( pAig ); - return vNodes; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llb4Nonlin.c b/src/aig/llb/llb4Nonlin.c deleted file mode 100644 index b29796f1..00000000 --- a/src/aig/llb/llb4Nonlin.c +++ /dev/null @@ -1,1080 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb2Nonlin.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Non-linear quantification scheduling.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb2Nonlin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Llb_Mnx_t_ Llb_Mnx_t; -struct Llb_Mnx_t_ -{ - // user info - Aig_Man_t * pAig; // AIG manager - Gia_ParLlb_t * pPars; // parameters - - // intermediate BDDs - DdManager * dd; // BDD manager - DdNode * bBad; // bad states in terms of CIs - DdNode * bReached; // reached states - DdNode * bCurrent; // from states - DdNode * bNext; // to states - Vec_Ptr_t * vRings; // onion rings in ddR - Vec_Ptr_t * vRoots; // BDDs for partitions - - // structural info - Vec_Int_t * vOrder; // for each object ID, its BDD variable number or -1 - Vec_Int_t * vVars2Q; // 1 if variable is quantifiable; 0 othervise - - int timeImage; - int timeRemap; - int timeReo; - int timeOther; - int timeTotal; -}; - -//extern int timeBuild, timeAndEx, timeOther; -//extern int nSuppMax; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes bad in working manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_Nonlin4ComputeBad( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder ) -{ - Vec_Ptr_t * vNodes; - DdNode * bBdd, * bBdd0, * bBdd1, * bTemp, * bResult, * bCube; - Aig_Obj_t * pObj; - int i; - Aig_ManCleanData( pAig ); - // assign elementary variables - Aig_ManConst1(pAig)->pData = Cudd_ReadOne(dd); - Aig_ManForEachPi( pAig, pObj, i ) - pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); - // compute internal nodes - vNodes = Aig_ManDfsNodes( pAig, (Aig_Obj_t **)Vec_PtrArray(pAig->vPos), Saig_ManPoNum(pAig) ); - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) - { - if ( !Aig_ObjIsNode(pObj) ) - continue; - bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); - bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); - if ( bBdd == NULL ) - { - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) - if ( Aig_ObjIsNode(pObj) && pObj->pData != NULL ) - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); - Vec_PtrFree( vNodes ); - return NULL; - } - Cudd_Ref( bBdd ); - pObj->pData = bBdd; - } - // quantify PIs of each PO - bResult = Cudd_ReadLogicZero( dd ); Cudd_Ref( bResult ); - Saig_ManForEachPo( pAig, pObj, i ) - { - bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bResult = Cudd_bddOr( dd, bTemp = bResult, bBdd0 ); - if ( bResult == NULL ) - { - Cudd_RecursiveDeref( dd, bTemp ); - break; - } - Cudd_Ref( bResult ); - Cudd_RecursiveDeref( dd, bTemp ); - } - // deref - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) - if ( Aig_ObjIsNode(pObj) && pObj->pData != NULL ) - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); - Vec_PtrFree( vNodes ); - if ( bResult ) - { - bCube = Cudd_ReadOne(dd); Cudd_Ref( bCube ); - Saig_ManForEachPi( pAig, pObj, i ) - { - bCube = Cudd_bddAnd( dd, bTemp = bCube, (DdNode *)pObj->pData ); Cudd_Ref( bCube ); - Cudd_RecursiveDeref( dd, bTemp ); - } - bResult = Cudd_bddExistAbstract( dd, bTemp = bResult, bCube ); Cudd_Ref( bResult ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bCube ); - Cudd_Deref( bResult ); - } -//if ( bResult ) -//printf( "Bad state = %d.\n", Cudd_DagSize(bResult) ); - return bResult; -} - -/**Function************************************************************* - - Synopsis [Derives BDDs for the partitions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_Nonlin4DerivePartitions( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder ) -{ - Vec_Ptr_t * vRoots; - Aig_Obj_t * pObj; - DdNode * bBdd, * bBdd0, * bBdd1, * bPart; - int i; - Aig_ManCleanData( pAig ); - // assign elementary variables - Aig_ManConst1(pAig)->pData = Cudd_ReadOne(dd); - Aig_ManForEachPi( pAig, pObj, i ) - pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); - Aig_ManForEachNode( pAig, pObj, i ) - if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) - { - pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); - Cudd_Ref( (DdNode *)pObj->pData ); - } - Saig_ManForEachLi( pAig, pObj, i ) - pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); - // compute intermediate BDDs - vRoots = Vec_PtrAlloc( 100 ); - Aig_ManForEachNode( pAig, pObj, i ) - { - bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); - bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); - if ( bBdd == NULL ) - goto finish; - Cudd_Ref( bBdd ); - if ( pObj->pData == NULL ) - { - pObj->pData = bBdd; - continue; - } - // create new partition - bPart = Cudd_bddXnor( dd, (DdNode *)pObj->pData, bBdd ); - if ( bPart == NULL ) - goto finish; - Cudd_Ref( bPart ); - Cudd_RecursiveDeref( dd, bBdd ); - Vec_PtrPush( vRoots, bPart ); -//printf( "%d ", Cudd_DagSize(bPart) ); - } - // compute register output BDDs - Saig_ManForEachLi( pAig, pObj, i ) - { - bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bPart = Cudd_bddXnor( dd, (DdNode *)pObj->pData, bBdd0 ); - if ( bPart == NULL ) - goto finish; - Cudd_Ref( bPart ); - Vec_PtrPush( vRoots, bPart ); -//printf( "%d ", Cudd_DagSize(bPart) ); - } -//printf( "\n" ); - Aig_ManForEachNode( pAig, pObj, i ) - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); - return vRoots; - // early termination -finish: - Aig_ManForEachNode( pAig, pObj, i ) - if ( pObj->pData ) - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); - Vec_PtrForEachEntry( DdNode *, vRoots, bPart, i ) - Cudd_RecursiveDeref( dd, bPart ); - Vec_PtrFree( vRoots ); - return NULL; -} - -/**Function************************************************************* - - Synopsis [Find simple variable ordering.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_Nonlin4CreateOrderSimple( Aig_Man_t * pAig ) -{ - Vec_Int_t * vOrder; - Aig_Obj_t * pObj; - int i, Counter = 0; - vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) ); - Aig_ManForEachPi( pAig, pObj, i ) - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); - Saig_ManForEachLi( pAig, pObj, i ) - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); - return vOrder; -} - -/**Function************************************************************* - - Synopsis [Find good static variable ordering.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4CreateOrder_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vOrder, int * pCounter ) -{ - Aig_Obj_t * pFanin0, * pFanin1; - if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) - return; - Aig_ObjSetTravIdCurrent( pAig, pObj ); - assert( Llb_ObjBddVar(vOrder, pObj) < 0 ); - if ( Aig_ObjIsPi(pObj) ) - { -// if ( Saig_ObjIsLo(pAig, pObj) ) -// Vec_IntWriteEntry( vOrder, Aig_ObjId(Saig_ObjLoToLi(pAig, pObj)), (*pCounter)++ ); - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); - return; - } - // try fanins with higher level first - pFanin0 = Aig_ObjFanin0(pObj); - pFanin1 = Aig_ObjFanin1(pObj); -// if ( pFanin0->Level > pFanin1->Level || (pFanin0->Level == pFanin1->Level && pFanin0->Id < pFanin1->Id) ) - if ( pFanin0->Level > pFanin1->Level ) - { - Llb_Nonlin4CreateOrder_rec( pAig, pFanin0, vOrder, pCounter ); - Llb_Nonlin4CreateOrder_rec( pAig, pFanin1, vOrder, pCounter ); - } - else - { - Llb_Nonlin4CreateOrder_rec( pAig, pFanin1, vOrder, pCounter ); - Llb_Nonlin4CreateOrder_rec( pAig, pFanin0, vOrder, pCounter ); - } - if ( pObj->fMarkA ) - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); -} - -/**Function************************************************************* - - Synopsis [Collect nodes with the given fanout count.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_Nonlin4CollectHighRefNodes( Aig_Man_t * pAig, int nFans ) -{ - Vec_Int_t * vNodes; - Aig_Obj_t * pObj; - int i; - Aig_ManCleanMarkA( pAig ); - Aig_ManForEachNode( pAig, pObj, i ) - if ( Aig_ObjRefs(pObj) >= nFans ) - pObj->fMarkA = 1; - // unmark flop drivers - Saig_ManForEachLi( pAig, pObj, i ) - Aig_ObjFanin0(pObj)->fMarkA = 0; - // collect mapping - vNodes = Vec_IntAlloc( 100 ); - Aig_ManForEachNode( pAig, pObj, i ) - if ( pObj->fMarkA ) - Vec_IntPush( vNodes, Aig_ObjId(pObj) ); - Aig_ManCleanMarkA( pAig ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Find good static variable ordering.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_Nonlin4CreateOrder( Aig_Man_t * pAig ) -{ - Vec_Int_t * vNodes = NULL; - Vec_Int_t * vOrder; - Aig_Obj_t * pObj; - int i, Counter = 0; -/* - // mark internal nodes to be used - Aig_ManCleanMarkA( pAig ); - vNodes = Llb_Nonlin4CollectHighRefNodes( pAig, 4 ); - Aig_ManForEachObjVec( vNodes, pAig, pObj, i ) - pObj->fMarkA = 1; -printf( "Techmapping added %d pivots.\n", Vec_IntSize(vNodes) ); -*/ - // collect nodes in the order - vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) ); - Aig_ManIncrementTravId( pAig ); - Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) ); - Saig_ManForEachLi( pAig, pObj, i ) - { - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); - Llb_Nonlin4CreateOrder_rec( pAig, Aig_ObjFanin0(pObj), vOrder, &Counter ); - } - Aig_ManForEachPi( pAig, pObj, i ) - if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) - { -// if ( Saig_ObjIsLo(pAig, pObj) ) -// Vec_IntWriteEntry( vOrder, Aig_ObjId(Saig_ObjLoToLi(pAig, pObj)), Counter++ ); - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); - } - assert( Counter <= Aig_ManPiNum(pAig) + Aig_ManRegNum(pAig) + (vNodes?Vec_IntSize(vNodes):0) ); - Aig_ManCleanMarkA( pAig ); - Vec_IntFreeP( &vNodes ); - return vOrder; -} - - -/**Function************************************************************* - - Synopsis [Creates quantifiable varaibles for both types of traversal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_Nonlin4CreateVars2Q( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fBackward ) -{ - Vec_Int_t * vVars2Q; - Aig_Obj_t * pObjLi, * pObjLo; - int i; - vVars2Q = Vec_IntAlloc( 0 ); - Vec_IntFill( vVars2Q, Cudd_ReadSize(dd), 1 ); - Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) - Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, fBackward ? pObjLo : pObjLi), 0 ); - return vVars2Q; -} - -/**Function************************************************************* - - Synopsis [Compute initial state in terms of current state variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4SetupVarMap( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder ) -{ - DdNode ** pVarsX, ** pVarsY; - Aig_Obj_t * pObjLo, * pObjLi; - int i; - pVarsX = ABC_ALLOC( DdNode *, Cudd_ReadSize(dd) ); - pVarsY = ABC_ALLOC( DdNode *, Cudd_ReadSize(dd) ); - Saig_ManForEachLiLo( pAig, pObjLo, pObjLi, i ) - { - assert( Llb_ObjBddVar(vOrder, pObjLo) >= 0 ); - assert( Llb_ObjBddVar(vOrder, pObjLi) >= 0 ); - pVarsX[i] = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObjLo) ); - pVarsY[i] = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObjLi) ); - } - Cudd_SetVarMap( dd, pVarsX, pVarsY, Aig_ManRegNum(pAig) ); - ABC_FREE( pVarsX ); - ABC_FREE( pVarsY ); -} - -/**Function************************************************************* - - Synopsis [Compute initial state in terms of current state variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_Nonlin4ComputeInitState( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fBackward ) -{ - Aig_Obj_t * pObjLi, * pObjLo; - DdNode * bRes, * bVar, * bTemp; - int i, TimeStop; - TimeStop = dd->TimeStop; dd->TimeStop = 0; - bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); - Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) - { - bVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, fBackward? pObjLi : pObjLo) ); - bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bRes ); - dd->TimeStop = TimeStop; - return bRes; -} - -/**Function************************************************************* - - Synopsis [Compute initial state in terms of current state variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_Nonlin4ComputeCube( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, char * pValues, int Flag ) -{ - Aig_Obj_t * pObjLo, * pObjLi, * pObjTemp; - DdNode * bRes, * bVar, * bTemp; - int i, TimeStop; - TimeStop = dd->TimeStop; dd->TimeStop = 0; - bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); - Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) - { - if ( Flag ) - pObjTemp = pObjLo, pObjLo = pObjLi, pObjLi = pObjTemp; - // get the correspoding flop input variable - bVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObjLi) ); - if ( pValues[Llb_ObjBddVar(vOrder, pObjLo)] != 1 ) - bVar = Cudd_Not(bVar); - // create cube - bRes = Cudd_bddAnd( dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bRes ); - dd->TimeStop = TimeStop; - return bRes; -} - -/**Function************************************************************* - - Synopsis [Compute initial state in terms of current state variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4RecordState( Aig_Man_t * pAig, Vec_Int_t * vOrder, unsigned * pState, char * pValues, int fBackward ) -{ - Aig_Obj_t * pObjLo, * pObjLi; - int i; - Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) - if ( pValues[Llb_ObjBddVar(vOrder, fBackward? pObjLi : pObjLo)] == 1 ) - Aig_InfoSetBit( pState, i ); -} - -/**Function************************************************************* - - Synopsis [Multiply every partition by the cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_Nonlin4Multiply( DdManager * dd, DdNode * bCube, Vec_Ptr_t * vParts ) -{ - Vec_Ptr_t * vNew; - DdNode * bTemp, * bFunc; - int i; - vNew = Vec_PtrAlloc( Vec_PtrSize(vParts) ); - Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i ) - { - bTemp = Cudd_bddAnd( dd, bFunc, bCube ); Cudd_Ref( bTemp ); - Vec_PtrPush( vNew, bTemp ); - } - return vNew; -} - -/**Function************************************************************* - - Synopsis [Multiply every partition by the cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4Deref( DdManager * dd, Vec_Ptr_t * vParts ) -{ - DdNode * bFunc; - int i; - Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i ) - Cudd_RecursiveDeref( dd, bFunc ); - Vec_PtrFree( vParts ); -} - -/**Function************************************************************* - - Synopsis [Derives counter-example by backward reachability.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_Nonlin4DeriveCex( Llb_Mnx_t * p, int fBackward, int fVerbose ) -{ - Vec_Int_t * vVars2Q; - Vec_Ptr_t * vStates, * vRootsNew; - Aig_Obj_t * pObj; - DdNode * bState, * bImage, * bOneCube, * bRing; - int i, v, RetValue, clk = clock(); - char * pValues; - assert( Vec_PtrSize(p->vRings) > 0 ); - // disable the timeout - p->dd->TimeStop = 0; - - // start the state set - vStates = Vec_PtrAllocSimInfo( Vec_PtrSize(p->vRings), Aig_BitWordNum(Aig_ManRegNum(p->pAig)) ); - Vec_PtrCleanSimInfo( vStates, 0, Aig_BitWordNum(Aig_ManRegNum(p->pAig)) ); - if ( fBackward ) - Vec_PtrReverseOrder( vStates ); - - // get the last cube - pValues = ABC_ALLOC( char, Cudd_ReadSize(p->dd) ); - bOneCube = Cudd_bddIntersect( p->dd, (DdNode *)Vec_PtrEntryLast(p->vRings), p->bBad ); Cudd_Ref( bOneCube ); - RetValue = Cudd_bddPickOneCube( p->dd, bOneCube, pValues ); - Cudd_RecursiveDeref( p->dd, bOneCube ); - assert( RetValue ); - - // record the cube - Llb_Nonlin4RecordState( p->pAig, p->vOrder, (unsigned *)Vec_PtrEntryLast(vStates), pValues, fBackward ); - - // write state in terms of NS variables - if ( Vec_PtrSize(p->vRings) > 1 ) - { - bState = Llb_Nonlin4ComputeCube( p->dd, p->pAig, p->vOrder, pValues, fBackward ); Cudd_Ref( bState ); - } - // perform backward analysis - vVars2Q = Llb_Nonlin4CreateVars2Q( p->dd, p->pAig, p->vOrder, !fBackward ); - Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v ) - { - if ( v == Vec_PtrSize(p->vRings) - 1 ) - continue; - - // preprocess partitions - vRootsNew = Llb_Nonlin4Multiply( p->dd, bState, p->vRoots ); - Cudd_RecursiveDeref( p->dd, bState ); - - // compute the next states - bImage = Llb_Nonlin4Image( p->dd, vRootsNew, NULL, vVars2Q ); Cudd_Ref( bImage ); - Llb_Nonlin4Deref( p->dd, vRootsNew ); - - // intersect with the previous set - bOneCube = Cudd_bddIntersect( p->dd, bImage, bRing ); Cudd_Ref( bOneCube ); - Cudd_RecursiveDeref( p->dd, bImage ); - - // find any assignment of the BDD - RetValue = Cudd_bddPickOneCube( p->dd, bOneCube, pValues ); - Cudd_RecursiveDeref( p->dd, bOneCube ); - assert( RetValue ); - - // record the cube - Llb_Nonlin4RecordState( p->pAig, p->vOrder, (unsigned *)Vec_PtrEntry(vStates, v), pValues, fBackward ); - - // check that we get the init state - if ( v == 0 ) - { - Saig_ManForEachLo( p->pAig, pObj, i ) - assert( fBackward || pValues[Llb_ObjBddVar(p->vOrder, pObj)] == 0 ); - break; - } - - // write state in terms of NS variables - bState = Llb_Nonlin4ComputeCube( p->dd, p->pAig, p->vOrder, pValues, fBackward ); Cudd_Ref( bState ); - } - Vec_IntFree( vVars2Q ); - ABC_FREE( pValues ); - if ( fBackward ) - Vec_PtrReverseOrder( vStates ); -// if ( fVerbose ) -// Abc_PrintTime( 1, "BDD-based cex generation time", clock() - clk ); - return vStates; -} - - -/**Function************************************************************* - - Synopsis [Perform reachability with hints.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_Nonlin4Reachability( Llb_Mnx_t * p ) -{ - DdNode * bAux; - int nIters, nBddSizeFr, nBddSizeTo, nBddSizeTo2; - int clkTemp, clkIter, clk = clock(); - assert( Aig_ManRegNum(p->pAig) > 0 ); - - if ( p->pPars->fBackward ) - { - // create bad state in the ring manager - if ( !p->pPars->fSkipOutCheck ) - { - p->bBad = Llb_Nonlin4ComputeInitState( p->dd, p->pAig, p->vOrder, p->pPars->fBackward ); Cudd_Ref( p->bBad ); - } - // create init state - if ( p->pPars->fCluster ) - p->bCurrent = p->dd->bFunc, p->dd->bFunc = NULL; - else - { - p->bCurrent = Llb_Nonlin4ComputeBad( p->dd, p->pAig, p->vOrder ); - if ( p->bCurrent == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = -1; - return -1; - } - Cudd_Ref( p->bCurrent ); - } - // remap into the next states - p->bCurrent = Cudd_bddVarMap( p->dd, bAux = p->bCurrent ); - if ( p->bCurrent == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during remapping bad states.\n", p->pPars->TimeLimit ); - Cudd_RecursiveDeref( p->dd, bAux ); - p->pPars->iFrame = -1; - return -1; - } - Cudd_Ref( p->bCurrent ); - Cudd_RecursiveDeref( p->dd, bAux ); - } - else - { - // create bad state in the ring manager - if ( !p->pPars->fSkipOutCheck ) - { - if ( p->pPars->fCluster ) - p->bBad = p->dd->bFunc, p->dd->bFunc = NULL; - else - { - p->bBad = Llb_Nonlin4ComputeBad( p->dd, p->pAig, p->vOrder ); - if ( p->bBad == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = -1; - return -1; - } - Cudd_Ref( p->bBad ); - } - } - else if ( p->dd->bFunc ) - Cudd_RecursiveDeref( p->dd, p->dd->bFunc ), p->dd->bFunc = NULL; - // compute the starting set of states - p->bCurrent = Llb_Nonlin4ComputeInitState( p->dd, p->pAig, p->vOrder, p->pPars->fBackward ); Cudd_Ref( p->bCurrent ); - } - // perform iterations - p->bReached = p->bCurrent; Cudd_Ref( p->bReached ); - for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ ) - { - clkIter = clock(); - // check the runtime limit - if ( p->pPars->TimeLimit && time(NULL) > p->pPars->TimeTarget ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - return -1; - } - - // save the onion ring - Vec_PtrPush( p->vRings, p->bCurrent ); Cudd_Ref( p->bCurrent ); - - // check it for bad states - if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->dd, p->bCurrent, Cudd_Not(p->bBad) ) ) - { - Vec_Ptr_t * vStates; - assert( p->pAig->pSeqModel == NULL ); - vStates = Llb_Nonlin4DeriveCex( p, p->pPars->fBackward, p->pPars->fVerbose ); - p->pAig->pSeqModel = Llb4_Nonlin4TransformCex( p->pAig, vStates, -1, p->pPars->fVerbose ); - Vec_PtrFreeP( &vStates ); - if ( !p->pPars->fSilent ) - { - printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump a witness). ", p->pAig->pSeqModel->iPo, nIters ); - Abc_PrintTime( 1, "Time", clock() - clk ); - } - p->pPars->iFrame = nIters - 1; - return 0; - } - - // compute the next states - clkTemp = clock(); - p->bNext = Llb_Nonlin4Image( p->dd, p->vRoots, p->bCurrent, p->vVars2Q ); - if ( p->bNext == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation in quantification.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - return -1; - } - Cudd_Ref( p->bNext ); - p->timeImage += clock() - clkTemp; - - // remap into current states - clkTemp = clock(); - p->bNext = Cudd_bddVarMap( p->dd, bAux = p->bNext ); - if ( p->bNext == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during remapping next states.\n", p->pPars->TimeLimit ); - Cudd_RecursiveDeref( p->dd, bAux ); - p->pPars->iFrame = nIters - 1; - return -1; - } - Cudd_Ref( p->bNext ); - Cudd_RecursiveDeref( p->dd, bAux ); - p->timeRemap += clock() - clkTemp; - - // collect statistics - if ( p->pPars->fVerbose ) - { - nBddSizeFr = Cudd_DagSize( p->bCurrent ); - nBddSizeTo = Cudd_DagSize( bAux ); - nBddSizeTo2 = Cudd_DagSize( p->bNext ); - } - Cudd_RecursiveDeref( p->dd, p->bCurrent ); p->bCurrent = NULL; - - // derive new states - p->bCurrent = Cudd_bddAnd( p->dd, p->bNext, Cudd_Not(p->bReached) ); - if ( p->bCurrent == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - return -1; - } - Cudd_Ref( p->bCurrent ); - Cudd_RecursiveDeref( p->dd, p->bNext ); p->bNext = NULL; - if ( Cudd_IsConstant(p->bCurrent) ) - break; -/* - // reduce BDD size using constrain // Cudd_bddRestrict - p->bCurrent = Cudd_bddRestrict( p->dd, bAux = p->bCurrent, Cudd_Not(p->bReached) ); - Cudd_Ref( p->bCurrent ); -printf( "Before = %d. After = %d.\n", Cudd_DagSize(bAux), Cudd_DagSize(p->bCurrent) ); - Cudd_RecursiveDeref( p->dd, bAux ); -*/ - - // add to the reached set - p->bReached = Cudd_bddOr( p->dd, bAux = p->bReached, p->bCurrent ); - if ( p->bReached == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->dd, bAux ); - return -1; - } - Cudd_Ref( p->bReached ); - Cudd_RecursiveDeref( p->dd, bAux ); - - - // report the results - if ( p->pPars->fVerbose ) - { - printf( "I =%5d : ", nIters ); - printf( "Fr =%7d ", nBddSizeFr ); - printf( "ImNs =%7d ", nBddSizeTo ); - printf( "ImCs =%7d ", nBddSizeTo2 ); - printf( "Rea =%7d ", Cudd_DagSize(p->bReached) ); - printf( "(%4d %4d) ", Cudd_ReadReorderings(p->dd), Cudd_ReadGarbageCollections(p->dd) ); - Abc_PrintTime( 1, "T", clock() - clkIter ); - } -/* - if ( pPars->fVerbose ) - { - double nMints = Cudd_CountMinterm(p->dd, bReached, Saig_ManRegNum(p->pAig) ); -// Extra_bddPrint( p->dd, bReached );printf( "\n" ); - printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); - fflush( stdout ); - } -*/ - if ( nIters == p->pPars->nIterMax - 1 ) - { - if ( !p->pPars->fSilent ) - printf( "Reached limit on the number of timeframes (%d).\n", p->pPars->nIterMax ); - p->pPars->iFrame = nIters; - return -1; - } - } - - // report the stats - if ( p->pPars->fVerbose ) - { - double nMints = Cudd_CountMinterm(p->dd, p->bReached, Saig_ManRegNum(p->pAig) ); - if ( p->bCurrent && Cudd_IsConstant(p->bCurrent) ) - printf( "Reachability analysis completed after %d frames.\n", nIters ); - else - printf( "Reachability analysis is stopped after %d frames.\n", nIters ); - printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); - fflush( stdout ); - } - if ( p->bCurrent == NULL || !Cudd_IsConstant(p->bCurrent) ) - { - if ( !p->pPars->fSilent ) - printf( "Verified only for states reachable in %d frames. ", nIters ); - p->pPars->iFrame = p->pPars->nIterMax; - return -1; // undecided - } - // report - if ( !p->pPars->fSilent ) - printf( "The miter is proved unreachable after %d iterations. ", nIters ); - p->pPars->iFrame = nIters - 1; - Abc_PrintTime( 1, "Time", clock() - clk ); - return 1; // unreachable -} - -/**Function************************************************************* - - Synopsis [Reorders BDDs in the working manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4Reorder( DdManager * dd, int fTwice, int fVerbose ) -{ - int clk = clock(); - if ( fVerbose ) - Abc_Print( 1, "Reordering... Before =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); - Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); - if ( fVerbose ) - Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); - if ( fTwice ) - { - Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); - if ( fVerbose ) - Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); - } - if ( fVerbose ) - Abc_PrintTime( 1, "Time", clock() - clk ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Mnx_t * Llb_MnxStart( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) -{ - Llb_Mnx_t * p; - - p = ABC_CALLOC( Llb_Mnx_t, 1 ); - p->pAig = pAig; - p->pPars = pPars; - - // compute time to stop - p->pPars->TimeTarget = p->pPars->TimeLimit ? time(NULL) + p->pPars->TimeLimit : 0; - - if ( pPars->fCluster ) - { -// Llb_Nonlin4Cluster( p->pAig, &p->dd, &p->vOrder, &p->vRoots, pPars->nBddMax, pPars->fVerbose ); -// Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); - Llb4_Nonlin4Sweep( p->pAig, pPars->nBddMax, pPars->nClusterMax, &p->dd, &p->vOrder, &p->vRoots, pPars->fVerbose ); - // set the stop time parameter - p->dd->TimeStop = p->pPars->TimeTarget; - } - else - { -// p->vOrder = Llb_Nonlin4CreateOrderSimple( pAig ); - p->vOrder = Llb_Nonlin4CreateOrder( pAig ); - p->dd = Cudd_Init( Vec_IntCountPositive(p->vOrder) + 1, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); - Cudd_SetMaxGrowth( p->dd, 1.05 ); - // set the stop time parameter - p->dd->TimeStop = p->pPars->TimeTarget; - p->vRoots = Llb_Nonlin4DerivePartitions( p->dd, pAig, p->vOrder ); - } - - Llb_Nonlin4SetupVarMap( p->dd, pAig, p->vOrder ); - p->vVars2Q = Llb_Nonlin4CreateVars2Q( p->dd, pAig, p->vOrder, p->pPars->fBackward ); - p->vRings = Vec_PtrAlloc( 100 ); - - if ( pPars->fReorder ) - Llb_Nonlin4Reorder( p->dd, 0, 1 ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MnxStop( Llb_Mnx_t * p ) -{ - DdNode * bTemp; - int i; - if ( p->pPars->fVerbose ) - { - p->timeReo = Cudd_ReadReorderingTime(p->dd); - p->timeOther = p->timeTotal - p->timeImage - p->timeRemap; - ABC_PRTP( "Image ", p->timeImage, p->timeTotal ); - ABC_PRTP( "Remap ", p->timeRemap, p->timeTotal ); - ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); - ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); - ABC_PRTP( " reo ", p->timeReo, p->timeTotal ); - } - // remove BDDs - if ( p->bBad ) - Cudd_RecursiveDeref( p->dd, p->bBad ); - if ( p->bReached ) - Cudd_RecursiveDeref( p->dd, p->bReached ); - if ( p->bCurrent ) - Cudd_RecursiveDeref( p->dd, p->bCurrent ); - if ( p->bNext ) - Cudd_RecursiveDeref( p->dd, p->bNext ); - if ( p->vRings ) - Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i ) - Cudd_RecursiveDeref( p->dd, bTemp ); - if ( p->vRoots ) - Vec_PtrForEachEntry( DdNode *, p->vRoots, bTemp, i ) - Cudd_RecursiveDeref( p->dd, bTemp ); - // remove arrays - Vec_PtrFreeP( &p->vRings ); - Vec_PtrFreeP( &p->vRoots ); -//Cudd_PrintInfo( p->dd, stdout ); - Extra_StopManager( p->dd ); - Vec_IntFreeP( &p->vOrder ); - Vec_IntFreeP( &p->vVars2Q ); - ABC_FREE( p ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MnxCheckNextStateVars( Llb_Mnx_t * p ) -{ - Aig_Obj_t * pObj; - int i, Counter0 = 0, Counter1 = 0; - Saig_ManForEachLi( p->pAig, pObj, i ) - if ( Saig_ObjIsLo(p->pAig, Aig_ObjFanin0(pObj)) ) - { - if ( Aig_ObjFaninC0(pObj) ) - Counter0++; - else - Counter1++; - } - printf( "Total = %d. Direct LO = %d. Compl LO = %d.\n", Aig_ManRegNum(p->pAig), Counter1, Counter0 ); -} - -/**Function************************************************************* - - Synopsis [Finds balanced cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_Nonlin4CoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) -{ - Llb_Mnx_t * pMnn; - int RetValue = -1; - if ( pPars->fVerbose ) - Aig_ManPrintStats( pAig ); - if ( pPars->fCluster && Aig_ManObjNum(pAig) >= (1 << 15) ) - { - printf( "The number of objects is more than 2^15. Clustering cannot be used.\n" ); - return RetValue; - } - { - int clk = clock(); - pMnn = Llb_MnxStart( pAig, pPars ); -//Llb_MnxCheckNextStateVars( pMnn ); - if ( !pPars->fSkipReach ) - RetValue = Llb_Nonlin4Reachability( pMnn ); - pMnn->timeTotal = clock() - clk; - Llb_MnxStop( pMnn ); - } - return RetValue; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llb4Sweep.c b/src/aig/llb/llb4Sweep.c deleted file mode 100644 index d13c366f..00000000 --- a/src/aig/llb/llb4Sweep.c +++ /dev/null @@ -1,588 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb2Sweep.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Non-linear quantification scheduling.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb2Sweep.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Find good static variable ordering.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4SweepOrder_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vOrder, int * pCounter, int fSaveAll ) -{ - Aig_Obj_t * pFanin0, * pFanin1; - if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) - return; - Aig_ObjSetTravIdCurrent( pAig, pObj ); - assert( Llb_ObjBddVar(vOrder, pObj) < 0 ); - if ( Aig_ObjIsPi(pObj) ) - { - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); - return; - } - // try fanins with higher level first - pFanin0 = Aig_ObjFanin0(pObj); - pFanin1 = Aig_ObjFanin1(pObj); -// if ( pFanin0->Level > pFanin1->Level || (pFanin0->Level == pFanin1->Level && pFanin0->Id < pFanin1->Id) ) - if ( pFanin0->Level > pFanin1->Level ) - { - Llb_Nonlin4SweepOrder_rec( pAig, pFanin0, vOrder, pCounter, fSaveAll ); - Llb_Nonlin4SweepOrder_rec( pAig, pFanin1, vOrder, pCounter, fSaveAll ); - } - else - { - Llb_Nonlin4SweepOrder_rec( pAig, pFanin1, vOrder, pCounter, fSaveAll ); - Llb_Nonlin4SweepOrder_rec( pAig, pFanin0, vOrder, pCounter, fSaveAll ); - } - if ( fSaveAll || pObj->fMarkA ) - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); -} - -/**Function************************************************************* - - Synopsis [Find good static variable ordering.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_Nonlin4SweepOrder( Aig_Man_t * pAig, int * pCounter, int fSaveAll ) -{ - Vec_Int_t * vOrder; - Aig_Obj_t * pObj; - int i, Counter = 0; - // collect nodes in the order - vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) ); - Aig_ManIncrementTravId( pAig ); - Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) ); - Aig_ManForEachPo( pAig, pObj, i ) - { - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); - Llb_Nonlin4SweepOrder_rec( pAig, Aig_ObjFanin0(pObj), vOrder, &Counter, fSaveAll ); - } - Aig_ManForEachPi( pAig, pObj, i ) - if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); -// assert( Counter == Aig_ManObjNum(pAig) - 1 ); // no dangling nodes - if ( pCounter ) - *pCounter = Counter - Aig_ManPiNum(pAig) - Aig_ManPoNum(pAig); - return vOrder; -} - - -/**Function************************************************************* - - Synopsis [Performs BDD sweep on the netlist.] - - Description [Returns AIG with internal cut points labeled with fMarkA.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb4_Nonlin4SweepCutpoints( Aig_Man_t * pAig, Vec_Int_t * vOrder, int nBddLimit, int fVerbose ) -{ - DdManager * dd; - DdNode * bFunc0, * bFunc1, * bFunc; - Aig_Obj_t * pObj; - int i, Counter = 0, Counter1 = 0; - dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - // assign elementary variables - Aig_ManCleanData( pAig ); - Aig_ManForEachPi( pAig, pObj, i ) - pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); - // sweep internal nodes - Aig_ManForEachNode( pAig, pObj, i ) - { -/* - if ( pObj->nRefs >= 4 ) - { - bFunc = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); Cudd_Ref( bFunc ); - pObj->pData = bFunc; - Counter1++; - continue; - } -*/ - bFunc0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bFunc1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); - bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); - if ( Cudd_DagSize(bFunc) > nBddLimit ) - { -// if ( fVerbose ) -// printf( "Node %5d : Beg =%5d. ", i, Cudd_DagSize(bFunc) ); - - // add cutpoint at a larger one - Cudd_RecursiveDeref( dd, bFunc ); - if ( Cudd_DagSize(bFunc0) >= Cudd_DagSize(bFunc1) ) - { - Cudd_RecursiveDeref( dd, (DdNode *)Aig_ObjFanin0(pObj)->pData ); - bFunc = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, Aig_ObjFanin0(pObj)) ); - Aig_ObjFanin0(pObj)->pData = bFunc; Cudd_Ref( bFunc ); - Aig_ObjFanin0(pObj)->fMarkA = 1; - -// if ( fVerbose ) -// printf( "Ref =%3d ", Aig_ObjFanin0(pObj)->nRefs ); - } - else - { - Cudd_RecursiveDeref( dd, (DdNode *)Aig_ObjFanin1(pObj)->pData ); - bFunc = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, Aig_ObjFanin1(pObj)) ); - Aig_ObjFanin1(pObj)->pData = bFunc; Cudd_Ref( bFunc ); - Aig_ObjFanin1(pObj)->fMarkA = 1; - -// if ( fVerbose ) -// printf( "Ref =%3d ", Aig_ObjFanin1(pObj)->nRefs ); - } - // perform new operation - bFunc0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bFunc1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); - bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); -// assert( Cudd_DagSize(bFunc) <= nBddLimit ); - -// if ( fVerbose ) -// printf( "End =%5d.\n", Cudd_DagSize(bFunc) ); - Counter++; - } - pObj->pData = bFunc; -//printf( "%d ", Cudd_DagSize(bFunc) ); - } -//printf( "\n" ); - // clean up - Aig_ManForEachNode( pAig, pObj, i ) - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); - Extra_StopManager( dd ); -// Aig_ManCleanMarkA( pAig ); - if ( fVerbose ) - printf( "Added %d cut points. Used %d high fanout points.\n", Counter, Counter1 ); - return Counter + Counter1; -} - -/**Function************************************************************* - - Synopsis [Derives BDDs for the partitions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_Nonlin4SweepPartitions_rec( DdManager * dd, Aig_Obj_t * pObj, Vec_Int_t * vOrder, Vec_Ptr_t * vRoots ) -{ - DdNode * bBdd, * bBdd0, * bBdd1, * bPart, * vVar; - if ( Aig_ObjIsConst1(pObj) ) - return Cudd_ReadOne(dd); - if ( Aig_ObjIsPi(pObj) ) - return Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); - if ( pObj->pData ) - return (DdNode *)pObj->pData; - if ( Aig_ObjIsPo(pObj) ) - { - bBdd0 = Cudd_NotCond( Llb_Nonlin4SweepPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) ); - bPart = Cudd_bddXnor( dd, Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ), bBdd0 ); Cudd_Ref( bPart ); - Vec_PtrPush( vRoots, bPart ); - return NULL; - } - bBdd0 = Cudd_NotCond( Llb_Nonlin4SweepPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) ); - bBdd1 = Cudd_NotCond( Llb_Nonlin4SweepPartitions_rec(dd, Aig_ObjFanin1(pObj), vOrder, vRoots), Aig_ObjFaninC1(pObj) ); - bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bBdd ); - if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) - { - vVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); - bPart = Cudd_bddXnor( dd, vVar, bBdd ); Cudd_Ref( bPart ); - Vec_PtrPush( vRoots, bPart ); - Cudd_RecursiveDeref( dd, bBdd ); - bBdd = vVar; Cudd_Ref( vVar ); - } - pObj->pData = bBdd; - return bBdd; -} - -/**Function************************************************************* - - Synopsis [Derives BDDs for the partitions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_Nonlin4SweepPartitions( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fTransition ) -{ - Vec_Ptr_t * vRoots; - Aig_Obj_t * pObj; - int i; - Aig_ManCleanData( pAig ); - vRoots = Vec_PtrAlloc( 100 ); - if ( fTransition ) - { - Saig_ManForEachLi( pAig, pObj, i ) - Llb_Nonlin4SweepPartitions_rec( dd, pObj, vOrder, vRoots ); - } - else - { - Saig_ManForEachPo( pAig, pObj, i ) - Llb_Nonlin4SweepPartitions_rec( dd, pObj, vOrder, vRoots ); - } - Aig_ManForEachNode( pAig, pObj, i ) - if ( pObj->pData ) - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); - return vRoots; -} - -/**Function************************************************************* - - Synopsis [Get bad state monitor.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb4_Nonlin4SweepBadMonitor( Aig_Man_t * pAig, Vec_Int_t * vOrder, DdManager * dd ) -{ - Aig_Obj_t * pObj; - DdNode * bRes, * bVar, * bTemp; - int i, TimeStop; - TimeStop = dd->TimeStop; dd->TimeStop = 0; - bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); - Saig_ManForEachPo( pAig, pObj, i ) - { - bVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); - bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bRes ); - dd->TimeStop = TimeStop; - return Cudd_Not(bRes); -} - -/**Function************************************************************* - - Synopsis [Creates quantifiable variables for both types of traversal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_Nonlin4SweepVars2Q( Aig_Man_t * pAig, Vec_Int_t * vOrder, int fAddLis ) -{ - Vec_Int_t * vVars2Q; - Aig_Obj_t * pObj; - int i; - vVars2Q = Vec_IntAlloc( 0 ); - Vec_IntFill( vVars2Q, Aig_ManObjNumMax(pAig), 1 ); - // add flop outputs - Saig_ManForEachLo( pAig, pObj, i ) - Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 ); - // add flop inputs - if ( fAddLis ) - Saig_ManForEachLi( pAig, pObj, i ) - Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 ); - return vVars2Q; -} - -/**Function************************************************************* - - Synopsis [Multiply every partition by the cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4SweepDeref( DdManager * dd, Vec_Ptr_t * vParts ) -{ - DdNode * bFunc; - int i; - Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i ) - Cudd_RecursiveDeref( dd, bFunc ); - Vec_PtrFree( vParts ); -} - -/**Function************************************************************* - - Synopsis [Multiply every partition by the cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4SweepPrint( Vec_Ptr_t * vFuncs ) -{ - DdNode * bFunc; - int i; - printf( "(%d) ", Vec_PtrSize(vFuncs) ); - Vec_PtrForEachEntry( DdNode *, vFuncs, bFunc, i ) - printf( "%d ", Cudd_DagSize(bFunc) ); - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Computes bad states.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdManager * Llb4_Nonlin4SweepBadStates( Aig_Man_t * pAig, Vec_Int_t * vOrder, int nVars ) -{ - DdManager * dd; - Vec_Ptr_t * vParts; - Vec_Int_t * vVars2Q; - DdNode * bMonitor, * bImage; - // get quantifiable variables - vVars2Q = Llb_Nonlin4SweepVars2Q( pAig, vOrder, 0 ); - // start BDD manager and create partitions - dd = Cudd_Init( nVars, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - vParts = Llb_Nonlin4SweepPartitions( dd, pAig, vOrder, 0 ); -//printf( "Outputs: " ); -//Llb_Nonlin4SweepPrint( vParts ); - // compute image of the partitions - bMonitor = Llb4_Nonlin4SweepBadMonitor( pAig, vOrder, dd ); Cudd_Ref( bMonitor ); - Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - bImage = Llb_Nonlin4Image( dd, vParts, bMonitor, vVars2Q ); Cudd_Ref( bImage ); - Cudd_RecursiveDeref( dd, bMonitor ); - Llb_Nonlin4SweepDeref( dd, vParts ); - Vec_IntFree( vVars2Q ); - // save image and return - dd->bFunc = bImage; - return dd; -} - -/**Function************************************************************* - - Synopsis [Computes clusters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdManager * Llb4_Nonlin4SweepGroups( Aig_Man_t * pAig, Vec_Int_t * vOrder, int nVars, Vec_Ptr_t ** pvGroups, int nBddLimitClp, int fVerbose ) -{ - DdManager * dd; - Vec_Ptr_t * vParts; - Vec_Int_t * vVars2Q; - // get quantifiable variables - vVars2Q = Llb_Nonlin4SweepVars2Q( pAig, vOrder, 1 ); - // start BDD manager and create partitions - dd = Cudd_Init( nVars, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - vParts = Llb_Nonlin4SweepPartitions( dd, pAig, vOrder, 1 ); -//printf( "Transitions: " ); -//Llb_Nonlin4SweepPrint( vParts ); - // compute image of the partitions - - Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - *pvGroups = Llb_Nonlin4Group( dd, vParts, vVars2Q, nBddLimitClp ); - Llb_Nonlin4SweepDeref( dd, vParts ); -// *pvGroups = vParts; - -if ( fVerbose ) -{ -printf( "Groups: " ); -Llb_Nonlin4SweepPrint( *pvGroups ); -} - - Vec_IntFree( vVars2Q ); - return dd; -} - - -/**Function************************************************************* - - Synopsis [Creates quantifiable variables for both types of traversal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4SweepPrintSuppProfile( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups, int fVerbose ) -{ - Aig_Obj_t * pObj; - int i, * pSupp; - int nSuppAll = 0, nSuppPi = 0, nSuppPo = 0, nSuppLi = 0, nSuppLo = 0, nSuppAnd = 0; - - pSupp = ABC_CALLOC( int, Cudd_ReadSize(dd) ); - Extra_VectorSupportArray( dd, (DdNode **)Vec_PtrArray(vGroups), Vec_PtrSize(vGroups), pSupp ); - - Aig_ManForEachObj( pAig, pObj, i ) - { - if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) - continue; - // remove variables that do not participate - if ( pSupp[Llb_ObjBddVar(vOrder, pObj)] == 0 ) - { - if ( Aig_ObjIsNode(pObj) ) - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), -1 ); - continue; - } - nSuppAll++; - if ( Saig_ObjIsPi(pAig, pObj) ) - nSuppPi++; - else if ( Saig_ObjIsLo(pAig, pObj) ) - nSuppLo++; - else if ( Saig_ObjIsPo(pAig, pObj) ) - nSuppPo++; - else if ( Saig_ObjIsLi(pAig, pObj) ) - nSuppLi++; - else - nSuppAnd++; - } - ABC_FREE( pSupp ); - - if ( fVerbose ) - { - printf( "Groups =%3d ", Vec_PtrSize(vGroups) ); - printf( "Variables: all =%4d ", nSuppAll ); - printf( "pi =%4d ", nSuppPi ); - printf( "po =%4d ", nSuppPo ); - printf( "lo =%4d ", nSuppLo ); - printf( "li =%4d ", nSuppLi ); - printf( "and =%4d", nSuppAnd ); - printf( "\n" ); - } -} - -/**Function************************************************************* - - Synopsis [Performs BDD sweep on the netlist.] - - Description [Returns BDD manager, ordering, clusters, and bad states - inside dd->bFunc.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb4_Nonlin4Sweep( Aig_Man_t * pAig, int nSweepMax, int nClusterMax, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int fVerbose ) -{ - DdManager * ddBad, * ddWork; - Vec_Ptr_t * vGroups; - Vec_Int_t * vOrder; - int Counter, nCutPoints; - - // get the original ordering - Aig_ManCleanMarkA( pAig ); - vOrder = Llb_Nonlin4SweepOrder( pAig, &Counter, 1 ); - assert( Counter == Aig_ManNodeNum(pAig) ); - // mark the nodes - nCutPoints = Llb4_Nonlin4SweepCutpoints( pAig, vOrder, nSweepMax, fVerbose ); - Vec_IntFree( vOrder ); - // get better ordering - vOrder = Llb_Nonlin4SweepOrder( pAig, &Counter, 0 ); - assert( Counter == nCutPoints ); - Aig_ManCleanMarkA( pAig ); - // compute the BAD states - ddBad = Llb4_Nonlin4SweepBadStates( pAig, vOrder, nCutPoints + Aig_ManPiNum(pAig) + Aig_ManPoNum(pAig) ); - // compute the clusters - ddWork = Llb4_Nonlin4SweepGroups( pAig, vOrder, nCutPoints + Aig_ManPiNum(pAig) + Aig_ManPoNum(pAig), &vGroups, nClusterMax, fVerbose ); - // transfer the result from the Bad manager -//printf( "Bad before = %d.\n", Cudd_DagSize(ddBad->bFunc) ); - ddWork->bFunc = Cudd_bddTransfer( ddBad, ddWork, ddBad->bFunc ); Cudd_Ref( ddWork->bFunc ); - Cudd_RecursiveDeref( ddBad, ddBad->bFunc ); ddBad->bFunc = NULL; - Extra_StopManager( ddBad ); - // update ordering to exclude quantified variables -//printf( "Bad after = %d.\n", Cudd_DagSize(ddWork->bFunc) ); - - Llb_Nonlin4SweepPrintSuppProfile( ddWork, pAig, vOrder, vGroups, fVerbose ); - - // return the result - *pdd = ddWork; - *pvOrder = vOrder; - *pvGroups = vGroups; -} - -/**Function************************************************************* - - Synopsis [Performs BDD sweep on the netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb4_Nonlin4SweepExperiment( Aig_Man_t * pAig ) -{ - DdManager * dd; - Vec_Int_t * vOrder; - Vec_Ptr_t * vGroups; - Llb4_Nonlin4Sweep( pAig, 100, 500, &dd, &vOrder, &vGroups, 1 ); - - Llb_Nonlin4SweepDeref( dd, vGroups ); - - Cudd_RecursiveDeref( dd, dd->bFunc ); - Extra_StopManager( dd ); - Vec_IntFree( vOrder ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llbInt.h b/src/aig/llb/llbInt.h deleted file mode 100644 index 4bc2496d..00000000 --- a/src/aig/llb/llbInt.h +++ /dev/null @@ -1,212 +0,0 @@ -/**CFile**************************************************************** - - FileName [llbInt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD-based reachability.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 8, 2010.] - - Revision [$Id: llbInt.h,v 1.00 2010/05/08 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __LLB_INT_H__ -#define __LLB_INT_H__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include "aig.h" -#include "saig.h" -#include "ssw.h" -#include "cuddInt.h" -#include "extra.h" -#include "llb.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -ABC_NAMESPACE_HEADER_START - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Llb_Man_t_ Llb_Man_t; -typedef struct Llb_Mtr_t_ Llb_Mtr_t; -typedef struct Llb_Grp_t_ Llb_Grp_t; - -struct Llb_Man_t_ -{ - Gia_ParLlb_t * pPars; // parameters - Aig_Man_t * pAigGlo; // initial AIG manager (owned by the caller) - Aig_Man_t * pAig; // derived AIG manager (created in this package) - DdManager * dd; // BDD manager - DdManager * ddG; // BDD manager - DdManager * ddR; // BDD manager - Vec_Int_t * vObj2Var; // mapping AIG ObjId into BDD var index - Vec_Int_t * vVar2Obj; // mapping BDD var index into AIG ObjId - Vec_Ptr_t * vGroups; // group Id into group pointer - Llb_Mtr_t * pMatrix; // dependency matrix - // image computation - Vec_Ptr_t * vRings; // onion rings - Vec_Int_t * vVarBegs; // the first group where the var appears - Vec_Int_t * vVarEnds; // the last group where the var appears - // variable mapping - Vec_Int_t * vNs2Glo; // next state variables into global variables - Vec_Int_t * vCs2Glo; // next state variables into global variables - Vec_Int_t * vGlo2Cs; // global variables into current state variables - Vec_Int_t * vGlo2Ns; // global variables into current state variables - // flow computation -// Vec_Int_t * vMem; -// Vec_Ptr_t * vTops; -// Vec_Ptr_t * vBots; -// Vec_Ptr_t * vCuts; -}; - -struct Llb_Mtr_t_ -{ - int nPis; // number of primary inputs - int nFfs; // number of flip-flops - int nRows; // number of rows - int nCols; // number of columns - int * pColSums; // sum of values in a column - Llb_Grp_t ** pColGrps; // group structure for each col - int * pRowSums; // sum of values in a row - char ** pMatrix; // dependency matrix - Llb_Man_t * pMan; // manager - // partial product - char * pProdVars; // variables in the partial product - int * pProdNums; // var counts in the remaining partitions -}; - -struct Llb_Grp_t_ -{ - int Id; // group ID - Vec_Ptr_t * vIns; // input AIG objs - Vec_Ptr_t * vOuts; // output AIG objs - Vec_Ptr_t * vNodes; // internal AIG objs - Llb_Man_t * pMan; // manager - Llb_Grp_t * pPrev; // previous group - Llb_Grp_t * pNext; // next group -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline int Llb_ObjBddVar( Vec_Int_t * vOrder, Aig_Obj_t * pObj ) { return Vec_IntEntry(vOrder, Aig_ObjId(pObj)); } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== llbConstr.c ======================================================*/ -extern Vec_Int_t * Llb_ManDeriveConstraints( Aig_Man_t * p ); -extern void Llb_ManPrintEntries( Aig_Man_t * p, Vec_Int_t * vCands ); -/*=== llbCore.c ======================================================*/ -extern int Llb_ManModelCheckAig( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars, Vec_Int_t * vHints, DdManager ** pddGlo ); -/*=== llbCluster.c ======================================================*/ -extern void Llb_ManCluster( Llb_Mtr_t * p ); -/*=== llbDump.c ======================================================*/ -extern void Llb_ManDumpReached( DdManager * ddG, DdNode * bReached, char * pModel, char * pFileName ); -/*=== llbFlow.c ======================================================*/ -extern Vec_Ptr_t * Llb_ManFlow( Aig_Man_t * p, Vec_Ptr_t * vSources, int * pnFlow ); -/*=== llbHint.c ======================================================*/ -extern int Llb_ManReachabilityWithHints( Llb_Man_t * p ); -extern int Llb_ManModelCheckAigWithHints( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars ); -/*=== llbMan.c =======================================================*/ -extern void Llb_ManPrepareVarMap( Llb_Man_t * p ); -extern Llb_Man_t * Llb_ManStart( Aig_Man_t * pAigGlo, Aig_Man_t * pAig, Gia_ParLlb_t * pPars ); -extern void Llb_ManStop( Llb_Man_t * p ); -/*=== llbMatrix.c ====================================================*/ -extern void Llb_MtrVerifyMatrix( Llb_Mtr_t * p ); -extern Llb_Mtr_t * Llb_MtrCreate( Llb_Man_t * p ); -extern void Llb_MtrFree( Llb_Mtr_t * p ); -extern void Llb_MtrPrint( Llb_Mtr_t * p, int fOrder ); -extern void Llb_MtrPrintMatrixStats( Llb_Mtr_t * p ); -/*=== llbPart.c ======================================================*/ -extern Llb_Grp_t * Llb_ManGroupAlloc( Llb_Man_t * pMan ); -extern void Llb_ManGroupStop( Llb_Grp_t * p ); -extern void Llb_ManPrepareGroups( Llb_Man_t * pMan ); -extern Llb_Grp_t * Llb_ManGroupsCombine( Llb_Grp_t * p1, Llb_Grp_t * p2 ); -extern Llb_Grp_t * Llb_ManGroupCreateFromCuts( Llb_Man_t * pMan, Vec_Int_t * vCut1, Vec_Int_t * vCut2 ); -extern void Llb_ManPrepareVarLimits( Llb_Man_t * p ); -/*=== llbPivot.c =====================================================*/ -extern int Llb_ManTracePaths( Aig_Man_t * p, Aig_Obj_t * pPivot ); -extern Vec_Int_t * Llb_ManMarkPivotNodes( Aig_Man_t * p, int fUseInternal ); -/*=== llbReach.c =====================================================*/ -extern int Llb_ManReachability( Llb_Man_t * p, Vec_Int_t * vHints, DdManager ** pddGlo ); -/*=== llbSched.c =====================================================*/ -extern void Llb_MtrSchedule( Llb_Mtr_t * p ); - -/*=== llb2Bad.c ======================================================*/ -extern DdNode * Llb_BddComputeBad( Aig_Man_t * pInit, DdManager * dd, int TimeOut ); -extern DdNode * Llb_BddQuantifyPis( Aig_Man_t * pInit, DdManager * dd, DdNode * bFunc ); -/*=== llb2Core.c ======================================================*/ -extern DdNode * Llb_CoreComputeCube( DdManager * dd, Vec_Int_t * vVars, int fUseVarIndex, char * pValues ); -extern int Llb_CoreExperiment( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars, Vec_Ptr_t * vResult, int TimeTarget ); -/*=== llb2Driver.c ======================================================*/ -extern Vec_Int_t * Llb_DriverCountRefs( Aig_Man_t * p ); -extern Vec_Int_t * Llb_DriverCollectNs( Aig_Man_t * pAig, Vec_Int_t * vDriRefs ); -extern Vec_Int_t * Llb_DriverCollectCs( Aig_Man_t * pAig ); -extern DdNode * Llb_DriverPhaseCube( Aig_Man_t * pAig, Vec_Int_t * vDriRefs, DdManager * dd ); -extern DdManager * Llb_DriverLastPartition( Aig_Man_t * p, Vec_Int_t * vVarsNs, int TimeTarget ); -/*=== llb2Image.c ======================================================*/ -extern Vec_Ptr_t * Llb_ImgSupports( Aig_Man_t * p, Vec_Ptr_t * vDdMans, Vec_Int_t * vStart, Vec_Int_t * vStop, int fAddPis, int fVerbose ); -extern void Llb_ImgSchedule( Vec_Ptr_t * vSupps, Vec_Ptr_t ** pvQuant0, Vec_Ptr_t ** pvQuant1, int fVerbose ); -extern DdManager * Llb_ImgPartition( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, int TimeTarget ); -extern void Llb_ImgQuantifyFirst( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, Vec_Ptr_t * vQuant0, int fVerbose ); -extern void Llb_ImgQuantifyReset( Vec_Ptr_t * vDdMans ); -extern DdNode * Llb_ImgComputeImage( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, DdManager * dd, DdNode * bInit, - Vec_Ptr_t * vQuant0, Vec_Ptr_t * vQuant1, Vec_Int_t * vDriRefs, - int TimeTarget, int fBackward, int fReorder, int fVerbose ); - -extern DdManager * Llb_NonlinImageStart( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, int * pOrder, int fFirst, int TimeTarget ); -extern DdNode * Llb_NonlinImageCompute( DdNode * bCurrent, int fReorder, int fDrop, int fVerbose, int * pOrder ); -extern void Llb_NonlinImageQuit(); - -/*=== llb3Image.c =======================================================*/ -extern DdNode * Llb_NonlinImage( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, - DdManager * dd, DdNode * bCurrent, int fReorder, int fVerbose, int * pOrder, int Limit, int TimeTarget ); -/*=== llb3Nonlin.c ======================================================*/ -extern DdNode * Llb_NonlinComputeInitState( Aig_Man_t * pAig, DdManager * dd ); - - -/*=== llb4Cex.c =======================================================*/ -extern Abc_Cex_t * Llb4_Nonlin4TransformCex( Aig_Man_t * pAig, Vec_Ptr_t * vStates, int iCexPo, int fVerbose ); -/*=== llb4Cluster.c =======================================================*/ -//extern void Llb_Nonlin4Cluster( Aig_Man_t * pAig, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int nBddMax, int fVerbose ); -/*=== llb4Image.c =======================================================*/ -extern DdNode * Llb_Nonlin4Image( DdManager * dd, Vec_Ptr_t * vParts, DdNode * bCurrent, Vec_Int_t * vVars2Q ); -extern Vec_Ptr_t * Llb_Nonlin4Group( DdManager * dd, Vec_Ptr_t * vParts, Vec_Int_t * vVars2Q, int nSizeMax ); -/*=== llb4Map.c =========================================================*/ -//extern Vec_Int_t * Llb_AigMap( Aig_Man_t * pAig, int nLutSize, int nLutMin ); -/*=== llb4Nonlin.c ======================================================*/ -//extern int Llb_Nonlin4CoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ); -/*=== llb4Sweep.c ======================================================*/ -extern void Llb4_Nonlin4Sweep( Aig_Man_t * pAig, int nSweepMax, int nClusterMax, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int fVerbose ); - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/llb/module.make b/src/aig/llb/module.make deleted file mode 100644 index 1e8ea974..00000000 --- a/src/aig/llb/module.make +++ /dev/null @@ -1,23 +0,0 @@ -SRC += src/aig/llb/llb.c \ - src/aig/llb/llb1Cluster.c \ - src/aig/llb/llb1Constr.c \ - src/aig/llb/llb1Core.c \ - src/aig/llb/llb1Group.c \ - src/aig/llb/llb1Hint.c \ - src/aig/llb/llb1Man.c \ - src/aig/llb/llb1Matrix.c \ - src/aig/llb/llb1Pivot.c \ - src/aig/llb/llb1Reach.c \ - src/aig/llb/llb1Sched.c \ - src/aig/llb/llb2Bad.c \ - src/aig/llb/llb2Core.c \ - src/aig/llb/llb2Driver.c \ - src/aig/llb/llb2Dump.c \ - src/aig/llb/llb2Flow.c \ - src/aig/llb/llb2Image.c \ - src/aig/llb/llb3Image.c \ - src/aig/llb/llb3Nonlin.c \ - src/aig/llb/llb4Cex.c \ - src/aig/llb/llb4Image.c \ - src/aig/llb/llb4Nonlin.c \ - src/aig/llb/llb4Sweep.c diff --git a/src/aig/mem/mem.c b/src/aig/mem/mem.c deleted file mode 100644 index 23d8d7ec..00000000 --- a/src/aig/mem/mem.c +++ /dev/null @@ -1,605 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 - 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 -}; - -//////////////////////////////////////////////////////////////////////// -/// 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 = ABC_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 = ABC_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++ ) - ABC_FREE( p->pChunks[i] ); - ABC_FREE( p->pChunks ); - ABC_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 = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); - } - p->pEntriesFree = ABC_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++ ) - ABC_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 = ABC_ALLOC( Mem_Flex_t, 1 ); - memset( p, 0, sizeof(Mem_Flex_t) ); - - p->nEntriesUsed = 0; - p->pCurrent = NULL; - p->pEnd = NULL; - - p->nChunkSize = (1 << 12); - p->nChunksAlloc = 64; - p->nChunks = 0; - p->pChunks = ABC_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++ ) - ABC_FREE( p->pChunks[i] ); - ABC_FREE( p->pChunks ); - ABC_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 = ABC_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 = ABC_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++ ) - ABC_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 ABC_FREE()ed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mem_Step_t * Mem_StepStart( int nSteps ) -{ - Mem_Step_t * p; - int i, k; - p = ABC_ALLOC( Mem_Step_t, 1 ); - memset( p, 0, sizeof(Mem_Step_t) ); - p->nMems = nSteps; - // start the fixed memory managers - p->pMems = ABC_ALLOC( Mem_Fixed_t *, p->nMems ); - for ( i = 0; i < p->nMems; i++ ) - p->pMems[i] = Mem_FixedStart( (8<nMapSize = (4<nMems); - p->pMap = ABC_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++ ) - ABC_FREE( p->pLargeChunks[i] ); - ABC_FREE( p->pLargeChunks ); - } - ABC_FREE( p->pMems ); - ABC_FREE( p->pMap ); - ABC_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 ); -// return ABC_ALLOC( char, nBytes ); - if ( p->nLargeChunks == p->nLargeChunksAlloc ) - { - if ( p->nLargeChunksAlloc == 0 ) - p->nLargeChunksAlloc = 32; - p->nLargeChunksAlloc *= 2; - p->pLargeChunks = (void **)ABC_REALLOC( char *, p->pLargeChunks, p->nLargeChunksAlloc ); - } - p->pLargeChunks[ p->nLargeChunks++ ] = ABC_ALLOC( char, nBytes ); - return (char *)p->pLargeChunks[ p->nLargeChunks - 1 ]; - } - 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 ) - { -// ABC_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 /// -//////////////////////////////////////////////////////////////////////// -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/mem/mem.h b/src/aig/mem/mem.h deleted file mode 100644 index 15cb56fe..00000000 --- a/src/aig/mem/mem.h +++ /dev/null @@ -1,75 +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__ - -#include "abc_global.h" - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 ); - - - -ABC_NAMESPACE_HEADER_END - - - -#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/mfx/mfx.h b/src/aig/mfx/mfx.h deleted file mode 100644 index 9d2c6795..00000000 --- a/src/aig/mfx/mfx.h +++ /dev/null @@ -1,85 +0,0 @@ -/**CFile**************************************************************** - - FileName [mfx.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [The good old minimization with complete don't-cares.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: mfx.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __MFX_H__ -#define __MFX_H__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Mfx_Par_t_ Mfx_Par_t; -struct Mfx_Par_t_ -{ - // general parameters - int nWinTfoLevs; // the maximum fanout levels - int nFanoutsMax; // the maximum number of fanouts - int nDepthMax; // the maximum number of logic levels - int nDivMax; // the maximum number of divisors - int nWinSizeMax; // the maximum size of the window - int nGrowthLevel; // the maximum allowed growth in level - int nBTLimit; // the maximum number of conflicts in one SAT run - int fResub; // performs resubstitution - int fArea; // performs optimization for area - int fMoreEffort; // performs high-affort minimization - int fSwapEdge; // performs edge swapping - int fDelay; // performs optimization for delay - int fPower; // performs power-aware optimization - int fVerbose; // enable basic stats - int fVeryVerbose; // enable detailed stats -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== mfxCore.c ==========================================================*/ -extern void Mfx_ParsDefault( Mfx_Par_t * pPars ); -extern int Mfx_Perform( Nwk_Man_t * pNtk, Mfx_Par_t * pPars, If_Lib_t * pLutLib ); - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/mfx/mfxCore.c b/src/aig/mfx/mfxCore.c deleted file mode 100644 index 77f35580..00000000 --- a/src/aig/mfx/mfxCore.c +++ /dev/null @@ -1,393 +0,0 @@ -/**CFile**************************************************************** - - FileName [mfxCore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [The good old minimization with complete don't-cares.] - - Synopsis [Core procedures of this package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: mfxCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "mfxInt.h" -#include "bar.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mfx_ParsDefault( Mfx_Par_t * pPars ) -{ - pPars->nWinTfoLevs = 2; - pPars->nFanoutsMax = 10; - pPars->nDepthMax = 20; - pPars->nDivMax = 250; - pPars->nWinSizeMax = 300; - pPars->nGrowthLevel = 0; - pPars->nBTLimit = 5000; - pPars->fResub = 1; - pPars->fArea = 0; - pPars->fMoreEffort = 0; - pPars->fSwapEdge = 0; - pPars->fPower = 0; - pPars->fVerbose = 0; - pPars->fVeryVerbose = 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mfx_Resub( Mfx_Man_t * p, Nwk_Obj_t * pNode ) -{ - int clk; - p->nNodesTried++; - // prepare data structure for this node - Mfx_ManClean( p ); - // compute window roots, window support, and window nodes -clk = clock(); - p->vRoots = Mfx_ComputeRoots( pNode, p->pPars->nWinTfoLevs, p->pPars->nFanoutsMax ); - p->vSupp = Nwk_ManSupportNodes( p->pNtk, (Nwk_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); - p->vNodes = Nwk_ManDfsNodes( p->pNtk, (Nwk_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); -p->timeWin += clock() - clk; - if ( p->pPars->nWinSizeMax && Vec_PtrSize(p->vNodes) > p->pPars->nWinSizeMax ) - return 1; - // compute the divisors of the window -clk = clock(); - p->vDivs = Mfx_ComputeDivisors( p, pNode, Nwk_ObjRequired(pNode) - If_LutLibSlowestPinDelay(pNode->pMan->pLutLib) ); -// p->vDivs = Mfx_ComputeDivisors( p, pNode, ABC_INFINITY ); - p->nTotalDivs += Vec_PtrSize(p->vDivs); -p->timeDiv += clock() - clk; - // construct AIG for the window -clk = clock(); - p->pAigWin = Mfx_ConstructAig( p, pNode ); -p->timeAig += clock() - clk; - // translate it into CNF -clk = clock(); - p->pCnf = Cnf_DeriveSimple( p->pAigWin, 1 + Vec_PtrSize(p->vDivs) ); -p->timeCnf += clock() - clk; - // create the SAT problem -clk = clock(); - p->pSat = Mfx_CreateSolverResub( p, NULL, 0, 0 ); - if ( p->pSat == NULL ) - { - p->nNodesBad++; - return 1; - } - // solve the SAT problem - if ( p->pPars->fPower ) - Mfx_EdgePower( p, pNode ); - else if ( p->pPars->fSwapEdge ) - Mfx_EdgeSwapEval( p, pNode ); - else - { - Mfx_ResubNode( p, pNode ); - if ( p->pPars->fMoreEffort ) - Mfx_ResubNode2( p, pNode ); - } -p->timeSat += clock() - clk; - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mfx_Node( Mfx_Man_t * p, Nwk_Obj_t * pNode ) -{ - Hop_Obj_t * pObj; - int RetValue; - float dProb; - int nGain, clk; - p->nNodesTried++; - // prepare data structure for this node - Mfx_ManClean( p ); - // compute window roots, window support, and window nodes -clk = clock(); - p->vRoots = Mfx_ComputeRoots( pNode, p->pPars->nWinTfoLevs, p->pPars->nFanoutsMax ); - p->vSupp = Nwk_ManSupportNodes( p->pNtk, (Nwk_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); - p->vNodes = Nwk_ManDfsNodes( p->pNtk, (Nwk_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); -p->timeWin += clock() - clk; - // count the number of patterns -// p->dTotalRatios += Mfx_ConstraintRatio( p, pNode ); - // construct AIG for the window -clk = clock(); - p->pAigWin = Mfx_ConstructAig( p, pNode ); -p->timeAig += clock() - clk; - // translate it into CNF -clk = clock(); - p->pCnf = Cnf_DeriveSimple( p->pAigWin, Nwk_ObjFaninNum(pNode) ); -p->timeCnf += clock() - clk; - // create the SAT problem -clk = clock(); - p->pSat = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, 1, 0 ); - if ( p->pSat == NULL ) - return 0; - // solve the SAT problem - RetValue = Mfx_SolveSat( p, pNode ); - p->nTotConfLevel += p->pSat->stats.conflicts; -p->timeSat += clock() - clk; - if ( RetValue == 0 ) - { - p->nTimeOutsLevel++; - p->nTimeOuts++; - return 0; - } - // minimize the local function of the node using bi-decomposition - assert( p->nFanins == Nwk_ObjFaninNum(pNode) ); - dProb = p->pPars->fPower? ((float *)p->vProbs->pArray)[pNode->Id] : -1.0; - pObj = Nwk_NodeIfNodeResyn( p->pManDec, pNode->pMan->pManHop, pNode->pFunc, p->nFanins, p->vTruth, p->uCare, dProb ); - nGain = Hop_DagSize(pNode->pFunc) - Hop_DagSize(pObj); - if ( nGain >= 0 ) - { - p->nNodesDec++; - p->nNodesGained += nGain; - p->nNodesGainedLevel += nGain; - pNode->pFunc = pObj; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Marks nodes for power-optimization.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Nwk_ManPowerEstimate( Nwk_Man_t * pNtk, int fProbOne ) -{ - extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ); - Vec_Int_t * vProbs; - Vec_Int_t * vSwitching; - float * pProbability; - float * pSwitching; - Aig_Man_t * pAig; - Aig_Obj_t * pObjAig; - Nwk_Obj_t * pObjAbc; - int i; - // start the resulting array - vProbs = Vec_IntStart( Nwk_ManObjNumMax(pNtk) ); - pProbability = (float *)vProbs->pArray; - // map network into an AIG - pAig = Nwk_ManStrash( pNtk ); - vSwitching = Saig_ManComputeSwitchProbs( pAig, 48, 16, fProbOne ); - pSwitching = (float *)vSwitching->pArray; - Nwk_ManForEachObj( pNtk, pObjAbc, i ) - { - if ( (pObjAig = Aig_Regular((Aig_Obj_t *)pObjAbc->pCopy)) ) - pProbability[pObjAbc->Id] = pSwitching[pObjAig->Id]; - } - Vec_IntFree( vSwitching ); - Aig_ManStop( pAig ); - return vProbs; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mfx_Perform( Nwk_Man_t * pNtk, Mfx_Par_t * pPars, If_Lib_t * pLutLib ) -{ - Bdc_Par_t Pars = {0}, * pDecPars = &Pars; - Bar_Progress_t * pProgress; - Mfx_Man_t * p; - Nwk_Obj_t * pObj; - Vec_Vec_t * vLevels; - Vec_Ptr_t * vNodes; - int i, k, nNodes, nFaninMax, clk = clock(), clk2; - int nTotalNodesBeg = Nwk_ManNodeNum(pNtk); - int nTotalEdgesBeg = Nwk_ManGetTotalFanins(pNtk); - - // prepare the network for processing - Nwk_ManRemoveDupFanins( pNtk, 0 ); - assert( Nwk_ManCheck( pNtk ) ); - - // check limits on the number of fanins - nFaninMax = Nwk_ManGetFaninMax(pNtk); - if ( pPars->fResub ) - { - if ( nFaninMax > 8 ) - { - printf( "Nodes with more than %d fanins will node be processed.\n", 8 ); - nFaninMax = 8; - } - } - else - { - if ( nFaninMax > MFX_FANIN_MAX ) - { - printf( "Nodes with more than %d fanins will node be processed.\n", MFX_FANIN_MAX ); - nFaninMax = MFX_FANIN_MAX; - } - } - if ( pLutLib && pLutLib->LutMax < nFaninMax ) - { - printf( "The selected LUT library with max LUT size (%d) cannot be used to compute timing for network with %d-input nodes. Using unit-delay model.\n", pLutLib->LutMax, nFaninMax ); - pLutLib = NULL; - } - pNtk->pLutLib = pLutLib; - - // compute levels - Nwk_ManLevel( pNtk ); - assert( Nwk_ManVerifyLevel( pNtk ) ); - // compute delay trace with white-boxes - Nwk_ManDelayTraceLut( pNtk ); - assert( Nwk_ManVerifyTiming( pNtk ) ); - - // start the manager - p = Mfx_ManAlloc( pPars ); - p->pNtk = pNtk; - p->nFaninMax = nFaninMax; - if ( !pPars->fResub ) - { - pDecPars->nVarsMax = (nFaninMax < 3) ? 3 : nFaninMax; - pDecPars->fVerbose = pPars->fVerbose; - p->vTruth = Vec_IntAlloc( 0 ); - p->pManDec = Bdc_ManAlloc( pDecPars ); - } - - // precomputer power-aware metrics - if ( pPars->fPower ) - { - extern Vec_Int_t * Nwk_ManPowerEstimate( Nwk_Man_t * pNtk, int fProbOne ); - if ( pPars->fResub ) - p->vProbs = Nwk_ManPowerEstimate( pNtk, 0 ); - else - p->vProbs = Nwk_ManPowerEstimate( pNtk, 1 ); - printf( "Total switching before = %7.2f.\n", Nwl_ManComputeTotalSwitching(pNtk) ); - } - - // compute don't-cares for each node - nNodes = 0; - p->nTotalNodesBeg = nTotalNodesBeg; - p->nTotalEdgesBeg = nTotalEdgesBeg; - if ( pPars->fResub ) - { - pProgress = Bar_ProgressStart( stdout, Nwk_ManObjNumMax(pNtk) ); - Nwk_ManForEachNode( pNtk, pObj, i ) - { - if ( p->pPars->nDepthMax && pObj->Level > p->pPars->nDepthMax ) - continue; - if ( Nwk_ObjFaninNum(pObj) < 2 || Nwk_ObjFaninNum(pObj) > nFaninMax ) - continue; - if ( !p->pPars->fVeryVerbose ) - Bar_ProgressUpdate( pProgress, i, NULL ); - Mfx_Resub( p, pObj ); - } - Bar_ProgressStop( pProgress ); - } - else - { - pProgress = Bar_ProgressStart( stdout, Nwk_ManNodeNum(pNtk) ); - vLevels = Nwk_ManLevelize( pNtk ); - - Vec_VecForEachLevelStart( vLevels, vNodes, k, 1 ) - { - if ( !p->pPars->fVeryVerbose ) - Bar_ProgressUpdate( pProgress, nNodes, NULL ); - p->nNodesGainedLevel = 0; - p->nTotConfLevel = 0; - p->nTimeOutsLevel = 0; - clk2 = clock(); - Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i ) - { - if ( p->pPars->nDepthMax && pObj->Level > p->pPars->nDepthMax ) - break; - if ( Nwk_ObjFaninNum(pObj) < 2 || Nwk_ObjFaninNum(pObj) > nFaninMax ) - continue; - Mfx_Node( p, pObj ); - } - nNodes += Vec_PtrSize(vNodes); - if ( pPars->fVerbose ) - { - printf( "Lev = %2d. Node = %5d. Ave gain = %5.2f. Ave conf = %5.2f. T/o = %6.2f %% ", - k, Vec_PtrSize(vNodes), - 1.0*p->nNodesGainedLevel/Vec_PtrSize(vNodes), - 1.0*p->nTotConfLevel/Vec_PtrSize(vNodes), - 100.0*p->nTimeOutsLevel/Vec_PtrSize(vNodes) ); - ABC_PRT( "Time", clock() - clk2 ); - } - } - - Bar_ProgressStop( pProgress ); - Vec_VecFree( vLevels ); - } - p->nTotalNodesEnd = Nwk_ManNodeNum(pNtk); - p->nTotalEdgesEnd = Nwk_ManGetTotalFanins(pNtk); - - assert( Nwk_ManVerifyLevel( pNtk ) ); - assert( Nwk_ManVerifyTiming( pNtk ) ); - - if ( pPars->fPower ) - printf( "Total switching after = %7.2f.\n", Nwl_ManComputeTotalSwitching(pNtk) ); - - // free the manager - p->timeTotal = clock() - clk; - Mfx_ManStop( p ); - - // update network into the topological order -// if ( pPars->fResub ) -// Nwk_ManTopological( pNtk ); - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/mfx/mfxDiv.c b/src/aig/mfx/mfxDiv.c deleted file mode 100644 index 35872da2..00000000 --- a/src/aig/mfx/mfxDiv.c +++ /dev/null @@ -1,308 +0,0 @@ -/**CFile**************************************************************** - - FileName [mfxDiv.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [The good old minimization with complete don't-cares.] - - Synopsis [Procedures to compute candidate divisors.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: mfxDiv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "mfxInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Marks and collects the TFI cone of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_MfxWinMarkTfi_rec( Nwk_Obj_t * pObj, Vec_Ptr_t * vCone ) -{ - Nwk_Obj_t * pFanin; - int i; - if ( Nwk_ObjIsTravIdCurrent(pObj) ) - return; - Nwk_ObjSetTravIdCurrent( pObj ); - if ( Nwk_ObjIsCi(pObj) ) - { - Vec_PtrPush( vCone, pObj ); - return; - } - assert( Nwk_ObjIsNode(pObj) ); - // visit the fanins of the node - Nwk_ObjForEachFanin( pObj, pFanin, i ) - Abc_MfxWinMarkTfi_rec( pFanin, vCone ); - Vec_PtrPush( vCone, pObj ); -} - -/**Function************************************************************* - - Synopsis [Marks and collects the TFI cone of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_MfxWinMarkTfi( Nwk_Obj_t * pNode ) -{ - Vec_Ptr_t * vCone; - vCone = Vec_PtrAlloc( 100 ); - Abc_MfxWinMarkTfi_rec( pNode, vCone ); - return vCone; -} - -/**Function************************************************************* - - Synopsis [Marks the TFO of the collected nodes up to the given level.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_MfxWinSweepLeafTfo_rec( Nwk_Obj_t * pObj, float tArrivalMax ) -{ - Nwk_Obj_t * pFanout; - int i; - if ( Nwk_ObjIsCo(pObj) || Nwk_ObjArrival(pObj) > tArrivalMax ) - return; - if ( Nwk_ObjIsTravIdCurrent(pObj) ) - return; - Nwk_ObjSetTravIdCurrent( pObj ); - Nwk_ObjForEachFanout( pObj, pFanout, i ) - Abc_MfxWinSweepLeafTfo_rec( pFanout, tArrivalMax ); -} - -/**Function************************************************************* - - Synopsis [Dereferences the node's MFFC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_MfxNodeDeref_rec( Nwk_Obj_t * pNode ) -{ - Nwk_Obj_t * pFanin; - int i, Counter = 1; - if ( Nwk_ObjIsCi(pNode) ) - return 0; - Nwk_ObjSetTravIdCurrent( pNode ); - Nwk_ObjForEachFanin( pNode, pFanin, i ) - { - assert( pFanin->nFanouts > 0 ); - if ( --pFanin->nFanouts == 0 ) - Counter += Abc_MfxNodeDeref_rec( pFanin ); - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [References the node's MFFC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_MfxNodeRef_rec( Nwk_Obj_t * pNode ) -{ - Nwk_Obj_t * pFanin; - int i, Counter = 1; - if ( Nwk_ObjIsCi(pNode) ) - return 0; - Nwk_ObjForEachFanin( pNode, pFanin, i ) - { - if ( pFanin->nFanouts++ == 0 ) - Counter += Abc_MfxNodeRef_rec( pFanin ); - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Labels MFFC of the node with the current trav ID.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_MfxWinVisitMffc( Nwk_Obj_t * pNode ) -{ - int Count1, Count2; - assert( Nwk_ObjIsNode(pNode) ); - // dereference the node (mark with the current trav ID) - Count1 = Abc_MfxNodeDeref_rec( pNode ); - // reference it back - Count2 = Abc_MfxNodeRef_rec( pNode ); - assert( Count1 == Count2 ); - return Count1; -} - -/**Function************************************************************* - - Synopsis [Computes divisors and add them to nodes in the window.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Mfx_ComputeDivisors( Mfx_Man_t * p, Nwk_Obj_t * pNode, float tArrivalMax ) -{ - Vec_Ptr_t * vCone, * vDivs; - Nwk_Obj_t * pObj, * pFanout, * pFanin; - int k, f, m; - int nDivsPlus = 0, nTrueSupp; - assert( p->vDivs == NULL ); - - // mark the TFI with the current trav ID - Nwk_ManIncrementTravId( pNode->pMan ); - vCone = Abc_MfxWinMarkTfi( pNode ); - - // count the number of PIs - nTrueSupp = 0; - Vec_PtrForEachEntry( Nwk_Obj_t *, vCone, pObj, k ) - nTrueSupp += Nwk_ObjIsCi(pObj); -// printf( "%d(%d) ", Vec_PtrSize(p->vSupp), m ); - - // 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) - Nwk_ManIncrementTravId( pNode->pMan ); - Abc_MfxWinSweepLeafTfo_rec( pNode, tArrivalMax ); - Abc_MfxWinVisitMffc( pNode ); - Nwk_ObjForEachFanin( pNode, pObj, k ) - Nwk_ObjSetTravIdCurrent( 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 - vDivs = Vec_PtrAlloc( p->pPars->nDivMax ); - Vec_PtrForEachEntry( Nwk_Obj_t *, vCone, pObj, k ) - { - if ( !Nwk_ObjIsTravIdPrevious(pObj) ) - continue; - if ( Nwk_ObjArrival(pObj) > tArrivalMax ) - continue; - Vec_PtrPush( vDivs, pObj ); - if ( Vec_PtrSize(vDivs) >= p->pPars->nDivMax ) - break; - } - Vec_PtrFree( vCone ); - - // explore the fanouts of already collected divisors - if ( Vec_PtrSize(vDivs) < p->pPars->nDivMax ) - Vec_PtrForEachEntry( Nwk_Obj_t *, vDivs, pObj, k ) - { - // consider fanouts of this node - Nwk_ObjForEachFanout( pObj, pFanout, f ) - { - // stop if there are too many fanouts - if ( f > 20 ) - break; - // skip nodes that are already added - if ( Nwk_ObjIsTravIdPrevious(pFanout) ) - continue; - // skip nodes in the TFO or in the MFFC of node - if ( Nwk_ObjIsTravIdCurrent(pFanout) ) - continue; - // skip COs - if ( !Nwk_ObjIsNode(pFanout) ) - continue; - // skip nodes with large level - if ( Nwk_ObjArrival(pFanout) > tArrivalMax ) - continue; - // skip nodes whose fanins are not divisors - Nwk_ObjForEachFanin( pFanout, pFanin, m ) - if ( !Nwk_ObjIsTravIdPrevious(pFanin) ) - break; - if ( m < Nwk_ObjFaninNum(pFanout) ) - continue; - // make sure this divisor in not among the nodes -// Vec_PtrForEachEntry( Aig_Obj_t *, p->vNodes, pFanin, m ) -// assert( pFanout != pFanin ); - // add the node to the divisors - Vec_PtrPush( vDivs, pFanout ); -// Vec_PtrPush( p->vNodes, pFanout ); - Vec_PtrPushUnique( p->vNodes, pFanout ); - Nwk_ObjSetTravIdPrevious( pFanout ); - nDivsPlus++; - if ( Vec_PtrSize(vDivs) >= p->pPars->nDivMax ) - break; - } - if ( Vec_PtrSize(vDivs) >= p->pPars->nDivMax ) - break; - } - - // sort the divisors by level in the increasing order - Vec_PtrSort( vDivs, (int (*)(void))Nwk_NodeCompareLevelsIncrease ); - - // add the fanins of the node - Nwk_ObjForEachFanin( pNode, pFanin, k ) - Vec_PtrPush( vDivs, pFanin ); - -/* - printf( "Node level = %d. ", Nwk_ObjLevel(p->pNode) ); - Vec_PtrForEachEntryStart( vDivs, pObj, k, Vec_PtrSize(vDivs)-p->nDivsPlus ) - printf( "%d ", Nwk_ObjLevel(pObj) ); - printf( "\n" ); -*/ -//printf( "%d ", p->nDivsPlus ); -// printf( "(%d+%d)(%d+%d+%d) ", Vec_PtrSize(p->vSupp), Vec_PtrSize(p->vNodes), -// nTrueSupp, Vec_PtrSize(vDivs)-nTrueSupp-nDivsPlus, nDivsPlus ); - return vDivs; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/mfx/mfxInt.h b/src/aig/mfx/mfxInt.h deleted file mode 100644 index 320e7a8e..00000000 --- a/src/aig/mfx/mfxInt.h +++ /dev/null @@ -1,168 +0,0 @@ -/**CFile**************************************************************** - - FileName [mfxInt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [The good old minimization with complete don't-cares.] - - Synopsis [Internal declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: mfxInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __MFX_INT_H__ -#define __MFX_INT_H__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "nwk.h" -#include "mfx.h" -#include "aig.h" -#include "cnf.h" -#include "satSolver.h" -#include "satStore.h" -#include "bdc.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -#define MFX_FANIN_MAX 12 - -typedef struct Mfx_Man_t_ Mfx_Man_t; -struct Mfx_Man_t_ -{ - // input data - Mfx_Par_t * pPars; - Nwk_Man_t * pNtk; - Aig_Man_t * pCare; - Vec_Ptr_t * vSuppsInv; - int nFaninMax; - // intermeditate data for the node - Vec_Ptr_t * vRoots; // the roots of the window - Vec_Ptr_t * vSupp; // the support of the window - Vec_Ptr_t * vNodes; // the internal nodes of the window - Vec_Ptr_t * vDivs; // the divisors of the node - Vec_Int_t * vDivLits; // the SAT literals of divisor nodes - Vec_Int_t * vProjVarsCnf; // the projection variables - Vec_Int_t * vProjVarsSat; // the projection variables - // intermediate simulation data - Vec_Ptr_t * vDivCexes; // the counter-example for dividors - int nDivWords; // the number of words - int nCexes; // the numbe rof current counter-examples - int nSatCalls; - int nSatCexes; - // used for bidecomposition - Vec_Int_t * vTruth; - Bdc_Man_t * pManDec; - int nNodesDec; - int nNodesGained; - int nNodesGainedLevel; - // solving data - Aig_Man_t * pAigWin; // window AIG with constraints - Cnf_Dat_t * pCnf; // the CNF for the window - sat_solver * pSat; // the SAT solver used - Int_Man_t * pMan; // interpolation manager; - Vec_Int_t * vMem; // memory for intermediate SOPs - Vec_Vec_t * vLevels; // levelized structure for updating - Vec_Ptr_t * vFanins; // the new set of fanins - int nTotConfLim; // total conflict limit - int nTotConfLevel; // total conflicts on this level - // switching activity - Vec_Int_t * vProbs; - // the result of solving - int nFanins; // the number of fanins - int nWords; // the number of words - int nCares; // the number of care minterms - unsigned uCare[(MFX_FANIN_MAX<=5)?1:1<<(MFX_FANIN_MAX-5)]; // the computed care-set - // performance statistics - int nNodesTried; - int nNodesResub; - int nMintsCare; - int nMintsTotal; - int nNodesBad; - int nTotalDivs; - int nTimeOuts; - int nTimeOutsLevel; - int nDcMints; - double dTotalRatios; - // node/edge stats - int nTotalNodesBeg; - int nTotalNodesEnd; - int nTotalEdgesBeg; - int nTotalEdgesEnd; - // statistics - int timeWin; - int timeDiv; - int timeAig; - int timeCnf; - int timeSat; - int timeInt; - int timeTotal; -}; - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== mfxDiv.c ==========================================================*/ -extern Vec_Ptr_t * Mfx_ComputeDivisors( Mfx_Man_t * p, Nwk_Obj_t * pNode, float tArrivalMax ); -/*=== mfxInter.c ==========================================================*/ -extern sat_solver * Mfx_CreateSolverResub( Mfx_Man_t * p, int * pCands, int nCands, int fInvert ); -extern Hop_Obj_t * Mfx_Interplate( Mfx_Man_t * p, int * pCands, int nCands ); -extern int Mfx_InterplateEval( Mfx_Man_t * p, int * pCands, int nCands ); -/*=== mfxMan.c ==========================================================*/ -extern Mfx_Man_t * Mfx_ManAlloc( Mfx_Par_t * pPars ); -extern void Mfx_ManStop( Mfx_Man_t * p ); -extern void Mfx_ManClean( Mfx_Man_t * p ); -/*=== mfxResub.c ==========================================================*/ -extern void Mfx_PrintResubStats( Mfx_Man_t * p ); -extern int Mfx_EdgePower( Mfx_Man_t * p, Nwk_Obj_t * pNode ); -extern int Mfx_EdgeSwapEval( Mfx_Man_t * p, Nwk_Obj_t * pNode ); -extern int Mfx_ResubNode( Mfx_Man_t * p, Nwk_Obj_t * pNode ); -extern int Mfx_ResubNode2( Mfx_Man_t * p, Nwk_Obj_t * pNode ); -/*=== mfxSat.c ==========================================================*/ -extern int Mfx_SolveSat( Mfx_Man_t * p, Nwk_Obj_t * pNode ); -/*=== mfxStrash.c ==========================================================*/ -extern Aig_Man_t * Mfx_ConstructAig( Mfx_Man_t * p, Nwk_Obj_t * pNode ); -extern double Mfx_ConstraintRatio( Mfx_Man_t * p, Nwk_Obj_t * pNode ); -/*=== mfxWin.c ==========================================================*/ -extern Vec_Ptr_t * Mfx_ComputeRoots( Nwk_Obj_t * pNode, int nWinTfoMax, int nFanoutLimit ); - - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/mfx/mfxInter.c b/src/aig/mfx/mfxInter.c deleted file mode 100644 index db2e5e7e..00000000 --- a/src/aig/mfx/mfxInter.c +++ /dev/null @@ -1,368 +0,0 @@ -/**CFile**************************************************************** - - FileName [mfxInter.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [The good old minimization with complete don't-cares.] - - Synopsis [Procedures for computing resub function by interpolation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: mfxInter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "mfxInt.h" -#include "kit.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Adds constraints for the two-input AND-gate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mfx_SatAddXor( sat_solver * pSat, int iVarA, int iVarB, int iVarC ) -{ - lit Lits[3]; - - Lits[0] = toLitCond( iVarA, 1 ); - Lits[1] = toLitCond( iVarB, 1 ); - Lits[2] = toLitCond( iVarC, 1 ); - if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) ) - return 0; - - Lits[0] = toLitCond( iVarA, 1 ); - Lits[1] = toLitCond( iVarB, 0 ); - Lits[2] = toLitCond( iVarC, 0 ); - if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) ) - return 0; - - Lits[0] = toLitCond( iVarA, 0 ); - Lits[1] = toLitCond( iVarB, 1 ); - Lits[2] = toLitCond( iVarC, 0 ); - if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) ) - return 0; - - Lits[0] = toLitCond( iVarA, 0 ); - Lits[1] = toLitCond( iVarB, 0 ); - Lits[2] = toLitCond( iVarC, 1 ); - if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) ) - return 0; - - return 1; -} - -/**Function************************************************************* - - Synopsis [Creates miter for checking resubsitution.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -sat_solver * Mfx_CreateSolverResub( Mfx_Man_t * p, int * pCands, int nCands, int fInvert ) -{ - sat_solver * pSat; - Aig_Obj_t * pObjPo; - int Lits[2], status, iVar, i, c; - - // get the literal for the output of F - pObjPo = Aig_ManPo( p->pAigWin, Aig_ManPoNum(p->pAigWin) - Vec_PtrSize(p->vDivs) - 1 ); - Lits[0] = toLitCond( p->pCnf->pVarNums[pObjPo->Id], fInvert ); - - // collect the outputs of the divisors - Vec_IntClear( p->vProjVarsCnf ); - Vec_PtrForEachEntryStart( Aig_Obj_t *, p->pAigWin->vPos, pObjPo, i, Aig_ManPoNum(p->pAigWin) - Vec_PtrSize(p->vDivs) ) - { - assert( p->pCnf->pVarNums[pObjPo->Id] >= 0 ); - Vec_IntPush( p->vProjVarsCnf, p->pCnf->pVarNums[pObjPo->Id] ); - } - assert( Vec_IntSize(p->vProjVarsCnf) == Vec_PtrSize(p->vDivs) ); - - // start the solver - pSat = sat_solver_new(); - sat_solver_setnvars( pSat, 2 * p->pCnf->nVars + Vec_PtrSize(p->vDivs) ); - if ( pCands ) - sat_solver_store_alloc( pSat ); - - // load the first copy of the clauses - for ( i = 0; i < p->pCnf->nClauses; i++ ) - { - if ( !sat_solver_addclause( pSat, p->pCnf->pClauses[i], p->pCnf->pClauses[i+1] ) ) - { - sat_solver_delete( pSat ); - return NULL; - } - } - // add the clause for the first output of F - if ( !sat_solver_addclause( pSat, Lits, Lits+1 ) ) - { - sat_solver_delete( pSat ); - return NULL; - } - - // bookmark the clauses of A - if ( pCands ) - sat_solver_store_mark_clauses_a( pSat ); - - // transform the literals - for ( i = 0; i < p->pCnf->nLiterals; i++ ) - p->pCnf->pClauses[0][i] += 2 * p->pCnf->nVars; - // load the second copy of the clauses - for ( i = 0; i < p->pCnf->nClauses; i++ ) - { - if ( !sat_solver_addclause( pSat, p->pCnf->pClauses[i], p->pCnf->pClauses[i+1] ) ) - { - sat_solver_delete( pSat ); - return NULL; - } - } - // transform the literals - for ( i = 0; i < p->pCnf->nLiterals; i++ ) - p->pCnf->pClauses[0][i] -= 2 * p->pCnf->nVars; - // add the clause for the second output of F - Lits[0] = 2 * p->pCnf->nVars + lit_neg( Lits[0] ); - if ( !sat_solver_addclause( pSat, Lits, Lits+1 ) ) - { - sat_solver_delete( pSat ); - return NULL; - } - - if ( pCands ) - { - // add relevant clauses for EXOR gates - for ( c = 0; c < nCands; c++ ) - { - // get the variable number of this divisor - i = lit_var( pCands[c] ) - 2 * p->pCnf->nVars; - // get the corresponding SAT variable - iVar = Vec_IntEntry( p->vProjVarsCnf, i ); - // add the corresponding EXOR gate - if ( !Mfx_SatAddXor( pSat, iVar, iVar + p->pCnf->nVars, 2 * p->pCnf->nVars + i ) ) - { - sat_solver_delete( pSat ); - return NULL; - } - // add the corresponding clause - if ( !sat_solver_addclause( pSat, pCands + c, pCands + c + 1 ) ) - { - sat_solver_delete( pSat ); - return NULL; - } - } - // bookmark the roots - sat_solver_store_mark_roots( pSat ); - } - else - { - // add the clauses for the EXOR gates - and remember their outputs - Vec_IntClear( p->vProjVarsSat ); - Vec_IntForEachEntry( p->vProjVarsCnf, iVar, i ) - { - if ( !Mfx_SatAddXor( pSat, iVar, iVar + p->pCnf->nVars, 2 * p->pCnf->nVars + i ) ) - { - sat_solver_delete( pSat ); - return NULL; - } - Vec_IntPush( p->vProjVarsSat, 2 * p->pCnf->nVars + i ); - } - assert( Vec_IntSize(p->vProjVarsCnf) == Vec_IntSize(p->vProjVarsSat) ); - // simplify the solver - status = sat_solver_simplify(pSat); - if ( status == 0 ) - { -// printf( "Mfx_CreateSolverResub(): SAT solver construction has failed. Skipping node.\n" ); - sat_solver_delete( pSat ); - return NULL; - } - } - return pSat; -} - -/**Function************************************************************* - - Synopsis [Performs interpolation.] - - Description [Derives the new function of the node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Mfx_InterplateTruth( Mfx_Man_t * p, int * pCands, int nCands, int fInvert ) -{ - sat_solver * pSat; - Sto_Man_t * pCnf = NULL; - unsigned * puTruth; - int nFanins, status; - int c, i, * pGloVars; - - // derive the SAT solver for interpolation - pSat = Mfx_CreateSolverResub( p, pCands, nCands, fInvert ); - - // solve the problem - status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)p->pPars->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); - if ( status != l_False ) - { - p->nTimeOuts++; - return NULL; - } - // get the learned clauses - pCnf = (Sto_Man_t *)sat_solver_store_release( pSat ); - sat_solver_delete( pSat ); - - // set the global variables - pGloVars = Int_ManSetGlobalVars( p->pMan, nCands ); - for ( c = 0; c < nCands; c++ ) - { - // get the variable number of this divisor - i = lit_var( pCands[c] ) - 2 * p->pCnf->nVars; - // get the corresponding SAT variable - pGloVars[c] = Vec_IntEntry( p->vProjVarsCnf, i ); - } - - // derive the interpolant - nFanins = Int_ManInterpolate( p->pMan, pCnf, 0, &puTruth ); - Sto_ManFree( pCnf ); - assert( nFanins == nCands ); - return puTruth; -} - -/**Function************************************************************* - - Synopsis [Performs interpolation.] - - Description [Derives the new function of the node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mfx_InterplateEval( Mfx_Man_t * p, int * pCands, int nCands ) -{ - unsigned * pTruth, uTruth0[2], uTruth1[2]; - int nCounter; - pTruth = Mfx_InterplateTruth( p, pCands, nCands, 0 ); - if ( nCands == 6 ) - { - uTruth1[0] = pTruth[0]; - uTruth1[1] = pTruth[1]; - } - else - { - uTruth1[0] = pTruth[0]; - uTruth1[1] = pTruth[0]; - } - pTruth = Mfx_InterplateTruth( p, pCands, nCands, 1 ); - if ( nCands == 6 ) - { - uTruth0[0] = ~pTruth[0]; - uTruth0[1] = ~pTruth[1]; - } - else - { - uTruth0[0] = ~pTruth[0]; - uTruth0[1] = ~pTruth[0]; - } - nCounter = Extra_WordCountOnes( uTruth0[0] ^ uTruth1[0] ); - nCounter += Extra_WordCountOnes( uTruth0[1] ^ uTruth1[1] ); -// printf( "%d ", nCounter ); - return nCounter; -} - - -/**Function************************************************************* - - Synopsis [Performs interpolation.] - - Description [Derives the new function of the node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Mfx_Interplate( Mfx_Man_t * p, int * pCands, int nCands ) -{ - extern Hop_Obj_t * Kit_GraphToHop( Hop_Man_t * pMan, Kit_Graph_t * pGraph ); - - sat_solver * pSat; - Sto_Man_t * pCnf = NULL; - unsigned * puTruth; - Kit_Graph_t * pGraph; - Hop_Obj_t * pFunc; - int nFanins, status; - int c, i, * pGloVars; - -// p->nDcMints += Mfx_InterplateEval( p, pCands, nCands ); - - // derive the SAT solver for interpolation - pSat = Mfx_CreateSolverResub( p, pCands, nCands, 0 ); - - // solve the problem - status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)p->pPars->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); - if ( status != l_False ) - { - p->nTimeOuts++; - return NULL; - } - // get the learned clauses - pCnf = (Sto_Man_t *)sat_solver_store_release( pSat ); - sat_solver_delete( pSat ); - - // set the global variables - pGloVars = Int_ManSetGlobalVars( p->pMan, nCands ); - for ( c = 0; c < nCands; c++ ) - { - // get the variable number of this divisor - i = lit_var( pCands[c] ) - 2 * p->pCnf->nVars; - // get the corresponding SAT variable - pGloVars[c] = Vec_IntEntry( p->vProjVarsCnf, i ); - } - - // derive the interpolant - nFanins = Int_ManInterpolate( p->pMan, pCnf, 0, &puTruth ); - Sto_ManFree( pCnf ); - assert( nFanins == nCands ); - - // transform interpolant into AIG - pGraph = Kit_TruthToGraph( puTruth, nFanins, p->vMem ); - pFunc = Kit_GraphToHop( p->pNtk->pManHop, pGraph ); - Kit_GraphFree( pGraph ); - return pFunc; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/mfx/mfxMan.c b/src/aig/mfx/mfxMan.c deleted file mode 100644 index ff8b02fd..00000000 --- a/src/aig/mfx/mfxMan.c +++ /dev/null @@ -1,195 +0,0 @@ -/**CFile**************************************************************** - - FileName [mfxMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [The good old minimization with complete don't-cares.] - - Synopsis [Procedures working with the manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: mfxMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "mfxInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mfx_Man_t * Mfx_ManAlloc( Mfx_Par_t * pPars ) -{ - Mfx_Man_t * p; - // start the manager - p = ABC_ALLOC( Mfx_Man_t, 1 ); - memset( p, 0, sizeof(Mfx_Man_t) ); - p->pPars = pPars; - p->vProjVarsCnf = Vec_IntAlloc( 100 ); - p->vProjVarsSat = Vec_IntAlloc( 100 ); - p->vDivLits = Vec_IntAlloc( 100 ); - p->nDivWords = Aig_BitWordNum(p->pPars->nDivMax + MFX_FANIN_MAX); - p->vDivCexes = Vec_PtrAllocSimInfo( p->pPars->nDivMax+MFX_FANIN_MAX+1, p->nDivWords ); - p->pMan = Int_ManAlloc(); - p->vMem = Vec_IntAlloc( 0 ); - p->vLevels = Vec_VecStart( 32 ); - p->vFanins = Vec_PtrAlloc( 32 ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mfx_ManClean( Mfx_Man_t * p ) -{ - if ( p->pAigWin ) - Aig_ManStop( p->pAigWin ); - if ( p->pCnf ) - Cnf_DataFree( p->pCnf ); - if ( p->pSat ) - sat_solver_delete( p->pSat ); - if ( p->vRoots ) - Vec_PtrFree( p->vRoots ); - if ( p->vSupp ) - Vec_PtrFree( p->vSupp ); - if ( p->vNodes ) - Vec_PtrFree( p->vNodes ); - if ( p->vDivs ) - Vec_PtrFree( p->vDivs ); - p->pAigWin = NULL; - p->pCnf = NULL; - p->pSat = NULL; - p->vRoots = NULL; - p->vSupp = NULL; - p->vNodes = NULL; - p->vDivs = NULL; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mfx_ManPrint( Mfx_Man_t * p ) -{ - if ( p->pPars->fResub ) - { - printf( "Reduction in nodes = %5d. (%.2f %%) ", - p->nTotalNodesBeg-p->nTotalNodesEnd, - 100.0*(p->nTotalNodesBeg-p->nTotalNodesEnd)/p->nTotalNodesBeg ); - printf( "Reduction in edges = %5d. (%.2f %%) ", - p->nTotalEdgesBeg-p->nTotalEdgesEnd, - 100.0*(p->nTotalEdgesBeg-p->nTotalEdgesEnd)/p->nTotalEdgesBeg ); - printf( "\n" ); - printf( "Nodes = %d. Try = %d. Resub = %d. Div = %d. SAT calls = %d. Timeouts = %d.\n", - Nwk_ManNodeNum(p->pNtk), p->nNodesTried, p->nNodesResub, p->nTotalDivs, p->nSatCalls, p->nTimeOuts ); - if ( p->pPars->fSwapEdge ) - printf( "Swappable edges = %d. Total edges = %d. Ratio = %5.2f.\n", - p->nNodesResub, Nwk_ManGetTotalFanins(p->pNtk), 1.00 * p->nNodesResub / Nwk_ManGetTotalFanins(p->pNtk) ); -// else -// Mfx_PrintResubStats( p ); -// printf( "Average ratio of DCs in the resubed nodes = %.2f.\n", 1.0*p->nDcMints/(64 * p->nNodesResub) ); - } - else - { - printf( "Nodes = %d. Try = %d. Total mints = %d. Local DC mints = %d. Ratio = %5.2f.\n", - Nwk_ManNodeNum(p->pNtk), p->nNodesTried, p->nMintsTotal, p->nMintsTotal-p->nMintsCare, - 1.0 * (p->nMintsTotal-p->nMintsCare) / p->nMintsTotal ); -// printf( "Average ratio of sequential DCs in the global space = %5.2f.\n", -// 1.0-(p->dTotalRatios/p->nNodesTried) ); - printf( "Nodes resyn = %d. Ratio = %5.2f. Total AIG node gain = %d. Timeouts = %d.\n", - p->nNodesDec, 1.0 * p->nNodesDec / p->nNodesTried, p->nNodesGained, p->nTimeOuts ); - } -/* - ABC_PRTP( "Win", p->timeWin , p->timeTotal ); - ABC_PRTP( "Div", p->timeDiv , p->timeTotal ); - ABC_PRTP( "Aig", p->timeAig , p->timeTotal ); - ABC_PRTP( "Cnf", p->timeCnf , p->timeTotal ); - ABC_PRTP( "Sat", p->timeSat-p->timeInt , p->timeTotal ); - ABC_PRTP( "Int", p->timeInt , p->timeTotal ); - ABC_PRTP( "ALL", p->timeTotal , p->timeTotal ); -*/ -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mfx_ManStop( Mfx_Man_t * p ) -{ - if ( p->pPars->fVerbose ) - Mfx_ManPrint( p ); - if ( p->vTruth ) - Vec_IntFree( p->vTruth ); - if ( p->pManDec ) - Bdc_ManFree( p->pManDec ); - if ( p->pCare ) - Aig_ManStop( p->pCare ); - if ( p->vSuppsInv ) - Vec_VecFree( (Vec_Vec_t *)p->vSuppsInv ); - if ( p->vProbs ) - Vec_IntFree( p->vProbs ); - Mfx_ManClean( p ); - Int_ManFree( p->pMan ); - Vec_IntFree( p->vMem ); - Vec_VecFree( p->vLevels ); - Vec_PtrFree( p->vFanins ); - Vec_IntFree( p->vProjVarsCnf ); - Vec_IntFree( p->vProjVarsSat ); - Vec_IntFree( p->vDivLits ); - Vec_PtrFree( p->vDivCexes ); - ABC_FREE( p ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/mfx/mfxResub.c b/src/aig/mfx/mfxResub.c deleted file mode 100644 index 5a4786d6..00000000 --- a/src/aig/mfx/mfxResub.c +++ /dev/null @@ -1,566 +0,0 @@ -/**CFile**************************************************************** - - FileName [mfxResub.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [The good old minimization with complete don't-cares.] - - Synopsis [Procedures to perform resubstitution.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: mfxResub.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "mfxInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Updates the network after resubstitution.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mfx_UpdateNetwork( Mfx_Man_t * p, Nwk_Obj_t * pObj, Vec_Ptr_t * vFanins, Hop_Obj_t * pFunc ) -{ - Nwk_Obj_t * pObjNew, * pFanin; - int k; - // create the new node - pObjNew = Nwk_ManCreateNode( pObj->pMan, Vec_PtrSize(vFanins), Nwk_ObjFanoutNum(pObj) ); - pObjNew->pFunc = pFunc; - Vec_PtrForEachEntry( Nwk_Obj_t *, vFanins, pFanin, k ) - Nwk_ObjAddFanin( pObjNew, pFanin ); - // replace the old node by the new node - Nwk_ManUpdate( pObj, pObjNew, p->vLevels ); -} - -/**Function************************************************************* - - Synopsis [Prints resub candidate stats.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mfx_PrintResubStats( Mfx_Man_t * p ) -{ - Nwk_Obj_t * pFanin, * pNode; - int i, k, nAreaCrits = 0, nAreaExpanse = 0; - int nFaninMax = Nwk_ManGetFaninMax(p->pNtk); - Nwk_ManForEachNode( p->pNtk, pNode, i ) - Nwk_ObjForEachFanin( pNode, pFanin, k ) - { - if ( !Nwk_ObjIsCi(pFanin) && Nwk_ObjFanoutNum(pFanin) == 1 ) - { - nAreaCrits++; - nAreaExpanse += (int)(Nwk_ObjFaninNum(pNode) < nFaninMax); - } - } - printf( "Total area-critical fanins = %d. Belonging to expandable nodes = %d.\n", - nAreaCrits, nAreaExpanse ); -} - -/**Function************************************************************* - - Synopsis [Tries resubstitution.] - - Description [Returns 1 if it is feasible, or 0 if c-ex is found.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mfx_TryResubOnce( Mfx_Man_t * p, int * pCands, int nCands ) -{ - unsigned * pData; - int RetValue, iVar, i; - p->nSatCalls++; - RetValue = sat_solver_solve( p->pSat, pCands, pCands + nCands, (ABC_INT64_T)p->pPars->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); -// assert( RetValue == l_False || RetValue == l_True ); - if ( RetValue == l_False ) - return 1; - if ( RetValue != l_True ) - { - p->nTimeOuts++; - return -1; - } - p->nSatCexes++; - // store the counter-example - Vec_IntForEachEntry( p->vProjVarsSat, iVar, i ) - { - pData = (unsigned *)Vec_PtrEntry( p->vDivCexes, i ); - if ( !sat_solver_var_value( p->pSat, iVar ) ) // remove 0s!!! - { - assert( Aig_InfoHasBit(pData, p->nCexes) ); - Aig_InfoXorBit( pData, p->nCexes ); - } - } - p->nCexes++; - return 0; -} - -/**Function************************************************************* - - Synopsis [Performs resubstitution for the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mfx_SolveSatResub( Mfx_Man_t * p, Nwk_Obj_t * pNode, int iFanin, int fOnlyRemove, int fSkipUpdate ) -{ - int fVeryVerbose = p->pPars->fVeryVerbose && Vec_PtrSize(p->vDivs) < 80; - unsigned * pData; - int pCands[MFX_FANIN_MAX]; - int RetValue, iVar, i, nCands, nWords, w, clk; - Nwk_Obj_t * pFanin; - Hop_Obj_t * pFunc; - assert( iFanin >= 0 ); - - // clean simulation info - Vec_PtrFillSimInfo( p->vDivCexes, 0, p->nDivWords ); - p->nCexes = 0; - if ( fVeryVerbose ) - { - printf( "\n" ); - printf( "Node %5d : Level = %2d. Divs = %3d. Fanin = %d (out of %d). MFFC = %d\n", - pNode->Id, pNode->Level, Vec_PtrSize(p->vDivs)-Nwk_ObjFaninNum(pNode), - iFanin, Nwk_ObjFaninNum(pNode), - Nwk_ObjFanoutNum(Nwk_ObjFanin(pNode, iFanin)) == 1 ? Nwk_ObjMffcLabel(Nwk_ObjFanin(pNode, iFanin)) : 0 ); - } - - // try fanins without the critical fanin - nCands = 0; - Vec_PtrClear( p->vFanins ); - Nwk_ObjForEachFanin( pNode, pFanin, i ) - { - if ( i == iFanin ) - continue; - Vec_PtrPush( p->vFanins, pFanin ); - iVar = Vec_PtrSize(p->vDivs) - Nwk_ObjFaninNum(pNode) + i; - pCands[nCands++] = toLitCond( Vec_IntEntry( p->vProjVarsSat, iVar ), 1 ); - } - RetValue = Mfx_TryResubOnce( p, pCands, nCands ); - if ( RetValue == -1 ) - return 0; - if ( RetValue == 1 ) - { - if ( fVeryVerbose ) - printf( "Node %d: Fanin %d can be removed.\n", pNode->Id, iFanin ); - p->nNodesResub++; - p->nNodesGainedLevel++; - if ( fSkipUpdate ) - return 1; -clk = clock(); - // derive the function - pFunc = Mfx_Interplate( p, pCands, nCands ); - if ( pFunc == NULL ) - return 0; - // update the network - Mfx_UpdateNetwork( p, pNode, p->vFanins, pFunc ); -p->timeInt += clock() - clk; - return 1; - } - - if ( fOnlyRemove ) - return 0; - - if ( fVeryVerbose ) - { - for ( i = 0; i < 8; i++ ) - printf( " " ); - for ( i = 0; i < Vec_PtrSize(p->vDivs)-Nwk_ObjFaninNum(pNode); i++ ) - printf( "%d", i % 10 ); - for ( i = 0; i < Nwk_ObjFaninNum(pNode); i++ ) - if ( i == iFanin ) - printf( "*" ); - else - printf( "%c", 'a' + i ); - printf( "\n" ); - } - iVar = -1; - while ( 1 ) - { - float * pProbab = (float *)(p->vProbs? p->vProbs->pArray : NULL); - assert( (pProbab != NULL) == p->pPars->fPower ); - if ( fVeryVerbose ) - { - printf( "%3d: %2d ", p->nCexes, iVar ); - for ( i = 0; i < Vec_PtrSize(p->vDivs); i++ ) - { - pData = (unsigned *)Vec_PtrEntry( p->vDivCexes, i ); - printf( "%d", Aig_InfoHasBit(pData, p->nCexes-1) ); - } - printf( "\n" ); - } - - // find the next divisor to try - nWords = Aig_BitWordNum(p->nCexes); - assert( nWords <= p->nDivWords ); - for ( iVar = 0; iVar < Vec_PtrSize(p->vDivs)-Nwk_ObjFaninNum(pNode); iVar++ ) - { - if ( p->pPars->fPower ) - { - Nwk_Obj_t * pDiv = (Nwk_Obj_t *)Vec_PtrEntry(p->vDivs, iVar); - // only accept the divisor if it is "cool" - if ( pProbab[Nwk_ObjId(pDiv)] >= 0.2 ) - continue; - } - pData = (unsigned *)Vec_PtrEntry( p->vDivCexes, iVar ); - for ( w = 0; w < nWords; w++ ) - if ( pData[w] != ~0 ) - break; - if ( w == nWords ) - break; - } - if ( iVar == Vec_PtrSize(p->vDivs)-Nwk_ObjFaninNum(pNode) ) - return 0; - - pCands[nCands] = toLitCond( Vec_IntEntry(p->vProjVarsSat, iVar), 1 ); - RetValue = Mfx_TryResubOnce( p, pCands, nCands+1 ); - if ( RetValue == -1 ) - return 0; - if ( RetValue == 1 ) - { - if ( fVeryVerbose ) - printf( "Node %d: Fanin %d can be replaced by divisor %d.\n", pNode->Id, iFanin, iVar ); - p->nNodesResub++; - p->nNodesGainedLevel++; - if ( fSkipUpdate ) - return 1; -clk = clock(); - // derive the function - pFunc = Mfx_Interplate( p, pCands, nCands+1 ); - if ( pFunc == NULL ) - return 0; - // update the network - Vec_PtrPush( p->vFanins, Vec_PtrEntry(p->vDivs, iVar) ); - Mfx_UpdateNetwork( p, pNode, p->vFanins, pFunc ); -p->timeInt += clock() - clk; - return 1; - } - if ( p->nCexes >= p->pPars->nDivMax ) - break; - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Performs resubstitution for the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mfx_SolveSatResub2( Mfx_Man_t * p, Nwk_Obj_t * pNode, int iFanin, int iFanin2 ) -{ - int fVeryVerbose = p->pPars->fVeryVerbose && Vec_PtrSize(p->vDivs) < 80; - unsigned * pData, * pData2; - int pCands[MFX_FANIN_MAX]; - int RetValue, iVar, iVar2, i, w, nCands, clk, nWords, fBreak; - Nwk_Obj_t * pFanin; - Hop_Obj_t * pFunc; - assert( iFanin >= 0 ); - assert( iFanin2 >= 0 || iFanin2 == -1 ); - - // clean simulation info - Vec_PtrFillSimInfo( p->vDivCexes, 0, p->nDivWords ); - p->nCexes = 0; - if ( fVeryVerbose ) - { - printf( "\n" ); - printf( "Node %5d : Level = %2d. Divs = %3d. Fanins = %d/%d (out of %d). MFFC = %d\n", - pNode->Id, pNode->Level, Vec_PtrSize(p->vDivs)-Nwk_ObjFaninNum(pNode), - iFanin, iFanin2, Nwk_ObjFaninNum(pNode), - Nwk_ObjFanoutNum(Nwk_ObjFanin(pNode, iFanin)) == 1 ? Nwk_ObjMffcLabel(Nwk_ObjFanin(pNode, iFanin)) : 0 ); - } - - // try fanins without the critical fanin - nCands = 0; - Vec_PtrClear( p->vFanins ); - Nwk_ObjForEachFanin( pNode, pFanin, i ) - { - if ( i == iFanin || i == iFanin2 ) - continue; - Vec_PtrPush( p->vFanins, pFanin ); - iVar = Vec_PtrSize(p->vDivs) - Nwk_ObjFaninNum(pNode) + i; - pCands[nCands++] = toLitCond( Vec_IntEntry( p->vProjVarsSat, iVar ), 1 ); - } - RetValue = Mfx_TryResubOnce( p, pCands, nCands ); - if ( RetValue == -1 ) - return 0; - if ( RetValue == 1 ) - { - if ( fVeryVerbose ) - printf( "Node %d: Fanins %d/%d can be removed.\n", pNode->Id, iFanin, iFanin2 ); - p->nNodesResub++; - p->nNodesGainedLevel++; -clk = clock(); - // derive the function - pFunc = Mfx_Interplate( p, pCands, nCands ); - if ( pFunc == NULL ) - return 0; - // update the network - Mfx_UpdateNetwork( p, pNode, p->vFanins, pFunc ); -p->timeInt += clock() - clk; - return 1; - } - - if ( fVeryVerbose ) - { - for ( i = 0; i < 11; i++ ) - printf( " " ); - for ( i = 0; i < Vec_PtrSize(p->vDivs)-Nwk_ObjFaninNum(pNode); i++ ) - printf( "%d", i % 10 ); - for ( i = 0; i < Nwk_ObjFaninNum(pNode); i++ ) - if ( i == iFanin || i == iFanin2 ) - printf( "*" ); - else - printf( "%c", 'a' + i ); - printf( "\n" ); - } - iVar = iVar2 = -1; - while ( 1 ) - { - if ( fVeryVerbose ) - { - printf( "%3d: %2d %2d ", p->nCexes, iVar, iVar2 ); - for ( i = 0; i < Vec_PtrSize(p->vDivs); i++ ) - { - pData = (unsigned *)Vec_PtrEntry( p->vDivCexes, i ); - printf( "%d", Aig_InfoHasBit(pData, p->nCexes-1) ); - } - printf( "\n" ); - } - - // find the next divisor to try - nWords = Aig_BitWordNum(p->nCexes); - assert( nWords <= p->nDivWords ); - fBreak = 0; - for ( iVar = 1; iVar < Vec_PtrSize(p->vDivs)-Nwk_ObjFaninNum(pNode); iVar++ ) - { - pData = (unsigned *)Vec_PtrEntry( p->vDivCexes, iVar ); - for ( iVar2 = 0; iVar2 < iVar; iVar2++ ) - { - pData2 = (unsigned *)Vec_PtrEntry( p->vDivCexes, iVar2 ); - for ( w = 0; w < nWords; w++ ) - if ( (pData[w] | pData2[w]) != ~0 ) - break; - if ( w == nWords ) - { - fBreak = 1; - break; - } - } - if ( fBreak ) - break; - } - if ( iVar == Vec_PtrSize(p->vDivs)-Nwk_ObjFaninNum(pNode) ) - return 0; - - pCands[nCands] = toLitCond( Vec_IntEntry(p->vProjVarsSat, iVar2), 1 ); - pCands[nCands+1] = toLitCond( Vec_IntEntry(p->vProjVarsSat, iVar), 1 ); - RetValue = Mfx_TryResubOnce( p, pCands, nCands+2 ); - if ( RetValue == -1 ) - return 0; - if ( RetValue == 1 ) - { - if ( fVeryVerbose ) - printf( "Node %d: Fanins %d/%d can be replaced by divisors %d/%d.\n", pNode->Id, iFanin, iFanin2, iVar, iVar2 ); - p->nNodesResub++; - p->nNodesGainedLevel++; -clk = clock(); - // derive the function - pFunc = Mfx_Interplate( p, pCands, nCands+2 ); - if ( pFunc == NULL ) - return 0; - // update the network - Vec_PtrPush( p->vFanins, Vec_PtrEntry(p->vDivs, iVar2) ); - Vec_PtrPush( p->vFanins, Vec_PtrEntry(p->vDivs, iVar) ); - assert( Vec_PtrSize(p->vFanins) == nCands + 2 ); - Mfx_UpdateNetwork( p, pNode, p->vFanins, pFunc ); -p->timeInt += clock() - clk; - return 1; - } - if ( p->nCexes >= p->pPars->nDivMax ) - break; - } - return 0; -} - - -/**Function************************************************************* - - Synopsis [Evaluates the possibility of replacing given edge by another edge.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mfx_EdgeSwapEval( Mfx_Man_t * p, Nwk_Obj_t * pNode ) -{ - Nwk_Obj_t * pFanin; - int i; - Nwk_ObjForEachFanin( pNode, pFanin, i ) - Mfx_SolveSatResub( p, pNode, i, 0, 1 ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Evaluates the possibility of replacing given edge by another edge.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mfx_EdgePower( Mfx_Man_t * p, Nwk_Obj_t * pNode ) -{ - Nwk_Obj_t * pFanin; - float * pProbab = (float *)p->vProbs->pArray; - int i; - // try replacing area critical fanins - Nwk_ObjForEachFanin( pNode, pFanin, i ) - if ( pProbab[pFanin->Id] >= 0.4 ) - { - if ( Mfx_SolveSatResub( p, pNode, i, 0, 0 ) ) - return 1; - } - return 0; -} - - -/**Function************************************************************* - - Synopsis [Performs resubstitution for the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mfx_ResubNode( Mfx_Man_t * p, Nwk_Obj_t * pNode ) -{ - Nwk_Obj_t * pFanin; - int i; - // try replacing area critical fanins - Nwk_ObjForEachFanin( pNode, pFanin, i ) - if ( !Nwk_ObjIsCi(pFanin) && Nwk_ObjFanoutNum(pFanin) == 1 ) - { - if ( Mfx_SolveSatResub( p, pNode, i, 0, 0 ) ) - return 1; - } - // try removing redundant edges - if ( !p->pPars->fArea ) - { - Nwk_ObjForEachFanin( pNode, pFanin, i ) - if ( Nwk_ObjIsCi(pFanin) || Nwk_ObjFanoutNum(pFanin) != 1 ) - { - if ( Mfx_SolveSatResub( p, pNode, i, 1, 0 ) ) - return 1; - } - } - if ( Nwk_ObjFaninNum(pNode) == p->nFaninMax ) - return 0; - - return 0; /// !!!!! temporary workaround - - // try replacing area critical fanins while adding two new fanins - Nwk_ObjForEachFanin( pNode, pFanin, i ) - if ( !Nwk_ObjIsCi(pFanin) && Nwk_ObjFanoutNum(pFanin) == 1 ) - { - if ( Mfx_SolveSatResub2( p, pNode, i, -1 ) ) - return 1; - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Performs resubstitution for the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mfx_ResubNode2( Mfx_Man_t * p, Nwk_Obj_t * pNode ) -{ - Nwk_Obj_t * pFanin, * pFanin2; - int i, k; -/* - Nwk_ObjForEachFanin( pNode, pFanin, i ) - if ( !Nwk_ObjIsCi(pFanin) && Nwk_ObjFanoutNum(pFanin) == 1 ) - { - if ( Mfx_SolveSatResub( p, pNode, i, 0, 0 ) ) - return 1; - } -*/ - if ( Nwk_ObjFaninNum(pNode) < 2 ) - return 0; - // try replacing one area critical fanin and one other fanin while adding two new fanins - Nwk_ObjForEachFanin( pNode, pFanin, i ) - { - if ( !Nwk_ObjIsCi(pFanin) && Nwk_ObjFanoutNum(pFanin) == 1 ) - { - // consider second fanin to remove at the same time - Nwk_ObjForEachFanin( pNode, pFanin2, k ) - { - if ( i != k && Mfx_SolveSatResub2( p, pNode, i, k ) ) - return 1; - } - } - } - return 0; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/mfx/mfxSat.c b/src/aig/mfx/mfxSat.c deleted file mode 100644 index 974563ab..00000000 --- a/src/aig/mfx/mfxSat.c +++ /dev/null @@ -1,145 +0,0 @@ -/**CFile**************************************************************** - - FileName [mfxSat.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [The good old minimization with complete don't-cares.] - - Synopsis [Procedures to compute don't-cares using SAT.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: mfxSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "mfxInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Enumerates through the SAT assignments.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mfx_SolveSat_iter( Mfx_Man_t * p ) -{ - int Lits[MFX_FANIN_MAX]; - int RetValue, nBTLimit, iVar, b, Mint; - if ( p->nTotConfLim && p->nTotConfLim <= p->pSat->stats.conflicts ) - return -1; - nBTLimit = p->nTotConfLim? p->nTotConfLim - p->pSat->stats.conflicts : 0; - RetValue = sat_solver_solve( p->pSat, NULL, NULL, (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); - assert( RetValue == l_Undef || RetValue == l_True || RetValue == l_False ); - if ( RetValue == l_Undef ) - return -1; - if ( RetValue == l_False ) - return 0; - p->nCares++; - // add SAT assignment to the solver - Mint = 0; - Vec_IntForEachEntry( p->vProjVarsSat, iVar, b ) - { - Lits[b] = toLit( iVar ); - if ( sat_solver_var_value( p->pSat, iVar ) ) - { - Mint |= (1 << b); - Lits[b] = lit_neg( Lits[b] ); - } - } - assert( !Aig_InfoHasBit(p->uCare, Mint) ); - Aig_InfoSetBit( p->uCare, Mint ); - // add the blocking clause - RetValue = sat_solver_addclause( p->pSat, Lits, Lits + Vec_IntSize(p->vProjVarsSat) ); - if ( RetValue == 0 ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Enumerates through the SAT assignments.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mfx_SolveSat( Mfx_Man_t * p, Nwk_Obj_t * pNode ) -{ - Aig_Obj_t * pObjPo; - int RetValue, i; - // collect projection variables - Vec_IntClear( p->vProjVarsSat ); - Vec_PtrForEachEntryStart( Aig_Obj_t *, p->pAigWin->vPos, pObjPo, i, Aig_ManPoNum(p->pAigWin) - Nwk_ObjFaninNum(pNode) ) - { - assert( p->pCnf->pVarNums[pObjPo->Id] >= 0 ); - Vec_IntPush( p->vProjVarsSat, p->pCnf->pVarNums[pObjPo->Id] ); - } - - // prepare the truth table of care set - p->nFanins = Vec_IntSize( p->vProjVarsSat ); - p->nWords = Aig_TruthWordNum( p->nFanins ); - memset( p->uCare, 0, sizeof(unsigned) * p->nWords ); - - // iterate through the SAT assignments - p->nCares = 0; - p->nTotConfLim = p->pPars->nBTLimit; - while ( (RetValue = Mfx_SolveSat_iter(p)) == 1 ); - if ( RetValue == -1 ) - return 0; - - // write statistics - p->nMintsCare += p->nCares; - p->nMintsTotal += (1<nFanins); - - if ( p->pPars->fVeryVerbose ) - { - printf( "Node %4d : Care = %2d. Total = %2d. ", pNode->Id, p->nCares, (1<nFanins) ); -// Kit_TruthPrintBinary( stdout, p->uCare, (1<nFanins) ); - printf( "\n" ); - } - - // map the care - if ( p->nFanins > 4 ) - return 1; - if ( p->nFanins == 4 ) - p->uCare[0] = p->uCare[0] | (p->uCare[0] << 16); - if ( p->nFanins == 3 ) - p->uCare[0] = p->uCare[0] | (p->uCare[0] << 8) | (p->uCare[0] << 16) | (p->uCare[0] << 24); - if ( p->nFanins == 2 ) - p->uCare[0] = p->uCare[0] | (p->uCare[0] << 4) | (p->uCare[0] << 8) | (p->uCare[0] << 12) | - (p->uCare[0] << 16) | (p->uCare[0] << 20) | (p->uCare[0] << 24) | (p->uCare[0] << 28); - assert( p->nFanins != 1 ); - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/mfx/mfxStrash.c b/src/aig/mfx/mfxStrash.c deleted file mode 100644 index f750523d..00000000 --- a/src/aig/mfx/mfxStrash.c +++ /dev/null @@ -1,344 +0,0 @@ -/**CFile**************************************************************** - - FileName [mfxStrash.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [The good old minimization with complete don't-cares.] - - Synopsis [Structural hashing of the window with ODCs.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: mfxStrash.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "mfxInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Construct BDDs and mark AIG nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ConvertHopToAig_rec( Hop_Obj_t * pObj, Aig_Man_t * pMan ) -{ - assert( !Hop_IsComplement(pObj) ); - if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) - return; - Nwk_ConvertHopToAig_rec( Hop_ObjFanin0(pObj), pMan ); - Nwk_ConvertHopToAig_rec( Hop_ObjFanin1(pObj), pMan ); - pObj->pData = Aig_And( pMan, (Aig_Obj_t *)Hop_ObjChild0Copy(pObj), (Aig_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 [] - -***********************************************************************/ -void Nwk_ConvertHopToAig( Nwk_Obj_t * pObjOld, Aig_Man_t * pMan ) -{ - Hop_Man_t * pHopMan; - Hop_Obj_t * pRoot; - Nwk_Obj_t * pFanin; - int i; - // get the local AIG - pHopMan = pObjOld->pMan->pManHop; - pRoot = pObjOld->pFunc; - // check the case of a constant - if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) ) - { - pObjOld->pCopy = (Nwk_Obj_t *)Aig_NotCond( Aig_ManConst1(pMan), Hop_IsComplement(pRoot) ); - pObjOld->pNext = pObjOld->pCopy; - return; - } - - // assign the fanin nodes - Nwk_ObjForEachFanin( pObjOld, pFanin, i ) - Hop_ManPi(pHopMan, i)->pData = pFanin->pCopy; - // construct the AIG - Nwk_ConvertHopToAig_rec( Hop_Regular(pRoot), pMan ); - pObjOld->pCopy = (Nwk_Obj_t *)Aig_NotCond( (Aig_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); - Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); - - // assign the fanin nodes - Nwk_ObjForEachFanin( pObjOld, pFanin, i ) - Hop_ManPi(pHopMan, i)->pData = pFanin->pNext; - // construct the AIG - Nwk_ConvertHopToAig_rec( Hop_Regular(pRoot), pMan ); - pObjOld->pNext = (Nwk_Obj_t *)Aig_NotCond( (Aig_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); - Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); -} - -/**Function************************************************************* - - Synopsis [Computes the care set of the node under ODCs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Mfx_ConstructAig_rec( Mfx_Man_t * p, Nwk_Obj_t * pNode, Aig_Man_t * pMan ) -{ - Aig_Obj_t * pRoot, * pExor; - Nwk_Obj_t * pObj; - int i; - // assign AIG nodes to the leaves - Vec_PtrForEachEntry( Nwk_Obj_t *, p->vSupp, pObj, i ) - pObj->pCopy = pObj->pNext = (Nwk_Obj_t *)Aig_ObjCreatePi( pMan ); - // strash intermediate nodes - Nwk_ManIncrementTravId( pNode->pMan ); - Vec_PtrForEachEntry( Nwk_Obj_t *, p->vNodes, pObj, i ) - { - Nwk_ConvertHopToAig( pObj, pMan ); - if ( pObj == pNode ) - pObj->pNext = Aig_Not((Aig_Obj_t *)pObj->pNext); - } - // create the observability condition - pRoot = Aig_ManConst0(pMan); - Vec_PtrForEachEntry( Nwk_Obj_t *, p->vRoots, pObj, i ) - { - pExor = Aig_Exor( pMan, (Aig_Obj_t *)pObj->pCopy, (Aig_Obj_t *)pObj->pNext ); - pRoot = Aig_Or( pMan, pRoot, pExor ); - } - return pRoot; -} - -/**Function************************************************************* - - Synopsis [Adds relevant constraints.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Mfx_ConstructCare_rec( Aig_Man_t * pCare, Aig_Obj_t * pObj, Aig_Man_t * pMan ) -{ - Aig_Obj_t * pObj0, * pObj1; - if ( Aig_ObjIsTravIdCurrent( pCare, pObj ) ) - return (Aig_Obj_t *)pObj->pData; - Aig_ObjSetTravIdCurrent( pCare, pObj ); - if ( Aig_ObjIsPi(pObj) ) - return (Aig_Obj_t *)(pObj->pData = NULL); - pObj0 = Mfx_ConstructCare_rec( pCare, Aig_ObjFanin0(pObj), pMan ); - if ( pObj0 == NULL ) - return (Aig_Obj_t *)(pObj->pData = NULL); - pObj1 = Mfx_ConstructCare_rec( pCare, Aig_ObjFanin1(pObj), pMan ); - if ( pObj1 == NULL ) - return (Aig_Obj_t *)(pObj->pData = NULL); - pObj0 = Aig_NotCond( pObj0, Aig_ObjFaninC0(pObj) ); - pObj1 = Aig_NotCond( pObj1, Aig_ObjFaninC1(pObj) ); - return (Aig_Obj_t *)(pObj->pData = Aig_And( pMan, pObj0, pObj1 )); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManVerifyManager( Nwk_Man_t * pNtk ) -{ - Nwk_Obj_t * pObj; - int i; - Nwk_ManForEachObj( pNtk, pObj, i ) - { - assert( pObj->pMan == pNtk ); - } -} - -/**Function************************************************************* - - Synopsis [Creates AIG for the window with constraints.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Mfx_ConstructAig( Mfx_Man_t * p, Nwk_Obj_t * pNode ) -{ - Aig_Man_t * pMan; - Nwk_Obj_t * pFanin; - Aig_Obj_t * pObjAig, * pPi, * pPo; - Vec_Int_t * vOuts; - int i, k, iOut; -// Nwk_ManVerifyManager( p->pNtk ); - // start the new manager - pMan = Aig_ManStart( 1000 ); - // construct the root node's AIG cone - pObjAig = Mfx_ConstructAig_rec( p, pNode, pMan ); -// assert( Aig_ManConst1(pMan) == pObjAig ); - Aig_ObjCreatePo( pMan, pObjAig ); - if ( p->pCare ) - { - // mark the care set - Aig_ManIncrementTravId( p->pCare ); - Vec_PtrForEachEntry( Nwk_Obj_t *, p->vSupp, pFanin, i ) - { - pPi = Aig_ManPi( p->pCare, pFanin->PioId ); - Aig_ObjSetTravIdCurrent( p->pCare, pPi ); - pPi->pData = pFanin->pCopy; - } - // construct the constraints - Vec_PtrForEachEntry( Nwk_Obj_t *, p->vSupp, pFanin, i ) - { - vOuts = (Vec_Int_t *)Vec_PtrEntry( p->vSuppsInv, pFanin->PioId ); - Vec_IntForEachEntry( vOuts, iOut, k ) - { - pPo = Aig_ManPo( p->pCare, iOut ); - if ( Aig_ObjIsTravIdCurrent( p->pCare, pPo ) ) - continue; - Aig_ObjSetTravIdCurrent( p->pCare, pPo ); - if ( Aig_ObjFanin0(pPo) == Aig_ManConst1(p->pCare) ) - continue; - pObjAig = Mfx_ConstructCare_rec( p->pCare, Aig_ObjFanin0(pPo), pMan ); - if ( pObjAig == NULL ) - continue; - pObjAig = Aig_NotCond( pObjAig, Aig_ObjFaninC0(pPo) ); - Aig_ObjCreatePo( pMan, pObjAig ); - } - } -/* - Aig_ManForEachPo( p->pCare, pPo, i ) - { -// assert( Aig_ObjFanin0(pPo) != Aig_ManConst1(p->pCare) ); - if ( Aig_ObjFanin0(pPo) == Aig_ManConst1(p->pCare) ) - continue; - pObjAig = Mfx_ConstructCare_rec( p->pCare, Aig_ObjFanin0(pPo), pMan ); - if ( pObjAig == NULL ) - continue; - pObjAig = Aig_NotCond( pObjAig, Aig_ObjFaninC0(pPo) ); - Aig_ObjCreatePo( pMan, pObjAig ); - } -*/ - } - if ( p->pPars->fResub ) - { - // construct the node - pObjAig = (Aig_Obj_t *)pNode->pCopy; - Aig_ObjCreatePo( pMan, pObjAig ); - // construct the divisors - Vec_PtrForEachEntry( Nwk_Obj_t *, p->vDivs, pFanin, i ) - { - pObjAig = (Aig_Obj_t *)pFanin->pCopy; - Aig_ObjCreatePo( pMan, pObjAig ); - } - } - else - { - // construct the fanins - Nwk_ObjForEachFanin( pNode, pFanin, i ) - { - pObjAig = (Aig_Obj_t *)pFanin->pCopy; - Aig_ObjCreatePo( pMan, pObjAig ); - } - } - Aig_ManCleanup( pMan ); - return pMan; -} - -/**Function************************************************************* - - Synopsis [Creates AIG for the window with constraints.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Nwk_AigForConstraints( Mfx_Man_t * p, Nwk_Obj_t * pNode ) -{ - Nwk_Obj_t * pFanin; - Aig_Man_t * pMan; - Aig_Obj_t * pPi, * pPo, * pObjAig, * pObjRoot; - Vec_Int_t * vOuts; - int i, k, iOut; - if ( p->pCare == NULL ) - return NULL; - pMan = Aig_ManStart( 1000 ); - // mark the care set - Aig_ManIncrementTravId( p->pCare ); - Vec_PtrForEachEntry( Nwk_Obj_t *, p->vSupp, pFanin, i ) - { - pPi = Aig_ManPi( p->pCare, pFanin->PioId ); - Aig_ObjSetTravIdCurrent( p->pCare, pPi ); - pPi->pData = Aig_ObjCreatePi(pMan); - } - // construct the constraints - pObjRoot = Aig_ManConst1(pMan); - Vec_PtrForEachEntry( Nwk_Obj_t *, p->vSupp, pFanin, i ) - { - vOuts = (Vec_Int_t *)Vec_PtrEntry( p->vSuppsInv, pFanin->PioId ); - Vec_IntForEachEntry( vOuts, iOut, k ) - { - pPo = Aig_ManPo( p->pCare, iOut ); - if ( Aig_ObjIsTravIdCurrent( p->pCare, pPo ) ) - continue; - Aig_ObjSetTravIdCurrent( p->pCare, pPo ); - if ( Aig_ObjFanin0(pPo) == Aig_ManConst1(p->pCare) ) - continue; - pObjAig = Mfx_ConstructCare_rec( p->pCare, Aig_ObjFanin0(pPo), pMan ); - if ( pObjAig == NULL ) - continue; - pObjAig = Aig_NotCond( pObjAig, Aig_ObjFaninC0(pPo) ); - pObjRoot = Aig_And( pMan, pObjRoot, pObjAig ); - } - } - Aig_ObjCreatePo( pMan, pObjRoot ); - Aig_ManCleanup( pMan ); - return pMan; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/mfx/mfxWin.c b/src/aig/mfx/mfxWin.c deleted file mode 100644 index 7cb3c53d..00000000 --- a/src/aig/mfx/mfxWin.c +++ /dev/null @@ -1,117 +0,0 @@ -/**CFile**************************************************************** - - FileName [mfxWin.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [The good old minimization with complete don't-cares.] - - Synopsis [Procedures to compute windows stretching to the PIs.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: mfxWin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "mfxInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns 1 if the node should be a root.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Mfx_ComputeRootsCheck( Nwk_Obj_t * pNode, int nLevelMax, int nFanoutLimit ) -{ - Nwk_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 ( Nwk_ObjFanoutNum(pNode) > nFanoutLimit ) - return 1; - // (2) the node has CO fanouts - // (3) the node has fanouts above the cutoff level - Nwk_ObjForEachFanout( pNode, pFanout, i ) - if ( Nwk_ObjIsCo(pFanout) || pFanout->Level > nLevelMax ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Recursively collects the root candidates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mfx_ComputeRoots_rec( Nwk_Obj_t * pNode, int nLevelMax, int nFanoutLimit, Vec_Ptr_t * vRoots ) -{ - Nwk_Obj_t * pFanout; - int i; - assert( Nwk_ObjIsNode(pNode) ); - if ( Nwk_ObjIsTravIdCurrent(pNode) ) - return; - Nwk_ObjSetTravIdCurrent( pNode ); - // check if the node should be the root - if ( Mfx_ComputeRootsCheck( pNode, nLevelMax, nFanoutLimit ) ) - Vec_PtrPush( vRoots, pNode ); - else // if not, explore its fanouts - Nwk_ObjForEachFanout( pNode, pFanout, i ) - Mfx_ComputeRoots_rec( pFanout, nLevelMax, nFanoutLimit, vRoots ); -} - -/**Function************************************************************* - - Synopsis [Recursively collects the root candidates.] - - Description [Returns 1 if the only root is this node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Mfx_ComputeRoots( Nwk_Obj_t * pNode, int nWinTfoMax, int nFanoutLimit ) -{ - Vec_Ptr_t * vRoots; - vRoots = Vec_PtrAlloc( 10 ); - Nwk_ManIncrementTravId( pNode->pMan ); - Mfx_ComputeRoots_rec( pNode, pNode->Level + nWinTfoMax, nFanoutLimit, vRoots ); - assert( Vec_PtrSize(vRoots) > 0 ); -// if ( Vec_PtrSize(vRoots) == 1 && Vec_PtrEntry(vRoots, 0) == pNode ) -// return 0; - return vRoots; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/mfx/mfx_.c b/src/aig/mfx/mfx_.c deleted file mode 100644 index 2682fa42..00000000 --- a/src/aig/mfx/mfx_.c +++ /dev/null @@ -1,52 +0,0 @@ -/**CFile**************************************************************** - - FileName [mfs_.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [The good old minimization with complete don't-cares.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: mfs_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "mfsInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/mfx/module.make b/src/aig/mfx/module.make deleted file mode 100644 index 22b9b72a..00000000 --- a/src/aig/mfx/module.make +++ /dev/null @@ -1,8 +0,0 @@ -SRC += src/aig/mfx/mfxCore.c \ - src/aig/mfx/mfxDiv.c \ - src/aig/mfx/mfxInter.c \ - src/aig/mfx/mfxMan.c \ - src/aig/mfx/mfxResub.c \ - src/aig/mfx/mfxSat.c \ - src/aig/mfx/mfxStrash.c \ - src/aig/mfx/mfxWin.c diff --git a/src/aig/ntl/module.make b/src/aig/ntl/module.make deleted file mode 100644 index 2af0f4e0..00000000 --- a/src/aig/ntl/module.make +++ /dev/null @@ -1,17 +0,0 @@ -SRC += src/aig/ntl/ntlCheck.c \ - src/aig/ntl/ntlCore.c \ - src/aig/ntl/ntlEc.c \ - src/aig/ntl/ntlExtract.c \ - src/aig/ntl/ntlFraig.c \ - src/aig/ntl/ntlInsert.c \ - src/aig/ntl/ntlMan.c \ - src/aig/ntl/ntlMap.c \ - src/aig/ntl/ntlNames.c \ - src/aig/ntl/ntlObj.c \ - src/aig/ntl/ntlReadBlif.c \ - src/aig/ntl/ntlSweep.c \ - src/aig/ntl/ntlTable.c \ - src/aig/ntl/ntlTime.c \ - src/aig/ntl/ntlUtil.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 c0d701e0..00000000 --- a/src/aig/ntl/ntl.h +++ /dev/null @@ -1,426 +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: ntl.h,v 1.3 2008/10/24 14:18:44 mjarvin Exp $] - -***********************************************************************/ - -#ifndef __NTL_H__ -#define __NTL_H__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "aig.h" -#include "tim.h" -#include "nwk.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -ABC_NAMESPACE_HEADER_START - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Ntl_Mod_t_ Ntl_Mod_t; -typedef struct Ntl_Reg_t_ Ntl_Reg_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 - NTL_OBJ_NODE, // 4: logic node - NTL_OBJ_LUT1, // 5: inverter/buffer - NTL_OBJ_BOX, // 6: white box or black box - NTL_OBJ_VOID // 7: 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 - int BoxTypes[32]; // the array of box types among the models - // 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 * vVisNodes; // the nodes of the abstracted part - Vec_Int_t * vBox1Cios; // the first COs of the boxes - Vec_Int_t * vRegClasses; // the classes of registers in the AIG - Vec_Int_t * vRstClasses; // the classes of reset registers in the AIG - Aig_Man_t * pAig; // the extracted AIG - Tim_Man_t * pManTime; // the timing manager - int iLastCi; // the last true CI - void * pNal; // additional data - void (*pNalF)(void *); // additional data - void (*pNalD)(void *,void *); // additional data - void (*pNalW)(void *,void *); // additional data - void (*pNalR)(void *); // additional data - // hashing names into models - Ntl_Mod_t ** pModTable; // the hash table of names into models - int nModTableSize; // the allocated table size - int nModEntries; // the number of entries in the hash table -}; - -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 - Vec_Ptr_t * vNets; // the array of nets - int nObjs[NTL_OBJ_VOID]; // counter of objects of each type - // box attributes - unsigned int attrWhite :1; // box has known logic - unsigned int attrBox :1; // box is to remain unmapped - unsigned int attrComb :1; // box is combinational - unsigned int attrKeep :1; // box cannot be removed by structural sweep - unsigned int attrNoMerge :1; // box outputs cannot be merged - // 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 - // clocks of the model - Vec_Ptr_t * vClocks; // the clock signals - Vec_Vec_t * vClockFlops; // the flops of each clock - // resets of the model - Vec_Ptr_t * vResets; // the reset signals - Vec_Vec_t * vResetFlops; // the ASYNC flops of each reset - // delay information - Vec_Int_t * vDelays; - Vec_Int_t * vTimeInputs; - Vec_Int_t * vTimeOutputs; - float * pDelayTable; - // other data members - Ntl_Mod_t * pNext; - void * pCopy; - int nUsed, nRems; -}; - -struct Ntl_Reg_t_ -{ - unsigned int regInit : 2; // register initial value - unsigned int regType : 3; // register type - unsigned int regClass : 28; // register class -}; - -struct Ntl_Obj_t_ -{ -// Ntl_Mod_t * pModel; // the model - void * pCopy; // the copy of this object - unsigned Type : 3; // object type - unsigned fMark : 1; // temporary mark - unsigned Id : 28; // object ID - int nFanins; // the number of fanins - int nFanouts; // the number of fanouts - int Reset; // reset of the flop - union { // functionality - Ntl_Mod_t * pImplem; // model (for boxes) - char * pSop; // SOP (for logic nodes) - Ntl_Reg_t LatchId; // init state + register class (for latches) - }; - union { // clock / other data - Ntl_Net_t * pClock; // clock (for registers) - void * pTemp; // other data - int iTemp; // other data - }; - Ntl_Net_t * pFanio[0]; // fanins/fanouts -}; - -struct Ntl_Net_t_ -{ - Ntl_Net_t * pNext; // next net in the hash table - void * pCopy; // the copy of this object - union { - void * pCopy2; // the copy of this object - float dTemp; // other data - int iTemp; // other data - }; - Ntl_Obj_t * pDriver; // driver of the net - unsigned NetId : 27; // unique ID of the net - unsigned nVisits : 2; // the number of times the net is visted - unsigned fMark : 1; // temporary mark - unsigned fMark2 : 1; // temporary mark - unsigned fFixed : 1; // the fixed net - 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 Ntl_Mod_t * Ntl_ManRootModel( Ntl_Man_t * p ) { return (Ntl_Mod_t *)Vec_PtrEntry( p->vModels, 0 ); } - -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_ModelLut1Num( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_LUT1]; } -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 Ntl_Obj_t * Ntl_ModelPi( Ntl_Mod_t * p, int i ) { return (Ntl_Obj_t *)Vec_PtrEntry(p->vPis, i); } -static inline Ntl_Obj_t * Ntl_ModelPo( Ntl_Mod_t * p, int i ) { return (Ntl_Obj_t *)Vec_PtrEntry(p->vPos, i); } -static inline Ntl_Obj_t * Ntl_ModelObj( Ntl_Mod_t * p, int i ) { return (Ntl_Obj_t *)Vec_PtrEntry(p->vObjs, i); } -static inline Ntl_Net_t * Ntl_ModelNet( Ntl_Mod_t * p, int i ) { return (Ntl_Net_t *)Vec_PtrEntry(p->vNets, 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_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 int Ntl_ObjIsLutBox( Ntl_Obj_t * p ) { return Ntl_ObjIsBox(p) && strncmp("LUT", p->pImplem->pName, 3) == 0; } - -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+i]; } - -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; } - -static inline int Ntl_ObjIsInit1( Ntl_Obj_t * p ) { assert( Ntl_ObjIsLatch(p) ); return p->LatchId.regInit == 1; } -static inline void Ntl_ObjSetInit0( Ntl_Obj_t * p ) { assert( Ntl_ObjIsLatch(p) ); p->LatchId.regInit = 0; } - -static inline int Ntl_BoxIsWhite( Ntl_Obj_t * p ) { assert( Ntl_ObjIsBox(p) ); return p->pImplem->attrWhite; } -static inline int Ntl_BoxIsBlack( Ntl_Obj_t * p ) { assert( Ntl_ObjIsBox(p) ); return !p->pImplem->attrWhite; } -static inline int Ntl_BoxIsComb( Ntl_Obj_t * p ) { assert( Ntl_ObjIsBox(p) ); return p->pImplem->attrComb; } -static inline int Ntl_BoxIsSeq( Ntl_Obj_t * p ) { assert( Ntl_ObjIsBox(p) ); return !p->pImplem->attrComb; } -static inline int Ntl_BoxIsNoMerge( Ntl_Obj_t * p ) { assert( Ntl_ObjIsBox(p) ); return !p->pImplem->attrNoMerge; } - -static inline int Ntl_ObjIsMapLeaf( Ntl_Obj_t * p ) { return Ntl_ObjIsPi(p) || (Ntl_ObjIsBox(p) && Ntl_BoxIsSeq(p)); } -static inline int Ntl_ObjIsMapRoot( Ntl_Obj_t * p ) { return Ntl_ObjIsPo(p) || (Ntl_ObjIsBox(p) && Ntl_BoxIsSeq(p)); } - -static inline int Ntl_ObjIsCombLeaf( Ntl_Obj_t * p ) { return Ntl_ObjIsPi(p) || (Ntl_ObjIsBox(p) && (Ntl_BoxIsSeq(p) || Ntl_BoxIsBlack(p))); } -static inline int Ntl_ObjIsCombRoot( Ntl_Obj_t * p ) { return Ntl_ObjIsPo(p) || (Ntl_ObjIsBox(p) && (Ntl_BoxIsSeq(p) || Ntl_BoxIsBlack(p))); } - -static inline int Ntl_ObjIsSeqLeaf( Ntl_Obj_t * p ) { return Ntl_ObjIsPi(p) || (Ntl_ObjIsBox(p) && Ntl_BoxIsBlack(p)); } -static inline int Ntl_ObjIsSeqRoot( Ntl_Obj_t * p ) { return Ntl_ObjIsPo(p) || (Ntl_ObjIsBox(p) && Ntl_BoxIsBlack(p)); } - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -#define Ntl_ManForEachModel( p, pMod, i ) \ - for ( i = 0; (i < Vec_PtrSize(p->vModels)) && (((pMod) = (Ntl_Mod_t*)Vec_PtrEntry(p->vModels, i)), 1); i++ ) -#define Ntl_ManForEachCiNet( p, pNet, i ) \ - Vec_PtrForEachEntry( Ntl_Net_t *, p->vCis, pNet, i ) -#define Ntl_ManForEachCoNet( p, pNet, i ) \ - Vec_PtrForEachEntry( Ntl_Net_t *, p->vCos, pNet, i ) - -#define Ntl_ModelForEachPi( pNwk, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize(pNwk->vPis)) && (((pObj) = (Ntl_Obj_t*)Vec_PtrEntry(pNwk->vPis, i)), 1); i++ ) -#define Ntl_ModelForEachPo( pNwk, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize(pNwk->vPos)) && (((pObj) = (Ntl_Obj_t*)Vec_PtrEntry(pNwk->vPos, i)), 1); i++ ) -#define Ntl_ModelForEachNet( pNwk, pNet, i ) \ - Vec_PtrForEachEntry( Ntl_Net_t *, pNwk->vNets, pNet, i ) \ - if ( pNet == NULL ) {} else -#define Ntl_ModelForEachObj( pNwk, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize(pNwk->vObjs)) && (((pObj) = (Ntl_Obj_t*)Vec_PtrEntry(pNwk->vObjs, i)), 1); i++ ) \ - if ( pObj == NULL ) {} else -#define Ntl_ModelForEachLatch( pNwk, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize(pNwk->vObjs)) && (((pObj) = (Ntl_Obj_t*)Vec_PtrEntry(pNwk->vObjs, i)), 1); i++ ) \ - if ( (pObj) == NULL || !Ntl_ObjIsLatch((Ntl_Obj_t*)pObj) ) {} else -#define Ntl_ModelForEachNode( pNwk, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize(pNwk->vObjs)) && (((pObj) = (Ntl_Obj_t*)Vec_PtrEntry(pNwk->vObjs, i)), 1); i++ ) \ - if ( (pObj) == NULL || !Ntl_ObjIsNode(pObj) ) {} else -#define Ntl_ModelForEachBox( pNwk, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize(pNwk->vObjs)) && (((pObj) = (Ntl_Obj_t*)Vec_PtrEntry(pNwk->vObjs, i)), 1); i++ ) \ - if ( (pObj) == NULL || !Ntl_ObjIsBox(pObj) ) {} else - -#define Ntl_ObjForEachFanin( pObj, pFanin, i ) \ - for ( i = 0; (i < (pObj)->nFanins) && (((pFanin) = (pObj)->pFanio[i]), 1); i++ ) -#define Ntl_ObjForEachFanout( pObj, pFanout, i ) \ - for ( i = 0; (i < (pObj)->nFanouts) && (((pFanout) = (pObj)->pFanio[(pObj)->nFanins+i]), 1); i++ ) - -#define Ntl_ModelForEachMapLeaf( pNwk, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize(pNwk->vObjs)) && (((pObj) = (Ntl_Obj_t*)Vec_PtrEntry(pNwk->vObjs, i)), 1); i++ ) \ - if ( (pObj) == NULL || !Ntl_ObjIsMapLeaf(pObj) ) {} else -#define Ntl_ModelForEachMapRoot( pNwk, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize(pNwk->vObjs)) && (((pObj) = (Ntl_Obj_t*)Vec_PtrEntry(pNwk->vObjs, i)), 1); i++ ) \ - if ( (pObj) == NULL || !Ntl_ObjIsMapRoot(pObj) ) {} else -#define Ntl_ModelForEachCombLeaf( pNwk, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize(pNwk->vObjs)) && (((pObj) = (Ntl_Obj_t*)Vec_PtrEntry(pNwk->vObjs, i)), 1); i++ ) \ - if ( (pObj) == NULL || !Ntl_ObjIsCombLeaf(pObj) ) {} else -#define Ntl_ModelForEachCombRoot( pNwk, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize(pNwk->vObjs)) && (((pObj) = (Ntl_Obj_t*)Vec_PtrEntry(pNwk->vObjs, i)), 1); i++ ) \ - if ( (pObj) == NULL || !Ntl_ObjIsCombRoot(pObj) ) {} else -#define Ntl_ModelForEachSeqLeaf( pNwk, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize(pNwk->vObjs)) && (((pObj) = (Ntl_Obj_t*)Vec_PtrEntry(pNwk->vObjs, i)), 1); i++ ) \ - if ( (pObj) == NULL || !Ntl_ObjIsSeqLeaf(pObj) ) {} else -#define Ntl_ModelForEachSeqRoot( pNwk, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize(pNwk->vObjs)) && (((pObj) = (Ntl_Obj_t*)Vec_PtrEntry(pNwk->vObjs, i)), 1); i++ ) \ - if ( (pObj) == NULL || !Ntl_ObjIsSeqRoot(pObj) ) {} else - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== ntlCore.c ==========================================================*/ -extern ABC_DLL int Ntl_ManInsertTest( Ntl_Man_t * p, Aig_Man_t * pAig ); -extern ABC_DLL int Ntl_ManInsertTestIf( Ntl_Man_t * p, Aig_Man_t * pAig ); -/*=== ntlEc.c ==========================================================*/ -extern ABC_DLL void Ntl_ManPrepareCecMans( Ntl_Man_t * pMan1, Ntl_Man_t * pMan2, Aig_Man_t ** ppAig1, Aig_Man_t ** ppAig2 ); -extern ABC_DLL void Ntl_ManPrepareCec( char * pFileName1, char * pFileName2, Aig_Man_t ** ppAig1, Aig_Man_t ** ppAig2 ); -extern ABC_DLL Aig_Man_t * Ntl_ManPrepareSec( char * pFileName1, char * pFileName2 ); -/*=== ntlExtract.c ==========================================================*/ -extern ABC_DLL Aig_Man_t * Ntl_ManExtract( Ntl_Man_t * p ); -extern ABC_DLL Aig_Man_t * Ntl_ManCollapse( Ntl_Man_t * p, int fSeq ); -extern ABC_DLL Aig_Man_t * Ntl_ManCollapseComb( Ntl_Man_t * p ); -extern ABC_DLL Aig_Man_t * Ntl_ManCollapseSeq( Ntl_Man_t * p, int nMinDomSize, int fVerbose ); -extern ABC_DLL Nwk_Man_t * Ntl_ManExtractNwk( Ntl_Man_t * p, Aig_Man_t * pAig, Tim_Man_t * pManTime ); -/*=== ntlInsert.c ==========================================================*/ -extern ABC_DLL Ntl_Man_t * Ntl_ManInsertMapping( Ntl_Man_t * p, Vec_Ptr_t * vMapping, Aig_Man_t * pAig ); -extern ABC_DLL Ntl_Man_t * Ntl_ManInsertAig( Ntl_Man_t * p, Aig_Man_t * pAig ); -extern ABC_DLL Ntl_Man_t * Ntl_ManInsertNtk( Ntl_Man_t * p, Nwk_Man_t * pNtk ); -/*=== ntlCheck.c ==========================================================*/ -extern ABC_DLL int Ntl_ManCheck( Ntl_Man_t * pMan ); -extern ABC_DLL int Ntl_ModelCheck( Ntl_Mod_t * pModel, int fMain ); -extern ABC_DLL void Ntl_ModelFixNonDrivenNets( Ntl_Mod_t * pModel ); -extern ABC_DLL void Ntl_ModelTransformLatches( Ntl_Mod_t * pModel ); -/*=== ntlMan.c ============================================================*/ -extern ABC_DLL Ntl_Man_t * Ntl_ManAlloc(); -extern ABC_DLL void Ntl_ManCleanup( Ntl_Man_t * p ); -extern ABC_DLL Ntl_Man_t * Ntl_ManStartFrom( Ntl_Man_t * p ); -extern ABC_DLL Ntl_Man_t * Ntl_ManDup( Ntl_Man_t * p ); -extern ABC_DLL Ntl_Man_t * Ntl_ManDupCollapseLuts( Ntl_Man_t * p ); -extern ABC_DLL void Ntl_ManFree( Ntl_Man_t * p ); -extern ABC_DLL void Ntl_ManPrintStats( Ntl_Man_t * p ); -extern ABC_DLL Tim_Man_t * Ntl_ManReadTimeMan( Ntl_Man_t * p ); -extern ABC_DLL void Ntl_ManPrintTypes( Ntl_Man_t * p ); -extern ABC_DLL int Ntl_ManCompareClockClasses( Vec_Ptr_t ** pp1, Vec_Ptr_t ** pp2 ); -extern ABC_DLL void Ntl_ManPrintClocks( Ntl_Man_t * p ); -extern ABC_DLL void Ntl_ManPrintResets( Ntl_Man_t * p ); -extern ABC_DLL Ntl_Mod_t * Ntl_ModelAlloc( Ntl_Man_t * pMan, char * pName ); -extern ABC_DLL Ntl_Mod_t * Ntl_ModelStartFrom( Ntl_Man_t * pManNew, Ntl_Mod_t * pModelOld ); -extern ABC_DLL Ntl_Mod_t * Ntl_ModelDup( Ntl_Man_t * pManNew, Ntl_Mod_t * pModelOld ); -extern ABC_DLL Ntl_Mod_t * Ntl_ModelDupCollapseLuts( Ntl_Man_t * pManNew, Ntl_Mod_t * pModelOld ); -extern ABC_DLL void Ntl_ModelFree( Ntl_Mod_t * p ); -extern ABC_DLL Ntl_Mod_t * Ntl_ManCreateLatchModel( Ntl_Man_t * pMan, int Init ); -extern ABC_DLL int Ntl_ModelCountLut0( Ntl_Mod_t * p ); -extern ABC_DLL int Ntl_ModelCountLut1( Ntl_Mod_t * p ); -extern ABC_DLL int Ntl_ModelCountBuf( Ntl_Mod_t * p ); -extern ABC_DLL int Ntl_ModelCountInv( Ntl_Mod_t * p ); -/*=== ntlMap.c ============================================================*/ -extern ABC_DLL Vec_Ptr_t * Ntl_MappingAlloc( int nLuts, int nVars ); -extern ABC_DLL Vec_Ptr_t * Ntl_MappingFromAig( Aig_Man_t * p ); -extern ABC_DLL Vec_Ptr_t * Ntl_MappingFpga( Aig_Man_t * p ); -extern ABC_DLL Vec_Ptr_t * Ntl_MappingIf( Ntl_Man_t * pMan, Aig_Man_t * p ); -/*=== ntlObj.c ============================================================*/ -extern ABC_DLL Ntl_Obj_t * Ntl_ModelCreatePi( Ntl_Mod_t * pModel ); -extern ABC_DLL Ntl_Obj_t * Ntl_ModelCreatePo( Ntl_Mod_t * pModel, Ntl_Net_t * pNet ); -extern ABC_DLL Ntl_Obj_t * Ntl_ModelCreateLatch( Ntl_Mod_t * pModel ); -extern ABC_DLL Ntl_Obj_t * Ntl_ModelCreateNode( Ntl_Mod_t * pModel, int nFanins ); -extern ABC_DLL Ntl_Obj_t * Ntl_ModelCreateBox( Ntl_Mod_t * pModel, int nFanins, int nFanouts ); -extern ABC_DLL Ntl_Obj_t * Ntl_ModelDupObj( Ntl_Mod_t * pModel, Ntl_Obj_t * pOld ); -extern ABC_DLL Ntl_Obj_t * Ntl_ModelCreatePiWithName( Ntl_Mod_t * pModel, char * pName ); -extern ABC_DLL char * Ntl_ManStoreName( Ntl_Man_t * p, char * pName ); -extern ABC_DLL char * Ntl_ManStoreSop( Aig_MmFlex_t * pMan, const char * pSop ); -extern ABC_DLL char * Ntl_ManStoreFileName( Ntl_Man_t * p, char * pFileName ); -extern ABC_DLL int Ntl_ManObjWhichFanout( Ntl_Obj_t * pNode, Ntl_Net_t * pFanout ); -/*=== ntlSweep.c ==========================================================*/ -extern ABC_DLL int Ntl_ManSweep( Ntl_Man_t * p, int fVerbose ); -/*=== ntlTable.c ==========================================================*/ -extern ABC_DLL Ntl_Net_t * Ntl_ModelFindNet( Ntl_Mod_t * p, const char * pName ); -extern ABC_DLL char * Ntl_ModelCreateNetName( Ntl_Mod_t * p, const char * pName, int Num ); -extern ABC_DLL Ntl_Net_t * Ntl_ModelFindOrCreateNet( Ntl_Mod_t * p, const char * pName ); -extern ABC_DLL Ntl_Net_t * Ntl_ModelDontFindCreateNet( Ntl_Mod_t * p, const char * pName ); -extern ABC_DLL void Ntl_ModelSetPioNumbers( Ntl_Mod_t * p ); -extern ABC_DLL int Ntl_ModelFindPioNumber( Ntl_Mod_t * p, int fPiOnly, int fPoOnly, const char * pName, int * pNumber ); -extern ABC_DLL int Ntl_ModelSetNetDriver( Ntl_Obj_t * pObj, Ntl_Net_t * pNet ); -extern ABC_DLL int Ntl_ModelClearNetDriver( Ntl_Obj_t * pObj, Ntl_Net_t * pNet ); -extern ABC_DLL void Ntl_ModelDeleteNet( Ntl_Mod_t * p, Ntl_Net_t * pNet ); -extern ABC_DLL void Ntl_ModelInsertNet( Ntl_Mod_t * p, Ntl_Net_t * pNet ); -extern ABC_DLL int Ntl_ModelCountNets( Ntl_Mod_t * p ); -extern ABC_DLL int Ntl_ManAddModel( Ntl_Man_t * p, Ntl_Mod_t * pModel ); -extern ABC_DLL Ntl_Mod_t * Ntl_ManFindModel( Ntl_Man_t * p, const char * pName ); -/*=== ntlTime.c ==========================================================*/ -extern ABC_DLL Tim_Man_t * Ntl_ManCreateTiming( Ntl_Man_t * p ); -/*=== ntlReadBlif.c ==========================================================*/ -extern ABC_DLL Ntl_Man_t * Ntl_ManReadBlif( char * pFileName, int fCheck ); -/*=== ntlWriteBlif.c ==========================================================*/ -extern ABC_DLL void Ntl_ManWriteBlif( Ntl_Man_t * p, char * pFileName ); -extern ABC_DLL void Ntl_WriteBlifLogic( Nwk_Man_t * pNtk, Ntl_Man_t * p, char * pFileName ); -/*=== ntlUtil.c ==========================================================*/ -extern ABC_DLL int Ntl_FileIsType( char * pFileName, char * pS1, char * pS2, char * pS3 ); -extern ABC_DLL int Ntl_ModelGetFaninMax( Ntl_Mod_t * pRoot ); -extern ABC_DLL Ntl_Net_t * Ntl_ModelFindSimpleNet( Ntl_Net_t * pNetCo ); -extern ABC_DLL int Ntl_ManCountSimpleCoDrivers( Ntl_Man_t * p ); -extern ABC_DLL Vec_Ptr_t * Ntl_ManCollectCiNames( Ntl_Man_t * p ); -extern ABC_DLL Vec_Ptr_t * Ntl_ManCollectCoNames( Ntl_Man_t * p ); -extern ABC_DLL void Ntl_ManMarkCiCoNets( Ntl_Man_t * p ); -extern ABC_DLL void Ntl_ManUnmarkCiCoNets( Ntl_Man_t * p ); -extern ABC_DLL void Ntl_ManSetZeroInitValues( Ntl_Man_t * p ); -extern ABC_DLL void Ntl_ManTransformInitValues( Ntl_Man_t * p ); -extern ABC_DLL Vec_Vec_t * Ntl_ManTransformRegClasses( Ntl_Man_t * pMan, int nSizeMax, int fVerbose ); -extern ABC_DLL void Ntl_ManFilterRegisterClasses( Aig_Man_t * pAig, Vec_Int_t * vRegClasses, int fVerbose ); -extern ABC_DLL int Ntl_ManLatchNum( Ntl_Man_t * p ); -extern ABC_DLL int Ntl_ManIsComb( Ntl_Man_t * p ); -extern ABC_DLL int Ntl_ModelCombLeafNum( Ntl_Mod_t * p ); -extern ABC_DLL int Ntl_ModelCombRootNum( Ntl_Mod_t * p ); -extern ABC_DLL int Ntl_ModelSeqLeafNum( Ntl_Mod_t * p ); -extern ABC_DLL int Ntl_ModelSeqRootNum( Ntl_Mod_t * p ); -extern ABC_DLL int Ntl_ModelCheckNetsAreNotMarked( Ntl_Mod_t * pModel ); -extern ABC_DLL void Ntl_ModelClearNets( Ntl_Mod_t * pModel ); -extern ABC_DLL void Ntl_ManRemoveUselessNets( Ntl_Man_t * p ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/ntl/ntlCheck.c b/src/aig/ntl/ntlCheck.c deleted file mode 100644 index 7aecf878..00000000 --- a/src/aig/ntl/ntlCheck.c +++ /dev/null @@ -1,379 +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.1 2008/10/10 14:09:29 mjarvin Exp $] - -***********************************************************************/ - -#include "ntl.h" -#include "aig.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ModelCheckCombPoPaths_rec( Ntl_Mod_t * pModel, Ntl_Net_t * pNet ) -{ - Ntl_Net_t * pFanin; - int i; - // skip visited nets - if ( pNet->nVisits == 2 ) - return 1; - pNet->nVisits = 2; - // process PIs - if ( Ntl_ObjIsPi(pNet->pDriver) ) - return 0; - // process registers - if ( Ntl_ObjIsLatch(pNet->pDriver) ) - return 1; - assert( Ntl_ObjIsNode(pNet->pDriver) ); - // call recursively - Ntl_ObjForEachFanin( pNet->pDriver, pFanin, i ) - if ( !Ntl_ModelCheckCombPoPaths_rec( pModel, pFanin ) ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Checks the existence of combinational paths from POs to PIs.] - - Description [Returns 0 if the path is found.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ModelCheckCombPoPaths( Ntl_Mod_t * pModel ) -{ - Ntl_Obj_t * pObj; - int i; - Ntl_ModelClearNets( pModel ); - Ntl_ModelForEachPo( pModel, pObj, i ) - if ( !Ntl_ModelCheckCombPoPaths_rec( pModel, Ntl_ObjFanin0(pObj) ) ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Checks one model.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ModelCheck( Ntl_Mod_t * pModel, int fMain ) -{ - Ntl_Obj_t * pObj; - Ntl_Net_t * pNet; - int i, k, fStatus = 1; - - // check root level model - if ( fMain ) - { - if ( Ntl_ModelLatchNum(pModel) > 0 ) - { - printf( "Root level model %s has %d registers.\n", pModel->pName, Ntl_ModelLatchNum(pModel) ); - fStatus = 0; - } - goto checkobjs; - } - - // check delay information - if ( pModel->attrBox && pModel->attrComb ) - { - if ( pModel->vDelays == NULL ) - { - printf( "Warning: Comb model %s does not have delay info. Default 1.0 delays are assumed.\n", pModel->pName ); - pModel->vDelays = Vec_IntAlloc( 3 ); - Vec_IntPush( pModel->vDelays, -1 ); - Vec_IntPush( pModel->vDelays, -1 ); - Vec_IntPush( pModel->vDelays, Aig_Float2Int(1.0) ); - } - if ( pModel->vTimeInputs != NULL ) - { - printf( "Combinational model %s has input arrival/required time information.\n", pModel->pName ); - fStatus = 0; - } - if ( pModel->vTimeOutputs != NULL ) - { - printf( "Combinational model %s has output arrival/required time information.\n", pModel->pName ); - fStatus = 0; - } - } - if ( pModel->attrBox && !pModel->attrComb ) - { - if ( pModel->vDelays != NULL ) - { - printf( "Sequential model %s has delay info.\n", pModel->pName ); - fStatus = 0; - } - if ( pModel->vTimeInputs == NULL ) - { - printf( "Warning: Seq model %s does not have input arrival/required time info. Default 0.0 is assumed.\n", pModel->pName ); - pModel->vTimeInputs = Vec_IntAlloc( 2 ); - Vec_IntPush( pModel->vTimeInputs, -1 ); - Vec_IntPush( pModel->vTimeInputs, Aig_Float2Int(0.0) ); - } - if ( pModel->vTimeOutputs == NULL ) - { -// printf( "Warning: Seq model %s does not have output arrival/required time info. Default 0.0 is assumed.\n", pModel->pName ); - pModel->vTimeOutputs = Vec_IntAlloc( 2 ); - Vec_IntPush( pModel->vTimeOutputs, -1 ); - Vec_IntPush( pModel->vTimeOutputs, Aig_Float2Int(0.0) ); - } - } - - // check box attributes - if ( pModel->attrBox ) - { - if ( !pModel->attrWhite ) - { - if ( Ntl_ModelNodeNum(pModel) + Ntl_ModelLut1Num(pModel) > 0 ) - { - printf( "Model %s is a blackbox, yet it has %d nodes.\n", pModel->pName, Ntl_ModelNodeNum(pModel) + Ntl_ModelLut1Num(pModel) ); - fStatus = 0; - } - if ( Ntl_ModelLatchNum(pModel) > 0 ) - { - printf( "Model %s is a blackbox, yet it has %d registers.\n", pModel->pName, Ntl_ModelLatchNum(pModel) ); - fStatus = 0; - } - return fStatus; - } - // this is a white box - if ( pModel->attrComb && Ntl_ModelNodeNum(pModel) + Ntl_ModelLut1Num(pModel) == 0 ) - { - printf( "Model %s is a comb white box, yet it has no nodes.\n", pModel->pName ); - fStatus = 0; - } - if ( pModel->attrComb && Ntl_ModelLatchNum(pModel) > 0 ) - { - printf( "Model %s is a comb white box, yet it has registers.\n", pModel->pName ); - fStatus = 0; - } - if ( !pModel->attrComb && Ntl_ModelLatchNum(pModel) == 0 ) - { - printf( "Model %s is a seq white box, yet it has no registers.\n", pModel->pName ); - fStatus = 0; - } - if ( !pModel->attrComb && !Ntl_ModelCheckCombPoPaths(pModel) ) - { - printf( "Model %s is a seq white box with comb paths from PIs to POs.\n", pModel->pName ); - fStatus = 0; - } - } - -checkobjs: - // check nets - Ntl_ModelForEachNet( pModel, pNet, i ) - { - if ( pNet->pName == NULL ) - { - printf( "Net in bin %d does not have a name\n", i ); - fStatus = 0; - } -/* - if ( pNet->pDriver == NULL ) - { - printf( "Net %s does not have a driver\n", pNet->pName ); - fStatus = 0; - } -*/ - } - - // check objects - Ntl_ModelForEachObj( pModel, pObj, i ) - { - Ntl_ObjForEachFanin( pObj, pNet, k ) - if ( pNet == NULL ) - { - printf( "Object %d does not have fanin net %d\n", i, k ); - fStatus = 0; - } - Ntl_ObjForEachFanout( pObj, pNet, k ) - if ( pNet == NULL ) - { - printf( "Object %d does not have fanout net %d\n", i, k ); - fStatus = 0; - } - } - return fStatus; -} - -/**Function************************************************************* - - Synopsis [Checks the netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManCheck( Ntl_Man_t * pMan ) -{ - Ntl_Mod_t * pMod1; - int i, fStatus = 1; - // check that the models have unique names - Ntl_ManForEachModel( pMan, pMod1, i ) - { - if ( pMod1->pName == NULL ) - { - printf( "Model %d does not have a name\n", i ); - fStatus = 0; - } - } - // check that the models (except the first one) do not have boxes - Ntl_ManForEachModel( pMan, pMod1, i ) - { - if ( i == 0 ) - continue; - if ( Ntl_ModelBoxNum(pMod1) > 0 ) - { - printf( "Non-root model %d (%s) has %d boxes.\n", i, pMod1->pName, Ntl_ModelBoxNum(pMod1) ); - fStatus = 0; - } - } - // check models - Ntl_ManForEachModel( pMan, pMod1, i ) - { - if ( !Ntl_ModelCheck( pMod1, i==0 ) ) - fStatus = 0; - } - return fStatus; -} - - -/**Function************************************************************* - - Synopsis [Fixed problems with non-driven nets in the model.] - - 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 ( !pModel->attrWhite ) - 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->pMemSops, " 0\n" ); - Ntl_ModelSetNetDriver( pNode, pNet ); - // add the net to those for which the warning will be printed - Vec_PtrPush( vNets, pNet ); - } - -#if 0 // sjang - // print the warning - if ( Vec_PtrSize(vNets) > 0 ) - { - printf( "Warning: Constant-0 drivers added to %d non-driven nets in network \"%s\": ", Vec_PtrSize(vNets), pModel->pName ); - Vec_PtrForEachEntry( Ntl_Net_t *, vNets, pNet, i ) - { - printf( "%s%s", (i? ", ": ""), pNet->pName ); - if ( i == 3 ) - { - if ( Vec_PtrSize(vNets) > 3 ) - printf( " ..." ); - break; - } - } - printf( "\n" ); - } -#endif - Vec_PtrFree( vNets ); -} - -/**Function************************************************************* - - Synopsis [Fixed problems with non-driven nets in the model.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ModelTransformLatches( Ntl_Mod_t * pModel ) -{ - Ntl_Mod_t * pMod[3] = { NULL }; - Ntl_Obj_t * pLatch; - int i, Init; - if ( Ntl_ModelLatchNum(pModel) == 0 ) - return; - Ntl_ModelForEachLatch( pModel, pLatch, i ) - { - Init = pLatch->LatchId.regInit; - if ( pMod[Init] == NULL ) - pMod[Init] = Ntl_ManCreateLatchModel( pModel->pMan, Init ); - pLatch->pImplem = pMod[Init]; - pLatch->Type = NTL_OBJ_BOX; - } - printf( "In the main model \"%s\", %d latches are transformed into white seq boxes.\n", pModel->pName, Ntl_ModelLatchNum(pModel) ); - pModel->nObjs[NTL_OBJ_BOX] += Ntl_ModelLatchNum(pModel); - pModel->nObjs[NTL_OBJ_LATCH] = 0; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ntl/ntlCore.c b/src/aig/ntl/ntlCore.c deleted file mode 100644 index c09bac0f..00000000 --- a/src/aig/ntl/ntlCore.c +++ /dev/null @@ -1,152 +0,0 @@ -/**CFile**************************************************************** - - FileName [ntlCore.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: ntlCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ntl.h" -#include "dch.h" -#include "dar.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Extracts AIG from the netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Ntl_ManPerformChoicing( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fConstruct, int nConfMax, int nLevelMax, int fVerbose ) -{ -// extern Aig_Man_t * Dar_ManBalance( Aig_Man_t * pAig, int fUpdateLevel ); -// extern Aig_Man_t * Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fVerbose ); -// extern Aig_Man_t * Dar_ManChoice( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fConstruct, int nConfMax, int nLevelMax, int fVerbose ); - Aig_Man_t * pTemp; - - // perform synthesis -//printf( "Pre-synthesis AIG: " ); -//Aig_ManPrintStats( pAig ); -// pTemp = Dar_ManBalance( pAig, 1 ); -// pTemp = Dar_ManCompress( pAig, 1, 1, 0, 0 ); - pTemp = Dar_ManChoice( pAig, fBalance, fUpdateLevel, fConstruct, nConfMax, nLevelMax, fVerbose ); -//printf( "Post-synthesis AIG: " ); -//Aig_ManPrintStats( pTemp ); - - return pTemp; -} - -/**Function************************************************************* - - Synopsis [Extracts AIG from the netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Ntl_ManPerformChoicingNew( Aig_Man_t * pAig, Dch_Pars_t * pPars ) -{ -// extern Aig_Man_t * Dar_ManChoiceNew( Aig_Man_t * pAig, Dch_Pars_t * pPars ); - Aig_Man_t * pTemp; -/* - Aig_Obj_t * pObj; - int i; - Aig_ManForEachPi( pAig, pObj, i ) - printf( "%d ", pObj->Level ); - printf( "\n" ); -*/ - pTemp = Dar_ManChoiceNew( pAig, pPars ); -/* - Aig_ManForEachPi( pTemp, pObj, i ) - printf( "%d ", pObj->Level ); - printf( "\n" ); -*/ - return pTemp; -} - -/**Function************************************************************* - - Synopsis [Testing procedure for insertion of mapping into the netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManInsertTest( Ntl_Man_t * p, Aig_Man_t * pAig ) -{ - Ntl_Man_t * pNew; - Vec_Ptr_t * vMapping; - int RetValue; - vMapping = Ntl_MappingFromAig( pAig ); - pNew = Ntl_ManInsertMapping( p, vMapping, pAig ); - RetValue = (pNew != NULL); - Ntl_ManFree( pNew ); - 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, Aig_Man_t * pAig ) -{ - Ntl_Man_t * pNew; - Vec_Ptr_t * vMapping; - int RetValue; - vMapping = Ntl_MappingIf( p, pAig ); - pNew = Ntl_ManInsertMapping( p, vMapping, pAig ); - RetValue = (pNew != NULL); - Ntl_ManFree( pNew ); - Vec_PtrFree( vMapping ); - return RetValue; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ntl/ntlEc.c b/src/aig/ntl/ntlEc.c deleted file mode 100644 index 331cd906..00000000 --- a/src/aig/ntl/ntlEc.c +++ /dev/null @@ -1,370 +0,0 @@ -/**CFile**************************************************************** - - FileName [ntlEc.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Netlist representation.] - - Synopsis [Equivalence checking procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ntlEc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ntl.h" -#include "saig.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Adds PIs to both models, so that they have the same PIs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManCreateMissingInputs( Ntl_Mod_t * p1, Ntl_Mod_t * p2, int fSeq ) -{ - Ntl_Obj_t * pObj; - Ntl_Net_t * pNet, * pNext; - int i, k; - if ( fSeq ) - { - Ntl_ModelForEachSeqLeaf( p1, pObj, i ) - { - Ntl_ObjForEachFanout( pObj, pNext, k ) - { - pNet = Ntl_ModelFindNet( p2, pNext->pName ); - if ( pNet == NULL ) - Ntl_ModelCreatePiWithName( p2, pNext->pName ); - } - } - Ntl_ModelForEachSeqLeaf( p2, pObj, i ) - { - Ntl_ObjForEachFanout( pObj, pNext, k ) - { - pNet = Ntl_ModelFindNet( p1, pNext->pName ); - if ( pNet == NULL ) - Ntl_ModelCreatePiWithName( p1, pNext->pName ); - } - } - } - else - { - Ntl_ModelForEachCombLeaf( p1, pObj, i ) - { - Ntl_ObjForEachFanout( pObj, pNext, k ) - { - pNet = Ntl_ModelFindNet( p2, pNext->pName ); - if ( pNet == NULL ) - Ntl_ModelCreatePiWithName( p2, pNext->pName ); - } - } - Ntl_ModelForEachCombLeaf( p2, pObj, i ) - { - Ntl_ObjForEachFanout( pObj, pNext, k ) - { - pNet = Ntl_ModelFindNet( p1, pNext->pName ); - if ( pNet == NULL ) - Ntl_ModelCreatePiWithName( p1, pNext->pName ); - } - } - } -} - -/**Function************************************************************* - - Synopsis [Creates arrays of combinational inputs in the same order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManDeriveCommonCis( Ntl_Man_t * pMan1, Ntl_Man_t * pMan2, int fSeq ) -{ - Ntl_Mod_t * p1 = Ntl_ManRootModel(pMan1); - Ntl_Mod_t * p2 = Ntl_ManRootModel(pMan2); - Ntl_Obj_t * pObj; - Ntl_Net_t * pNet, * pNext; - int i, k; - // order the CIs - Vec_PtrClear( pMan1->vCis ); - Vec_PtrClear( pMan2->vCis ); - if ( fSeq ) - { - assert( Ntl_ModelSeqLeafNum(p1) == Ntl_ModelSeqLeafNum(p2) ); - Ntl_ModelForEachSeqLeaf( p1, pObj, i ) - { - Ntl_ObjForEachFanout( pObj, pNext, k ) - { - pNet = Ntl_ModelFindNet( p2, pNext->pName ); - if ( pNet == NULL ) - { - printf( "Ntl_ManDeriveCommonCis(): Internal error!\n" ); - return; - } - Vec_PtrPush( pMan1->vCis, pNext ); - Vec_PtrPush( pMan2->vCis, pNet ); - } - } - } - else - { - assert( Ntl_ModelCombLeafNum(p1) == Ntl_ModelCombLeafNum(p2) ); - Ntl_ModelForEachCombLeaf( p1, pObj, i ) - { - Ntl_ObjForEachFanout( pObj, pNext, k ) - { - pNet = Ntl_ModelFindNet( p2, pNext->pName ); - if ( pNet == NULL ) - { - printf( "Ntl_ManDeriveCommonCis(): Internal error!\n" ); - return; - } - Vec_PtrPush( pMan1->vCis, pNext ); - Vec_PtrPush( pMan2->vCis, pNet ); - } - } - } -} - -/**Function************************************************************* - - Synopsis [Creates arrays of combinational outputs in the same order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManDeriveCommonCos( Ntl_Man_t * pMan1, Ntl_Man_t * pMan2, int fSeq ) -{ - Ntl_Mod_t * p1 = Ntl_ManRootModel(pMan1); - Ntl_Mod_t * p2 = Ntl_ManRootModel(pMan2); - Ntl_Obj_t * pObj; - Ntl_Net_t * pNet, * pNext; - int i, k; - // order the COs - Vec_PtrClear( pMan1->vCos ); - Vec_PtrClear( pMan2->vCos ); - if ( fSeq ) - { - Ntl_ModelForEachSeqRoot( p1, pObj, i ) - { - Ntl_ObjForEachFanin( pObj, pNext, k ) - { - pNet = Ntl_ModelFindNet( p2, pNext->pName ); - if ( pNet == NULL ) - { - printf( "Ntl_ManDeriveCommonCos(): Cannot find output %s in the second design. Skipping it!\n", - pNext->pName ); - continue; - } - Vec_PtrPush( pMan1->vCos, pNext ); - Vec_PtrPush( pMan2->vCos, pNet ); - } - } - } - else - { - Ntl_ModelForEachCombRoot( p1, pObj, i ) - { - Ntl_ObjForEachFanin( pObj, pNext, k ) - { - pNet = Ntl_ModelFindNet( p2, pNext->pName ); - if ( pNet == NULL ) - { - printf( "Ntl_ManDeriveCommonCos(): Cannot find output %s in the second design. Skipping it!\n", - pNext->pName ); - continue; - } - Vec_PtrPush( pMan1->vCos, pNext ); - Vec_PtrPush( pMan2->vCos, pNet ); - } - } - } -} - -/**Function************************************************************* - - Synopsis [Prepares AIGs for combinational equivalence checking.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManPrepareCecMans( Ntl_Man_t * pMan1, Ntl_Man_t * pMan2, Aig_Man_t ** ppAig1, Aig_Man_t ** ppAig2 ) -{ - Ntl_Mod_t * pModel1, * pModel2; - *ppAig1 = NULL; - *ppAig2 = NULL; - // make sure they are compatible - pModel1 = Ntl_ManRootModel( pMan1 ); - pModel2 = Ntl_ManRootModel( pMan2 ); - if ( Ntl_ModelCombLeafNum(pModel1) != Ntl_ModelCombLeafNum(pModel2) ) - { - printf( "Warning: The number of inputs in the designs is different (%d and %d).\n", - Ntl_ModelCombLeafNum(pModel1), Ntl_ModelCombLeafNum(pModel2) ); - } - if ( Ntl_ModelCombRootNum(pModel1) != Ntl_ModelCombRootNum(pModel2) ) - { - printf( "Warning: The number of outputs in the designs is different (%d and %d).\n", - Ntl_ModelCombRootNum(pModel1), Ntl_ModelCombRootNum(pModel2) ); - } - // normalize inputs/outputs - Ntl_ManCreateMissingInputs( pModel1, pModel2, 0 ); - if ( Ntl_ModelCombLeafNum(pModel1) != Ntl_ModelCombLeafNum(pModel2) ) - { - printf( "Ntl_ManPrepareCec(): Cannot verify designs with too many different CIs.\n" ); - return; - } - Ntl_ManDeriveCommonCis( pMan1, pMan2, 0 ); - Ntl_ManDeriveCommonCos( pMan1, pMan2, 0 ); - if ( Vec_PtrSize(pMan1->vCos) == 0 ) - { - printf( "Ntl_ManPrepareCec(): There is no identically-named primary outputs to compare.\n" ); - return; - } - // derive AIGs - *ppAig1 = Ntl_ManCollapse( pMan1, 0 ); - *ppAig2 = Ntl_ManCollapse( pMan2, 0 ); -} - -/**Function************************************************************* - - Synopsis [Prepares AIGs for combinational equivalence checking.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManPrepareCec( char * pFileName1, char * pFileName2, Aig_Man_t ** ppAig1, Aig_Man_t ** ppAig2 ) -{ - Ntl_Man_t * pMan1, * pMan2; - // read the netlists - pMan1 = Ntl_ManReadBlif( pFileName1, 1 ); - pMan2 = Ntl_ManReadBlif( pFileName2, 1 ); - if ( !pMan1 || !pMan2 ) - { - if ( pMan1 ) Ntl_ManFree( pMan1 ); - if ( pMan2 ) Ntl_ManFree( pMan2 ); - printf( "Ntl_ManPrepareCec(): Reading designs from file has failed.\n" ); - return; - } - Ntl_ManPrepareCecMans( pMan1, pMan2, ppAig1, ppAig2 ); - // cleanup - Ntl_ManFree( pMan1 ); - Ntl_ManFree( pMan2 ); -} - -/**Function************************************************************* - - Synopsis [Prepares AIGs for sequential equivalence checking.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Ntl_ManPrepareSec( char * pFileName1, char * pFileName2 ) -{ -// extern Aig_Man_t * Saig_ManCreateMiter( Aig_Man_t * p1, Aig_Man_t * p2, int Oper ); - - Aig_Man_t * pAig1, * pAig2, * pAig; - Ntl_Man_t * pMan1, * pMan2; - Ntl_Mod_t * pModel1, * pModel2; - // read the netlists - pMan1 = Ntl_ManReadBlif( pFileName1, 1 ); - pMan2 = Ntl_ManReadBlif( pFileName2, 1 ); - if ( !pMan1 || !pMan2 ) - { - if ( pMan1 ) Ntl_ManFree( pMan1 ); - if ( pMan2 ) Ntl_ManFree( pMan2 ); - printf( "Ntl_ManPrepareSec(): Reading designs from file has failed.\n" ); - return NULL; - } - // make sure they are compatible - if ( Ntl_ManLatchNum(pMan1) == 0 || Ntl_ManLatchNum(pMan2) == 0 ) - { - if ( pMan1 ) Ntl_ManFree( pMan1 ); - if ( pMan2 ) Ntl_ManFree( pMan2 ); - printf( "Ntl_ManPrepareSec(): The designs have no latches. Use combinational command \"*cec\".\n" ); - return NULL; - } - pModel1 = Ntl_ManRootModel( pMan1 ); - pModel2 = Ntl_ManRootModel( pMan2 ); - if ( Ntl_ModelSeqLeafNum(pModel1) != Ntl_ModelSeqLeafNum(pModel2) ) - { - printf( "Warning: The number of inputs in the designs is different (%d and %d).\n", - Ntl_ModelPiNum(pModel1), Ntl_ModelPiNum(pModel2) ); - } - if ( Ntl_ModelSeqRootNum(pModel1) != Ntl_ModelSeqRootNum(pModel2) ) - { - printf( "Warning: The number of outputs in the designs is different (%d and %d).\n", - Ntl_ModelPoNum(pModel1), Ntl_ModelPoNum(pModel2) ); - } - // normalize inputs/outputs - Ntl_ManCreateMissingInputs( pModel1, pModel2, 1 ); - Ntl_ManDeriveCommonCis( pMan1, pMan2, 1 ); - Ntl_ManDeriveCommonCos( pMan1, pMan2, 1 ); - if ( Vec_PtrSize(pMan1->vCos) == 0 ) - { - printf( "Ntl_ManPrepareSec(): There is no identically-named primary outputs to compare.\n" ); - if ( pMan1 ) Ntl_ManFree( pMan1 ); - if ( pMan2 ) Ntl_ManFree( pMan2 ); - return NULL; - } - // derive AIGs - pAig1 = Ntl_ManCollapse( pMan1, 1 ); - pAig2 = Ntl_ManCollapse( pMan2, 1 ); - pAig = Saig_ManCreateMiter( pAig1, pAig2, 0 ); - Aig_ManCleanup( pAig ); - Aig_ManStop( pAig1 ); - Aig_ManStop( pAig2 ); - // cleanup - Ntl_ManFree( pMan1 ); - Ntl_ManFree( pMan2 ); - return pAig; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ntl/ntlExtract.c b/src/aig/ntl/ntlExtract.c deleted file mode 100644 index a6268b2c..00000000 --- a/src/aig/ntl/ntlExtract.c +++ /dev/null @@ -1,877 +0,0 @@ -/**CFile**************************************************************** - - FileName [ntlExtract.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: ntlExtract.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ntl.h" -#include "dec.h" -#include "kit.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**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 = Kit_PlaGetVarNum(pSop); - // go through the cubes of the node's SOP - pSum = Aig_ManConst0(pMan); - Kit_PlaForEachCube( pSop, nFanins, pCube ) - { - // create the AND of literals - pAnd = Aig_ManConst1(pMan); - Kit_PlaCubeForEachVar( pCube, Value, i ) - { - pNet = Ntl_ObjFanin( pNode, i ); - if ( Value == '1' ) - pAnd = Aig_And( pMan, pAnd, (Aig_Obj_t *)pNet->pCopy ); - else if ( Value == '0' ) - pAnd = Aig_And( pMan, pAnd, Aig_Not((Aig_Obj_t *)pNet->pCopy) ); - } - // add to the sum of cubes - pSum = Aig_Or( pMan, pSum, pAnd ); - } - // decide whether to complement the result - if ( Kit_PlaIsComplement(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 = NULL; // Suppress "might be used uninitialized" - 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( (Aig_Obj_t *)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( (Aig_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); - pAnd1 = Aig_NotCond( (Aig_Obj_t *)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( (Aig_Obj_t *)pNode->pFunc, Dec_GraphIsComplement(pGraph) ); -} - -/**Function************************************************************* - - Synopsis [Converts the network from AIG to BDD representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Ntl_ManBuildNodeAig( Ntl_Man_t * p, Ntl_Obj_t * pNode ) -{ - int fUseFactor = 1; - // consider the constant node - if ( Kit_PlaGetVarNum(pNode->pSop) == 0 ) - return Aig_NotCond( Aig_ManConst1(p->pAig), Kit_PlaIsConst0(pNode->pSop) ); - // decide when to use factoring - if ( fUseFactor && Kit_PlaGetVarNum(pNode->pSop) > 2 && Kit_PlaGetCubeNum(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)->pCopy; - // perform strashing - pFunc = Ntl_GraphToNetworkAig( p->pAig, pFForm ); - Dec_GraphFree( pFForm ); - return pFunc; - } - return Ntl_ConvertSopToAigInternal( p->pAig, pNode, pNode->pSop ); -} - -/**Function************************************************************* - - Synopsis [Collects the nodes in a topological order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManExtract_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_ManExtract_rec( p, pNetFanin ) ) - return 0; - // add box inputs/outputs to COs/CIs - if ( Ntl_ObjIsBox(pObj) ) - { - int LevelCur, LevelMax = -TIM_ETERNITY; - assert( Ntl_BoxIsComb(pObj) ); - assert( Ntl_ModelLatchNum(pObj->pImplem) == 0 ); - assert( pObj->pImplem->vDelays != NULL ); - Vec_IntPush( p->vBox1Cios, Aig_ManPoNum(p->pAig) ); - Ntl_ObjForEachFanin( pObj, pNetFanin, i ) - { - LevelCur = Aig_ObjLevel( Aig_Regular((Aig_Obj_t *)pNetFanin->pCopy) ); - LevelMax = ABC_MAX( LevelMax, LevelCur ); - Vec_PtrPush( p->vCos, pNetFanin ); - Aig_ObjCreatePo( p->pAig, (Aig_Obj_t *)pNetFanin->pCopy ); - } - Ntl_ObjForEachFanout( pObj, pNetFanin, i ) - { - Vec_PtrPush( p->vCis, pNetFanin ); - pNetFanin->pCopy = Aig_ObjCreatePi( p->pAig ); - Aig_ObjSetLevel( (Aig_Obj_t *)pNetFanin->pCopy, LevelMax + 1 ); - } - } - Vec_PtrPush( p->vVisNodes, pObj ); - if ( Ntl_ObjIsNode(pObj) ) - pNet->pCopy = Ntl_ManBuildNodeAig( p, 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 [] - -***********************************************************************/ -Aig_Man_t * Ntl_ManExtract( Ntl_Man_t * p ) -{ - Aig_Man_t * pAig; - Ntl_Mod_t * pRoot; - Ntl_Obj_t * pObj; - Ntl_Net_t * pNet; - int i, k, nUselessObjects; - Ntl_ManCleanup( p ); - Vec_PtrClear( p->vCis ); - Vec_PtrClear( p->vCos ); - Vec_PtrClear( p->vVisNodes ); - Vec_IntClear( p->vBox1Cios ); - // start the AIG manager - assert( p->pAig == NULL ); - p->pAig = Aig_ManStart( 10000 ); - p->pAig->pName = Aig_UtilStrsav( p->pName ); - p->pAig->pSpec = Aig_UtilStrsav( p->pSpec ); - // get the root model - pRoot = Ntl_ManRootModel( p ); - assert( Ntl_ModelLatchNum(pRoot) == 0 ); - // clear net visited flags - Ntl_ModelClearNets( pRoot ); - // collect mapping leafs - Ntl_ModelForEachMapLeaf( pRoot, pObj, i ) - { - assert( !Ntl_ObjIsBox(pObj) || Ntl_BoxIsBlack(pObj) || Ntl_ModelLatchNum(pObj->pImplem) > 0 ); - Ntl_ObjForEachFanout( pObj, pNet, k ) - { - Vec_PtrPush( p->vCis, pNet ); - pNet->pCopy = Aig_ObjCreatePi( p->pAig ); - if ( pNet->nVisits ) - { - printf( "Ntl_ManExtract(): Seq leaf is duplicated or defined as a primary input.\n" ); - return 0; - } - pNet->nVisits = 2; - } - } - p->iLastCi = Aig_ManPiNum(p->pAig); - // collect mapping roots - Ntl_ModelForEachMapRoot( pRoot, pObj, i ) - { - Ntl_ObjForEachFanin( pObj, pNet, k ) - { - if ( !Ntl_ManExtract_rec( p, pNet ) ) - { - printf( "Ntl_ManExtract(): Error: Combinational loop is detected.\n" ); - return 0; - } - Vec_PtrPush( p->vCos, pNet ); - Aig_ObjCreatePo( p->pAig, (Aig_Obj_t *)pNet->pCopy ); - } - } - // visit dangling boxes - Ntl_ModelForEachBox( pRoot, pObj, i ) - { - pNet = Ntl_ObjFanout0(pObj); - if ( !Ntl_ManExtract_rec( p, pNet ) ) - { - printf( "Ntl_ManExtract(): Error: Combinational loop is detected.\n" ); - return 0; - } - } - // report the number of dangling objects - nUselessObjects = Ntl_ModelNodeNum(pRoot) + Ntl_ModelLut1Num(pRoot) + Ntl_ModelBoxNum(pRoot) - Vec_PtrSize(p->vVisNodes); -// if ( nUselessObjects ) -// printf( "The number of dangling objects = %d.\n", nUselessObjects ); - // cleanup the AIG - Aig_ManCleanup( p->pAig ); - // extract the timing manager - assert( p->pManTime == NULL ); - p->pManTime = Ntl_ManCreateTiming( p ); - // discretize timing info - p->pAig->pManTime = Tim_ManDup( p->pManTime, 1 ); - pAig = p->pAig; p->pAig = NULL; - return pAig; -} - - - - -/**Function************************************************************* - - Synopsis [Collects the nodes in a topological order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManCollapseBoxComb_rec( Ntl_Man_t * p, Ntl_Obj_t * pBox ) -{ - extern int Ntl_ManCollapse_rec( Ntl_Man_t * p, Ntl_Net_t * pNet ); - Ntl_Mod_t * pModel = pBox->pImplem; - Ntl_Obj_t * pObj; - Ntl_Net_t * pNet, * pNetBox; - int i; - assert( Ntl_ObjFaninNum(pBox) == Ntl_ModelPiNum(pModel) ); - assert( Ntl_ObjFanoutNum(pBox) == Ntl_ModelPoNum(pModel) ); - // clear net visited flags - Ntl_ModelClearNets( pModel ); - // transfer from the box to the PIs of the model - Ntl_ModelForEachPi( pModel, pObj, i ) - { - pNet = Ntl_ObjFanout0(pObj); - pNetBox = Ntl_ObjFanin( pBox, i ); - pNet->pCopy = pNetBox->pCopy; - pNet->nVisits = 2; - } - // compute AIG for the internal nodes - Ntl_ModelForEachPo( pModel, pObj, i ) - { - pNet = Ntl_ObjFanin0(pObj); - if ( !Ntl_ManCollapse_rec( p, pNet ) ) - return 0; - pNetBox = Ntl_ObjFanout( pBox, i ); - pNetBox->pCopy = pNet->pCopy; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Collects the nodes in a topological order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManCollapseBoxSeq1_rec( Ntl_Man_t * p, Ntl_Obj_t * pBox ) -{ - extern int Ntl_ManCollapse_rec( Ntl_Man_t * p, Ntl_Net_t * pNet ); - Ntl_Mod_t * pModel = pBox->pImplem; - Ntl_Obj_t * pObj; - Ntl_Net_t * pNet, * pNetBox; - int i; - assert( Ntl_ModelLatchNum(pModel) > 0 ); - assert( Ntl_ObjFaninNum(pBox) == Ntl_ModelPiNum(pModel) ); - assert( Ntl_ObjFanoutNum(pBox) == Ntl_ModelPoNum(pModel) ); - // clear net visited flags - Ntl_ModelClearNets( pModel ); - // initialize the registers - Ntl_ModelForEachLatch( pModel, pObj, i ) - { - pNet = Ntl_ObjFanout0(pObj); - pNet->pCopy = Aig_ObjCreatePi( p->pAig ); - if ( Ntl_ObjIsInit1( pObj ) ) - pNet->pCopy = Aig_Not((Aig_Obj_t *)pNet->pCopy); - pNet->nVisits = 2; - // remember the class of this register - Vec_IntPush( p->vRegClasses, p->pNal ? pBox->iTemp : pObj->LatchId.regClass ); - Vec_IntPush( p->vRstClasses, p->pNal ? pBox->Reset : -1 ); - } - // compute AIG for the internal nodes - Ntl_ModelForEachPo( pModel, pObj, i ) - { - pNet = Ntl_ObjFanin0(pObj); - if ( !Ntl_ManCollapse_rec( p, pNet ) ) - return 0; - pNetBox = Ntl_ObjFanout( pBox, i ); - pNetBox->pCopy = pNet->pCopy; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Collects the nodes in a topological order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManCollapseBoxSeq2_rec( Ntl_Man_t * p, Ntl_Obj_t * pBox, int iFirstPi ) -{ - extern int Ntl_ManCollapse_rec( Ntl_Man_t * p, Ntl_Net_t * pNet ); - Ntl_Mod_t * pModel = pBox->pImplem; - Ntl_Obj_t * pObj; - Ntl_Net_t * pNet, * pNetBox; - int i; - assert( Ntl_ModelLatchNum(pModel) > 0 ); - assert( Ntl_ObjFaninNum(pBox) == Ntl_ModelPiNum(pModel) ); - assert( Ntl_ObjFanoutNum(pBox) == Ntl_ModelPoNum(pModel) ); - // clear net visited flags - Ntl_ModelClearNets( pModel ); - // transfer from the box to the PIs of the model - Ntl_ModelForEachPi( pModel, pObj, i ) - { - pNet = Ntl_ObjFanout0(pObj); - pNetBox = Ntl_ObjFanin( pBox, i ); - pNet->pCopy = pNetBox->pCopy; - pNet->nVisits = 2; - } - // initialize the registers - Ntl_ModelForEachLatch( pModel, pObj, i ) - { - pNet = Ntl_ObjFanout0(pObj); - pNet->pCopy = Aig_ManPi( p->pAig, iFirstPi++ ); - if ( Ntl_ObjIsInit1( pObj ) ) - pNet->pCopy = Aig_Not((Aig_Obj_t *)pNet->pCopy); - pNet->nVisits = 2; - } - // compute AIGs for the registers - Ntl_ModelForEachLatch( pModel, pObj, i ) - { - pNet = Ntl_ObjFanin0(pObj); - if ( !Ntl_ManCollapse_rec( p, pNet ) ) - return 0; - if ( Ntl_ObjIsInit1( pObj ) ) - Aig_ObjCreatePo( p->pAig, Aig_Not((Aig_Obj_t *)pNet->pCopy) ); - else - Aig_ObjCreatePo( p->pAig, (Aig_Obj_t *)pNet->pCopy ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Collects the nodes in a topological order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManCollapse_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_ManCollapse_rec( p, pNetFanin ) ) - return 0; - // add box inputs/outputs to COs/CIs - if ( Ntl_ObjIsBox(pObj) ) - { - assert( Ntl_BoxIsWhite(pObj) && Ntl_BoxIsComb(pObj) ); - if ( !Ntl_ManCollapseBoxComb_rec( p, pObj ) ) - return 0; - } - if ( Ntl_ObjIsNode(pObj) ) - pNet->pCopy = Ntl_ManBuildNodeAig( p, 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 [] - -***********************************************************************/ -Aig_Man_t * Ntl_ManCollapse( Ntl_Man_t * p, int fSeq ) -{ - Aig_Man_t * pAig; - Ntl_Mod_t * pRoot; - Ntl_Obj_t * pBox; - Ntl_Net_t * pNet; - int i, k, nTruePis, nTruePos, iBox = 0; - assert( Vec_PtrSize(p->vCis) != 0 ); - assert( Vec_PtrSize(p->vCos) != 0 ); - Vec_IntClear( p->vBox1Cios ); - Vec_IntClear( p->vRegClasses ); - Vec_IntClear( p->vRstClasses ); - // clear net visited flags - pRoot = Ntl_ManRootModel(p); - assert( Ntl_ModelLatchNum(pRoot) == 0 ); - Ntl_ModelClearNets( pRoot ); - // create the manager - p->pAig = Aig_ManStart( 10000 ); - p->pAig->pName = Aig_UtilStrsav( p->pName ); - p->pAig->pSpec = Aig_UtilStrsav( p->pSpec ); - // set the inputs - Ntl_ManForEachCiNet( p, pNet, i ) - { - pNet->pCopy = Aig_ObjCreatePi( p->pAig ); - if ( pNet->nVisits ) - { - printf( "Ntl_ManCollapse(): Primary input appears twice in the list.\n" ); - return 0; - } - pNet->nVisits = 2; - } - nTruePis = Aig_ManPiNum(p->pAig); - // create inputs of seq boxes - if ( fSeq ) { - Ntl_ModelForEachBox( pRoot, pBox, i ) - { - if ( !(Ntl_BoxIsSeq(pBox) && Ntl_BoxIsWhite(pBox)) ) - continue; - Vec_IntPush( p->vBox1Cios, Aig_ManPiNum(p->pAig) ); - Ntl_ManCollapseBoxSeq1_rec( p, pBox ); - Ntl_ObjForEachFanout( pBox, pNet, k ) - pNet->nVisits = 2; - } - } - // derive the outputs - Ntl_ManForEachCoNet( p, pNet, i ) - { - if ( !Ntl_ManCollapse_rec( p, pNet ) ) - { - printf( "Ntl_ManCollapse(): Error: Combinational loop is detected.\n" ); - return 0; - } - Aig_ObjCreatePo( p->pAig, (Aig_Obj_t *)pNet->pCopy ); - } - nTruePos = Aig_ManPoNum(p->pAig); - // create outputs of seq boxes - if ( fSeq ) { - Ntl_ModelForEachBox( pRoot, pBox, i ) - { - if ( !(Ntl_BoxIsSeq(pBox) && Ntl_BoxIsWhite(pBox)) ) - continue; - Ntl_ObjForEachFanin( pBox, pNet, k ) - if ( !Ntl_ManCollapse_rec( p, pNet ) ) - { - printf( "Ntl_ManCollapse(): Error: Combinational loop is detected.\n" ); - return 0; - } - Ntl_ManCollapseBoxSeq2_rec( p, pBox, Vec_IntEntry(p->vBox1Cios, iBox++) ); - } - } - // make sure registers are added correctly - if ( Aig_ManPiNum(p->pAig) - nTruePis != Aig_ManPoNum(p->pAig) - nTruePos ) - { - printf( "Ntl_ManCollapse(): Error: Registers are created incorrectly.\n" ); - return 0; - } - // cleanup the AIG - Aig_ManSetRegNum( p->pAig, Aig_ManPiNum(p->pAig) - nTruePis ); - Aig_ManCleanup( p->pAig ); - pAig = p->pAig; p->pAig = NULL; - return pAig; -} - - -/**Function************************************************************* - - Synopsis [Collapses the netlist combinationally.] - - Description [Checks for combinational loops. Collects PI/PO nets. - Collects nodes in the topological order.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Ntl_ManCollapseComb( Ntl_Man_t * p ) -{ - Ntl_Mod_t * pRoot; - Ntl_Obj_t * pObj; - Ntl_Net_t * pNet; - int i, k; - Vec_PtrClear( p->vCis ); - Vec_PtrClear( p->vCos ); - // prepare the model - pRoot = Ntl_ManRootModel(p); - // collect the leaves for this traversal - Ntl_ModelForEachCombLeaf( pRoot, pObj, i ) - Ntl_ObjForEachFanout( pObj, pNet, k ) - Vec_PtrPush( p->vCis, pNet ); - // collect the roots for this traversal - Ntl_ModelForEachCombRoot( pRoot, pObj, i ) - Ntl_ObjForEachFanin( pObj, pNet, k ) - Vec_PtrPush( p->vCos, pNet ); - // perform the traversal - return Ntl_ManCollapse( p, 0 ); -} - -/**Function************************************************************* - - Synopsis [Collapses the netlist combinationally.] - - Description [Checks for combinational loops. Collects PI/PO nets. - Collects nodes in the topological order.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Ntl_ManCollapseSeq( Ntl_Man_t * p, int nMinDomSize, int fVerbose ) -{ - Aig_Man_t * pAig; - Ntl_Mod_t * pRoot; - Ntl_Obj_t * pObj; - Ntl_Net_t * pNet; - int i, k; - Vec_PtrClear( p->vCis ); - Vec_PtrClear( p->vCos ); - // prepare the model - pRoot = Ntl_ManRootModel(p); - // collect the leaves for this traversal - Ntl_ModelForEachSeqLeaf( pRoot, pObj, i ) - Ntl_ObjForEachFanout( pObj, pNet, k ) - Vec_PtrPush( p->vCis, pNet ); - // collect the roots for this traversal - Ntl_ModelForEachSeqRoot( pRoot, pObj, i ) - Ntl_ObjForEachFanin( pObj, pNet, k ) - Vec_PtrPush( p->vCos, pNet ); - // perform the traversal - pAig = Ntl_ManCollapse( p, 1 ); - // check if there are register classes - pAig->vClockDoms = Ntl_ManTransformRegClasses( p, nMinDomSize, fVerbose ); - if ( pAig->vClockDoms ) - { - if ( Vec_VecSize(pAig->vClockDoms) == 0 ) - { - printf( "Register classes are below the limit (%d). Seq synthesis is not performed.\n", nMinDomSize ); - Aig_ManStop( pAig ); - pAig = NULL; - } - else if ( fVerbose ) - printf( "Performing seq synthesis for %d register classes.\n", Vec_VecSize(pAig->vClockDoms) ); - if ( fVerbose ) - printf( "\n" ); - } - return pAig; -} - - - -/**Function************************************************************* - - Synopsis [Increments reference counter of the net.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Ntl_NetIncrementRefs( Ntl_Net_t * pNet ) -{ - int nRefs = (int)(long)pNet->pCopy; - pNet->pCopy = (void *)(long)(nRefs + 1); -} - -/**Function************************************************************* - - Synopsis [Extracts logic newtork out of the netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Nwk_Obj_t * Ntl_ManExtractNwk_rec( Ntl_Man_t * p, Ntl_Net_t * pNet, Nwk_Man_t * pNtk, Vec_Int_t * vCover, Vec_Int_t * vMemory ) -{ - extern Hop_Obj_t * Kit_CoverToHop( Hop_Man_t * pMan, Vec_Int_t * vCover, int nVars, Vec_Int_t * vMemory ); - Ntl_Net_t * pFaninNet; - Nwk_Obj_t * pNode; - int i; - if ( pNet->fMark ) - return (Nwk_Obj_t *)pNet->pCopy2; - pNet->fMark = 1; - pNode = Nwk_ManCreateNode( pNtk, Ntl_ObjFaninNum(pNet->pDriver), (int)(long)pNet->pCopy ); - Ntl_ObjForEachFanin( pNet->pDriver, pFaninNet, i ) - { - Ntl_ManExtractNwk_rec( p, pFaninNet, pNtk, vCover, vMemory ); - Nwk_ObjAddFanin( pNode, (Nwk_Obj_t *)pFaninNet->pCopy2 ); - } - if ( Ntl_ObjFaninNum(pNet->pDriver) == 0 || Kit_PlaGetVarNum(pNet->pDriver->pSop) == 0 ) - pNode->pFunc = Hop_NotCond( Hop_ManConst1(pNtk->pManHop), Kit_PlaIsConst0(pNet->pDriver->pSop) ); - else - { - Kit_PlaToIsop( pNet->pDriver->pSop, vCover ); - pNode->pFunc = Kit_CoverToHop( pNtk->pManHop, vCover, Ntl_ObjFaninNum(pNet->pDriver), vMemory ); - if ( Kit_PlaIsComplement(pNet->pDriver->pSop) ) - pNode->pFunc = Hop_Not(pNode->pFunc); - } - return (Nwk_Obj_t *)(pNet->pCopy2 = pNode); -} - -/**Function************************************************************* - - Synopsis [Extracts logic network out of the netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Nwk_Man_t * Ntl_ManExtractNwk( Ntl_Man_t * p, Aig_Man_t * pAig, Tim_Man_t * pManTime ) -{ - Nwk_Man_t * pNtk; - Nwk_Obj_t * pNode; - Ntl_Mod_t * pRoot; - Ntl_Net_t * pNet, * pNetSimple; - Ntl_Obj_t * pObj; - Aig_Obj_t * pAnd; - Vec_Int_t * vCover, * vMemory; - int i, k; - pRoot = Ntl_ManRootModel( p ); - if ( Ntl_ModelGetFaninMax(pRoot) > 6 ) - { - printf( "The network contains logic nodes with more than 6 inputs.\n" ); - return NULL; - } - vCover = Vec_IntAlloc( 100 ); - vMemory = Vec_IntAlloc( 1 << 16 ); - // count the number of fanouts of each net - Ntl_ModelClearNets( pRoot ); - Ntl_ModelForEachObj( pRoot, pObj, i ) - Ntl_ObjForEachFanin( pObj, pNet, k ) - Ntl_NetIncrementRefs( pNet ); - // remember netlist objects int the AIG nodes - if ( pManTime != NULL ) // logic netlist - { - assert( Ntl_ModelPiNum(pRoot) == Aig_ManPiNum(pAig) ); - assert( Ntl_ModelPoNum(pRoot) == Aig_ManPoNum(pAig) ); - Aig_ManForEachPi( pAig, pAnd, i ) - pAnd->pData = Ntl_ObjFanout0( Ntl_ModelPi(pRoot, i) ); - Aig_ManForEachPo( pAig, pAnd, i ) - pAnd->pData = Ntl_ObjFanin0(Ntl_ModelPo(pRoot, i) ); - } - else // real netlist - { - assert( p->vCis && p->vCos ); - Aig_ManForEachPi( pAig, pAnd, i ) - pAnd->pData = Vec_PtrEntry( p->vCis, i ); - Aig_ManForEachPo( pAig, pAnd, i ) - pAnd->pData = Vec_PtrEntry( p->vCos, i ); - } - // construct the network - pNtk = Nwk_ManAlloc(); - pNtk->pName = Aig_UtilStrsav( pAig->pName ); - pNtk->pSpec = Aig_UtilStrsav( pAig->pSpec ); - Aig_ManForEachObj( pAig, pAnd, i ) - { - if ( Aig_ObjIsPi(pAnd) ) - { - pNet = (Ntl_Net_t *)pAnd->pData; - pNet->fMark = 1; - pNet->pCopy2 = Nwk_ManCreateCi( pNtk, (int)(long)pNet->pCopy ); - } - else if ( Aig_ObjIsPo(pAnd) ) - { - pNet = (Ntl_Net_t *)pAnd->pData; - pNode = Nwk_ManCreateCo( pNtk ); - if ( (pNetSimple = Ntl_ModelFindSimpleNet( pNet )) ) - { - pNetSimple->pCopy2 = Ntl_ManExtractNwk_rec( p, pNetSimple, pNtk, vCover, vMemory ); - Nwk_ObjAddFanin( pNode, (Nwk_Obj_t *)pNetSimple->pCopy2 ); - pNode->fInvert = Kit_PlaIsInv( pNet->pDriver->pSop ); - } - else - { - pNet->pCopy2 = Ntl_ManExtractNwk_rec( p, pNet, pNtk, vCover, vMemory ); - Nwk_ObjAddFanin( pNode, (Nwk_Obj_t *)pNet->pCopy2 ); - pNode->fInvert = (Nwk_ObjFanin0(pNode)->pFunc == Hop_ManConst0(pNtk->pManHop)); // fixed on June 7, 2009 - } - } - } - Ntl_ModelClearNets( pRoot ); - Vec_IntFree( vCover ); - Vec_IntFree( vMemory ); - // create timing manager from the current design - if ( pManTime ) - pNtk->pManTime = Tim_ManDup( pManTime, 0 ); - else - pNtk->pManTime = Tim_ManDup( p->pManTime, 0 ); - Nwk_ManRemoveDupFanins( pNtk, 0 ); - assert( Nwk_ManCheck( pNtk ) ); - return pNtk; -} - -/**Function************************************************************* - - Synopsis [Extracts logic newtork out of the netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Nwk_Man_t * Ntl_ManReadNwk( char * pFileName, Aig_Man_t * pAig, Tim_Man_t * pManTime ) -{ - Nwk_Man_t * pNtk; - Ntl_Man_t * pNtl; - Ntl_Mod_t * pRoot; - pNtl = Ntl_ManReadBlif( pFileName, 1 ); - if ( pNtl == NULL ) - { - printf( "Ntl_ManReadNwk(): Reading BLIF has failed.\n" ); - return NULL; - } - pRoot = Ntl_ManRootModel( pNtl ); - if ( Ntl_ModelLatchNum(pRoot) != 0 ) - { - printf( "Ntl_ManReadNwk(): The input network has %d registers.\n", Ntl_ModelLatchNum(pRoot) ); - return NULL; - } - if ( Ntl_ModelBoxNum(pRoot) != 0 ) - { - printf( "Ntl_ManReadNwk(): The input network has %d boxes.\n", Ntl_ModelBoxNum(pRoot) ); - return NULL; - } - if ( Ntl_ModelPiNum(pRoot) != Aig_ManPiNum(pAig) ) - { - printf( "Ntl_ManReadNwk(): The number of primary inputs does not match (%d and %d).\n", - Ntl_ModelPiNum(pRoot), Aig_ManPiNum(pAig) ); - return NULL; - } - if ( Ntl_ModelPoNum(pRoot) != Aig_ManPoNum(pAig) ) - { - printf( "Ntl_ManReadNwk(): The number of primary outputs does not match (%d and %d).\n", - Ntl_ModelPoNum(pRoot), Aig_ManPoNum(pAig) ); - return NULL; - } - pNtk = Ntl_ManExtractNwk( pNtl, pAig, pManTime ); - Ntl_ManFree( pNtl ); - return pNtk; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ntl/ntlFraig.c b/src/aig/ntl/ntlFraig.c deleted file mode 100644 index 9470df3e..00000000 --- a/src/aig/ntl/ntlFraig.c +++ /dev/null @@ -1,1004 +0,0 @@ -/**CFile**************************************************************** - - FileName [ntlFraig.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Netlist representation.] - - Synopsis [Performing fraiging with white-boxes.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ntlFraig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ntl.h" -#include "fra.h" -#include "ssw.h" -#include "dch.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Remaps representatives of the equivalence classes.] - - Description [For each equivalence class, if the current representative - of the class cannot be used because its corresponding net has no-merge - attribute, find the topologically-shallowest node, which can be used - as a representative.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManUpdateNoMergeReprs( Aig_Man_t * pAig, Aig_Obj_t ** pReprs ) -{ - Aig_Obj_t ** pReprsNew = NULL; - Aig_Obj_t * pObj, * pRepres, * pRepresNew; - Ntl_Net_t * pNet, * pNetObj; - int i; - - // allocate room for the new representative - pReprsNew = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) ); - memset( pReprsNew, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(pAig) ); - Aig_ManForEachObj( pAig, pObj, i ) - { - // get the old representative node - pRepres = pReprs[pObj->Id]; - if ( pRepres == NULL ) - continue; - // if this representative node is already remapped, skip it - pRepresNew = pReprsNew[ pRepres->Id ]; - if ( pRepresNew != NULL ) - continue; - // get the net of the representative node - pNet = (Ntl_Net_t *)pRepres->pData; - assert( pRepres->pData != NULL ); - if ( Ntl_ObjIsBox(pNet->pDriver) && pNet->pDriver->pImplem->attrNoMerge ) - { - // the net belongs to the no-merge box - pNetObj = (Ntl_Net_t *)pObj->pData; - if ( Ntl_ObjIsBox(pNetObj->pDriver) && pNetObj->pDriver->pImplem->attrNoMerge ) - continue; - // the object's net does not belong to the no-merge box - // pObj can be used instead of pRepres - pReprsNew[ pRepres->Id ] = pObj; - } - else - { - // otherwise, it is fine to use pRepres - pReprsNew[ pRepres->Id ] = pRepres; - } - } - // update the representatives - Aig_ManForEachObj( pAig, pObj, i ) - { - // get the representative node - pRepres = pReprs[ pObj->Id ]; - if ( pRepres == NULL ) - continue; - // if the representative has no mapping, undo the mapping of the node - pRepresNew = pReprsNew[ pRepres->Id ]; - if ( pRepresNew == NULL || pRepresNew == pObj ) - { - pReprs[ pObj->Id ] = NULL; - continue; - } - // remap the representative -// assert( pObj->Id > pRepresNew->Id ); -// pReprs[ pObj->Id ] = pRepresNew; - if ( pObj->Id > pRepresNew->Id ) - pReprs[ pObj->Id ] = pRepresNew; - else - pReprs[ pObj->Id ] = NULL; - } - ABC_FREE( pReprsNew ); -} - -/**Function************************************************************* - - Synopsis [Transfers equivalence class info from pAigCol to pAig.] - - Description [pAig points to the nodes of netlist (pNew) derived using it. - pNew points to the nodes of the collapsed AIG (pAigCol) derived using it.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t ** Ntl_ManFraigDeriveClasses( Aig_Man_t * pAig, Ntl_Man_t * pNew, Aig_Man_t * pAigCol ) -{ - Ntl_Net_t * pNet; - Aig_Obj_t ** pReprs = NULL, ** pMapBack = NULL; - Aig_Obj_t * pObj, * pObjCol, * pObjColRepr, * pCorresp; - int i; - - // remember pointers to the nets of pNew - Aig_ManForEachObj( pAig, pObj, i ) - pObj->pNext = (Aig_Obj_t *)pObj->pData; - - // map the AIG managers - Aig_ManForEachObj( pAig, pObj, i ) - { - if ( Aig_ObjIsConst1(pObj) ) - pObj->pData = Aig_ManConst1(pAigCol); - else if ( !Aig_ObjIsPo(pObj) ) - { - pNet = (Ntl_Net_t *)pObj->pData; - pObjCol = Aig_Regular((Aig_Obj_t *)pNet->pCopy); - pObj->pData = pObjCol; - } - } - - // create mapping from the collapsed manager into the original manager - // (each node in the collapsed manager may have more than one equivalent node - // in the original manager; this procedure finds the first node in the original - // manager that is equivalent to the given node in the collapsed manager) - pMapBack = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAigCol) ); - memset( pMapBack, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(pAigCol) ); - Aig_ManForEachObj( pAig, pObj, i ) - { - if ( Aig_ObjIsPo(pObj) ) - continue; - pObjCol = (Aig_Obj_t *)pObj->pData; - if ( pObjCol == NULL ) - continue; - if ( pMapBack[pObjCol->Id] == NULL ) - pMapBack[pObjCol->Id] = pObj; - } - - // create the equivalence classes for the original manager - pReprs = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) ); - memset( pReprs, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(pAig) ); - Aig_ManForEachObj( pAig, pObj, i ) - { - if ( Aig_ObjIsPo(pObj) ) - continue; - // get the collapsed node - pObjCol = (Aig_Obj_t *)pObj->pData; - if ( pObjCol == NULL ) - continue; - // get the representative of the collapsed node - pObjColRepr = pAigCol->pReprs[pObjCol->Id]; - if ( pObjColRepr == NULL ) - pObjColRepr = pObjCol; - // get the corresponding original node - pCorresp = pMapBack[pObjColRepr->Id]; - if ( pCorresp == NULL || pCorresp == pObj ) - continue; - // set the representative - if ( pCorresp->Id < pObj->Id ) - pReprs[pObj->Id] = pCorresp; - else - pReprs[pCorresp->Id] = pObj; - } - ABC_FREE( pMapBack ); - - // recall pointers to the nets of pNew - Aig_ManForEachObj( pAig, pObj, i ) - pObj->pData = pObj->pNext, pObj->pNext = NULL; - - // remap no-merge representatives to point to - // the shallowest nodes in the class without no-merge - Ntl_ManUpdateNoMergeReprs( pAig, pReprs ); - return pReprs; -} - -/**Function************************************************************* - - Synopsis [Uses equivalences in the AIG to reduce the design.] - - Description [The AIG (pAig) was extracted from the netlist and still - points to it (pObj->pData is the pointer to the nets in the netlist). - Equivalences have been computed for the collapsed AIG and transfered - to this AIG (pAig). This procedure reduces the corresponding nets.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManReduce( Ntl_Man_t * p, Aig_Man_t * pAig ) -{ - Aig_Obj_t * pObj, * pObjRepr; - Ntl_Net_t * pNet, * pNetRepr, * pNetNew; - Ntl_Mod_t * pRoot; - Ntl_Obj_t * pNode, * pNodeOld; - int i, fCompl, Counter = 0; - char * pNameNew; -// int Lenght; - assert( pAig->pReprs ); - pRoot = Ntl_ManRootModel( p ); - Aig_ManForEachObj( pAig, pObj, i ) - { - pObjRepr = Aig_ObjRepr( pAig, pObj ); - if ( pObjRepr == NULL ) - continue; - assert( pObj != pObjRepr ); - pNet = (Ntl_Net_t *)pObj->pData; - pNetRepr = (Ntl_Net_t *)pObjRepr->pData; - // consider special cases, when the net should not be reduced - if ( Ntl_ObjIsBox(pNet->pDriver) ) - { - // do not reduce the net if it is driven by a multi-output box - if ( Ntl_ObjFanoutNum(pNet->pDriver) > 1 ) - continue; - // do not reduce the net if it has no-merge attribute - if ( pNet->pDriver->pImplem->attrNoMerge ) - continue; - // do not reduce the net if the replacement net has no-merge attribute - if ( pNetRepr != NULL && Ntl_ObjIsBox(pNetRepr->pDriver) && - pNetRepr->pDriver->pImplem->attrNoMerge ) - continue; - } - if ( pNetRepr == NULL ) - { - // this is the constant node - assert( Aig_ObjIsConst1(pObjRepr) ); - pNode = Ntl_ModelCreateNode( pRoot, 0 ); - pNode->pSop = Ntl_ManStoreSop( p->pMemSops, " 1\n" ); - if ( (pNetRepr = Ntl_ModelFindNet( pRoot, "Const1" )) ) - { - printf( "Ntl_ManReduce(): Internal error: Intermediate net name is not unique.\n" ); - return; - } - pNetRepr = Ntl_ModelFindOrCreateNet( pRoot, "Const1" ); - if ( !Ntl_ModelSetNetDriver( pNode, pNetRepr ) ) - { - printf( "Ntl_ManReduce(): Internal error: Net has more than one fanin.\n" ); - return; - } - pObjRepr->pData = pNetRepr; - pNetRepr->pCopy = Aig_ManConst1(pAig); - } - // get the complemented attributes of the nets - fCompl = Aig_IsComplement((Aig_Obj_t *)pNet->pCopy) ^ Aig_Regular((Aig_Obj_t *)pNet->pCopy)->fPhase ^ - Aig_IsComplement((Aig_Obj_t *)pNetRepr->pCopy) ^ Aig_Regular((Aig_Obj_t *)pNetRepr->pCopy)->fPhase; - // create interter/buffer driven by the representative net - pNode = Ntl_ModelCreateNode( pRoot, 1 ); - pNode->pSop = fCompl? Ntl_ManStoreSop( p->pMemSops, "0 1\n" ) : Ntl_ManStoreSop( p->pMemSops, "1 1\n" ); - Ntl_ObjSetFanin( pNode, pNetRepr, 0 ); - // make the new node drive the equivalent net (pNet) - pNodeOld = pNet->pDriver; - if ( !Ntl_ModelClearNetDriver( pNet->pDriver, pNet ) ) - printf( "Ntl_ManReduce(): Internal error! Net already has no driver.\n" ); - if ( !Ntl_ModelSetNetDriver( pNode, pNet ) ) - printf( "Ntl_ManReduce(): Internal error! Net already has a driver.\n" ); -/* - // remove this net from the hash table (but do not remove from the array) - Ntl_ModelDeleteNet( pRoot, pNet ); - // create new net with the same name - pNetNew = Ntl_ModelFindOrCreateNet( pRoot, pNet->pName ); - // clean the name - pNet->pName[0] = 0; -*/ - // create new net with a new name - pNameNew = Ntl_ModelCreateNetName( pRoot, "noname", (int)(ABC_PTRINT_T)pNet ); - pNetNew = Ntl_ModelFindOrCreateNet( pRoot, pNameNew ); - - // make the old node drive the new net without fanouts - if ( !Ntl_ModelSetNetDriver( pNodeOld, pNetNew ) ) - printf( "Ntl_ManReduce(): Internal error! Net already has a driver.\n" ); - - Counter++; - } -// printf( "Nets without names = %d.\n", Counter ); -} - -/**Function************************************************************* - - Synopsis [Resets complemented attributes of the collapsed AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManResetComplemented( Ntl_Man_t * p, Aig_Man_t * pAigCol ) -{ - Ntl_Mod_t * pRoot; - Ntl_Obj_t * pObj; - Aig_Obj_t * pObjCol; - int i; - pRoot = Ntl_ManRootModel(p); - Ntl_ModelForEachLatch( pRoot, pObj, i ) - { - if ( Ntl_ObjIsInit1( pObj ) ) - { - pObjCol = (Aig_Obj_t *)Ntl_ObjFanout0(pObj)->pCopy; - assert( pObjCol->fPhase == 0 ); - pObjCol->fPhase = 1; - } - } -} - -/**Function************************************************************* - - Synopsis [Finalizes the transformation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Man_t * Ntl_ManFinalize( Ntl_Man_t * pNew, Aig_Man_t * pAig, Aig_Man_t * pAigCol, int fVerbose ) -{ - int fUseExtraSweep = 1; - Ntl_Man_t * pSwept; - Aig_Man_t * pTemp; - assert( pAig->pReprs == NULL ); - assert( pAigCol->pReprs != NULL ); - - // transfer equivalence classes to the original AIG - pAig->pReprs = Ntl_ManFraigDeriveClasses( pAig, pNew, pAigCol ); - pAig->nReprsAlloc = Aig_ManObjNumMax(pAig); -if ( fVerbose ) - printf( "Equivalences: Collapsed = %5d. Extracted = %5d.\n", Aig_ManCountReprs(pAigCol), Aig_ManCountReprs(pAig) ); -/* -{ - Aig_Obj_t * pObj; - int i; - Aig_ManForEachObj( pAig, pObj, i ) - if ( pAig->pReprs[i] != NULL ) - printf( "%s%d->%s%d ", - (Aig_ObjIsPi(pObj)? "pi": ""), - pObj->Id, - (Aig_ObjIsPi(pAig->pReprs[i])? "pi": ""), - pAig->pReprs[i]->Id ); - printf( "\n" ); -} -*/ - // implement equivalence classes and remove dangling nodes - Ntl_ManReduce( pNew, pAig ); - Ntl_ManSweep( pNew, fVerbose ); - - // perform one more sweep - if ( fUseExtraSweep ) - { - pTemp = Ntl_ManExtract( pNew ); - pSwept = Ntl_ManInsertAig( pNew, pTemp ); - Aig_ManStop( pTemp ); - Ntl_ManSweep( pSwept, fVerbose ); - return pSwept; - } - return Ntl_ManDup(pNew); -} - -/**Function************************************************************* - - Synopsis [Returns AIG with WB after fraiging.] - - Description [Consumes the input NTL to save memory.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Man_t * Ntl_ManFraig( Ntl_Man_t * p, int nPartSize, int nConfLimit, int nLevelMax, int fUseCSat, int fVerbose ) -{ - Ntl_Man_t * pNew, * pAux; - Aig_Man_t * pAig, * pAigCol, * pTemp; - - if ( Ntl_ModelNodeNum(Ntl_ManRootModel(p)) == 0 ) - return p; - - // collapse the AIG - pAig = Ntl_ManExtract( p ); - pNew = Ntl_ManInsertAig( p, pAig ); - Ntl_ManFree( p ); - pAigCol = Ntl_ManCollapseComb( pNew ); - if ( pAigCol == NULL ) - { - Aig_ManStop( pAig ); - return pNew; - } - - // perform fraiging for the given design - if ( fUseCSat ) - { -// extern Aig_Man_t * Cec_FraigCombinational( Aig_Man_t * pAig, int nConfs, int fVerbose ); -// pTemp = Cec_FraigCombinational( pAigCol, nConfLimit, fVerbose ); -// Aig_ManStop( pTemp ); - extern void Dch_ComputeEquivalences( Aig_Man_t * pAig, Dch_Pars_t * pPars ); - Dch_Pars_t Pars, * pPars = &Pars; - Dch_ManSetDefaultParams( pPars ); - pPars->nBTLimit = nConfLimit; - pPars->fVerbose = fVerbose; - Dch_ComputeEquivalences( pAigCol, pPars ); - } - else - { - nPartSize = nPartSize? nPartSize : Aig_ManPoNum(pAigCol); - pTemp = Aig_ManFraigPartitioned( pAigCol, nPartSize, nConfLimit, nLevelMax, fVerbose ); - Aig_ManStop( pTemp ); - } - - // finalize the transformation - pNew = Ntl_ManFinalize( pAux = pNew, pAig, pAigCol, fVerbose ); - Ntl_ManFree( pAux ); - Aig_ManStop( pAig ); - Aig_ManStop( pAigCol ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Counts the number of resets.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManAigCountResets( Ntl_Man_t * pNtl ) -{ -/* - Ntl_Mod_t * pModel = Ntl_ManRootModel(pNtl); - Ntl_Obj_t * pBox; - int i, Counter = -1; - Ntl_ModelForEachObj( pModel, pBox, i ) - Counter = ABC_MAX( Counter, pBox->Reset ); - return Counter + 1; -*/ - return -1; -} - -/**Function************************************************************* - - Synopsis [Transforms sequential AIG to allow for async reset.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Ntl_ManAigToRst( Ntl_Man_t * pNtl, Aig_Man_t * p ) -{ - Ntl_Mod_t * pModel = Ntl_ManRootModel(pNtl); - Aig_Man_t * pNew; - Aig_Obj_t * pObj; - int i, iRegNum, iRstNum, Counter = 0; - int nResets = Ntl_ManAigCountResets( pNtl ); - assert( pNtl->pNal != NULL ); - assert( Aig_ManRegNum(p) > 0 ); - assert( Vec_IntSize(pNtl->vRstClasses) == Aig_ManRegNum(p) ); -//printf( "Number of resets before synthesis = %d.\n", nResets ); - // create the PIs - Aig_ManCleanData( p ); - Aig_ManSetPioNumbers( p ); - // create the new manager - pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->pSpec = Aig_UtilStrsav( p->pSpec ); - // create special PIs - for ( i = 0; i < nResets; i++ ) - Aig_ObjCreatePi( pNew ); - // duplicate internal nodes - Aig_ManForEachPi( p, pObj, i ) - pObj->pData = Aig_ObjCreatePi( pNew ); - Aig_ManForEachObj( p, pObj, i ) - { - if ( Aig_ObjIsNode(pObj) ) - pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - else if ( Aig_ObjIsPo(pObj) ) - pObj->pData = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); - else if ( Aig_ObjIsPi(pObj) ) - { -// pObj->pData = Aig_ObjCreatePi( pNew ); - iRegNum = Aig_ObjPioNum(pObj) - (Aig_ManPiNum(p) - Aig_ManRegNum(p)); - if ( iRegNum < 0 ) - continue; - iRstNum = Vec_IntEntry(pNtl->vRstClasses, iRegNum); - if ( iRstNum < 0 ) - continue; - assert( iRstNum < nResets ); - pObj->pData = Aig_And( pNew, (Aig_Obj_t *)pObj->pData, Aig_ManPi(pNew, iRstNum) ); // could be NOT(pi) - Counter++; - } - else if ( Aig_ObjIsConst1(pObj) ) - pObj->pData = Aig_ManConst1(pNew); - else - assert( 0 ); - } - assert( Aig_ManNodeNum(p) + Counter == Aig_ManNodeNum(pNew) ); - if ( (Counter = Aig_ManCleanup( pNew )) ) - printf( "Aig_ManDupOrdered(): Cleanup after AIG duplication removed %d nodes.\n", Counter ); - Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Remaps equivalence classes from the new nodes to the old ones.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManRemapClassesLcorr( Ntl_Man_t * pNtl, Aig_Man_t * p, Aig_Man_t * pNew ) -{ - Ntl_Mod_t * pModel = Ntl_ManRootModel(pNtl); - Aig_Obj_t * pObj, * pObjRepr, * pObjNew, * pObjNewRepr; - int i, nResets = Ntl_ManAigCountResets( pNtl ); - int nTruePis = Aig_ManPiNum(p) - Aig_ManRegNum(p); - assert( pNew->pReprs != NULL ); - assert( nResets == Aig_ManPiNum(pNew) - Aig_ManPiNum(p) ); - Aig_ManReprStart( p, Aig_ManObjNumMax(p) ); - Aig_ManForEachLoSeq( pNew, pObjNew, i ) - { - pObj = Aig_ManPi( p, i - nResets ); - pObjNewRepr = pNew->pReprs[pObjNew->Id]; - if ( pObjNewRepr == NULL ) - continue; - if ( pObjNewRepr == Aig_ManConst1(pNew) ) - { - Aig_ObjCreateRepr( p, Aig_ManConst1(p), pObj ); - continue; - } - assert( Aig_ObjIsPi(pObjNewRepr) ); - // find the corresponding representative node - pObjRepr = Aig_ManPi( p, Aig_ObjPioNum(pObjNewRepr) - nResets ); - // if they belong to different domains, quit - if ( Vec_IntEntry( pNtl->vRstClasses, Aig_ObjPioNum(pObj) - nTruePis ) != - Vec_IntEntry( pNtl->vRstClasses, Aig_ObjPioNum(pObjRepr) - nTruePis ) ) - continue; - Aig_ObjCreateRepr( p, pObjRepr, pObj ); - } -} - -/**Function************************************************************* - - Synopsis [Remaps equivalence classes from the new nodes to the old ones.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManRemapClassesScorr( Ntl_Man_t * pNtl, Aig_Man_t * p, Aig_Man_t * pNew ) -{ - Aig_Obj_t * pObj, * pObjRepr, * pObjNew, * pObjNewRepr; - int i; - // map things back - Aig_ManForEachObj( p, pObj, i ) - { - pObjNew = (Aig_Obj_t *)pObj->pData; - assert( pObjNew != NULL && !Aig_IsComplement(pObjNew) ); - pObjNew->pData = pObj; - } - // remap the classes - Aig_ManForEachObj( pNew, pObjNew, i ) - { - pObjNewRepr = pNew->pReprs[pObjNew->Id]; - if ( pObjNewRepr == NULL ) - continue; - pObj = (Aig_Obj_t *)pObjNew->pData; - pObjRepr = (Aig_Obj_t *)pObjNewRepr->pData; - assert( Aig_ObjId(pObjRepr) < Aig_ObjId(pObj) ); - Aig_ObjCreateRepr( p, pObjRepr, pObj ); - } -} - - -/**Function************************************************************* - - Synopsis [Performs sequential cleanup.] - - Description [Consumes the input NTL to save memory.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Man_t * Ntl_ManScl( Ntl_Man_t * p, int fLatchConst, int fLatchEqual, int fVerbose ) -{ - Ntl_Man_t * pNew, * pAux; - Aig_Man_t * pAig, * pAigCol, * pTemp; - - // collapse the AIG - pAig = Ntl_ManExtract( p ); -//Ntl_ManPrintStats( p ); -//Aig_ManPrintStats( pAig ); - pNew = Ntl_ManInsertAig( p, pAig ); - Ntl_ManFree( p ); - pAigCol = Ntl_ManCollapseSeq( pNew, 0, fVerbose ); - if ( pAigCol == NULL ) - { - Aig_ManStop( pAig ); - return pNew; - } -//Ntl_ManPrintStats( pNew ); -//Aig_ManPrintStats( pAigCol ); - - // perform SCL - if ( pNew->pNal ) - { - Aig_Man_t * pAigRst; - pAigRst = Ntl_ManAigToRst( pNew, pAigCol ); - pTemp = Aig_ManScl( pAigRst, fLatchConst, fLatchEqual, 0, -1, -1, fVerbose, 0 ); - Aig_ManStop( pTemp ); - Ntl_ManRemapClassesLcorr( pNew, pAigCol, pAigRst ); - Aig_ManStop( pAigRst ); - } - else - { - pTemp = Aig_ManScl( pAigCol, fLatchConst, fLatchEqual, 0, -1, -1, fVerbose, 0 ); - Aig_ManStop( pTemp ); - } - - // finalize the transformation - pNew = Ntl_ManFinalize( pAux = pNew, pAig, pAigCol, fVerbose ); - Ntl_ManFree( pAux ); - Aig_ManStop( pAig ); - Aig_ManStop( pAigCol ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Returns AIG with WB after fraiging.] - - Description [Consumes the input NTL to save memory.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Man_t * Ntl_ManLcorr( Ntl_Man_t * p, int nConfMax, int fScorrGia, int fUseCSat, int fVerbose ) -{ - Ntl_Man_t * pNew, * pAux; - Aig_Man_t * pAig, * pAigCol, * pTemp; - Ssw_Pars_t Pars, * pPars = &Pars; - Ssw_ManSetDefaultParamsLcorr( pPars ); - pPars->nBTLimit = nConfMax; - pPars->fVerbose = fVerbose; - - // collapse the AIG - pAig = Ntl_ManExtract( p ); - pNew = Ntl_ManInsertAig( p, pAig ); - Ntl_ManFree( p ); - pAigCol = Ntl_ManCollapseSeq( pNew, pPars->nMinDomSize, pPars->fVerbose ); - if ( pAigCol == NULL ) - { - Aig_ManStop( pAig ); - return pNew; - } - - // perform LCORR - pPars->fScorrGia = fScorrGia; - pPars->fUseCSat = fUseCSat; - if ( pNew->pNal ) - { - Aig_Man_t * pAigRst; - pAigRst = Ntl_ManAigToRst( pNew, pAigCol ); - pTemp = Ssw_LatchCorrespondence( pAigRst, pPars ); - Aig_ManStop( pTemp ); - Ntl_ManRemapClassesLcorr( pNew, pAigCol, pAigRst ); - Aig_ManStop( pAigRst ); - } - else - { - pTemp = Ssw_LatchCorrespondence( pAigCol, pPars ); - Aig_ManStop( pTemp ); - } - - // finalize the transformation - pNew = Ntl_ManFinalize( pAux = pNew, pAig, pAigCol, fVerbose ); - Ntl_ManFree( pAux ); - Aig_ManStop( pAig ); - Aig_ManStop( pAigCol ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Returns AIG with WB after fraiging.] - - Description [Consumes the input NTL to save memory.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Man_t * Ntl_ManSsw( Ntl_Man_t * p, Fra_Ssw_t * pPars ) -{ - Ntl_Man_t * pNew, * pAux; - Aig_Man_t * pAig, * pAigCol, * pTemp; - assert( 0 ); // not updated for nal - - // collapse the AIG - pAig = Ntl_ManExtract( p ); - pNew = Ntl_ManInsertAig( p, pAig ); - Ntl_ManFree( p ); - pAigCol = Ntl_ManCollapseSeq( pNew, pPars->nMinDomSize, pPars->fVerbose ); - if ( pAigCol == NULL ) - { - Aig_ManStop( pAig ); - return pNew; - } - - // perform SCL for the given design - pTemp = Fra_FraigInduction( pAigCol, pPars ); - Aig_ManStop( pTemp ); - - // finalize the transformation - pNew = Ntl_ManFinalize( pAux = pNew, pAig, pAigCol, pPars->fVerbose ); - Ntl_ManFree( pAux ); - Aig_ManStop( pAig ); - Aig_ManStop( pAigCol ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Returns AIG with WB after fraiging.] - - Description [Consumes the input NTL to save memory.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Man_t * Ntl_ManScorr( Ntl_Man_t * p, Ssw_Pars_t * pPars ) -{ - Ntl_Man_t * pNew, * pAux; - Aig_Man_t * pAig, * pAigCol, * pTemp; - - // collapse the AIG - pAig = Ntl_ManExtract( p ); - pNew = Ntl_ManInsertAig( p, pAig ); - Ntl_ManFree( p ); - pAigCol = Ntl_ManCollapseSeq( pNew, pPars->nMinDomSize, pPars->fVerbose ); - if ( pAigCol == NULL ) - { - Aig_ManStop( pAig ); - return pNew; - } - - // perform SCL - if ( pNew->pNal ) - { - Aig_Man_t * pAigRst; - pAigRst = Ntl_ManAigToRst( pNew, pAigCol ); - pTemp = Ssw_SignalCorrespondence( pAigRst, pPars ); - Aig_ManStop( pTemp ); - Ntl_ManRemapClassesLcorr( pNew, pAigCol, pAigRst ); - Aig_ManStop( pAigRst ); - } - else - { - pPars->fVerbose = 1; - - pTemp = Ssw_SignalCorrespondence( pAigCol, pPars ); - Aig_ManStop( pTemp ); - } - - // finalize the transformation - pNew = Ntl_ManFinalize( pAux = pNew, pAig, pAigCol, pPars->fVerbose ); - Ntl_ManFree( pAux ); - Aig_ManStop( pAig ); - Aig_ManStop( pAigCol ); - return pNew; -} - - -/**Function************************************************************* - - Synopsis [Transfers the copy field into the second copy field.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManTransferCopy( Ntl_Man_t * p ) -{ - Ntl_Net_t * pNet; - Ntl_Mod_t * pRoot; - int i; - pRoot = Ntl_ManRootModel( p ); - Ntl_ModelForEachNet( pRoot, pNet, i ) - { - pNet->pCopy2 = pNet->pCopy; - pNet->pCopy = NULL; - } -} - -/**Function************************************************************* - - Synopsis [Reattaches one white-box.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManAttachWhiteBox( Ntl_Man_t * p, Aig_Man_t * pAigCol, Aig_Man_t * pAigRed, Ntl_Man_t * pNew, Ntl_Obj_t * pBox ) -{ -} - -/**Function************************************************************* - - Synopsis [Reattaches white-boxes after reducing the netlist.] - - Description [The following parameters are given: - Original netlist (p) whose nets point to the nodes of collapsed AIG. - Collapsed AIG (pAigCol) whose objects point to those of reduced AIG. - Reduced AIG (pAigRed) whose objects point to the nets of the new netlist. - The new netlist is changed by this procedure to have those white-boxes - from the original AIG (p) those outputs are preserved after reduction. - Note that if outputs are preserved, the inputs are also preserved.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManAttachWhiteBoxes( Ntl_Man_t * p, Aig_Man_t * pAigCol, Aig_Man_t * pAigRed, Ntl_Man_t * pNew, int fVerbose ) -{ - Ntl_Mod_t * pRoot; - Ntl_Obj_t * pBox; - Ntl_Net_t * pNet; - int i, k, Counter = 0; - // go through the white-boxes and check if they are preserved - pRoot = Ntl_ManRootModel( p ); - Ntl_ModelForEachBox( pRoot, pBox, i ) - { - Ntl_ObjForEachFanout( pBox, pNet, k ) - { - // skip dangling outputs of the box - if ( pNet->pCopy == NULL ) - continue; - // skip the outputs that are not preserved after merging equivalence - if ( Aig_Regular((Aig_Obj_t *)pNet->pCopy2)->pData == NULL ) - continue; - break; - } - if ( k == Ntl_ObjFanoutNum(pBox) ) - continue; - // the box is preserved - Ntl_ManAttachWhiteBox( p, pAigCol, pAigRed, pNew, pBox ); - Counter++; - } - if ( fVerbose ) - printf( "Attached %d boxed (out of %d).\n", Counter, Ntl_ModelBoxNum(pRoot) ); -} - -/**Function************************************************************* - - Synopsis [Flip complemented edges.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManFlipEdges( Ntl_Man_t * p, Aig_Man_t * pAigCol ) -{ - Ntl_Mod_t * pRoot; - Ntl_Obj_t * pObj; - Aig_Obj_t * pObjCol, * pFanin; - int i, iLatch; - pRoot = Ntl_ManRootModel(p); - iLatch = 0; - Ntl_ModelForEachLatch( pRoot, pObj, i ) - { - if ( Ntl_ObjIsInit1( pObj ) ) - { - pObjCol = Aig_ManPi( pAigCol, Ntl_ModelPiNum(pRoot) + iLatch ); - assert( pObjCol->fMarkA == 0 ); - pObjCol->fMarkA = 1; - } - iLatch++; - } - // flip pointers to the complemented edges - Aig_ManForEachObj( pAigCol, pObjCol, i ) - { - pFanin = Aig_ObjFanin0(pObjCol); - if ( pFanin && pFanin->fMarkA ) - pObjCol->pFanin0 = Aig_Not(pObjCol->pFanin0); - pFanin = Aig_ObjFanin1(pObjCol); - if ( pFanin && pFanin->fMarkA ) - pObjCol->pFanin1 = Aig_Not(pObjCol->pFanin1); - } - // flip complemented latch derivers and undo the marks - iLatch = 0; - Ntl_ModelForEachLatch( pRoot, pObj, i ) - { - if ( Ntl_ObjIsInit1( pObj ) ) - { - // flip the latch input - pObjCol = Aig_ManPo( pAigCol, Ntl_ModelPoNum(pRoot) + iLatch ); - pObjCol->pFanin0 = Aig_Not(pObjCol->pFanin0); - // unmark the latch output - pObjCol = Aig_ManPi( pAigCol, Ntl_ModelPiNum(pRoot) + iLatch ); - assert( pObjCol->fMarkA == 1 ); - pObjCol->fMarkA = 0; - } - iLatch++; - } -} - -/**Function************************************************************* - - Synopsis [Returns AIG with WB after sequential SAT sweeping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Man_t * Ntl_ManSsw2( Ntl_Man_t * p, Fra_Ssw_t * pPars ) -{ - Ntl_Man_t * pNew; - Aig_Man_t * pAigRed, * pAigCol; - // collapse the AIG - pAigCol = Ntl_ManCollapseSeq( p, pPars->nMinDomSize, pPars->fVerbose ); - // transform the collapsed AIG - pAigRed = Fra_FraigInduction( pAigCol, pPars ); - Aig_ManStop( pAigRed ); - pAigRed = Aig_ManDupReprBasic( pAigCol ); - // insert the result back - Ntl_ManFlipEdges( p, pAigRed ); - Ntl_ManTransferCopy( p ); - pNew = Ntl_ManInsertAig( p, pAigRed ); - // attach the white-boxes - Ntl_ManAttachWhiteBoxes( p, pAigCol, pAigRed, pNew, pPars->fVerbose ); - Ntl_ManSweep( pNew, pPars->fVerbose ); - // cleanup - Aig_ManStop( pAigRed ); - Aig_ManStop( pAigCol ); - return pNew; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ntl/ntlInsert.c b/src/aig/ntl/ntlInsert.c deleted file mode 100644 index 8b0e3493..00000000 --- a/src/aig/ntl/ntlInsert.c +++ /dev/null @@ -1,614 +0,0 @@ -/**CFile**************************************************************** - - FileName [ntlInsert.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Netlist representation.] - - Synopsis [Procedures to insert mapping into a design.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ntlInsert.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ntl.h" -#include "kit.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Inserts the given mapping into the netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Man_t * Ntl_ManInsertMapping( Ntl_Man_t * p, Vec_Ptr_t * vMapping, Aig_Man_t * pAig ) -{ - char Buffer[1000]; - 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; - assert( Vec_PtrSize(p->vCis) == Aig_ManPiNum(pAig) ); - assert( Vec_PtrSize(p->vCos) == Aig_ManPoNum(pAig) ); - p = Ntl_ManStartFrom( p ); - pRoot = Ntl_ManRootModel( p ); - assert( Ntl_ModelNodeNum(pRoot) == 0 ); - // map the AIG back onto the design - Ntl_ManForEachCiNet( p, pNet, i ) - pNet->pCopy = Aig_ManPi( pAig, i ); - // start mapping of AIG nodes into their copies - vCopies = Vec_PtrStart( Aig_ManObjNumMax(pAig) ); - Ntl_ManForEachCiNet( p, pNet, i ) - Vec_PtrWriteEntry( vCopies, ((Aig_Obj_t *)pNet->pCopy)->Id, pNet ); - // create a new node for each LUT - vCover = Vec_IntAlloc( 1 << 16 ); - nDigits = Aig_Base10Log( Vec_PtrSize(vMapping) ); - Vec_PtrForEachEntry( Ntl_Lut_t *, vMapping, pLut, i ) - { - pNode = Ntl_ModelCreateNode( pRoot, pLut->nFanins ); - pNode->pSop = Kit_PlaFromTruth( p->pMemSops, 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 = (Ntl_Net_t *)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 ); - } - } - else - pNode->nFanins = 0; - 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->fMark = 1; - // update the CO pointers - Ntl_ManForEachCoNet( p, pNetCo, i ) - { - if ( pNetCo->fMark ) - continue; - pNetCo->fMark = 1; - pNet = (Ntl_Net_t *)Vec_PtrEntry( vCopies, Aig_Regular((Aig_Obj_t *)pNetCo->pCopy)->Id ); - pNode = Ntl_ModelCreateNode( pRoot, 1 ); - pNode->pSop = Aig_IsComplement((Aig_Obj_t *)pNetCo->pCopy)? Ntl_ManStoreSop( p->pMemSops, "0 1\n" ) : Ntl_ManStoreSop( p->pMemSops, "1 1\n" ); - Ntl_ObjSetFanin( pNode, pNet, 0 ); - // update the CO driver net - assert( 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 ); - // clean CI/CO marks - Ntl_ManUnmarkCiCoNets( p ); - if ( !Ntl_ManCheck( p ) ) - printf( "Ntl_ManInsertNtk: The check has failed for design %s.\n", p->pName ); - return p; -} - -/**Function************************************************************* - - Synopsis [Inserts the given mapping into the netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Man_t * Ntl_ManInsertAig( Ntl_Man_t * p, Aig_Man_t * pAig ) -{ - char Buffer[1000]; - Ntl_Mod_t * pRoot; - Ntl_Obj_t * pNode; - Ntl_Net_t * pNet, * pNetCo; - Aig_Obj_t * pObj, * pFanin; - int i, nDigits, Counter; - assert( Vec_PtrSize(p->vCis) == Aig_ManPiNum(pAig) ); - assert( Vec_PtrSize(p->vCos) == Aig_ManPoNum(pAig) ); - p = Ntl_ManStartFrom( p ); - pRoot = Ntl_ManRootModel( p ); - assert( Ntl_ModelNodeNum(pRoot) == 0 ); - // set the correspondence between the PI/PO nodes - Aig_ManCleanData( pAig ); - Ntl_ManForEachCiNet( p, pNet, i ) - Aig_ManPi( pAig, i )->pData = pNet; - // create constant node if needed - if ( Aig_ManConst1(pAig)->nRefs > 0 ) - { - pNode = Ntl_ModelCreateNode( pRoot, 0 ); - pNode->pSop = Ntl_ManStoreSop( p->pMemSops, " 1\n" ); - if ( (pNet = Ntl_ModelFindNet( pRoot, "Const1" )) ) - { - printf( "Ntl_ManInsertAig(): Internal error: Intermediate net name is not unique.\n" ); - return 0; - } - pNet = Ntl_ModelFindOrCreateNet( pRoot, "Const1" ); - if ( !Ntl_ModelSetNetDriver( pNode, pNet ) ) - { - printf( "Ntl_ManInsertAig(): Internal error: Net has more than one fanin.\n" ); - return 0; - } - Aig_ManConst1(pAig)->pData = pNet; - } - // create a new node for each LUT - Counter = 0; - nDigits = Aig_Base10Log( Aig_ManNodeNum(pAig) ); - Aig_ManForEachObj( pAig, pObj, i ) - { - if ( !Aig_ObjIsNode(pObj) ) - continue; - if ( Aig_ObjFanin0(pObj)->pData == NULL || Aig_ObjFanin1(pObj)->pData == NULL ) - { - printf( "Ntl_ManInsertAig(): Internal error: Net not found.\n" ); - return 0; - } - pNode = Ntl_ModelCreateNode( pRoot, 2 ); - Ntl_ObjSetFanin( pNode, (Ntl_Net_t *)Aig_ObjFanin0(pObj)->pData, 0 ); - Ntl_ObjSetFanin( pNode, (Ntl_Net_t *)Aig_ObjFanin1(pObj)->pData, 1 ); - if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) - pNode->pSop = Ntl_ManStoreSop( p->pMemSops, "00 1\n" ); - else if ( Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) ) - pNode->pSop = Ntl_ManStoreSop( p->pMemSops, "01 1\n" ); - else if ( !Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) - pNode->pSop = Ntl_ManStoreSop( p->pMemSops, "10 1\n" ); - else // if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) - pNode->pSop = Ntl_ManStoreSop( p->pMemSops, "11 1\n" ); - sprintf( Buffer, "and%0*d", nDigits, Counter++ ); - if ( (pNet = Ntl_ModelFindNet( pRoot, Buffer )) ) - { - printf( "Ntl_ManInsertAig(): Internal error: Intermediate net name is not unique.\n" ); - return 0; - } - pNet = Ntl_ModelFindOrCreateNet( pRoot, Buffer ); - if ( !Ntl_ModelSetNetDriver( pNode, pNet ) ) - { - printf( "Ntl_ManInsertAig(): Internal error: Net has more than one fanin.\n" ); - return 0; - } - pObj->pData = pNet; - } - // mark CIs and outputs of the registers - Ntl_ManForEachCiNet( p, pNetCo, i ) - pNetCo->fMark = 1; - // update the CO pointers - Ntl_ManForEachCoNet( p, pNetCo, i ) - { - if ( pNetCo->fMark ) - continue; - pNetCo->fMark = 1; - // get the corresponding PO and its driver - pObj = Aig_ManPo( pAig, i ); - pFanin = Aig_ObjFanin0( pObj ); - // get the net driving the driver - pNet = (Ntl_Net_t *)pFanin->pData; - pNode = Ntl_ModelCreateNode( pRoot, 1 ); - pNode->pSop = Aig_ObjFaninC0(pObj)? Ntl_ManStoreSop( p->pMemSops, "0 1\n" ) : Ntl_ManStoreSop( p->pMemSops, "1 1\n" ); - Ntl_ObjSetFanin( pNode, pNet, 0 ); - // update the CO driver net - assert( pNetCo->pDriver == NULL ); - if ( !Ntl_ModelSetNetDriver( pNode, pNetCo ) ) - { - printf( "Ntl_ManInsertAig(): Internal error: PO net has more than one fanin.\n" ); - return 0; - } - } - // clean CI/CO marks - Ntl_ManUnmarkCiCoNets( p ); - if ( !Ntl_ManCheck( p ) ) - printf( "Ntl_ManInsertAig: The check has failed for design %s.\n", p->pName ); - return p; -} - -/**Function************************************************************* - - Synopsis [Find drivers of the given net.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManFindDriver( Ntl_Man_t * p, char * pName ) -{ - Ntl_Mod_t * pRoot; - Ntl_Obj_t * pNode; - Ntl_Net_t * pNet, * pNetThis; - int i, k; - pRoot = Ntl_ManRootModel( p ); - pNetThis = Ntl_ModelFindNet( pRoot, pName ); - printf( "\n*** Net %d \"%s\":\n", pNetThis->NetId, pName ); - // mark from the nodes - Ntl_ModelForEachPo( pRoot, pNode, i ) - if ( pNetThis == Ntl_ObjFanin0(pNode) ) - printf( "driven by PO %d\n", i ); - Ntl_ModelForEachNode( pRoot, pNode, i ) - Ntl_ObjForEachFanin( pNode, pNet, k ) - if ( pNetThis == pNet ) - printf( "driven by node %d with %d fanins and %d fanouts\n (%s)\n", - pNode->Id, Ntl_ObjFaninNum(pNode), Ntl_ObjFanoutNum(pNode), Ntl_ObjFanout(pNode,0)->pName ); - Ntl_ModelForEachBox( pRoot, pNode, i ) - Ntl_ObjForEachFanin( pNode, pNet, k ) - if ( pNetThis == pNet ) - printf( "driven by box %d with %d fanins and %d fanouts\n (%s)\n", - pNode->Id, Ntl_ObjFaninNum(pNode), Ntl_ObjFanoutNum(pNode), Ntl_ObjFanout(pNode,0)->pName ); -} - -/**Function************************************************************* - - Synopsis [Inserts the given mapping into the netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Man_t * Ntl_ManInsertNtk2( Ntl_Man_t * p, Nwk_Man_t * pNtk ) -{ - int fWriteConstants = 1; - char Buffer[1000]; - Vec_Ptr_t * vObjs; - Vec_Int_t * vTruth; - Vec_Int_t * vCover; - Ntl_Mod_t * pRoot; - Ntl_Obj_t * pNode; - Ntl_Net_t * pNet, * pNetCo; - Nwk_Obj_t * pObj, * pFanin; - int i, k, nDigits; - unsigned * pTruth; - assert( Vec_PtrSize(p->vCis) == Nwk_ManCiNum(pNtk) ); - assert( Vec_PtrSize(p->vCos) == Nwk_ManCoNum(pNtk) ); - p = Ntl_ManStartFrom( p ); - pRoot = Ntl_ManRootModel( p ); - assert( Ntl_ModelNodeNum(pRoot) == 0 ); - // set the correspondence between the PI/PO nodes - Ntl_ManForEachCiNet( p, pNet, i ) - Nwk_ManCi( pNtk, i )->pCopy = pNet; - // create a new node for each LUT - vTruth = Vec_IntAlloc( 1 << 16 ); - vCover = Vec_IntAlloc( 1 << 16 ); - nDigits = Aig_Base10Log( Nwk_ManNodeNum(pNtk) ); - // go through the nodes in the topological order - vObjs = Nwk_ManDfs( pNtk ); - Vec_PtrForEachEntry( Nwk_Obj_t *, vObjs, pObj, i ) - { - if ( !Nwk_ObjIsNode(pObj) ) - continue; -/* - if ( fWriteConstants && Nwk_ObjFaninNum(pObj) == 0 ) - { - pObj->pCopy = NULL; - continue; - } -*/ - // skip constant drivers if they only drive COs - if ( fWriteConstants && Nwk_ObjFaninNum(pObj) == 0 ) - { - Nwk_Obj_t * pFanout; - int i; - Nwk_ObjForEachFanout( pObj, pFanout, i ) - if ( Nwk_ObjIsNode(pFanout) ) - break; - if ( i == Nwk_ObjFanoutNum(pObj) ) - { - pObj->pCopy = NULL; - continue; - } - } - - pNode = Ntl_ModelCreateNode( pRoot, Nwk_ObjFaninNum(pObj) ); - pTruth = Hop_ManConvertAigToTruth( pNtk->pManHop, Hop_Regular(pObj->pFunc), Nwk_ObjFaninNum(pObj), vTruth, 0 ); - if ( Hop_IsComplement(pObj->pFunc) ) - Kit_TruthNot( pTruth, pTruth, Nwk_ObjFaninNum(pObj) ); - if ( !Kit_TruthIsConst0(pTruth, Nwk_ObjFaninNum(pObj)) && !Kit_TruthIsConst1(pTruth, Nwk_ObjFaninNum(pObj)) ) - { - Nwk_ObjForEachFanin( pObj, pFanin, k ) - { - pNet = (Ntl_Net_t *)pFanin->pCopy; - if ( pNet == NULL ) - { - printf( "Ntl_ManInsertNtk(): Internal error: Net not found.\n" ); - return 0; - } - Ntl_ObjSetFanin( pNode, pNet, k ); - } - } - else if ( Kit_TruthIsConst0(pTruth, Nwk_ObjFaninNum(pObj)) ) - { - pObj->pFunc = Hop_ManConst0(pNtk->pManHop); - pNode->nFanins = 0; - } - else if ( Kit_TruthIsConst1(pTruth, Nwk_ObjFaninNum(pObj)) ) - { - pObj->pFunc = Hop_ManConst1(pNtk->pManHop); - pNode->nFanins = 0; - } - pNode->pSop = Kit_PlaFromTruth( p->pMemSops, pTruth, Nwk_ObjFaninNum(pObj), vCover ); - sprintf( Buffer, "lut%0*d", nDigits, i ); - if ( (pNet = Ntl_ModelFindNet( pRoot, Buffer )) ) - { - printf( "Ntl_ManInsertNtk(): Internal error: Intermediate net name is not unique.\n" ); - return 0; - } - pNet = Ntl_ModelFindOrCreateNet( pRoot, Buffer ); - if ( !Ntl_ModelSetNetDriver( pNode, pNet ) ) - { - printf( "Ntl_ManInsertNtk(): Internal error: Net has more than one fanin.\n" ); - return 0; - } - pObj->pCopy = pNet; - } - Vec_PtrFree( vObjs ); - Vec_IntFree( vCover ); - Vec_IntFree( vTruth ); - // mark the nets driving special boxes - if ( p->pNalR ) - p->pNalR( p ); - // mark CIs and outputs of the registers - Ntl_ManForEachCiNet( p, pNetCo, i ) - pNetCo->fMark = 1; - // update the CO pointers - Ntl_ManForEachCoNet( p, pNetCo, i ) - { - if ( pNetCo->fMark ) - continue; - pNetCo->fMark = 1; - // get the corresponding PO and its driver - pObj = Nwk_ManCo( pNtk, i ); - pFanin = Nwk_ObjFanin0( pObj ); - // get the net driving this PO - pNet = (Ntl_Net_t *)pFanin->pCopy; - if ( pNet == NULL ) // constant net - { - assert( fWriteConstants ); - pNode = Ntl_ModelCreateNode( pRoot, 0 ); - pNode->pSop = pObj->fInvert? Ntl_ManStoreSop( p->pMemSops, " 0\n" ) : Ntl_ManStoreSop( p->pMemSops, " 1\n" ); - } - else - if ( Nwk_ObjFanoutNum(pFanin) == 1 && Ntl_ObjIsNode(pNet->pDriver) && !pNet->fMark2 ) - { - pNode = pNet->pDriver; - if ( !Ntl_ModelClearNetDriver( pNode, pNet ) ) - { - printf( "Ntl_ManInsertNtk(): Internal error! Net already has no driver.\n" ); - return NULL; - } - // remove this net - Ntl_ModelDeleteNet( pRoot, pNet ); - Vec_PtrWriteEntry( pRoot->vNets, pNet->NetId, NULL ); - // update node's function - if ( pObj->fInvert ) - Kit_PlaComplement( pNode->pSop ); - } - else - { -/* - if ( fWriteConstants && Ntl_ObjFaninNum(pNet->pDriver) == 0 ) - { - pNode = Ntl_ModelCreateNode( pRoot, 0 ); - pNode->pSop = pObj->fInvert? Ntl_ManStoreSop( p->pMemSops, " 0\n" ) : Ntl_ManStoreSop( p->pMemSops, " 1\n" ); - } - else -*/ - { -// assert( Ntl_ObjFaninNum(pNet->pDriver) != 0 ); - pNode = Ntl_ModelCreateNode( pRoot, 1 ); - pNode->pSop = pObj->fInvert? Ntl_ManStoreSop( p->pMemSops, "0 1\n" ) : Ntl_ManStoreSop( p->pMemSops, "1 1\n" ); - Ntl_ObjSetFanin( pNode, pNet, 0 ); - } - } - // update the CO driver net - assert( pNetCo->pDriver == NULL ); - if ( !Ntl_ModelSetNetDriver( pNode, pNetCo ) ) - { - printf( "Ntl_ManInsertNtk(): Internal error: PO net has more than one fanin.\n" ); - return NULL; - } - } - // clean CI/CO marks - Ntl_ManUnmarkCiCoNets( p ); - if ( !Ntl_ManCheck( p ) ) - { - printf( "Ntl_ManInsertNtk: The check has failed for design %s.\n", p->pName ); - return NULL; - } - return p; -} - - -/**Function************************************************************* - - Synopsis [Inserts the given mapping into the netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Man_t * Ntl_ManInsertNtk( Ntl_Man_t * p, Nwk_Man_t * pNtk ) -{ - char Buffer[1000]; - Vec_Ptr_t * vObjs; - Vec_Int_t * vTruth; - Vec_Int_t * vCover; - Ntl_Mod_t * pRoot; - Ntl_Obj_t * pNode; - Ntl_Net_t * pNet, * pNetCo; - Nwk_Obj_t * pObj, * pFanin; - int i, k, nDigits; - unsigned * pTruth; - assert( Vec_PtrSize(p->vCis) == Nwk_ManCiNum(pNtk) ); - assert( Vec_PtrSize(p->vCos) == Nwk_ManCoNum(pNtk) ); - p = Ntl_ManStartFrom( p ); - pRoot = Ntl_ManRootModel( p ); - assert( Ntl_ModelNodeNum(pRoot) == 0 ); - // set the correspondence between the PI/PO nodes - Ntl_ManForEachCiNet( p, pNet, i ) - Nwk_ManCi( pNtk, i )->pCopy = pNet; - // create a new node for each LUT - vTruth = Vec_IntAlloc( 1 << 16 ); - vCover = Vec_IntAlloc( 1 << 16 ); - nDigits = Aig_Base10Log( Nwk_ManNodeNum(pNtk) ); - // go through the nodes in the topological order - vObjs = Nwk_ManDfs( pNtk ); - Vec_PtrForEachEntry( Nwk_Obj_t *, vObjs, pObj, i ) - { - if ( !Nwk_ObjIsNode(pObj) ) - continue; - pNode = Ntl_ModelCreateNode( pRoot, Nwk_ObjFaninNum(pObj) ); - pTruth = Hop_ManConvertAigToTruth( pNtk->pManHop, Hop_Regular(pObj->pFunc), Nwk_ObjFaninNum(pObj), vTruth, 0 ); - if ( Hop_IsComplement(pObj->pFunc) ) - Kit_TruthNot( pTruth, pTruth, Nwk_ObjFaninNum(pObj) ); - if ( !Kit_TruthIsConst0(pTruth, Nwk_ObjFaninNum(pObj)) && !Kit_TruthIsConst1(pTruth, Nwk_ObjFaninNum(pObj)) ) - { - Nwk_ObjForEachFanin( pObj, pFanin, k ) - { - pNet = (Ntl_Net_t *)pFanin->pCopy; - if ( pNet == NULL ) - { - printf( "Ntl_ManInsertNtk(): Internal error: Net not found.\n" ); - return 0; - } - Ntl_ObjSetFanin( pNode, pNet, k ); - } - } - else if ( Kit_TruthIsConst0(pTruth, Nwk_ObjFaninNum(pObj)) ) - { - pObj->pFunc = Hop_ManConst0(pNtk->pManHop); - pNode->nFanins = 0; - } - else if ( Kit_TruthIsConst1(pTruth, Nwk_ObjFaninNum(pObj)) ) - { - pObj->pFunc = Hop_ManConst1(pNtk->pManHop); - pNode->nFanins = 0; - } - pNode->pSop = Kit_PlaFromTruth( p->pMemSops, pTruth, Nwk_ObjFaninNum(pObj), vCover ); - sprintf( Buffer, "lut%0*d", nDigits, i ); - if ( (pNet = Ntl_ModelFindNet( pRoot, Buffer )) ) - { - printf( "Ntl_ManInsertNtk(): Internal error: Intermediate net name is not unique.\n" ); - return 0; - } - pNet = Ntl_ModelFindOrCreateNet( pRoot, Buffer ); - if ( !Ntl_ModelSetNetDriver( pNode, pNet ) ) - { - printf( "Ntl_ManInsertNtk(): Internal error: Net has more than one fanin.\n" ); - return 0; - } - pObj->pCopy = pNet; - } - Vec_PtrFree( vObjs ); - Vec_IntFree( vCover ); - Vec_IntFree( vTruth ); - // mark CIs and outputs of the registers - Ntl_ManForEachCiNet( p, pNetCo, i ) - pNetCo->fMark = 1; - // update the CO pointers - Ntl_ManForEachCoNet( p, pNetCo, i ) - { - if ( pNetCo->fMark ) - continue; - pNetCo->fMark = 1; - // get the corresponding PO and its driver - pObj = Nwk_ManCo( pNtk, i ); - pFanin = Nwk_ObjFanin0( pObj ); - // get the net driving this PO - pNet = (Ntl_Net_t *)pFanin->pCopy; - if ( Nwk_ObjFanoutNum(pFanin) == 1 && Ntl_ObjIsNode(pNet->pDriver) ) - { - pNode = pNet->pDriver; - if ( !Ntl_ModelClearNetDriver( pNode, pNet ) ) - { - printf( "Ntl_ManInsertNtk(): Internal error! Net already has no driver.\n" ); - return NULL; - } - // remove this net - Ntl_ModelDeleteNet( pRoot, pNet ); - Vec_PtrWriteEntry( pRoot->vNets, pNet->NetId, NULL ); - // update node's function - if ( pObj->fInvert ) - Kit_PlaComplement( pNode->pSop ); - } - else - { - pNode = Ntl_ModelCreateNode( pRoot, 1 ); - pNode->pSop = pObj->fInvert? Ntl_ManStoreSop( p->pMemSops, "0 1\n" ) : Ntl_ManStoreSop( p->pMemSops, "1 1\n" ); - Ntl_ObjSetFanin( pNode, pNet, 0 ); - } - // update the CO driver net - assert( pNetCo->pDriver == NULL ); - if ( !Ntl_ModelSetNetDriver( pNode, pNetCo ) ) - { - printf( "Ntl_ManInsertNtk(): Internal error: PO net has more than one fanin.\n" ); - return NULL; - } - } - // clean CI/CO marks - Ntl_ManUnmarkCiCoNets( p ); - if ( !Ntl_ManCheck( p ) ) - { - printf( "Ntl_ManInsertNtk: The check has failed for design %s.\n", p->pName ); - return NULL; - } - return p; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ntl/ntlMan.c b/src/aig/ntl/ntlMan.c deleted file mode 100644 index 45fb7226..00000000 --- a/src/aig/ntl/ntlMan.c +++ /dev/null @@ -1,1068 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates the netlist manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Man_t * Ntl_ManAlloc() -{ - Ntl_Man_t * p; - // start the manager - p = ABC_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->vVisNodes = Vec_PtrAlloc( 1000 ); - p->vBox1Cios = Vec_IntAlloc( 1000 ); - p->vRegClasses = Vec_IntAlloc( 1000 ); - p->vRstClasses = Vec_IntAlloc( 1000 ); - // start the manager - p->pMemObjs = Aig_MmFlexStart(); - p->pMemSops = Aig_MmFlexStart(); - // allocate model table - p->nModTableSize = Aig_PrimeCudd( 100 ); - p->pModTable = ABC_ALLOC( Ntl_Mod_t *, p->nModTableSize ); - memset( p->pModTable, 0, sizeof(Ntl_Mod_t *) * p->nModTableSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Cleanups extended representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManCleanup( Ntl_Man_t * p ) -{ - if ( p->pAig ) - { - Aig_ManStop( p->pAig ); - p->pAig = NULL; - } - if ( p->pManTime ) - { - Tim_ManStop( p->pManTime ); - p->pManTime = NULL; - } -} - -/**Function************************************************************* - - Synopsis [Duplicates the design without the nodes of the root model.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Man_t * Ntl_ManStartFrom( Ntl_Man_t * pOld ) -{ - Ntl_Man_t * pNew; - Ntl_Mod_t * pModel; - Ntl_Obj_t * pBox; - Ntl_Net_t * pNet; - int i, k; - pNew = Ntl_ManAlloc(); - pNew->pName = Ntl_ManStoreFileName( pNew, pOld->pName ); - pNew->pSpec = Ntl_ManStoreName( pNew, pOld->pName ); - Vec_PtrForEachEntry( Ntl_Mod_t *, pOld->vModels, pModel, i ) - { - if ( i == 0 ) - { - Ntl_ManMarkCiCoNets( pOld ); - pModel->pCopy = Ntl_ModelStartFrom( pNew, pModel ); - Ntl_ManUnmarkCiCoNets( pOld ); - } - else - pModel->pCopy = Ntl_ModelDup( pNew, pModel ); - } - Vec_PtrForEachEntry( Ntl_Mod_t *, pOld->vModels, pModel, i ) - Ntl_ModelForEachBox( pModel, pBox, k ) - { - ((Ntl_Obj_t *)pBox->pCopy)->pImplem = (Ntl_Mod_t *)pBox->pImplem->pCopy; - ((Ntl_Obj_t *)pBox->pCopy)->iTemp = pBox->iTemp; -// ((Ntl_Obj_t *)pBox->pCopy)->Reset = pBox->Reset; - } - Ntl_ManForEachCiNet( pOld, pNet, i ) - Vec_PtrPush( pNew->vCis, pNet->pCopy ); - Ntl_ManForEachCoNet( pOld, pNet, i ) - Vec_PtrPush( pNew->vCos, pNet->pCopy ); - if ( pOld->pManTime ) - pNew->pManTime = Tim_ManDup( pOld->pManTime, 0 ); - if ( pOld->pNal ) - pOld->pNalD( pOld, pNew ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Duplicates the design.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Man_t * Ntl_ManDup( Ntl_Man_t * pOld ) -{ - Ntl_Man_t * pNew; - Ntl_Mod_t * pModel; - Ntl_Obj_t * pBox; - Ntl_Net_t * pNet; - int i, k; - pNew = Ntl_ManAlloc(); - pNew->pName = Ntl_ManStoreFileName( pNew, pOld->pName ); - pNew->pSpec = Ntl_ManStoreName( pNew, pOld->pName ); - Vec_PtrForEachEntry( Ntl_Mod_t *, pOld->vModels, pModel, i ) - pModel->pCopy = Ntl_ModelDup( pNew, pModel ); - Vec_PtrForEachEntry( Ntl_Mod_t *, pOld->vModels, pModel, i ) - Ntl_ModelForEachBox( pModel, pBox, k ) - ((Ntl_Obj_t *)pBox->pCopy)->pImplem = (Ntl_Mod_t *)pBox->pImplem->pCopy; - Ntl_ManForEachCiNet( pOld, pNet, i ) - Vec_PtrPush( pNew->vCis, pNet->pCopy ); - Ntl_ManForEachCoNet( pOld, pNet, i ) - Vec_PtrPush( pNew->vCos, pNet->pCopy ); - if ( pOld->pManTime ) - pNew->pManTime = Tim_ManDup( pOld->pManTime, 0 ); - if ( !Ntl_ManCheck( pNew ) ) - printf( "Ntl_ManDup: The check has failed for design %s.\n", pNew->pName ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Duplicates the design.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Man_t * Ntl_ManDupCollapseLuts( Ntl_Man_t * pOld ) -{ - Ntl_Man_t * pNew; - Ntl_Mod_t * pModel; - Ntl_Obj_t * pBox; -// Ntl_Net_t * pNet; - int i, k; - pNew = Ntl_ManAlloc(); - pNew->pName = Ntl_ManStoreFileName( pNew, pOld->pName ); - pNew->pSpec = Ntl_ManStoreName( pNew, pOld->pName ); - Vec_PtrForEachEntry( Ntl_Mod_t *, pOld->vModels, pModel, i ) - pModel->pCopy = Ntl_ModelDupCollapseLuts( pNew, pModel ); - Vec_PtrForEachEntry( Ntl_Mod_t *, pOld->vModels, pModel, i ) - Ntl_ModelForEachBox( pModel, pBox, k ) - if ( pBox->pCopy ) - ((Ntl_Obj_t *)pBox->pCopy)->pImplem = (Ntl_Mod_t *)pBox->pImplem->pCopy; -// Ntl_ManForEachCiNet( pOld, pNet, i ) -// Vec_PtrPush( pNew->vCis, pNet->pCopy ); -// Ntl_ManForEachCoNet( pOld, pNet, i ) -// Vec_PtrPush( pNew->vCos, pNet->pCopy ); -// if ( pOld->pManTime ) -// pNew->pManTime = Tim_ManDup( pOld->pManTime, 0 ); - if ( !Ntl_ManCheck( pNew ) ) - printf( "Ntl_ManDup: The check has failed for design %s.\n", pNew->pName ); - return pNew; -} - -/**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->vVisNodes ) Vec_PtrFree( p->vVisNodes ); - if ( p->vRegClasses) Vec_IntFree( p->vRegClasses ); - if ( p->vRstClasses) Vec_IntFree( p->vRstClasses ); - if ( p->vBox1Cios ) Vec_IntFree( p->vBox1Cios ); - if ( p->pMemObjs ) Aig_MmFlexStop( p->pMemObjs, 0 ); - if ( p->pMemSops ) Aig_MmFlexStop( p->pMemSops, 0 ); - if ( p->pAig ) Aig_ManStop( p->pAig ); - if ( p->pManTime ) Tim_ManStop( p->pManTime ); - if ( p->pNal ) p->pNalF( p->pNal ); - ABC_FREE( p->pModTable ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManPrintStats( Ntl_Man_t * p ) -{ - Ntl_Mod_t * pRoot; - pRoot = Ntl_ManRootModel( p ); - printf( "%-15s : ", p->pName ); - printf( "pi = %5d ", Ntl_ModelPiNum(pRoot) ); - printf( "po = %5d ", Ntl_ModelPoNum(pRoot) ); - printf( "lat = %5d ", Ntl_ModelLatchNum(pRoot) ); - printf( "node = %5d ", Ntl_ModelNodeNum(pRoot) ); - printf( "\n " ); - printf( "inv/buf = %5d ", Ntl_ModelLut1Num(pRoot) ); - printf( "box = %4d ", Ntl_ModelBoxNum(pRoot) ); - printf( "mod = %3d ", Vec_PtrSize(p->vModels) ); - printf( "net = %d", Ntl_ModelCountNets(pRoot) ); - printf( "\n" ); - fflush( stdout ); - assert( Ntl_ModelLut1Num(pRoot) == Ntl_ModelCountLut1(pRoot) ); - Ntl_ManPrintTypes( p ); - fflush( stdout ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManPrintStatsShort( Ntl_Man_t * p, Aig_Man_t * pAig, Nwk_Man_t * pNtk ) -{ - Ntl_Mod_t * pRoot; - Ntl_Obj_t * pObj; - int i, Counter = 0; - pRoot = Ntl_ManRootModel( p ); - Ntl_ModelForEachBox( pRoot, pObj, i ) - if ( strcmp(pObj->pImplem->pName, "dff") == 0 ) - Counter++; - if ( Counter == 0 ) - { - Ntl_ModelForEachBox( pRoot, pObj, i ) - Counter += (pObj->pImplem->attrWhite && !pObj->pImplem->attrComb); - } - printf( "%-15s : ", p->pName ); - printf( "pi =%5d ", Ntl_ModelPiNum(pRoot) ); - printf( "po =%5d ", Ntl_ModelPoNum(pRoot) ); - printf( "ff =%5d ", Counter ); - printf( "box =%6d ", Ntl_ModelBoxNum(pRoot) ); - if ( pAig != NULL ) - { - Counter = Aig_ManChoiceNum( pAig ); - if ( Counter ) - printf( "cho =%7d ", Counter ); - else - printf( "aig =%7d ", Aig_ManNodeNum(pAig) ); - } - if ( pNtk == NULL ) - printf( "No mapping.\n" ); - else - { - printf( "lut =%5d ", Nwk_ManNodeNum(pNtk) ); - printf( "lev =%3d ", Nwk_ManLevel(pNtk) ); -// printf( "del =%5.2f ", Nwk_ManDelayTraceLut(pNtk) ); - printf( "\n" ); - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManStatsRegs( Ntl_Man_t * p ) -{ - Ntl_Mod_t * pRoot; - Ntl_Obj_t * pObj; - int i, Counter = 0; - pRoot = Ntl_ManRootModel( p ); - Ntl_ModelForEachBox( pRoot, pObj, i ) - if ( strcmp(pObj->pImplem->pName, "m_dff") == 0 ) - Counter++; - return Counter; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManStatsLuts( Ntl_Man_t * p ) -{ - return Ntl_ModelLut1Num( Ntl_ManRootModel(p) ) + Ntl_ModelNodeNum( Ntl_ManRootModel(p) ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManStatsLuts( Nwk_Man_t * pNtk ) -{ - return pNtk ? Nwk_ManNodeNum(pNtk) : -1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManStatsLevs( Nwk_Man_t * pNtk ) -{ - return pNtk ? Nwk_ManLevel(pNtk) : -1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManPrintStatsUpdate( Ntl_Man_t * p, Aig_Man_t * pAig, Nwk_Man_t * pNtk, - int nRegInit, int nLutInit, int nLevInit, int Time ) -{ - printf( "FF =%7d (%5.1f%%) ", Ntl_ManStatsRegs(p), nRegInit ? (100.0*(nRegInit-Ntl_ManStatsRegs(p))/nRegInit) : 0.0 ); - if ( pNtk == NULL ) - printf( "Mapping is not available. " ); - else - { - printf( "Lut =%7d (%5.1f%%) ", Ntl_ManStatsLuts(p), nLutInit ? (100.0*(nLutInit-Ntl_ManStatsLuts(p))/nLutInit) : 0.0 ); - printf( "Lev =%4d (%5.1f%%) ", Nwk_ManStatsLevs(pNtk), nLevInit ? (100.0*(nLevInit-Nwk_ManStatsLevs(pNtk))/nLevInit) : 0.0 ); - } - ABC_PRT( "Time", clock() - Time ); -} - - -/**Function************************************************************* - - Synopsis [Deallocates the netlist manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Tim_Man_t * Ntl_ManReadTimeMan( Ntl_Man_t * p ) -{ - return p->pManTime; -} - -/**Function************************************************************* - - Synopsis [Saves the model type.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManSaveBoxType( Ntl_Obj_t * pObj ) -{ - Ntl_Mod_t * pModel = pObj->pImplem; - int Number = 0; - assert( Ntl_ObjIsBox(pObj) ); - Number |= (pModel->attrWhite << 0); - Number |= (pModel->attrBox << 1); - Number |= (pModel->attrComb << 2); - Number |= (pModel->attrKeep << 3); - Number |= (pModel->attrNoMerge << 4); - pModel->pMan->BoxTypes[Number]++; -} - -/**Function************************************************************* - - Synopsis [Saves the model type.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManPrintTypes( Ntl_Man_t * p ) -{ - Vec_Ptr_t * vFlops; - Ntl_Net_t * pNet; - Ntl_Mod_t * pModel; - Ntl_Obj_t * pObj; - int i; - pModel = Ntl_ManRootModel( p ); - if ( Ntl_ModelBoxNum(pModel) == 0 ) - return; - printf( "BOX STATISTICS:\n" ); - Ntl_ModelForEachBox( pModel, pObj, i ) - Ntl_ManSaveBoxType( pObj ); - for ( i = 0; i < 32; i++ ) - { - if ( !p->BoxTypes[i] ) - continue; - printf( "Type %2d Num = %7d :", i, p->BoxTypes[i] ); - printf( " %s", ((i & 1) > 0)? "white ": "black " ); - printf( " %s", ((i & 2) > 0)? "box ": "logic " ); - printf( " %s", ((i & 4) > 0)? "comb ": "seq " ); - printf( " %s", ((i & 8) > 0)? "keep ": "sweep " ); - printf( " %s", ((i & 16) > 0)? "no_merge": "merge " ); - printf( "\n" ); - } - printf( "MODEL STATISTICS:\n" ); - Ntl_ManForEachModel( p, pModel, i ) - if ( i ) printf( "Model %2d : Name = %10s Used = %6d.\n", i, pModel->pName, pModel->nUsed ); - for ( i = 0; i < 32; i++ ) - p->BoxTypes[i] = 0; - pModel = Ntl_ManRootModel( p ); - if ( pModel->vClockFlops ) - { - printf( "CLOCK STATISTICS:\n" ); - Vec_VecForEachLevel( pModel->vClockFlops, vFlops, i ) - { - pNet = (Ntl_Net_t *)Vec_PtrEntry( pModel->vClocks, i ); - printf( "Clock %2d : Name = %30s Flops = %6d.\n", i+1, pNet->pName, Vec_PtrSize(vFlops) ); - } - } - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManCompareClockClasses( Vec_Ptr_t ** pp1, Vec_Ptr_t ** pp2 ) -{ - int Diff = Vec_PtrSize(*pp1) - Vec_PtrSize(*pp2); - if ( Diff > 0 ) - return -1; - if ( Diff < 0 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Saves the model type.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManPrintClocks( Ntl_Man_t * p ) -{ - Vec_Ptr_t * vFlops; - Ntl_Net_t * pNet; - Ntl_Mod_t * pModel; - int i; - pModel = Ntl_ManRootModel( p ); - if ( Ntl_ModelBoxNum(pModel) == 0 ) - return; - if ( pModel->vClockFlops ) - { - printf( "CLOCK STATISTICS:\n" ); - Vec_VecForEachLevel( pModel->vClockFlops, vFlops, i ) - { - pNet = (Ntl_Net_t *)Vec_PtrEntry( pModel->vClocks, i ); - printf( "Clock %2d : Name = %30s Flops = %6d.\n", i+1, pNet->pName, Vec_PtrSize(vFlops) ); - if ( i == 10 ) - { - printf( "Skipping... (the total is %d)\n", Vec_VecSize(pModel->vClockFlops) ); - break; - } - } - } -// printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Saves the model type.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManPrintResets( Ntl_Man_t * p ) -{ - Vec_Ptr_t * vFlops; - Ntl_Net_t * pNet; - Ntl_Mod_t * pModel; - int i; - pModel = Ntl_ManRootModel( p ); - if ( Ntl_ModelBoxNum(pModel) == 0 ) - return; - if ( pModel->vResetFlops ) - { - printf( "RESET STATISTICS:\n" ); - Vec_VecForEachLevel( pModel->vResetFlops, vFlops, i ) - { - pNet = (Ntl_Net_t *)Vec_PtrEntry( pModel->vResets, i ); - printf( "Reset %2d : Name = %30s Flops = %6d.\n", i+1, pNet->pName, Vec_PtrSize(vFlops) ); - if ( i == 10 ) - { - printf( "Skipping... (the total is %d)\n", Vec_VecSize(pModel->vResetFlops) ); - break; - } - } - } -// 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 = ABC_ALLOC( Ntl_Mod_t, 1 ); - memset( p, 0, sizeof(Ntl_Mod_t) ); - p->attrBox = 1; - p->attrComb = 1; - p->attrWhite = 1; - p->attrKeep = 0; - p->attrNoMerge = 0; - p->pMan = pMan; - p->pName = Ntl_ManStoreName( p->pMan, pName ); - p->vObjs = Vec_PtrAlloc( 100 ); - p->vPis = Vec_PtrAlloc( 10 ); - p->vPos = Vec_PtrAlloc( 10 ); - p->vNets = Vec_PtrAlloc( 100 ); - // start the table - p->nTableSize = Aig_PrimeCudd( 100 ); - p->pTable = ABC_ALLOC( Ntl_Net_t *, p->nTableSize ); - memset( p->pTable, 0, sizeof(Ntl_Net_t *) * p->nTableSize ); - // add model to the table - if ( !Ntl_ManAddModel( pMan, p ) ) - { - Ntl_ModelFree( p ); - return NULL; - } - return p; -} - -/**Function************************************************************* - - Synopsis [Duplicates the model without nodes but with CI/CO nets.] - - Description [The CI/CO nets of the old model should be marked before - calling this procedure.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Mod_t * Ntl_ModelStartFrom( Ntl_Man_t * pManNew, Ntl_Mod_t * pModelOld ) -{ - Ntl_Mod_t * pModelNew; - Ntl_Net_t * pNet; - Ntl_Obj_t * pObj; - int i, k; - pModelNew = Ntl_ModelAlloc( pManNew, pModelOld->pName ); - pModelNew->attrWhite = pModelOld->attrWhite; - pModelNew->attrBox = pModelOld->attrBox; - pModelNew->attrComb = pModelOld->attrComb; - pModelNew->attrKeep = pModelOld->attrKeep; - pModelNew->attrNoMerge = pModelOld->attrNoMerge; - Ntl_ModelForEachObj( pModelOld, pObj, i ) - { - if ( Ntl_ObjIsNode(pObj) ) - pObj->pCopy = NULL; - else - pObj->pCopy = Ntl_ModelDupObj( pModelNew, pObj ); - } - Ntl_ModelForEachNet( pModelOld, pNet, i ) - { - if ( pNet->pDriver == NULL ) - pNet->pCopy = Ntl_ModelFindOrCreateNet( pModelNew, pNet->pName ); - else if ( pNet->fMark ) - { - pNet->pCopy = Ntl_ModelFindOrCreateNet( pModelNew, pNet->pName ); - ((Ntl_Net_t *)pNet->pCopy)->pDriver = (Ntl_Obj_t *)pNet->pDriver->pCopy; - } - else - pNet->pCopy = NULL; - if ( pNet->pCopy ) - ((Ntl_Net_t *)pNet->pCopy)->fFixed = pNet->fFixed; - } - Ntl_ModelForEachObj( pModelOld, pObj, i ) - { - if ( Ntl_ObjIsNode(pObj) ) - continue; - Ntl_ObjForEachFanin( pObj, pNet, k ) - if ( pNet->pCopy != NULL ) - Ntl_ObjSetFanin( (Ntl_Obj_t *)pObj->pCopy, (Ntl_Net_t *)pNet->pCopy, k ); - Ntl_ObjForEachFanout( pObj, pNet, k ) - if ( pNet->pCopy != NULL ) - Ntl_ObjSetFanout( (Ntl_Obj_t *)pObj->pCopy, (Ntl_Net_t *)pNet->pCopy, k ); - if ( Ntl_ObjIsLatch(pObj) ) - { - ((Ntl_Obj_t *)pObj->pCopy)->LatchId = pObj->LatchId; - ((Ntl_Obj_t *)pObj->pCopy)->pClock = (Ntl_Net_t *)pObj->pClock->pCopy; - } - } - pModelNew->vDelays = pModelOld->vDelays? Vec_IntDup( pModelOld->vDelays ) : NULL; - pModelNew->vTimeInputs = pModelOld->vTimeInputs? Vec_IntDup( pModelOld->vTimeInputs ) : NULL; - pModelNew->vTimeOutputs = pModelOld->vTimeOutputs? Vec_IntDup( pModelOld->vTimeOutputs ) : NULL; - return pModelNew; -} - -/**Function************************************************************* - - Synopsis [Duplicates the model.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Mod_t * Ntl_ModelDup( Ntl_Man_t * pManNew, Ntl_Mod_t * pModelOld ) -{ - Ntl_Mod_t * pModelNew; - Ntl_Net_t * pNet; - Ntl_Obj_t * pObj; - int i, k; - pModelNew = Ntl_ModelAlloc( pManNew, pModelOld->pName ); - pModelNew->attrWhite = pModelOld->attrWhite; - pModelNew->attrBox = pModelOld->attrBox; - pModelNew->attrComb = pModelOld->attrComb; - pModelNew->attrKeep = pModelOld->attrKeep; - pModelNew->attrNoMerge = pModelOld->attrNoMerge; - Ntl_ModelForEachObj( pModelOld, pObj, i ) - pObj->pCopy = Ntl_ModelDupObj( pModelNew, pObj ); - Ntl_ModelForEachNet( pModelOld, pNet, i ) - { - pNet->pCopy = Ntl_ModelFindOrCreateNet( pModelNew, pNet->pName ); - ((Ntl_Net_t *)pNet->pCopy)->fFixed = pNet->fFixed; - if ( pNet->pDriver == NULL ) - { - assert( !pModelOld->attrWhite ); - continue; - } - ((Ntl_Net_t *)pNet->pCopy)->pDriver = (Ntl_Obj_t *)pNet->pDriver->pCopy; - assert( pNet->pDriver->pCopy != NULL ); - } - Ntl_ModelForEachObj( pModelOld, pObj, i ) - { - Ntl_ObjForEachFanin( pObj, pNet, k ) - Ntl_ObjSetFanin( (Ntl_Obj_t *)pObj->pCopy, (Ntl_Net_t *)pNet->pCopy, k ); - Ntl_ObjForEachFanout( pObj, pNet, k ) - Ntl_ObjSetFanout( (Ntl_Obj_t *)pObj->pCopy, (Ntl_Net_t *)pNet->pCopy, k ); - if ( Ntl_ObjIsLatch(pObj) ) - { - ((Ntl_Obj_t *)pObj->pCopy)->LatchId = pObj->LatchId; - ((Ntl_Obj_t *)pObj->pCopy)->pClock = pObj->pClock? (Ntl_Net_t *)pObj->pClock->pCopy : NULL; - } - if ( Ntl_ObjIsNode(pObj) ) - ((Ntl_Obj_t *)pObj->pCopy)->pSop = Ntl_ManStoreSop( pManNew->pMemSops, pObj->pSop ); - } - pModelNew->vDelays = pModelOld->vDelays? Vec_IntDup( pModelOld->vDelays ) : NULL; - pModelNew->vTimeInputs = pModelOld->vTimeInputs? Vec_IntDup( pModelOld->vTimeInputs ) : NULL; - pModelNew->vTimeOutputs = pModelOld->vTimeOutputs? Vec_IntDup( pModelOld->vTimeOutputs ) : NULL; - return pModelNew; -} - - -// *r x\large\club_u2.blif.bz2; *ps; *clplut; *ps -// *r x\large\amazon_core.blif.bz2; *ps; *clplut; *ps - - -/**Function************************************************************* - - Synopsis [Duplicates the model.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Mod_t * Ntl_ModelDupCollapseLuts( Ntl_Man_t * pManNew, Ntl_Mod_t * pModelOld ) -{ - Ntl_Mod_t * pModelNew, * pModelBox; - Ntl_Net_t * pNet; - Ntl_Obj_t * pObj, * pObjBox; - char * pNameBuf = ABC_ALLOC( char, 10000 ); - int i, k, m, Counter = 0; - pModelNew = Ntl_ModelAlloc( pManNew, pModelOld->pName ); - pModelNew->attrWhite = pModelOld->attrWhite; - pModelNew->attrBox = pModelOld->attrBox; - pModelNew->attrComb = pModelOld->attrComb; - pModelNew->attrKeep = pModelOld->attrKeep; - pModelNew->attrNoMerge = pModelOld->attrNoMerge; - Ntl_ModelForEachObj( pModelOld, pObj, i ) - if ( Ntl_ObjIsLutBox(pObj) ) // skip collapsible LUT boxes - pObj->pCopy = NULL; - else - pObj->pCopy = Ntl_ModelDupObj( pModelNew, pObj ); - Ntl_ModelForEachNet( pModelOld, pNet, i ) - { - pNet->pCopy = Ntl_ModelFindOrCreateNet( pModelNew, pNet->pName ); - ((Ntl_Net_t *)pNet->pCopy)->fFixed = pNet->fFixed; - if ( pNet->pDriver == NULL ) - { - assert( !pModelOld->attrWhite ); - continue; - } - if ( Ntl_ObjIsLutBox(pNet->pDriver) ) - continue; - ((Ntl_Net_t *)pNet->pCopy)->pDriver = (Ntl_Obj_t *)pNet->pDriver->pCopy; - assert( pNet->pDriver->pCopy != NULL ); - } - Ntl_ModelForEachObj( pModelOld, pObj, i ) - { - if ( Ntl_ObjIsLutBox(pObj) ) // collapse LUT boxes - { - pModelBox = pObj->pImplem; - assert( pModelBox->attrComb ); - assert( Ntl_ObjFaninNum(pObj) == Ntl_ModelPiNum(pModelBox) ); - assert( Ntl_ObjFanoutNum(pObj) == Ntl_ModelPoNum(pModelBox) ); - Ntl_ModelClearNets( pModelBox ); - // attach PI/PO nets - Ntl_ModelForEachPi( pModelBox, pObjBox, k ) - Ntl_ObjFanout0(pObjBox)->pCopy = Ntl_ObjFanin(pObj, k)->pCopy; - Ntl_ModelForEachPo( pModelBox, pObjBox, k ) - Ntl_ObjFanin0(pObjBox)->pCopy = Ntl_ObjFanout(pObj, k)->pCopy; - // duplicate internal nodes - Ntl_ModelForEachNode( pModelBox, pObjBox, k ) - pObjBox->pCopy = Ntl_ModelDupObj( pModelNew, pObjBox ); - // duplicate and connect nets - Ntl_ModelForEachNet( pModelBox, pNet, k ) - { - if ( pNet->pCopy != NULL ) - continue; - sprintf( pNameBuf, "box%d_%s", i, pNet->pName ); - pNet->pCopy = Ntl_ModelFindOrCreateNet( pModelNew, pNameBuf ); // change name!!! - ((Ntl_Net_t *)pNet->pCopy)->pDriver = (Ntl_Obj_t *)pNet->pDriver->pCopy; - } - // connect nodes - Ntl_ModelForEachNode( pModelBox, pObjBox, k ) - { - Ntl_ObjForEachFanin( pObjBox, pNet, m ) - Ntl_ObjSetFanin( (Ntl_Obj_t *)pObjBox->pCopy, (Ntl_Net_t *)pNet->pCopy, m ); - Ntl_ObjForEachFanout( pObjBox, pNet, m ) - Ntl_ObjSetFanout( (Ntl_Obj_t *)pObjBox->pCopy, (Ntl_Net_t *)pNet->pCopy, m ); - ((Ntl_Obj_t *)pObjBox->pCopy)->pSop = Ntl_ManStoreSop( pManNew->pMemSops, pObjBox->pSop ); - } - // connect the PO nets - Ntl_ModelForEachPo( pModelBox, pObjBox, k ) - ((Ntl_Net_t *)Ntl_ObjFanin0(pObjBox)->pCopy)->pDriver = (Ntl_Obj_t *)Ntl_ObjFanin0(pObjBox)->pDriver->pCopy; - assert( pObj->pCopy == NULL ); - Counter++; - } - else - { - Ntl_ObjForEachFanin( pObj, pNet, k ) - Ntl_ObjSetFanin( (Ntl_Obj_t *)pObj->pCopy, (Ntl_Net_t *)pNet->pCopy, k ); - Ntl_ObjForEachFanout( pObj, pNet, k ) - Ntl_ObjSetFanout( (Ntl_Obj_t *)pObj->pCopy, (Ntl_Net_t *)pNet->pCopy, k ); - if ( Ntl_ObjIsLatch(pObj) ) - { - ((Ntl_Obj_t *)pObj->pCopy)->LatchId = pObj->LatchId; - ((Ntl_Obj_t *)pObj->pCopy)->pClock = pObj->pClock? (Ntl_Net_t *)pObj->pClock->pCopy : NULL; - } - if ( Ntl_ObjIsNode(pObj) ) - ((Ntl_Obj_t *)pObj->pCopy)->pSop = Ntl_ManStoreSop( pManNew->pMemSops, pObj->pSop ); - } - } - pModelNew->vDelays = pModelOld->vDelays? Vec_IntDup( pModelOld->vDelays ) : NULL; - pModelNew->vTimeInputs = pModelOld->vTimeInputs? Vec_IntDup( pModelOld->vTimeInputs ) : NULL; - pModelNew->vTimeOutputs = pModelOld->vTimeOutputs? Vec_IntDup( pModelOld->vTimeOutputs ) : NULL; - ABC_FREE( pNameBuf ); - if ( Counter ) - printf( "Collapsed %d LUT boxes.\n", Counter ); - return pModelNew; -} - -/**Function************************************************************* - - Synopsis [Deallocates the model.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ModelFree( Ntl_Mod_t * p ) -{ - assert( Ntl_ModelCheckNetsAreNotMarked(p) ); - if ( p->vTimeOutputs ) Vec_IntFree( p->vTimeOutputs ); - if ( p->vTimeInputs ) Vec_IntFree( p->vTimeInputs ); - if ( p->vDelays ) Vec_IntFree( p->vDelays ); - if ( p->vClocks ) Vec_PtrFree( p->vClocks ); - if ( p->vClockFlops ) Vec_VecFree( p->vClockFlops ); - if ( p->vResets ) Vec_PtrFree( p->vResets ); - if ( p->vResetFlops ) Vec_VecFree( p->vResetFlops ); - Vec_PtrFree( p->vNets ); - Vec_PtrFree( p->vObjs ); - Vec_PtrFree( p->vPis ); - Vec_PtrFree( p->vPos ); - ABC_FREE( p->pTable ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Create model equal to the latch with the given init value.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Mod_t * Ntl_ManCreateLatchModel( Ntl_Man_t * pMan, int Init ) -{ - char Name[100]; - Ntl_Mod_t * pModel; - Ntl_Obj_t * pObj; - Ntl_Net_t * pNetLi, * pNetLo; - // create model - sprintf( Name, "%s%d", "latch", Init ); - pModel = Ntl_ModelAlloc( pMan, Name ); - pModel->attrWhite = 1; - pModel->attrBox = 1; - pModel->attrComb = 0; - pModel->attrKeep = 0; - pModel->attrNoMerge = 0; - // create primary input - pObj = Ntl_ModelCreatePi( pModel ); - pNetLi = Ntl_ModelFindOrCreateNet( pModel, "li" ); - Ntl_ModelSetNetDriver( pObj, pNetLi ); - // create latch - pObj = Ntl_ModelCreateLatch( pModel ); - pObj->LatchId.regInit = Init; - pObj->pFanio[0] = pNetLi; - // create primary output - pNetLo = Ntl_ModelFindOrCreateNet( pModel, "lo" ); - Ntl_ModelSetNetDriver( pObj, pNetLo ); - pObj = Ntl_ModelCreatePo( pModel, pNetLo ); - // set timing information - pModel->vTimeInputs = Vec_IntAlloc( 2 ); - Vec_IntPush( pModel->vTimeInputs, -1 ); - Vec_IntPush( pModel->vTimeInputs, Aig_Float2Int(0.0) ); - pModel->vTimeOutputs = Vec_IntAlloc( 2 ); - Vec_IntPush( pModel->vTimeOutputs, -1 ); - Vec_IntPush( pModel->vTimeOutputs, Aig_Float2Int(0.0) ); - return pModel; -} - - -/**Function************************************************************* - - Synopsis [Count constant nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ModelCountLut0( Ntl_Mod_t * p ) -{ - Ntl_Obj_t * pNode; - int i, Counter = 0; - Ntl_ModelForEachNode( p, pNode, i ) - if ( Ntl_ObjFaninNum(pNode) == 0 ) - Counter++; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Count single-output nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ModelCountLut1( Ntl_Mod_t * p ) -{ - Ntl_Obj_t * pNode; - int i, Counter = 0; - Ntl_ModelForEachNode( p, pNode, i ) - if ( Ntl_ObjFaninNum(pNode) == 1 ) - Counter++; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Count buffers] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ModelCountBuf( Ntl_Mod_t * p ) -{ - Ntl_Obj_t * pNode; - int i, Counter = 0; - Ntl_ModelForEachNode( p, pNode, i ) - if ( Ntl_ObjFaninNum(pNode) == 1 && pNode->pSop[0] == '1' ) - Counter++; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Count inverters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ModelCountInv( Ntl_Mod_t * p ) -{ - Ntl_Obj_t * pNode; - int i, Counter = 0; - Ntl_ModelForEachNode( p, pNode, i ) - if ( Ntl_ObjFaninNum(pNode) == 1 && pNode->pSop[0] == '0' ) - Counter++; - return Counter; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ntl/ntlMap.c b/src/aig/ntl/ntlMap.c deleted file mode 100644 index 0ce8549d..00000000 --- a/src/aig/ntl/ntlMap.c +++ /dev/null @@ -1,346 +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" -#include "if.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 **)ABC_ALLOC( char, (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 = (Ntl_Lut_t *)Vec_PtrEntry( vMapping, k++ ); - pLut->Id = 0; - pLut->nFanins = 0; - memset( pLut->pTruth, 0xFF, nBytes ); - } - Aig_ManForEachNode( p, pObj, i ) - { - pLut = (Ntl_Lut_t *)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; -} - - -/**Function************************************************************* - - Synopsis [Load the network into FPGA manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_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->Epsilon = (float)0.005; - pPars->fPreprocess = 1; - pPars->fArea = 0; - pPars->fFancy = 0; - pPars->fExpRed = 0; - pPars->fLatchPaths = 0; - pPars->fEdge = 1; - pPars->fCutMin = 0; - 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 * Ntl_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; - if ( pIfMan->nLevelMax < (int)pNode->Level ) - pIfMan->nLevelMax = (int)pNode->Level; - } - else if ( Aig_ObjIsPo(pNode) ) - pNode->pData = If_ManCreateCo( pIfMan, If_NotCond( (If_Obj_t *)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 ); -// } - { - If_Obj_t * pIfObj = (If_Obj_t *)pNode->pData; - assert( !If_IsComplement(pIfObj) ); - assert( pIfObj->Id == pNode->Id ); - } - } - return pIfMan; -} - -/**Function************************************************************* - - Synopsis [Creates the mapped network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Ntl_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 = (If_Obj_t *)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 = (Ntl_Lut_t *)Vec_PtrEntry( vMapping, nLuts++ ); - pLut->Id = 0; - pLut->nFanins = 0; - memset( pLut->pTruth, 0xFF, 4 * nWords ); - } - Vec_PtrForEachEntry( If_Obj_t *, vIfMap, pNode, i ) - { - // get the best cut - pCutBest = If_ObjCutBest(pNode); - nLeaves = If_CutLeaveNum( pCutBest ); - ppLeaves = If_CutLeaves( pCutBest ); - // fill the LUT - pLut = (Ntl_Lut_t *)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 - Ntl_ManSetIfParsDefault( pPars ); - // set the arrival times - pPars->pTimesArr = ABC_ALLOC( float, Aig_ManPiNum(p) ); - memset( pPars->pTimesArr, 0, sizeof(float) * Aig_ManPiNum(p) ); - // translate into the mapper - pIfMan = Ntl_ManToIf( p, pPars ); - if ( pIfMan == NULL ) - return NULL; - pIfMan->pManTim = Tim_ManDup( pMan->pManTime, 0 ); - if ( !If_ManPerformMapping( pIfMan ) ) - { - If_ManStop( pIfMan ); - return NULL; - } - // transform the result of mapping into the new network - vMapping = Ntl_ManFromIf( p, pIfMan ); - If_ManStop( pIfMan ); - if ( vMapping == NULL ) - return NULL; - return vMapping; -} - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ntl/ntlNames.c b/src/aig/ntl/ntlNames.c deleted file mode 100644 index fa91711d..00000000 --- a/src/aig/ntl/ntlNames.c +++ /dev/null @@ -1,471 +0,0 @@ -/**CFile**************************************************************** - - FileName [ntlNames.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Netlist representation.] - - Synopsis [Data-structure for storing hiNamrchical object names.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ntlNames.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ntl.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// name object -typedef struct Ntl_ObjNam_t_ Ntl_ObjNam_t; -struct Ntl_ObjNam_t_ -{ - int iPrev; // prefix of this name - int iNext; // the next name in the hash table - char pName[0]; // name characters -}; - -// name manager -typedef struct Ntl_ManNam_t_ Ntl_ManNam_t; -struct Ntl_ManNam_t_ -{ - // info storage for names - char * pStore; // storage for name objects - int nStore; // the size of allocated storage - int iHandle; // the current free handle - int nHandles; // the number of handles - int nRefs; // reference counter for the manager - // hash table for names - int nBins; - unsigned * pBins; - // temporaries - Vec_Str_t * vName; // storage for returned name -}; - -static inline Ntl_ObjNam_t * Ntl_ManNamObj( Ntl_ManNam_t * p, int h ) { assert( !(h & 3) ); return (Ntl_ObjNam_t *)(p->pStore + h); } -static inline int Ntl_ManNamObjHandle( Ntl_ManNam_t * p, Ntl_ObjNam_t * pObj ) { return ((char *)pObj) - p->pStore; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_ManNam_t * Ntl_ManNamStart() -{ - Ntl_ManNam_t * p; - p = ABC_CALLOC( Ntl_ManNam_t, 1 ); - p->nStore = (1 << 20); - p->pStore = ABC_ALLOC( char, p->nStore ); - p->iHandle = 4; - p->nBins = Aig_PrimeCudd( 500000 ); - p->pBins = ABC_CALLOC( unsigned, p->nBins ); - p->vName = Vec_StrAlloc( 1000 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Deletes manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManNamStop( Ntl_ManNam_t * p ) -{ - Vec_StrFree( p->vName ); - ABC_FREE( p->pStore ); - ABC_FREE( p->pBins ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Deletes manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManNamReportMemUsage( Ntl_ManNam_t * p ) -{ - return sizeof(Ntl_ManNam_t) + p->nStore + sizeof(int) * p->nBins + sizeof(int) * Vec_StrSize(p->vName); -} - -/**Function************************************************************* - - Synopsis [References the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManNamRef( Ntl_ManNam_t * p ) -{ - p->nRefs++; -} - -/**Function************************************************************* - - Synopsis [Dereferences the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManNamDeref( Ntl_ManNam_t * p ) -{ - if ( --p->nRefs == 0 ) - Ntl_ManNamStop( p ); -} - -/**Function************************************************************* - - Synopsis [Returns object with the given handle.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -/**Function************************************************************* - - Synopsis [Computes hash value of the node using its simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManNamStrHash( char * pStr, int Length, 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 < Length; i++ ) - if ( i & 1 ) - uHash *= pStr[i] * s_FPrimes[i & 0x7F]; - else - uHash ^= pStr[i] * s_FPrimes[i & 0x7F]; - return uHash % nTableSize; -} - - -/**Function************************************************************* - - Synopsis [Compares two strings to be equal.] - - Description [Returns 1 if the strings match.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManNamStrCompare_rec( Ntl_ManNam_t * p, char * pStr, int Length, Ntl_ObjNam_t * pThis ) -{ - Ntl_ObjNam_t * pNext = (pThis->iPrev)? Ntl_ManNamObj(p, pThis->iPrev) : NULL; - int LengthNew = strlen(pThis->pName); - if ( !strncmp( pThis->pName, pStr + Length - LengthNew, LengthNew ) ) - return 0; - if ( pNext == NULL ) - return 1; - return Ntl_ManNamStrCompare_rec( p, pStr, Length - LengthNew, pNext ); -} - - -/**Function************************************************************* - - Synopsis [Returns the place of this state in the table or NULL if it exists.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned * Ntl_ManNamStrHashFind( Ntl_ManNam_t * p, char * pStr, int Length, int * pHandle ) -{ - Ntl_ObjNam_t * pThis; - unsigned * pPlace = p->pBins + Ntl_ManNamStrHash( pStr, Length, p->nBins ); - for ( pThis = (*pPlace)? Ntl_ManNamObj(p, *pPlace) : NULL; pThis; - pPlace = (unsigned *)&pThis->iNext, pThis = (*pPlace)? Ntl_ManNamObj(p, *pPlace) : NULL ) - if ( !Ntl_ManNamStrCompare_rec( p, pStr, Length, pThis ) ) - { - *pHandle = Ntl_ManNamObjHandle( p, pThis ); - return NULL; - } - *pHandle = -1; - return pPlace; -} - -/**Function************************************************************* - - Synopsis [Resizes the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManNamStrHashResize( Ntl_ManNam_t * p ) -{ - Ntl_ObjNam_t * pThis; - unsigned * pBinsOld, * piPlace; - int nBinsOld, iNext, iHandle, Counter, i; - assert( p->pBins != NULL ); - // replace the table - pBinsOld = p->pBins; - nBinsOld = p->nBins; - p->nBins = Aig_PrimeCudd( 3 * p->nBins ); - p->pBins = ABC_CALLOC( unsigned, p->nBins ); - // rehash the entries from the old table - Counter = 0; - for ( i = 0; i < nBinsOld; i++ ) - for ( pThis = (pBinsOld[i]? Ntl_ManNamObj(p, pBinsOld[i]) : NULL), - iNext = (pThis? pThis->iNext : 0); - pThis; pThis = (iNext? Ntl_ManNamObj(p, iNext) : NULL), - iNext = (pThis? pThis->iNext : 0) ) - { - pThis->iNext = 0; - piPlace = Ntl_ManNamStrHashFind( p, pThis->pName, strlen(pThis->pName), &iHandle ); - assert( *piPlace == 0 ); // should not be there - *piPlace = Ntl_ManNamObjHandle( p, pThis ); - Counter++; - } - assert( Counter == p->nHandles ); - ABC_FREE( pBinsOld ); -} - -/**Function************************************************************* - - Synopsis [Returns the handle of a new object to represent the name.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManNamStrGrow_rec( Ntl_ManNam_t * p, char * pStr, int Length, unsigned * piPlace ) -{ - Ntl_ObjNam_t * pThis; - char * pStrNew; - int Separ, LengthNew; - int iHandle; - assert( Length > 0 ); - // find the separator symbol - for ( Separ = Length - 2; Separ >= 0 && pStr[Separ] != '/'; Separ-- ); - pStrNew = (Separ == -1) ? pStr : pStr + Separ + 1; - LengthNew = Length - (pStrNew - pStr); - // realloc memory if needed - if ( p->iHandle + (int)sizeof(Ntl_ObjNam_t) + LengthNew+5 > p->nStore ) - { - int OffSet; - if ( (char *)piPlace > p->pStore && (char *)piPlace < p->pStore + p->nStore ) - OffSet = (char *)piPlace - p->pStore; - else - OffSet = -1; - p->nStore *= 2; - p->pStore = ABC_REALLOC( char, p->pStore, p->nStore ); - if ( OffSet >= 0 ) - piPlace = (unsigned *)(p->pStore + OffSet); - } - // new entry is created - p->nHandles++; - *piPlace = p->iHandle; - pThis = Ntl_ManNamObj( p, p->iHandle ); - p->iHandle += sizeof(Ntl_ObjNam_t) + 4 * Aig_BitWordNum( 8*(LengthNew+1) ); - pThis->iNext = 0; - pThis->iPrev = 0; - strncpy( pThis->pName, pStrNew, LengthNew ); - pThis->pName[LengthNew] = 0; - // expand hash table if needed -// if ( p->nHandles > 2 * p->nBins ) -// Ntl_ManNamStrHashResize( p ); - // create previous object if needed - if ( Separ >= 0 ) - { - assert( pStr[Separ] == '/' ); - Separ++; - piPlace = Ntl_ManNamStrHashFind( p, pStr, Separ, &iHandle ); - if ( piPlace != NULL ) - iHandle = Ntl_ManNamStrGrow_rec( p, pStr, Separ, piPlace ); - pThis->iPrev = iHandle; - } - return Ntl_ManNamObjHandle( p, pThis ); -} - -/**Function************************************************************* - - Synopsis [Finds or adds the given name to storage.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManNamStrFind( Ntl_ManNam_t * p, char * pStr ) -{ - int iHandle; - Ntl_ManNamStrHashFind( p, pStr, strlen(pStr), &iHandle ); - return iHandle; -} - -/**Function************************************************************* - - Synopsis [Finds or adds the given name to storage.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Ntl_ManNamStrFindOrAdd( Ntl_ManNam_t * p, char * pStr ) -{ - unsigned * piPlace; - int iHandle, Length = strlen(pStr); - assert( Length > 0 ); - piPlace = Ntl_ManNamStrHashFind( p, pStr, Length, &iHandle ); - if ( piPlace == NULL ) - return iHandle; - assert( *piPlace == 0 ); - return Ntl_ManNamStrGrow_rec( p, pStr, Length, piPlace ); -} - -/**Function************************************************************* - - Synopsis [Returns name from handle.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Ntl_ManNamStr( Ntl_ManNam_t * p, int h ) -{ - Ntl_ObjNam_t * pObj; - int k; - assert( h && h < p->iHandle ); - Vec_StrClear( p->vName ); - for ( pObj = Ntl_ManNamObj( p, h ); pObj; pObj = pObj->iPrev ? Ntl_ManNamObj(p, pObj->iPrev) : NULL ) - for ( k = strlen(pObj->pName) - 1; k >= 0; k-- ) - Vec_StrPush( p->vName, pObj->pName[k] ); - Vec_StrReverseOrder( p->vName ); - Vec_StrPush( p->vName, 0 ); - return Vec_StrArray( p->vName ); -} - -/**Function************************************************************* - - Synopsis [Testing procedure for the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManNamTest( Ntl_Man_t * pNtl ) -{ - Ntl_ManNam_t * p; - Ntl_Mod_t * pRoot; - Ntl_Net_t * pNet; - int Memory; - int i, iHandle; - int clk = clock(); - - p = Ntl_ManNamStart(); -printf( "a" ); - Memory = 0; - pRoot = Ntl_ManRootModel( pNtl ); - Ntl_ModelForEachNet( pRoot, pNet, i ) - { - Memory += strlen(pNet->pName) + 1; - iHandle = Ntl_ManNamStrFindOrAdd( p, pNet->pName ); - -// printf( "Before = %s\n", pNet->pName ); -// printf( "After = %s\n", Ntl_ManNamStr(p, iHandle) ); - } - printf( "Net =%7d. Handle =%8d. ", Vec_PtrSize(pRoot->vNets), p->nHandles ); - printf( "Mem old = %7.2f Mb. Mem new = %7.2f Mb.\n", - 1.0 * Memory / (1 << 20), 1.0 * Ntl_ManNamReportMemUsage(p) / (1 << 20) ); - ABC_PRT( "Time", clock() - clk ); -printf( "b" ); - - Ntl_ManNamStop( p ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ntl/ntlObj.c b/src/aig/ntl/ntlObj.c deleted file mode 100644 index 209974aa..00000000 --- a/src/aig/ntl/ntlObj.c +++ /dev/null @@ -1,319 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 = 1; - 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; - if ( nFanins == 1 ) - pModel->nObjs[NTL_OBJ_LUT1]++; - else - 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; - p->Reset = -1; - pModel->nObjs[NTL_OBJ_BOX]++; - return p; -} - -/**Function************************************************************* - - Synopsis [Create the latch.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Obj_t * Ntl_ModelDupObj( Ntl_Mod_t * pModel, Ntl_Obj_t * pOld ) -{ - Ntl_Obj_t * pNew = NULL; // Supprses "might be used uninitialized" - if ( Ntl_ObjIsPi( pOld ) ) - pNew = Ntl_ModelCreatePi( pModel ); - else if ( Ntl_ObjIsPo( pOld ) ) - pNew = Ntl_ModelCreatePo( pModel, NULL ); - else if ( Ntl_ObjIsLatch( pOld ) ) - pNew = Ntl_ModelCreateLatch( pModel ); - else if ( Ntl_ObjIsNode( pOld ) ) - pNew = Ntl_ModelCreateNode( pModel, Ntl_ObjFaninNum(pOld) ); - else if ( Ntl_ObjIsBox( pOld ) ) - pNew = Ntl_ModelCreateBox( pModel, Ntl_ObjFaninNum(pOld), Ntl_ObjFanoutNum(pOld) ); - return pNew; -} - - -/**Function************************************************************* - - Synopsis [Creates the primary input with the given name.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Obj_t * Ntl_ModelCreatePiWithName( Ntl_Mod_t * pModel, char * pName ) -{ - Ntl_Obj_t * pObj; - Ntl_Net_t * pNet; - pNet = Ntl_ModelFindOrCreateNet( pModel, pName ); - if ( pNet->pDriver ) - return NULL; - pObj = Ntl_ModelCreatePi( pModel ); - Ntl_ModelSetNetDriver( pObj, pNet ); - return pObj; -} - -/**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( Aig_MmFlex_t * pMan, const char * pSop ) -{ - char * pStore; - pStore = Aig_MmFlexEntryFetch( pMan, 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; -} - - -/**Function************************************************************* - - Synopsis [Returns the index of the fanin in the fanin list of the fanout.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManObjWhichFanout( Ntl_Obj_t * pNode, Ntl_Net_t * pFanout ) -{ - Ntl_Net_t * pObj; - int i; - Ntl_ObjForEachFanout( pNode, pObj, i ) - if ( pObj == pFanout ) - return i; - return -1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ntl/ntlReadBlif.c b/src/aig/ntl/ntlReadBlif.c deleted file mode 100644 index 88962efa..00000000 --- a/src/aig/ntl/ntlReadBlif.c +++ /dev/null @@ -1,1446 +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.1 2008/10/10 14:09:30 mjarvin Exp $] - -***********************************************************************/ - -// The code in this file is developed in collaboration with Mark Jarvin of Toronto. - -#include "ntl.h" -#include "bzlib.h" -#include "zlib.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Ntl_ReadMod_t_ Ntl_ReadMod_t; // parsing model -typedef struct Ntl_ReadMan_t_ Ntl_ReadMan_t; // parsing manager - -struct Ntl_ReadMod_t_ -{ - // file lines - char * pFirst; // .model line - char * pAttrib; // .attrib 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 * vTimeInputs; // .input_arrival/required lines - Vec_Ptr_t * vTimeOutputs; // .output_required/arrival lines - int fBlackBox; // indicates blackbox model - int fNoMerge; // indicates no-merge model - char fInArr; - char fInReq; - char fOutArr; - char fOutReq; - // the resulting network - Ntl_Mod_t * pNtk; - // the parent manager - Ntl_ReadMan_t * pMan; -}; - -struct Ntl_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 - Ntl_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 Ntl_ReadMan_t * Ntl_ReadAlloc(); -static void Ntl_ReadFree( Ntl_ReadMan_t * p ); -static Ntl_ReadMod_t * Ntl_ReadModAlloc(); -static void Ntl_ReadModFree( Ntl_ReadMod_t * p ); -static char * Ntl_ReadLoadFile( char * pFileName ); -static char * Ntl_ReadLoadFileBz2( char * pFileName ); -static char * Ntl_ReadLoadFileGz( char * pFileName ); -static void Ntl_ReadReadPreparse( Ntl_ReadMan_t * p ); -static int Ntl_ReadReadInterfaces( Ntl_ReadMan_t * p ); -static Ntl_Man_t * Ntl_ReadParse( Ntl_ReadMan_t * p ); -static int Ntl_ReadParseLineModel( Ntl_ReadMod_t * p, char * pLine ); -static int Ntl_ReadParseLineAttrib( Ntl_ReadMod_t * p, char * pLine ); -static int Ntl_ReadParseLineInputs( Ntl_ReadMod_t * p, char * pLine ); -static int Ntl_ReadParseLineOutputs( Ntl_ReadMod_t * p, char * pLine ); -static int Ntl_ReadParseLineLatch( Ntl_ReadMod_t * p, char * pLine ); -static int Ntl_ReadParseLineSubckt( Ntl_ReadMod_t * p, char * pLine ); -static int Ntl_ReadParseLineDelay( Ntl_ReadMod_t * p, char * pLine ); -static int Ntl_ReadParseLineTimes( Ntl_ReadMod_t * p, char * pLine, int fOutput ); -static int Ntl_ReadParseLineNamesBlif( Ntl_ReadMod_t * p, char * pLine ); - -static int Ntl_ReadCharIsSpace( char s ) { return s == ' ' || s == '\t' || s == '\r' || s == '\n'; } -static int Ntl_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 * Ntl_ManReadBlif( char * pFileName, int fCheck ) -{ - FILE * pFile; - Ntl_ReadMan_t * p; - Ntl_Man_t * pDesign; - if ( !Ntl_FileIsType(pFileName, ".blif", ".blif.gz", ".blif.bz2") ) - { - printf( "Wrong file format\n" ); - return NULL; - } - // check that the file is available - pFile = fopen( pFileName, "rb" ); - if ( pFile == NULL ) - { - printf( "Ntl_ManReadBlif(): The file is unavailable (absent or open).\n" ); - return 0; - } - fclose( pFile ); - - // start the file reader - p = Ntl_ReadAlloc(); - p->pFileName = pFileName; - if ( !strncmp(pFileName+strlen(pFileName)-4,".bz2",4) ) - p->pBuffer = Ntl_ReadLoadFileBz2( pFileName ); - else if ( !strncmp(pFileName+strlen(pFileName)-3,".gz",3) ) - p->pBuffer = Ntl_ReadLoadFileGz( pFileName ); - else - p->pBuffer = Ntl_ReadLoadFile( pFileName ); - if ( p->pBuffer == NULL ) - { - Ntl_ReadFree( p ); - return NULL; - } - // set the design name - p->pDesign = Ntl_ManAlloc(); - p->pDesign->pName = Ntl_ManStoreFileName( p->pDesign, pFileName ); - p->pDesign->pSpec = Ntl_ManStoreName( p->pDesign, pFileName ); - // prepare the file for parsing - Ntl_ReadReadPreparse( p ); - // parse interfaces of each network - if ( !Ntl_ReadReadInterfaces( p ) ) - { - if ( p->sError[0] ) - fprintf( stdout, "%s\n", p->sError ); - Ntl_ReadFree( p ); - return NULL; - } - // construct the network - pDesign = Ntl_ReadParse( p ); - if ( p->sError[0] ) - fprintf( stdout, "%s\n", p->sError ); - if ( pDesign == NULL ) - { - Ntl_ReadFree( p ); - return NULL; - } - p->pDesign = NULL; - Ntl_ReadFree( p ); -// pDesign should be linked to all models of the design - - // make sure that everything is okay with the network structure - if ( fCheck ) - { - if ( !Ntl_ManCheck( pDesign ) ) - { - printf( "Ntl_ReadBlif: The check has failed for design %s.\n", pDesign->pName ); - Ntl_ManFree( pDesign ); - return NULL; - } - - } - // transform the design by removing the CO drivers -// if ( (nNodes = Ntl_ManReconnectCoDrivers(pDesign)) ) -// printf( "The design was transformed by removing %d buf/inv CO drivers.\n", nNodes ); -//Ntl_ManWriteBlif( pDesign, "_temp_.blif" ); -/* - { - Aig_Man_t * p = Ntl_ManCollapseSeq( pDesign ); - Aig_ManStop( p ); - } -*/ - return pDesign; -} - -/**Function************************************************************* - - Synopsis [Allocates the BLIF parsing structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static Ntl_ReadMan_t * Ntl_ReadAlloc() -{ - Ntl_ReadMan_t * p; - p = ABC_ALLOC( Ntl_ReadMan_t, 1 ); - memset( p, 0, sizeof(Ntl_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 Ntl_ReadFree( Ntl_ReadMan_t * p ) -{ - Ntl_ReadMod_t * pMod; - int i; - if ( p->pDesign ) - Ntl_ManFree( p->pDesign ); - if ( p->pBuffer ) - ABC_FREE( p->pBuffer ); - if ( p->vLines ) - Vec_PtrFree( p->vLines ); - if ( p->vModels ) - { - Vec_PtrForEachEntry( Ntl_ReadMod_t *, p->vModels, pMod, i ) - Ntl_ReadModFree( pMod ); - Vec_PtrFree( p->vModels ); - } - Vec_PtrFree( p->vTokens ); - Vec_PtrFree( p->vTokens2 ); - Vec_StrFree( p->vFunc ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Allocates the BLIF parsing structure for one model.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static Ntl_ReadMod_t * Ntl_ReadModAlloc() -{ - Ntl_ReadMod_t * p; - p = ABC_ALLOC( Ntl_ReadMod_t, 1 ); - memset( p, 0, sizeof(Ntl_ReadMod_t) ); - p->vInputs = Vec_PtrAlloc( 8 ); - p->vOutputs = Vec_PtrAlloc( 8 ); - p->vLatches = Vec_PtrAlloc( 8 ); - p->vNames = Vec_PtrAlloc( 8 ); - p->vSubckts = Vec_PtrAlloc( 8 ); - p->vDelays = Vec_PtrAlloc( 8 ); - p->vTimeInputs = Vec_PtrAlloc( 8 ); - p->vTimeOutputs = Vec_PtrAlloc( 8 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Deallocates the BLIF parsing structure for one model.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Ntl_ReadModFree( Ntl_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->vTimeInputs ); - Vec_PtrFree( p->vTimeOutputs ); - ABC_FREE( p ); -} - - - -/**Function************************************************************* - - Synopsis [Counts the number of given chars.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Ntl_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 Ntl_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 Ntl_ReadSplitIntoTokens( Vec_Ptr_t * vTokens, char * pLine, char Stop ) -{ - char * pCur; - // clear spaces - for ( pCur = pLine; *pCur != Stop; pCur++ ) - if ( Ntl_ReadCharIsSpace(*pCur) ) - *pCur = 0; - // collect tokens - Ntl_ReadCollectTokens( vTokens, pLine, pCur ); -} - -/**Function************************************************************* - - Synopsis [Splits the line into tokens.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Ntl_ReadSplitIntoTokensAndClear( Vec_Ptr_t * vTokens, char * pLine, char Stop, char Char ) -{ - char * pCur; - // clear spaces - for ( pCur = pLine; *pCur != Stop; pCur++ ) - if ( Ntl_ReadCharIsSpace(*pCur) || *pCur == Char ) - *pCur = 0; - // collect tokens - Ntl_ReadCollectTokens( vTokens, pLine, pCur ); -} - -/**Function************************************************************* - - Synopsis [Returns the 1-based number of the line in which the token occurs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Ntl_ReadGetLine( Ntl_ReadMan_t * p, char * pToken ) -{ - char * pLine; - int i; - Vec_PtrForEachEntry( char *, 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 * Ntl_ReadLoadFile( char * pFileName ) -{ - FILE * pFile; - int nFileSize; - char * pContents; - pFile = fopen( pFileName, "rb" ); - if ( pFile == NULL ) - { - fclose( pFile ); - printf( "Ntl_ReadLoadFile(): The file is unavailable (absent or open).\n" ); - return NULL; - } - fseek( pFile, 0, SEEK_END ); - nFileSize = ftell( pFile ); - if ( nFileSize == 0 ) - { - fclose( pFile ); - printf( "Ntl_ReadLoadFile(): The file is empty.\n" ); - return NULL; - } - pContents = ABC_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 [Reads the file into a character buffer.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -typedef struct buflist { - char buf[1<<20]; - int nBuf; - struct buflist * next; -} buflist; - -static char * Ntl_ReadLoadFileBz2( char * pFileName ) -{ - FILE * pFile; - int nFileSize = 0; - char * pContents; - BZFILE * b; - int bzError; - struct buflist * pNext; - buflist * bufHead = NULL, * buf = NULL; - - pFile = fopen( pFileName, "rb" ); - if ( pFile == NULL ) - { - printf( "Ntl_ReadLoadFileBz2(): The file is unavailable (absent or open).\n" ); - return NULL; - } - b = BZ2_bzReadOpen(&bzError,pFile,0,0,NULL,0); - if (bzError != BZ_OK) { - printf( "Ntl_ReadLoadFileBz2(): BZ2_bzReadOpen() failed with error %d.\n",bzError ); - return NULL; - } - do { - if (!bufHead) - buf = bufHead = ABC_ALLOC( buflist, 1 ); - else - buf = buf->next = ABC_ALLOC( buflist, 1 ); - nFileSize += buf->nBuf = BZ2_bzRead(&bzError,b,buf->buf,1<<20); - buf->next = NULL; - } while (bzError == BZ_OK); - if (bzError == BZ_STREAM_END) { - // we're okay - char * p; - int nBytes = 0; - BZ2_bzReadClose(&bzError,b); - p = pContents = ABC_ALLOC( char, nFileSize + 10 ); - buf = bufHead; - do { - memcpy(p+nBytes,buf->buf,buf->nBuf); - nBytes += buf->nBuf; -// } while((buf = buf->next)); - pNext = buf->next; - ABC_FREE( buf ); - } while((buf = pNext)); - } else if (bzError == BZ_DATA_ERROR_MAGIC) { - // not a BZIP2 file - BZ2_bzReadClose(&bzError,b); - fseek( pFile, 0, SEEK_END ); - nFileSize = ftell( pFile ); - if ( nFileSize == 0 ) - { - printf( "Ntl_ReadLoadFileBz2(): The file is empty.\n" ); - return NULL; - } - pContents = ABC_ALLOC( char, nFileSize + 10 ); - rewind( pFile ); - fread( pContents, nFileSize, 1, pFile ); - } else { - // Some other error. - printf( "Ntl_ReadLoadFileBz2(): Unable to read the compressed BLIF.\n" ); - return NULL; - } - 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 [Reads the file into a character buffer.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static char * Ntl_ReadLoadFileGz( char * pFileName ) -{ - const int READ_BLOCK_SIZE = 100000; - FILE * pFile; - char * pContents; - int amtRead, readBlock, nFileSize = READ_BLOCK_SIZE; - pFile = (FILE *)gzopen( pFileName, "rb" ); // if pFileName doesn't end in ".gz" then this acts as a passthrough to fopen - pContents = ABC_ALLOC( char, nFileSize ); - readBlock = 0; - while ((amtRead = gzread(pFile, pContents + readBlock * READ_BLOCK_SIZE, READ_BLOCK_SIZE)) == READ_BLOCK_SIZE) { - //printf("%d: read %d bytes\n", readBlock, amtRead); - nFileSize += READ_BLOCK_SIZE; - pContents = ABC_REALLOC(char, pContents, nFileSize); - ++readBlock; - } - //printf("%d: read %d bytes\n", readBlock, amtRead); - assert( amtRead != -1 ); // indicates a zlib error - nFileSize -= (READ_BLOCK_SIZE - amtRead); - gzclose(pFile); - 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 Ntl_ReadReadPreparse( Ntl_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( char *, p->vLines, pCur, i ) - { - if ( *pCur == 0 ) - continue; - // find previous non-space character - for ( pPrev = pCur - 2; pPrev >= p->pBuffer; pPrev-- ) - if ( !Ntl_ReadCharIsSpace(*pPrev) ) - break; - // if it is the line extender, overwrite it with spaces - if ( pPrev >= p->pBuffer && *pPrev == '\\' ) - { - for ( ; *pPrev; pPrev++ ) - *pPrev = ' '; - *pPrev = ' '; - continue; - } - // skip spaces at the beginning of the line - while ( Ntl_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) || - !strncmp(pCur, "input_required", 14) ) - { - if ( !strncmp(pCur, "input_arrival", 13) ) - p->pLatest->fInArr = 1; - if ( !strncmp(pCur, "input_required", 14) ) - p->pLatest->fInReq = 1; - Vec_PtrPush( p->pLatest->vTimeInputs, pCur ); - } - else if ( !strncmp(pCur, "output_required", 15) || - !strncmp(pCur, "output_arrival", 14) ) - { - if ( !strncmp(pCur, "output_required", 15) ) - p->pLatest->fOutReq = 1; - if ( !strncmp(pCur, "output_arrival", 14) ) - p->pLatest->fOutArr = 1; - Vec_PtrPush( p->pLatest->vTimeOutputs, pCur ); - } - else if ( !strncmp(pCur, "blackbox", 8) ) - p->pLatest->fBlackBox = 1; - else if ( !strncmp(pCur, "model", 5) ) - { - p->pLatest = Ntl_ReadModAlloc(); - p->pLatest->pFirst = pCur; - p->pLatest->pMan = p; - } - else if ( !strncmp(pCur, "attrib", 6) ) - { - if ( p->pLatest->pAttrib != NULL ) - fprintf( stdout, "Line %d: Skipping second .attrib line for this model.\n", Ntl_ReadGetLine(p, pCur) ); - else - p->pLatest->pAttrib = pCur; - } - 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", Ntl_ReadGetLine(p, pCur) ); - break; - } - else if ( !strncmp(pCur, "no_merge", 8) ) - { - p->pLatest->fNoMerge = 1; - } - else - { - pCur--; - if ( pCur[strlen(pCur)-1] == '\r' ) - pCur[strlen(pCur)-1] = 0; - fprintf( stdout, "Line %d: Skipping line \"%s\".\n", Ntl_ReadGetLine(p, pCur), pCur ); - } - } -} - -/**Function************************************************************* - - Synopsis [Parses interfaces of the models.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Ntl_ReadReadInterfaces( Ntl_ReadMan_t * p ) -{ - Ntl_ReadMod_t * pMod; - char * pLine; - int i, k; - // iterate through the models - Vec_PtrForEachEntry( Ntl_ReadMod_t *, p->vModels, pMod, i ) - { - // parse the model - if ( !Ntl_ReadParseLineModel( pMod, pMod->pFirst ) ) - return 0; - // parse the model attributes - if ( pMod->pAttrib && !Ntl_ReadParseLineAttrib( pMod, pMod->pAttrib ) ) - return 0; - // parse no-merge - if ( pMod->fNoMerge ) - pMod->pNtk->attrNoMerge = 1; - // parse the inputs - Vec_PtrForEachEntry( char *, pMod->vInputs, pLine, k ) - if ( !Ntl_ReadParseLineInputs( pMod, pLine ) ) - return 0; - // parse the outputs - Vec_PtrForEachEntry( char *, pMod->vOutputs, pLine, k ) - if ( !Ntl_ReadParseLineOutputs( pMod, pLine ) ) - return 0; - // parse the delay info - Ntl_ModelSetPioNumbers( pMod->pNtk ); - Vec_PtrForEachEntry( char *, pMod->vDelays, pLine, k ) - if ( !Ntl_ReadParseLineDelay( pMod, pLine ) ) - return 0; - Vec_PtrForEachEntry( char *, pMod->vTimeInputs, pLine, k ) - if ( !Ntl_ReadParseLineTimes( pMod, pLine, 0 ) ) - return 0; - Vec_PtrForEachEntry( char *, pMod->vTimeOutputs, pLine, k ) - if ( !Ntl_ReadParseLineTimes( pMod, pLine, 1 ) ) - return 0; - // report timing line stats - if ( pMod->fInArr && pMod->fInReq ) - printf( "Model %s has both .input_arrival and .input_required.\n", pMod->pNtk->pName ); - if ( pMod->fOutArr && pMod->fOutReq ) - printf( "Model %s has both .output_arrival and .output_required.\n", pMod->pNtk->pName ); - if ( !pMod->vDelays && !pMod->fInArr && !pMod->fInReq ) - printf( "Model %s has neither .input_arrival nor .input_required.\n", pMod->pNtk->pName ); - if ( !pMod->vDelays && !pMod->fOutArr && !pMod->fOutReq ) - printf( "Model %s has neither .output_arrival nor .output_required.\n", pMod->pNtk->pName ); - } - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static Ntl_Man_t * Ntl_ReadParse( Ntl_ReadMan_t * p ) -{ - Ntl_Man_t * pDesign; - Ntl_ReadMod_t * pMod; - char * pLine; - int i, k; - // iterate through the models - Vec_PtrForEachEntry( Ntl_ReadMod_t *, p->vModels, pMod, i ) - { - // parse the latches - Vec_PtrForEachEntry( char *, pMod->vLatches, pLine, k ) - if ( !Ntl_ReadParseLineLatch( pMod, pLine ) ) - return NULL; - // parse the nodes - Vec_PtrForEachEntry( char *, pMod->vNames, pLine, k ) - if ( !Ntl_ReadParseLineNamesBlif( pMod, pLine ) ) - return NULL; - // parse the subcircuits - Vec_PtrForEachEntry( char *, pMod->vSubckts, pLine, k ) - if ( !Ntl_ReadParseLineSubckt( pMod, pLine ) ) - return NULL; - // finalize the network - Ntl_ModelFixNonDrivenNets( pMod->pNtk ); - } - if ( i == 0 ) - return NULL; - // update the design name - pMod = (Ntl_ReadMod_t *)Vec_PtrEntry( p->vModels, 0 ); - if ( Ntl_ModelLatchNum(pMod->pNtk) > 0 ) - Ntl_ModelTransformLatches( pMod->pNtk ); - p->pDesign->pName = Ntl_ManStoreName( p->pDesign, pMod->pNtk->pName ); - // return the network - pDesign = p->pDesign; - p->pDesign = NULL; - return pDesign; -} - -/**Function************************************************************* - - Synopsis [Parses the model line.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Ntl_ReadParseLineModel( Ntl_ReadMod_t * p, char * pLine ) -{ - Vec_Ptr_t * vTokens = p->pMan->vTokens; - char * pToken; - Ntl_ReadSplitIntoTokens( vTokens, pLine, '\0' ); - pToken = (char *)Vec_PtrEntry( vTokens, 0 ); - assert( !strcmp(pToken, "model") ); - if ( Vec_PtrSize(vTokens) != 2 ) - { - sprintf( p->pMan->sError, "Line %d: The number of entries (%d) in .model line is different from two.", Ntl_ReadGetLine(p->pMan, pToken), Vec_PtrSize(vTokens) ); - return 0; - } - p->pNtk = Ntl_ModelAlloc( p->pMan->pDesign, (char *)Vec_PtrEntry(vTokens, 1) ); - if ( p->pNtk == NULL ) - { - sprintf( p->pMan->sError, "Line %d: Model %s already exists.", Ntl_ReadGetLine(p->pMan, pToken), (char*)Vec_PtrEntry(vTokens, 1) ); - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses the model line.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Ntl_ReadParseLineAttrib( Ntl_ReadMod_t * p, char * pLine ) -{ - Vec_Ptr_t * vTokens = p->pMan->vTokens; - char * pToken; - int i; - Ntl_ReadSplitIntoTokens( vTokens, pLine, '\0' ); - pToken = (char *)Vec_PtrEntry( vTokens, 0 ); - assert( !strncmp(pToken, "attrib", 6) ); - Vec_PtrForEachEntryStart( char *, vTokens, pToken, i, 1 ) - { - pToken = (char *)Vec_PtrEntry( vTokens, i ); - if ( strcmp( pToken, "white" ) == 0 ) - p->pNtk->attrWhite = 1; - else if ( strcmp( pToken, "black" ) == 0 ) - p->pNtk->attrWhite = 0; - else if ( strcmp( pToken, "box" ) == 0 ) - p->pNtk->attrBox = 1; - else if ( strcmp( pToken, "logic" ) == 0 ) - p->pNtk->attrBox = 0; - else if ( strcmp( pToken, "comb" ) == 0 ) - p->pNtk->attrComb = 1; - else if ( strcmp( pToken, "seq" ) == 0 ) - p->pNtk->attrComb = 0; - else if ( strcmp( pToken, "keep" ) == 0 ) - p->pNtk->attrKeep = 1; - else if ( strcmp( pToken, "sweep" ) == 0 ) - p->pNtk->attrKeep = 0; - else - { - sprintf( p->pMan->sError, "Line %d: Unknown attribute (%s) in the .attrib line of model %s.", Ntl_ReadGetLine(p->pMan, pToken), pToken, p->pNtk->pName ); - return 0; - } - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses the inputs line.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Ntl_ReadParseLineInputs( Ntl_ReadMod_t * p, char * pLine ) -{ - Ntl_Net_t * pNet; - Ntl_Obj_t * pObj; - Vec_Ptr_t * vTokens = p->pMan->vTokens; - char * pToken; - int i; - Ntl_ReadSplitIntoTokens( vTokens, pLine, '\0' ); - pToken = (char *)Vec_PtrEntry(vTokens, 0); - assert( !strcmp(pToken, "inputs") ); - Vec_PtrForEachEntryStart( char *, 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.", Ntl_ReadGetLine(p->pMan, pToken), pNet->pName ); - return 0; - } - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses the outputs line.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Ntl_ReadParseLineOutputs( Ntl_ReadMod_t * p, char * pLine ) -{ - Ntl_Net_t * pNet; - Ntl_Obj_t * pObj; - Vec_Ptr_t * vTokens = p->pMan->vTokens; - char * pToken; - int i; - Ntl_ReadSplitIntoTokens( vTokens, pLine, '\0' ); - pToken = (char *)Vec_PtrEntry(vTokens, 0); - assert( !strcmp(pToken, "outputs") ); - Vec_PtrForEachEntryStart( char *, vTokens, pToken, i, 1 ) - { - pNet = Ntl_ModelFindOrCreateNet( p->pNtk, pToken ); - pObj = Ntl_ModelCreatePo( p->pNtk, pNet ); - pNet->pCopy = pObj; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses the latches line.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Ntl_ReadParseLineLatch( Ntl_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; - Ntl_ReadSplitIntoTokens( vTokens, pLine, '\0' ); - pToken = (char *)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.", Ntl_ReadGetLine(p->pMan, pToken) ); - return 0; - } - // create latch - pNameLi = (char *)Vec_PtrEntry( vTokens, 1 ); - pNameLo = (char *)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.", Ntl_ReadGetLine(p->pMan, pToken), pNetLo->pName ); - return 0; - } - // get initial value - if ( Vec_PtrSize(vTokens) > 3 ) - pObj->LatchId.regInit = atoi( (char *)Vec_PtrEntry(vTokens,Vec_PtrSize(vTokens)-1) ); - else - pObj->LatchId.regInit = 2; - if ( pObj->LatchId.regInit < 0 || pObj->LatchId.regInit > 2 ) - { - sprintf( p->pMan->sError, "Line %d: Initial state of the latch is incorrect \"%s\".", Ntl_ReadGetLine(p->pMan, pToken), (char*)Vec_PtrEntry(vTokens,3) ); - return 0; - } - // get the register class -// if ( Vec_PtrSize(vTokens) == 6 ) - if ( Vec_PtrSize(vTokens) == 5 || Vec_PtrSize(vTokens) == 6 ) - { - pToken = (char *)Vec_PtrEntry(vTokens,3); - if ( strcmp( pToken, "fe" ) == 0 ) - pObj->LatchId.regType = 1; - else if ( strcmp( pToken, "re" ) == 0 ) - pObj->LatchId.regType = 2; - else if ( strcmp( pToken, "ah" ) == 0 ) - pObj->LatchId.regType = 3; - else if ( strcmp( pToken, "al" ) == 0 ) - pObj->LatchId.regType = 4; - else if ( strcmp( pToken, "as" ) == 0 ) - pObj->LatchId.regType = 5; - else if ( pToken[0] >= '0' && pToken[0] <= '9' ) - pObj->LatchId.regClass = atoi(pToken); - else - { - sprintf( p->pMan->sError, "Line %d: Type/class of the latch is incorrect \"%s\".", Ntl_ReadGetLine(p->pMan, pToken), pToken ); - return 0; - } - } - if ( pObj->LatchId.regClass < 0 || pObj->LatchId.regClass > (1<<24) ) - { - sprintf( p->pMan->sError, "Line %d: Class of the latch is incorrect \"%s\".", Ntl_ReadGetLine(p->pMan, pToken), (char*)Vec_PtrEntry(vTokens,3) ); - return 0; - } - // get the clock -// if ( Vec_PtrSize(vTokens) == 5 || Vec_PtrSize(vTokens) == 6 ) - if ( Vec_PtrSize(vTokens) == 6 ) - { - pToken = (char *)Vec_PtrEntry(vTokens,Vec_PtrSize(vTokens)-2); - pNetLi = Ntl_ModelFindOrCreateNet( p->pNtk, pToken ); - pObj->pClock = pNetLi; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses the subckt line.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Ntl_ReadParseLineSubckt( Ntl_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 = Ntl_ReadCountChars( pLine, '=' ); - Ntl_ReadSplitIntoTokensAndClear( vTokens, pLine, '\0', '=' ); - pToken = (char *)Vec_PtrEntry(vTokens,0); - assert( !strcmp(pToken, "subckt") ); - - // get the model for this box - pName = (char *)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.", Ntl_ReadGetLine(p->pMan, pToken), pName ); - return 0; - } -/* - // temporary fix for splitting the .subckt line - if ( nEquals < Ntl_ModelPiNum(pModel) + Ntl_ModelPoNum(pModel) ) - { - Vec_Ptr_t * vTokens2 = Vec_PtrAlloc( 10 ); - // get one additional token - pToken = Vec_PtrEntry( vTokens, Vec_PtrSize(vTokens) - 1 ); - for ( ; *pToken; pToken++ ); - for ( ; *pToken == 0; pToken++ ); - Ntl_ReadSplitIntoTokensAndClear( vTokens2, pToken, '\0', '=' ); -// assert( Vec_PtrSize( vTokens2 ) == 2 ); - Vec_PtrForEachEntry( char *, vTokens2, pToken, i ) - Vec_PtrPush( vTokens, pToken ); - nEquals += Vec_PtrSize(vTokens2)/2; - Vec_PtrFree( vTokens2 ); - } -*/ - // 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 %s differs from the sum of PIs and POs of the model (%d).", - Ntl_ReadGetLine(p->pMan, pToken), nEquals, pName, 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.", - Ntl_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.", - Ntl_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 Ntl_ReadParseLineDelay( Ntl_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) ); - Ntl_ReadSplitIntoTokens( vTokens, pLine, '\0' ); - pToken = (char *)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).", Ntl_ReadGetLine(p->pMan, pToken) ); - return 0; - } - // find the delay number - pTokenNum = (char *)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.", Ntl_ReadGetLine(p->pMan, pToken), (char*)Vec_PtrEntryLast(vTokens) ); - return 0; - } - // find the PI/PO numbers - RetValue1 = 0; Number1 = -1; - if ( Vec_PtrSize(vTokens) > 2 ) - { - RetValue1 = Ntl_ModelFindPioNumber( p->pNtk, 0, 0, (char *)Vec_PtrEntry(vTokens, 1), &Number1 ); - if ( RetValue1 == 0 ) - { - sprintf( p->pMan->sError, "Line %d: Cannot find signal \"%s\" among PIs/POs.", Ntl_ReadGetLine(p->pMan, pToken), (char*)Vec_PtrEntry(vTokens, 1) ); - return 0; - } - } - RetValue2 = 0; Number2 = -1; - if ( Vec_PtrSize(vTokens) > 3 ) - { - RetValue2 = Ntl_ModelFindPioNumber( p->pNtk, 0, 0, (char *)Vec_PtrEntry(vTokens, 2), &Number2 ); - if ( RetValue2 == 0 ) - { - sprintf( p->pMan->sError, "Line %d: Cannot find signal \"%s\" among PIs/POs.", Ntl_ReadGetLine(p->pMan, pToken), (char*)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.", - Ntl_ReadGetLine(p->pMan, pToken), (char*)Vec_PtrEntry(vTokens, 1), (char*)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 Ntl_ReadParseLineTimes( Ntl_ReadMod_t * p, char * pLine, int fOutput ) -{ - Vec_Ptr_t * vTokens = p->pMan->vTokens; - int RetValue, Number = -1; - char * pToken, * pTokenNum; - float Delay; - assert( sizeof(float) == sizeof(int) ); - Ntl_ReadSplitIntoTokens( vTokens, pLine, '\0' ); - pToken = (char *)Vec_PtrEntry(vTokens,0); - if ( fOutput ) - assert( !strncmp(pToken, "output_", 7) ); - else - assert( !strncmp(pToken, "input_", 6) ); - if ( Vec_PtrSize(vTokens) != 2 && Vec_PtrSize(vTokens) != 3 ) - { - sprintf( p->pMan->sError, "Line %d: Delay line does not have a valid number of parameters (2 or 3).", Ntl_ReadGetLine(p->pMan, pToken) ); - return 0; - } - // find the delay number - pTokenNum = (char *)Vec_PtrEntryLast(vTokens); - if ( !strcmp( pTokenNum, "-inf" ) ) - Delay = -TIM_ETERNITY; - else if ( !strcmp( pTokenNum, "inf" ) ) - Delay = TIM_ETERNITY; - else - Delay = atof( pTokenNum ); - if ( Delay == 0.0 && pTokenNum[0] != '0' ) - { - sprintf( p->pMan->sError, "Line %d: Delay value (%s) appears to be invalid.", Ntl_ReadGetLine(p->pMan, pToken), (char*)Vec_PtrEntryLast(vTokens) ); - return 0; - } - // find the PI/PO numbers - if ( fOutput ) - { - if ( Vec_PtrSize(vTokens) == 3 ) - { - RetValue = Ntl_ModelFindPioNumber( p->pNtk, 0, 1, (char *)Vec_PtrEntry(vTokens, 1), &Number ); - if ( RetValue == 0 ) - { - sprintf( p->pMan->sError, "Line %d: Cannot find signal \"%s\" among POs.", Ntl_ReadGetLine(p->pMan, pToken), (char*)Vec_PtrEntry(vTokens, 1) ); - return 0; - } - } - // store the values - if ( p->pNtk->vTimeOutputs == NULL ) - p->pNtk->vTimeOutputs = Vec_IntAlloc( 100 ); - Vec_IntPush( p->pNtk->vTimeOutputs, Number ); - Vec_IntPush( p->pNtk->vTimeOutputs, Aig_Float2Int(Delay) ); - } - else - { - if ( Vec_PtrSize(vTokens) == 3 ) - { - RetValue = Ntl_ModelFindPioNumber( p->pNtk, 1, 0, (char *)Vec_PtrEntry(vTokens, 1), &Number ); - if ( RetValue == 0 ) - { - sprintf( p->pMan->sError, "Line %d: Cannot find signal \"%s\" among PIs.", Ntl_ReadGetLine(p->pMan, pToken), (char*)Vec_PtrEntry(vTokens, 1) ); - return 0; - } - } - // store the values - if ( p->pNtk->vTimeInputs == NULL ) - p->pNtk->vTimeInputs = Vec_IntAlloc( 100 ); - Vec_IntPush( p->pNtk->vTimeInputs, Number ); - Vec_IntPush( p->pNtk->vTimeInputs, Aig_Float2Int(Delay) ); - } - return 1; -} - - -/**Function************************************************************* - - Synopsis [Constructs the SOP cover from the file parsing info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static char * Ntl_ReadParseTableBlif( Ntl_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 - Ntl_ReadSplitIntoTokens( vTokens, pTable, '.' ); - if ( Vec_PtrSize(vTokens) == 0 ) - return Ntl_ManStoreSop( p->pMan->pDesign->pMemSops, " 0\n" ); - if ( Vec_PtrSize(vTokens) == 1 ) - { - pOutput = (char *)Vec_PtrEntry( vTokens, 0 ); - if ( *pOutput == '\"' ) - return Ntl_ManStoreSop( p->pMan->pDesign->pMemSops, pOutput ); - if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] ) - { - sprintf( p->pMan->sError, "Line %d: Constant table has wrong output value \"%s\".", Ntl_ReadGetLine(p->pMan, pOutput), pOutput ); - return NULL; - } - return Ntl_ManStoreSop( p->pMan->pDesign->pMemSops, (pOutput[0] == '0') ? " 0\n" : " 1\n" ); - } - pProduct = (char *)Vec_PtrEntry( vTokens, 0 ); - if ( Vec_PtrSize(vTokens) % 2 == 1 ) - { - sprintf( p->pMan->sError, "Line %d: Table has odd number of tokens (%d).", Ntl_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 = (char *)Vec_PtrEntry( vTokens, 2*i + 0 ); - pOutput = (char *)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).", Ntl_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.", Ntl_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).", Ntl_ReadGetLine(p->pMan, pProduct), pOutput, Polarity ); - return NULL; - } - // parse one product - Vec_StrPrintStr( 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 Ntl_ReadParseLineNamesBlif( Ntl_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; - Ntl_ReadSplitIntoTokens( vTokens, pLine, '\0' ); - // parse the mapped node -// if ( !strcmp(Vec_PtrEntry(vTokens,0), "gate") ) -// return Ntl_ReadParseLineGateBlif( p, vTokens ); - // parse the regular name line - assert( !strcmp((char *)Vec_PtrEntry(vTokens,0), "names") ); - pNameOut = (char *)Vec_PtrEntryLast( vTokens ); - 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 = (char *)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.", Ntl_ReadGetLine(p->pMan, pNameOut), pNameOut ); - return 0; - } - // parse the table of this node - pNode->pSop = Ntl_ReadParseTableBlif( p, pNameOut + strlen(pNameOut), pNode->nFanins ); - if ( pNode->pSop == NULL ) - return 0; - pNode->pSop = Ntl_ManStoreSop( p->pNtk->pMan->pMemSops, pNode->pSop ); - return 1; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ntl/ntlSweep.c b/src/aig/ntl/ntlSweep.c deleted file mode 100644 index 29e40f30..00000000 --- a/src/aig/ntl/ntlSweep.c +++ /dev/null @@ -1,214 +0,0 @@ -/**CFile**************************************************************** - - FileName [ntlSweep.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Netlist representation.] - - Synopsis [Performs structural sweep of the netlist.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ntlSweep.c,v 1.1 2008/10/10 14:09:30 mjarvin Exp $] - -***********************************************************************/ - -#include "ntl.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Detects logic that does not fanout into POs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManSweepMark_rec( Ntl_Man_t * p, Ntl_Obj_t * pObj ) -{ - Ntl_Net_t * pNet; - int i; - if ( pObj->fMark ) - return; - pObj->fMark = 1; - Ntl_ObjForEachFanin( pObj, pNet, i ) - Ntl_ManSweepMark_rec( p, pNet->pDriver ); -} - -/**Function************************************************************* - - Synopsis [Detects logic that does not fanout into POs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManSweepMark( Ntl_Man_t * p ) -{ - Ntl_Mod_t * pRoot; - Ntl_Obj_t * pObj; - int i; - // get the root model - pRoot = Ntl_ManRootModel( p ); - // clear net visited flags - Ntl_ModelForEachObj( pRoot, pObj, i ) - assert( pObj->fMark == 0 ); - // label the primary inputs - Ntl_ModelForEachPi( pRoot, pObj, i ) - pObj->fMark = 1; - // start from the primary outputs - Ntl_ModelForEachPo( pRoot, pObj, i ) - Ntl_ManSweepMark_rec( p, pObj ); - // start from the persistant boxes - Ntl_ModelForEachBox( pRoot, pObj, i ) - if ( pObj->pImplem->attrKeep ) - Ntl_ManSweepMark_rec( p, pObj ); -} - -/**Function************************************************************* - - Synopsis [Removes logic that does not fanout into POs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManSweep( Ntl_Man_t * p, int fVerbose ) -{ - int nObjsOld[NTL_OBJ_VOID]; - Ntl_Mod_t * pRoot, * pMod; - Ntl_Net_t * pNet; - Ntl_Obj_t * pObj; - int i, k, nNetsOld; - int ModelCounter = 0, Counter = 0; - - // remember the number of objects - pRoot = Ntl_ManRootModel( p ); - for ( i = 0; i < NTL_OBJ_VOID; i++ ) - nObjsOld[i] = pRoot->nObjs[i]; - nNetsOld = Ntl_ModelCountNets(pRoot); - - // mark the nets that do not fanout into POs - Ntl_ManSweepMark( p ); - - // count how many boxes of each type are swept away - if ( fVerbose ) - { - Ntl_ManForEachModel( p, pMod, i ) - pMod->nUsed = pMod->nRems = 0; - Ntl_ModelForEachObj( pRoot, pObj, i ) - if ( Ntl_ObjIsBox(pObj) && pObj->pImplem ) - { - pObj->pImplem->nUsed++; - if ( !pObj->fMark ) - { - if ( pObj->pImplem->nRems++ == 0 ) - ModelCounter++; - } - } - } - - // remove the useless objects and their nets - Ntl_ModelForEachObj( pRoot, pObj, i ) - { - if ( pObj->fMark ) - { - pObj->fMark = 0; - continue; - } - // remove the fanout nets - Ntl_ObjForEachFanout( pObj, pNet, k ) - if ( pNet != NULL && pNet->pName[0] != 0 ) - { - Ntl_ModelDeleteNet( pRoot, pNet ); - Vec_PtrWriteEntry( pRoot->vNets, pNet->NetId, NULL ); - } - // remove the object - if ( Ntl_ObjIsNode(pObj) && Ntl_ObjFaninNum(pObj) == 1 ) - pRoot->nObjs[NTL_OBJ_LUT1]--; - else - pRoot->nObjs[pObj->Type]--; - Vec_PtrWriteEntry( pRoot->vObjs, pObj->Id, NULL ); - pObj->Type = NTL_OBJ_NONE; - Counter++; - } - - - - // print detailed statistics of sweeping - if ( fVerbose && Counter > 0) - { - int numLutBox = 0; - - printf( "Swept away:" ); - printf( " Node = %d (%4.1f %%)", - nObjsOld[NTL_OBJ_NODE] - pRoot->nObjs[NTL_OBJ_NODE], - !nObjsOld[NTL_OBJ_NODE]? 0.0: 100.0 * (nObjsOld[NTL_OBJ_NODE] - pRoot->nObjs[NTL_OBJ_NODE]) / nObjsOld[NTL_OBJ_NODE] ); - printf( " Buf/Inv = %d (%4.1f %%)", - nObjsOld[NTL_OBJ_LUT1] - pRoot->nObjs[NTL_OBJ_LUT1], - !nObjsOld[NTL_OBJ_LUT1]? 0.0: 100.0 * (nObjsOld[NTL_OBJ_LUT1] - pRoot->nObjs[NTL_OBJ_LUT1]) / nObjsOld[NTL_OBJ_LUT1] ); - printf( " Lat = %d (%4.1f %%)", - nObjsOld[NTL_OBJ_LATCH] - pRoot->nObjs[NTL_OBJ_LATCH], - !nObjsOld[NTL_OBJ_LATCH]? 0.0: 100.0 * (nObjsOld[NTL_OBJ_LATCH] - pRoot->nObjs[NTL_OBJ_LATCH]) / nObjsOld[NTL_OBJ_LATCH] ); - printf( " Box = %d (%4.1f %%)", - nObjsOld[NTL_OBJ_BOX] - pRoot->nObjs[NTL_OBJ_BOX], - !nObjsOld[NTL_OBJ_BOX]? 0.0: 100.0 * (nObjsOld[NTL_OBJ_BOX] - pRoot->nObjs[NTL_OBJ_BOX]) / nObjsOld[NTL_OBJ_BOX] ); - printf( "\n" ); - if ( ModelCounter ) - { - printf( "Sweep removed %d boxed of %d types (out of %d types):\n", - nObjsOld[NTL_OBJ_BOX] - pRoot->nObjs[NTL_OBJ_BOX], ModelCounter, Vec_PtrSize(p->vModels)-1 ); - Ntl_ManForEachModel( p, pMod, i ) - { - if ( i && (pMod->nRems + pMod->nUsed-pMod->nRems) > 0) - { - - if (strncmp(pMod->pName, "LUT", 3) != 0) - { - //printf( "( M%d: %s, S=%d, L=%d ) ", i, pMod->pName, pMod->nRems, pMod->nUsed-pMod->nRems ); - //printf( "Model %3d : %-40s Swept = %5d. Left = %5d.\n", i, pMod->pName, pMod->nRems, pMod->nUsed-pMod->nRems ); - } else - { - numLutBox++; - } - } - } -// printf("\nLUTboxType =%d\n", numLutBox); - } - } - if ( !Ntl_ManCheck( p ) ) - printf( "Ntl_ManSweep: The check has failed for design %s.\n", p->pName ); - return Counter; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ntl/ntlTable.c b/src/aig/ntl/ntlTable.c deleted file mode 100644 index 23207081..00000000 --- a/src/aig/ntl/ntlTable.c +++ /dev/null @@ -1,554 +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.3 2008/10/24 14:18:44 mjarvin Exp $] - -***********************************************************************/ - -#include "ntl.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// hashing for strings -static unsigned Ntl_HashString( const 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, const char * pName ) -{ - Ntl_Net_t * pNet; - int nSize = sizeof(Ntl_Net_t) + strlen(pName) + 1; - nSize = (nSize / sizeof(char*) + ((nSize % sizeof(char*)) > 0)) * sizeof(char*); // added by Saurabh on Sep 3, 2009 - pNet = (Ntl_Net_t *)Aig_MmFlexEntryFetch( p->pMan->pMemObjs, nSize ); - memset( pNet, 0, sizeof(Ntl_Net_t) ); - strcpy( pNet->pName, pName ); - pNet->NetId = Vec_PtrSize( p->vNets ); - Vec_PtrPush( p->vNets, pNet ); - return pNet; -} - -/**Function************************************************************* - - Synopsis [Allocates memory for the net.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Ntl_ModelCreateNetName( Ntl_Mod_t * p, const char * pName, int Num ) -{ - char * pResult; - char Buffer[1000]; - assert( strlen(pName) < 900 ); - do { - sprintf( Buffer, "%s%d", pName, Num++ ); - } while ( Ntl_ModelFindNet( p, Buffer ) != NULL ); - pResult = (char *)Aig_MmFlexEntryFetch( p->pMan->pMemObjs, strlen(Buffer) + 1 ); - strcpy( pResult, Buffer ); - return pResult; -} - -/**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 = ABC_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 ); -// ABC_PRT( "Time", clock() - clk ); - // replace the table and the parameters - ABC_FREE( p->pTable ); - p->pTable = pTableNew; - p->nTableSize = nTableSizeNew; -} - -/**Function************************************************************* - - Synopsis [Finds net.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Net_t * Ntl_ModelFindNet( Ntl_Mod_t * p, const 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 [Deletes net from the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ModelDeleteNet( Ntl_Mod_t * p, Ntl_Net_t * pNet ) -{ - Ntl_Net_t * pEnt, * pPrev; - unsigned Key = Ntl_HashString( pNet->pName, p->nTableSize ); - for ( pPrev = NULL, pEnt = p->pTable[Key]; pEnt; pPrev = pEnt, pEnt = pEnt->pNext ) - if ( pEnt == pNet ) - break; - if ( pEnt == NULL ) - { - printf( "Ntl_ModelDeleteNet(): Net to be deleted is not found in the hash table.\n" ); - return; - } - if ( pPrev == NULL ) - p->pTable[Key] = pEnt->pNext; - else - pPrev->pNext = pEnt->pNext; - p->nEntries--; -} - -/**Function************************************************************* - - Synopsis [Inserts net into the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ModelInsertNet( Ntl_Mod_t * p, Ntl_Net_t * pNet ) -{ - unsigned Key = Ntl_HashString( pNet->pName, p->nTableSize ); - assert( Ntl_ModelFindNet( p, pNet->pName ) == NULL ); - pNet->pNext = p->pTable[Key]; - p->pTable[Key] = pNet; -} - -/**Function************************************************************* - - Synopsis [Finds or creates the net.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Net_t * Ntl_ModelFindOrCreateNet( Ntl_Mod_t * p, const 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 [Creates new net.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Net_t * Ntl_ModelDontFindCreateNet( Ntl_Mod_t * p, const char * pName ) -{ - Ntl_Net_t * pEnt; - unsigned Key = Ntl_HashString( pName, p->nTableSize ); - 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 [Assigns numbers to PIs and POs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ModelSetPioNumbers( Ntl_Mod_t * p ) -{ - Ntl_Obj_t * pObj; - int i; - Ntl_ModelForEachPi( p, pObj, i ) - pObj->iTemp = i; - Ntl_ModelForEachPo( p, pObj, i ) - pObj->iTemp = i; -} - -/**Function************************************************************* - - Synopsis [Returns -1, 0, +1 (when it is PI, not found, or PO).] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ModelFindPioNumber_old( Ntl_Mod_t * p, int fPiOnly, int fPoOnly, const 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; - if ( fPiOnly ) - { - Ntl_ModelForEachPi( p, pObj, i ) - { - if ( Ntl_ObjFanout0(pObj) == pNet ) - { - *pNumber = i; - return -1; - } - } - return 0; - } - if ( fPoOnly ) - { - Ntl_ModelForEachPo( p, pObj, i ) - { - if ( Ntl_ObjFanin0(pObj) == pNet ) - { - *pNumber = i; - return 1; - } - } - 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; -} - -/**Function************************************************************* - - Synopsis [Returns -1, 0, +1 (when it is PI, not found, or PO).] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ModelFindPioNumber( Ntl_Mod_t * p, int fPiOnly, int fPoOnly, const char * pName, int * pNumber ) -{ - Ntl_Net_t * pNet; - Ntl_Obj_t * pTerm; - *pNumber = -1; - pNet = Ntl_ModelFindNet( p, pName ); - if ( pNet == NULL ) - return 0; - if ( fPiOnly ) - { - pTerm = pNet->pDriver; - if ( pTerm && Ntl_ObjIsPi(pTerm) ) - { - *pNumber = pTerm->iTemp; - return -1; - } - return 0; - } - if ( fPoOnly ) - { - pTerm = (Ntl_Obj_t *)pNet->pCopy; - if ( pTerm && Ntl_ObjIsPo(pTerm) ) - { - *pNumber = pTerm->iTemp; - return 1; - } - return 0; - } - pTerm = (Ntl_Obj_t *)pNet->pCopy; - if ( pTerm && Ntl_ObjIsPo(pTerm) ) - { - *pNumber = pTerm->iTemp; - return 1; - } - pTerm = pNet->pDriver; - if ( pTerm && Ntl_ObjIsPi(pTerm) ) - { - *pNumber = pTerm->iTemp; - return -1; - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Sets the driver of 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 [Clears the driver of the net.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ModelClearNetDriver( 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] = NULL; - pNet->pDriver = NULL; - return 1; -} - -/**Function************************************************************* - - Synopsis [Counts the number of nets.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ModelCountNets( Ntl_Mod_t * p ) -{ - Ntl_Net_t * pNet; - int i, Counter = 0; - Ntl_ModelForEachNet( p, pNet, i ) - Counter++; - return Counter; -} - - - - -/**Function************************************************************* - - Synopsis [Resizes the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManModelTableResize( Ntl_Man_t * p ) -{ - Ntl_Mod_t ** pModTableNew, ** ppSpot, * pEntry, * pEntry2; - int nModTableSizeNew, Counter, e, clk; -clk = clock(); - // get the new table size - nModTableSizeNew = Aig_PrimeCudd( 3 * p->nModTableSize ); - // allocate a new array - pModTableNew = ABC_ALLOC( Ntl_Mod_t *, nModTableSizeNew ); - memset( pModTableNew, 0, sizeof(Ntl_Mod_t *) * nModTableSizeNew ); - // rehash entries - Counter = 0; - for ( e = 0; e < p->nModTableSize; e++ ) - for ( pEntry = p->pModTable[e], pEntry2 = pEntry? pEntry->pNext : NULL; - pEntry; pEntry = pEntry2, pEntry2 = pEntry? pEntry->pNext : NULL ) - { - ppSpot = pModTableNew + Ntl_HashString( pEntry->pName, nModTableSizeNew ); - pEntry->pNext = *ppSpot; - *ppSpot = pEntry; - Counter++; - } - assert( Counter == p->nModEntries ); -// printf( "Increasing the structural table size from %6d to %6d. ", p->nTableSize, nTableSizeNew ); -// ABC_PRT( "Time", clock() - clk ); - // replace the table and the parameters - ABC_FREE( p->pModTable ); - p->pModTable = pModTableNew; - p->nModTableSize = nModTableSizeNew; -} - -/**Function************************************************************* - - Synopsis [Finds or creates the net.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManAddModel( Ntl_Man_t * p, Ntl_Mod_t * pModel ) -{ - Ntl_Mod_t * pEnt; - unsigned Key = Ntl_HashString( pModel->pName, p->nModTableSize ); - for ( pEnt = p->pModTable[Key]; pEnt; pEnt = pEnt->pNext ) - if ( !strcmp( pEnt->pName, pModel->pName ) ) - return 0; - pModel->pNext = p->pModTable[Key]; - p->pModTable[Key] = pModel; - if ( ++p->nModEntries > 2 * p->nModTableSize ) - Ntl_ManModelTableResize( p ); - Vec_PtrPush( p->vModels, pModel ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Finds or creates the net.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Mod_t * Ntl_ManFindModel( Ntl_Man_t * p, const char * pName ) -{ - Ntl_Mod_t * pEnt; - unsigned Key = Ntl_HashString( pName, p->nModTableSize ); - for ( pEnt = p->pModTable[Key]; pEnt; pEnt = pEnt->pNext ) - if ( !strcmp( pEnt->pName, pName ) ) - return pEnt; - return NULL; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ntl/ntlTime.c b/src/aig/ntl/ntlTime.c deleted file mode 100644 index 7a531482..00000000 --- a/src/aig/ntl/ntlTime.c +++ /dev/null @@ -1,245 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 = ABC_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 [Records the arrival times for the map leaves.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManUnpackLeafTiming( Ntl_Man_t * p, Tim_Man_t * pMan ) -{ - Vec_Int_t * vTimes; - Ntl_Mod_t * pRoot; - Ntl_Obj_t * pObj; - Ntl_Net_t * pNet; - float dTime; - int i, k, v, Entry, Counter; - // clean the place - pRoot = Ntl_ManRootModel( p ); - Ntl_ModelForEachMapLeaf( pRoot, pObj, i ) - Ntl_ObjForEachFanout( pObj, pNet, k ) - pNet->dTemp = 0; - // store the PI timing - vTimes = pRoot->vTimeInputs; - if ( vTimes ) { - Vec_IntForEachEntry( vTimes, Entry, i ) - { - dTime = Aig_Int2Float( Vec_IntEntry(vTimes,++i) ); - if ( Entry == -1 ) - { - Ntl_ModelForEachPi( pRoot, pObj, v ) - Ntl_ObjFanout0(pObj)->dTemp = dTime; - } - else - { - pObj = Ntl_ModelPi( pRoot, Entry ); - Ntl_ObjFanout0(pObj)->dTemp = dTime; - } - } - } - // store box timing - Ntl_ModelForEachMapLeaf( pRoot, pObj, k ) - { - if ( !(Ntl_ObjIsBox(pObj) && Ntl_BoxIsSeq(pObj)) ) - continue; - vTimes = pObj->pImplem->vTimeOutputs; - if ( vTimes == NULL ) - continue; - Vec_IntForEachEntry( vTimes, Entry, i ) - { - dTime = Aig_Int2Float( Vec_IntEntry(vTimes,++i) ); - if ( Entry == -1 ) - { - Ntl_ObjForEachFanout( pObj, pNet, v ) - pNet->dTemp = dTime; - } - else - { - pNet = Ntl_ObjFanout( pObj, Entry ); - pNet->dTemp = dTime; - } - } - } - // load them into the timing manager - Counter = 0; - Ntl_ModelForEachMapLeaf( pRoot, pObj, i ) - Ntl_ObjForEachFanout( pObj, pNet, k ) - { - if ( pNet->dTemp == TIM_ETERNITY ) - pNet->dTemp = -TIM_ETERNITY; - Tim_ManInitCiArrival( pMan, Counter++, pNet->dTemp ); - } - assert( Counter == p->iLastCi ); -} - -/**Function************************************************************* - - Synopsis [Records the required times for the map leaves.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManUnpackRootTiming( Ntl_Man_t * p, Tim_Man_t * pMan ) -{ -} - -/**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 = Ntl_ManRootModel( p ); - // start the timing manager - pMan = Tim_ManStart( Aig_ManPiNum(p->pAig), Aig_ManPoNum(p->pAig) ); - // unpack the timing data - Ntl_ManUnpackLeafTiming( p, pMan ); -// Ntl_ManUnpackRootTiming( p, pMan ); -/* - if ( pRoot->vTimeInputs ) - { - Vec_IntForEachEntry( pRoot->vTimeInputs, Entry, i ) - { - if ( Entry == -1 ) - Tim_ManSetCiArrivalAll( pMan, Aig_Int2Float(Vec_IntEntry(pRoot->vTimeInputs,++i)) ); - else - Tim_ManInitCiArrival( pMan, Entry, Aig_Int2Float(Vec_IntEntry(pRoot->vTimeInputs,++i)) ); - } - } - // unpack the data in the required times - if ( pRoot->vTimeOutputs ) - { - Vec_IntForEachEntry( pRoot->vTimeOutputs, Entry, i ) - { - if ( Entry == -1 ) - Tim_ManSetCoRequiredAll( pMan, Aig_Int2Float(Vec_IntEntry(pRoot->vTimeOutputs,++i)) ); - else - Tim_ManInitCoRequired( pMan, Entry, Aig_Int2Float(Vec_IntEntry(pRoot->vTimeOutputs,++i)) ); - } - } -*/ - // derive timing tables for the whilte comb boxes - 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 = p->iLastCi; - Vec_PtrForEachEntry( Ntl_Obj_t *, p->vVisNodes, pObj, i ) - { - if ( !Ntl_ObjIsBox(pObj) ) - continue; - Tim_ManCreateBoxFirst( pMan, Vec_IntEntry(p->vBox1Cios, 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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ntl/ntlUtil.c b/src/aig/ntl/ntlUtil.c deleted file mode 100644 index c3c6fd49..00000000 --- a/src/aig/ntl/ntlUtil.c +++ /dev/null @@ -1,737 +0,0 @@ -/**CFile**************************************************************** - - FileName [ntlUtil.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Netlist representation.] - - Synopsis [Various utilities.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ntlUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ntl.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns one if the file has a given extension.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_FileIsType( char * pFileName, char * pS1, char * pS2, char * pS3 ) -{ - int lenS, lenF = strlen(pFileName); - lenS = pS1 ? strlen(pS1) : 0; - if ( lenS && lenF > lenS && !strncmp( pFileName+lenF-lenS, pS1, lenS ) ) - return 1; - lenS = pS2 ? strlen(pS2) : 0; - if ( lenS && lenF > lenS && !strncmp( pFileName+lenF-lenS, pS2, lenS ) ) - return 1; - lenS = pS3 ? strlen(pS3) : 0; - if ( lenS && lenF > lenS && !strncmp( pFileName+lenF-lenS, pS3, lenS ) ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Reads the maximum number of fanins.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ModelGetFaninMax( Ntl_Mod_t * pRoot ) -{ - Ntl_Obj_t * pNode; - int i, nFaninsMax = 0; - Ntl_ModelForEachNode( pRoot, pNode, i ) - { - if ( nFaninsMax < Ntl_ObjFaninNum(pNode) ) - nFaninsMax = Ntl_ObjFaninNum(pNode); - } - return nFaninsMax; -} - -/**Function************************************************************* - - Synopsis [If the net is driven by an inv/buf, returns its fanin.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ntl_Net_t * Ntl_ModelFindSimpleNet( Ntl_Net_t * pNetCo ) -{ - // skip the case when the net is not driven by a node - if ( !Ntl_ObjIsNode(pNetCo->pDriver) ) - return NULL; - // skip the case when the node is not an inv/buf - if ( Ntl_ObjFaninNum(pNetCo->pDriver) != 1 ) - return NULL; - return Ntl_ObjFanin0(pNetCo->pDriver); -} - -/**Function************************************************************* - - Synopsis [Connects COs to the internal nodes other than inv/bufs.] - - Description [Should be called immediately after reading from file.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManCountSimpleCoDriversOne( Ntl_Net_t * pNetCo ) -{ - Ntl_Net_t * pNetFanin; - // skip the case when the net is not driven by a node - if ( !Ntl_ObjIsNode(pNetCo->pDriver) ) - return 0; - // skip the case when the node is not an inv/buf - if ( Ntl_ObjFaninNum(pNetCo->pDriver) != 1 ) - return 0; - // skip the case when the second-generation driver is not a node - pNetFanin = Ntl_ObjFanin0(pNetCo->pDriver); - if ( !Ntl_ObjIsNode(pNetFanin->pDriver) ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Counts COs that are connected to the internal nodes through invs/bufs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManCountSimpleCoDrivers( Ntl_Man_t * p ) -{ - Ntl_Net_t * pNetCo; - Ntl_Obj_t * pObj; - Ntl_Mod_t * pRoot; - int i, k, Counter; - Counter = 0; - pRoot = Ntl_ManRootModel( p ); - Ntl_ModelForEachPo( pRoot, pObj, i ) - Counter += Ntl_ManCountSimpleCoDriversOne( Ntl_ObjFanin0(pObj) ); - Ntl_ModelForEachLatch( pRoot, pObj, i ) - Counter += Ntl_ManCountSimpleCoDriversOne( Ntl_ObjFanin0(pObj) ); - Ntl_ModelForEachBox( pRoot, pObj, i ) - Ntl_ObjForEachFanin( pObj, pNetCo, k ) - Counter += Ntl_ManCountSimpleCoDriversOne( pNetCo ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Derives the array of CI names.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Ntl_ManCollectCiNames( Ntl_Man_t * p ) -{ - Vec_Ptr_t * vNames; - Ntl_Net_t * pNet; - int i; - vNames = Vec_PtrAlloc( 1000 ); - Ntl_ManForEachCiNet( p, pNet, i ) - Vec_PtrPush( vNames, pNet->pName ); - return vNames; -} - -/**Function************************************************************* - - Synopsis [Derives the array of CI names.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Ntl_ManCollectCoNames( Ntl_Man_t * p ) -{ - Vec_Ptr_t * vNames; - Ntl_Net_t * pNet; - int i; - vNames = Vec_PtrAlloc( 1000 ); - Ntl_ManForEachCoNet( p, pNet, i ) - Vec_PtrPush( vNames, pNet->pName ); - return vNames; -} - -/**Function************************************************************* - - Synopsis [Marks the CI/CO nets.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManMarkCiCoNets( Ntl_Man_t * p ) -{ - Ntl_Net_t * pNet; - int i; - Ntl_ManForEachCiNet( p, pNet, i ) - pNet->fMark = 1; - Ntl_ManForEachCoNet( p, pNet, i ) - pNet->fMark = 1; -} - -/**Function************************************************************* - - Synopsis [Unmarks the CI/CO nets.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManUnmarkCiCoNets( Ntl_Man_t * p ) -{ - Ntl_Net_t * pNet; - int i; - Ntl_ManForEachCiNet( p, pNet, i ) - pNet->fMark = 0; - Ntl_ManForEachCoNet( p, pNet, i ) - pNet->fMark = 0; -} - -/**Function************************************************************* - - Synopsis [Convert initial values of registers to be zero.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManSetZeroInitValues( Ntl_Man_t * p ) -{ - Ntl_Mod_t * pRoot; - Ntl_Obj_t * pObj; - int i; - pRoot = Ntl_ManRootModel(p); - Ntl_ModelForEachLatch( pRoot, pObj, i ) - pObj->LatchId.regInit = 0; -} - -/**Function************************************************************* - - Synopsis [Transforms the netlist to have latches with const-0 init-values.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManAddInverters( Ntl_Mod_t * pRoot, Ntl_Obj_t * pObj ) -{ - char * pStore; -// Ntl_Mod_t * pRoot = pObj->pModel; - Ntl_Man_t * pMan = pRoot->pMan; - Ntl_Net_t * pNetLo, * pNetLi, * pNetLoInv, * pNetLiInv; - Ntl_Obj_t * pNode; - int nLength, RetValue; - assert( Ntl_ObjIsInit1( pObj ) ); - // get the nets - pNetLi = Ntl_ObjFanin0(pObj); - pNetLo = Ntl_ObjFanout0(pObj); - // get storage for net names - nLength = strlen(pNetLi->pName) + strlen(pNetLo->pName) + 10; - pStore = Aig_MmFlexEntryFetch( pMan->pMemSops, nLength ); - // create input interter - pNode = Ntl_ModelCreateNode( pRoot, 1 ); - pNode->pSop = Ntl_ManStoreSop( pMan->pMemSops, "0 1\n" ); - Ntl_ObjSetFanin( pNode, pNetLi, 0 ); - // create input net - strcpy( pStore, pNetLi->pName ); - strcat( pStore, "_inv" ); - if ( Ntl_ModelFindNet( pRoot, pStore ) ) - { - printf( "Ntl_ManTransformInitValues(): Internal error! Cannot create net with LI-name + _inv\n" ); - return; - } - pNetLiInv = Ntl_ModelFindOrCreateNet( pRoot, pStore ); - RetValue = Ntl_ModelSetNetDriver( pNode, pNetLiInv ); - assert( RetValue ); - // connect latch to the input net - Ntl_ObjSetFanin( pObj, pNetLiInv, 0 ); - // disconnect latch from the output net - RetValue = Ntl_ModelClearNetDriver( pObj, pNetLo ); - assert( RetValue ); - // create the output net - strcpy( pStore, pNetLo->pName ); - strcat( pStore, "_inv" ); - if ( Ntl_ModelFindNet( pRoot, pStore ) ) - { - printf( "Ntl_ManTransformInitValues(): Internal error! Cannot create net with LO-name + _inv\n" ); - return; - } - pNetLoInv = Ntl_ModelFindOrCreateNet( pRoot, pStore ); - RetValue = Ntl_ModelSetNetDriver( pObj, pNetLoInv ); - assert( RetValue ); - // create output interter - pNode = Ntl_ModelCreateNode( pRoot, 1 ); - pNode->pSop = Ntl_ManStoreSop( pMan->pMemSops, "0 1\n" ); - Ntl_ObjSetFanin( pNode, pNetLoInv, 0 ); - // redirect the old output net - RetValue = Ntl_ModelSetNetDriver( pNode, pNetLo ); - assert( RetValue ); -} - -/**Function************************************************************* - - Synopsis [Transforms the netlist to have latches with const-0 init-values.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManTransformInitValues( Ntl_Man_t * p ) -{ - Ntl_Mod_t * pRoot; - Ntl_Obj_t * pObj; - int i; - pRoot = Ntl_ManRootModel(p); - Ntl_ModelForEachLatch( pRoot, pObj, i ) - { - if ( Ntl_ObjIsInit1( pObj ) ) - Ntl_ManAddInverters( pRoot, pObj ); - pObj->LatchId.regInit = 0; - } -} - -/**Function************************************************************* - - Synopsis [Transforms register classes.] - - Description [Returns the vector of vectors containing the numbers - of registers belonging to the same class. Skips classes containing - less than the given number of registers.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Vec_t * Ntl_ManTransformRegClasses( Ntl_Man_t * pMan, int nSizeMax, int fVerbose ) -{ - Vec_Ptr_t * vParts; - Vec_Int_t * vPart; - int * pClassNums, nClasses; - int Class, ClassMax, i, k; - if ( Vec_IntSize(pMan->vRegClasses) == 0 ) - { - printf( "Ntl_ManReportRegClasses(): Register classes are not defined.\n" ); -// return (Vec_Vec_t *)Vec_PtrAlloc(0); - return NULL; - } - // find the largest class - ClassMax = -1; - Vec_IntForEachEntry( pMan->vRegClasses, Class, k ) - { - if ( Class < 0 ) - { - printf( "Ntl_ManReportRegClasses(): Register class (%d) is negative.\n", Class ); - return NULL; - } - if ( ClassMax < Class ) - ClassMax = Class; - } - if ( ClassMax > 1000000 ) - { - printf( "Ntl_ManReportRegClasses(): The largest number of a register class (%d) is too large (> 1000000).\n", ClassMax ); - return NULL; - } - // count the number of classes - pClassNums = ABC_CALLOC( int, ClassMax + 1 ); - Vec_IntForEachEntry( pMan->vRegClasses, Class, k ) - pClassNums[Class]++; - // count the number of classes - nClasses = 0; - for ( i = 0; i <= ClassMax; i++ ) - nClasses += (int)(pClassNums[i] > 0); - // report the classes - if ( fVerbose && nClasses > 1 ) - { - printf( "The number of register clases = %d.\n", nClasses ); - for ( i = 0; i <= ClassMax; i++ ) - if ( pClassNums[i] ) - printf( "(%d, %d) ", i, pClassNums[i] ); - printf( "\n" ); - } - // skip if there is only one class - if ( nClasses == 1 ) - { - vParts = NULL; - if ( Vec_IntSize(pMan->vRegClasses) >= nSizeMax ) - { - vParts = Vec_PtrAlloc( 100 ); - vPart = Vec_IntStartNatural( Vec_IntSize(pMan->vRegClasses) ); - Vec_PtrPush( vParts, vPart ); - } - printf( "There is only one class with %d registers.\n", Vec_IntSize(pMan->vRegClasses) ); - ABC_FREE( pClassNums ); - return (Vec_Vec_t *)vParts; - } - // create classes - vParts = Vec_PtrAlloc( 100 ); - for ( i = 0; i <= ClassMax; i++ ) - { - if ( pClassNums[i] == 0 || pClassNums[i] < nSizeMax ) - continue; - vPart = Vec_IntAlloc( pClassNums[i] ); - Vec_IntForEachEntry( pMan->vRegClasses, Class, k ) - if ( Class == i ) - Vec_IntPush( vPart, k ); - assert( Vec_IntSize(vPart) == pClassNums[i] ); - Vec_PtrPush( vParts, vPart ); - } - ABC_FREE( pClassNums ); - Vec_VecSort( (Vec_Vec_t *)vParts, 1 ); - // report the selected classes - if ( fVerbose ) - { - printf( "The number of selected register clases = %d.\n", Vec_PtrSize(vParts) ); - Vec_PtrForEachEntry( Vec_Int_t *, vParts, vPart, i ) - printf( "(%d, %d) ", i, Vec_IntSize(vPart) ); - printf( "\n" ); - } - return (Vec_Vec_t *)vParts; -} - -/**Function************************************************************* - - Synopsis [Filter register clases using clock-domain information.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManFilterRegisterClasses( Aig_Man_t * pAig, Vec_Int_t * vRegClasses, int fVerbose ) -{ - Aig_Obj_t * pObj, * pRepr; - int i, k, nOmitted, nTotal; - if ( pAig->pReprs == NULL ) - return; - assert( pAig->nRegs > 0 ); - Aig_ManForEachPi( pAig, pObj, i ) - pObj->PioNum = -1; - k = 0; - Aig_ManForEachLoSeq( pAig, pObj, i ) - pObj->PioNum = k++; - // consider equivalences - nOmitted = nTotal = 0; - Aig_ManForEachObj( pAig, pObj, i ) - { - pRepr = pAig->pReprs[pObj->Id]; - if ( pRepr == NULL ) - continue; - nTotal++; - assert( Aig_ObjIsPi(pObj) ); - assert( Aig_ObjIsPi(pRepr) || Aig_ObjIsConst1(pRepr) ); - if ( Aig_ObjIsConst1(pRepr) ) - continue; - assert( pObj->PioNum >= 0 && pRepr->PioNum >= 0 ); - // remove equivalence if they belong to different classes - if ( Vec_IntEntry( vRegClasses, pObj->PioNum ) == - Vec_IntEntry( vRegClasses, pRepr->PioNum ) ) - continue; - pAig->pReprs[pObj->Id] = NULL; - nOmitted++; - } - Aig_ManForEachPi( pAig, pObj, i ) - pObj->PioNum = -1; - if ( fVerbose ) - printf( "Omitted %d (out of %d) equivs due to register class mismatch.\n", - nOmitted, nTotal ); -} - - -/**Function************************************************************* - - Synopsis [Counts the number of CIs in the model.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManLatchNum( Ntl_Man_t * p ) -{ - Ntl_Mod_t * pRoot; - Ntl_Obj_t * pObj; - int i, Counter = 0; - pRoot = Ntl_ManRootModel(p); - Ntl_ModelForEachBox( pRoot, pObj, i ) - Counter += Ntl_ModelLatchNum( pObj->pImplem ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the design is combinational.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ManIsComb( Ntl_Man_t * p ) -{ - return Ntl_ManLatchNum(p) == 0; -} - -/**Function************************************************************* - - Synopsis [Counts the number of CIs in the model.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ModelCombLeafNum( Ntl_Mod_t * p ) -{ - Ntl_Obj_t * pObj; - int i, Counter = 0; - Ntl_ModelForEachCombLeaf( p, pObj, i ) - Counter += Ntl_ObjFanoutNum( pObj ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts the number of COs in the model.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ModelCombRootNum( Ntl_Mod_t * p ) -{ - Ntl_Obj_t * pObj; - int i, Counter = 0; - Ntl_ModelForEachCombRoot( p, pObj, i ) - Counter += Ntl_ObjFaninNum( pObj ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts the number of CIs in the model.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ModelSeqLeafNum( Ntl_Mod_t * p ) -{ - Ntl_Obj_t * pObj; - int i, Counter = 0; - Ntl_ModelForEachSeqLeaf( p, pObj, i ) - Counter += Ntl_ObjFanoutNum( pObj ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts the number of COs in the model.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ModelSeqRootNum( Ntl_Mod_t * p ) -{ - Ntl_Obj_t * pObj; - int i, Counter = 0; - Ntl_ModelForEachSeqRoot( p, pObj, i ) - Counter += Ntl_ObjFaninNum( pObj ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Unmarks the CI/CO nets.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ntl_ModelCheckNetsAreNotMarked( Ntl_Mod_t * pModel ) -{ - Ntl_Net_t * pNet; - int i; - Ntl_ModelForEachNet( pModel, pNet, i ) - assert( pNet->fMark == 0 ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Unmarks the CI/CO nets.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ModelClearNets( Ntl_Mod_t * pModel ) -{ - Ntl_Net_t * pNet; - int i; - Ntl_ModelForEachNet( pModel, pNet, i ) - { - pNet->nVisits = pNet->fMark = 0; - pNet->pCopy = pNet->pCopy2 = NULL; - } -} - -/**Function************************************************************* - - Synopsis [Removes nets without fanins and fanouts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManRemoveUselessNets( Ntl_Man_t * p ) -{ - Ntl_Mod_t * pRoot; - Ntl_Obj_t * pNode; - Ntl_Net_t * pNet; - int i, k, Counter; - pRoot = Ntl_ManRootModel( p ); - Ntl_ModelForEachNet( pRoot, pNet, i ) - pNet->fMark = 0; - Ntl_ModelForEachPi( pRoot, pNode, i ) - { - pNet = Ntl_ObjFanout0(pNode); - pNet->fMark = 1; - } - Ntl_ModelForEachPo( pRoot, pNode, i ) - { - pNet = Ntl_ObjFanin0(pNode); - pNet->fMark = 1; - } - Ntl_ModelForEachNode( pRoot, pNode, i ) - { - Ntl_ObjForEachFanin( pNode, pNet, k ) - pNet->fMark = 1; - Ntl_ObjForEachFanout( pNode, pNet, k ) - pNet->fMark = 1; - } - Ntl_ModelForEachBox( pRoot, pNode, i ) - { - Ntl_ObjForEachFanin( pNode, pNet, k ) - pNet->fMark = 1; - Ntl_ObjForEachFanout( pNode, pNet, k ) - pNet->fMark = 1; - } - Counter = 0; - Ntl_ModelForEachNet( pRoot, pNet, i ) - { - if ( pNet->fMark ) - { - pNet->fMark = 0; - continue; - } - if ( pNet->fFixed ) - continue; - Ntl_ModelDeleteNet( pRoot, pNet ); - Vec_PtrWriteEntry( pRoot->vNets, pNet->NetId, NULL ); - Counter++; - } - if ( Counter ) - printf( "Deleted %d nets without fanins/fanouts.\n", Counter ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ntl/ntlWriteBlif.c b/src/aig/ntl/ntlWriteBlif.c deleted file mode 100644 index f9b2781f..00000000 --- a/src/aig/ntl/ntlWriteBlif.c +++ /dev/null @@ -1,697 +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 $] - -***********************************************************************/ - -// The code in this file is developed in collaboration with Mark Jarvin of Toronto. - -#include "ntl.h" -#include "ioa.h" - -#include -#include "bzlib.h" -#include "zlib.h" - -ABC_NAMESPACE_IMPL_START - - -#ifdef _WIN32 -#define vsnprintf _vsnprintf -#endif - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Writes one model into the BLIF file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManWriteBlifModel( FILE * pFile, Ntl_Mod_t * pModel, int fMain ) -{ - Ntl_Obj_t * pObj; - Ntl_Net_t * pNet; - float Delay; - int i, k; - fprintf( pFile, ".model %s\n", pModel->pName ); - if ( pModel->attrWhite || pModel->attrBox || pModel->attrComb || pModel->attrKeep ) - { - fprintf( pFile, ".attrib" ); - fprintf( pFile, " %s", pModel->attrWhite? "white": "black" ); - fprintf( pFile, " %s", pModel->attrBox? "box" : "logic" ); - fprintf( pFile, " %s", pModel->attrComb? "comb" : "seq" ); -// fprintf( pFile, " %s", pModel->attrKeep? "keep" : "sweep" ); - fprintf( pFile, "\n" ); - } - if ( pModel->attrNoMerge ) - fprintf( pFile, ".no_merge\n" ); - 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" ); - // write delays - if ( pModel->vDelays ) - { - for ( i = 0; i < Vec_IntSize(pModel->vDelays); i += 3 ) - { - fprintf( pFile, ".delay" ); - if ( Vec_IntEntry(pModel->vDelays,i) != -1 ) - fprintf( pFile, " %s", Ntl_ObjFanout0(Ntl_ModelPi(pModel, Vec_IntEntry(pModel->vDelays,i)))->pName ); - if ( Vec_IntEntry(pModel->vDelays,i+1) != -1 ) - fprintf( pFile, " %s", Ntl_ObjFanin0(Ntl_ModelPo(pModel, Vec_IntEntry(pModel->vDelays,i+1)))->pName ); - fprintf( pFile, " %.3f", Aig_Int2Float(Vec_IntEntry(pModel->vDelays,i+2)) ); - fprintf( pFile, "\n" ); - } - } - if ( pModel->vTimeInputs ) - { - for ( i = 0; i < Vec_IntSize(pModel->vTimeInputs); i += 2 ) - { - if ( fMain ) - fprintf( pFile, ".input_arrival" ); - else - fprintf( pFile, ".input_required" ); - if ( Vec_IntEntry(pModel->vTimeInputs,i) != -1 ) - fprintf( pFile, " %s", Ntl_ObjFanout0(Ntl_ModelPi(pModel, Vec_IntEntry(pModel->vTimeInputs,i)))->pName ); - Delay = Aig_Int2Float(Vec_IntEntry(pModel->vTimeInputs,i+1)); - if ( Delay == -TIM_ETERNITY ) - fprintf( pFile, " -inf" ); - else if ( Delay == TIM_ETERNITY ) - fprintf( pFile, " inf" ); - else - fprintf( pFile, " %.3f", Delay ); - fprintf( pFile, "\n" ); - } - } - if ( pModel->vTimeOutputs ) - { - for ( i = 0; i < Vec_IntSize(pModel->vTimeOutputs); i += 2 ) - { - if ( fMain ) - fprintf( pFile, ".output_required" ); - else - fprintf( pFile, ".output_arrival" ); - if ( Vec_IntEntry(pModel->vTimeOutputs,i) != -1 ) - fprintf( pFile, " %s", Ntl_ObjFanin0(Ntl_ModelPo(pModel, Vec_IntEntry(pModel->vTimeOutputs,i)))->pName ); - Delay = Aig_Int2Float(Vec_IntEntry(pModel->vTimeOutputs,i+1)); - if ( Delay == -TIM_ETERNITY ) - fprintf( pFile, " -inf" ); - else if ( Delay == TIM_ETERNITY ) - fprintf( pFile, " inf" ); - else - fprintf( pFile, " %.3f", Delay ); - fprintf( pFile, "\n" ); - } - } - // write objects - 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 ); - if ( *pObj->pSop == '\"' ) - fprintf( pFile, "\n" ); - } - else if ( Ntl_ObjIsLatch(pObj) ) - { - fprintf( pFile, ".latch" ); - fprintf( pFile, " %s", Ntl_ObjFanin0(pObj)->pName ); - fprintf( pFile, " %s", Ntl_ObjFanout0(pObj)->pName ); - assert( pObj->LatchId.regType == 0 || pObj->LatchId.regClass == 0 ); - if ( pObj->LatchId.regType ) - { - if ( pObj->LatchId.regType == 1 ) - fprintf( pFile, " fe" ); - else if ( pObj->LatchId.regType == 2 ) - fprintf( pFile, " re" ); - else if ( pObj->LatchId.regType == 3 ) - fprintf( pFile, " ah" ); - else if ( pObj->LatchId.regType == 4 ) - fprintf( pFile, " al" ); - else if ( pObj->LatchId.regType == 5 ) - fprintf( pFile, " as" ); - else - assert( 0 ); - } - else if ( pObj->LatchId.regClass ) - fprintf( pFile, " %d", pObj->LatchId.regClass ); - if ( pObj->pClock ) - fprintf( pFile, " %s", pObj->pClock->pName ); - fprintf( pFile, " %d", pObj->LatchId.regInit ); - 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 netlist into the BLIF file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManWriteBlif_old( 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, "Ntl_ManWriteBlif(): Cannot open the output file \"%s\".\n", pFileName ); - return; - } - fprintf( pFile, "# Benchmark \"%s\" written by ABC-8 on %s\n", p->pName, Aig_TimeStamp() ); - // write the models - Ntl_ManForEachModel( p, pModel, i ) - Ntl_ManWriteBlifModel( pFile, pModel, i==0 ); - // close the file - fclose( pFile ); -} - -/**Function************************************************************* - - Synopsis [Writes the logic network into the BLIF file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManWriteBlifLogic( Nwk_Man_t * pNtk, Ntl_Man_t * p, char * pFileName ) -{ - Ntl_Man_t * pNew; - pNew = Ntl_ManInsertNtk( p, pNtk ); - Ntl_ManWriteBlif( pNew, pFileName ); - Ntl_ManFree( pNew ); -} - - - -/**Function************************************************************* - - Synopsis [Procedure to write data into BZ2 file.] - - Description [Based on the vsnprintf() man page.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -typedef struct bz2file { - FILE * f; - BZFILE * b; - char * buf; - int nBytes; - int nBytesMax; -} bz2file; - -int fprintfBz2(bz2file * b, char * fmt, ...) { - if (b->b) { - char * newBuf; - int bzError; - va_list ap; - while (1) { - va_start(ap,fmt); - b->nBytes = vsnprintf(b->buf,b->nBytesMax,fmt,ap); - va_end(ap); - if (b->nBytes > -1 && b->nBytes < b->nBytesMax) - break; - if (b->nBytes > -1) - b->nBytesMax = b->nBytes + 1; - else - b->nBytesMax *= 2; - if ((newBuf = ABC_REALLOC( char,b->buf,b->nBytesMax )) == NULL) - return -1; - else - b->buf = newBuf; - } - BZ2_bzWrite( &bzError, b->b, b->buf, b->nBytes ); - if (bzError == BZ_IO_ERROR) { - fprintf( stdout, "Ntl_ManWriteBlif(): I/O error writing to compressed stream.\n" ); - return -1; - } - return b->nBytes; - } else { - int n; - va_list ap; - va_start(ap,fmt); - n = vfprintf( b->f, fmt, ap); - va_end(ap); - return n; - } -} - -/**Function************************************************************* - - Synopsis [Writes one model into the BLIF file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManWriteBlifModelGz( gzFile pFile, Ntl_Mod_t * pModel, int fMain ) -{ - Ntl_Obj_t * pObj; - Ntl_Net_t * pNet; - float Delay; - int i, k; - gzprintf( pFile, ".model %s\n", pModel->pName ); - if ( pModel->attrWhite || pModel->attrBox || pModel->attrComb || pModel->attrKeep ) - { - gzprintf( pFile, ".attrib" ); - gzprintf( pFile, " %s", pModel->attrWhite? "white": "black" ); - gzprintf( pFile, " %s", pModel->attrBox? "box" : "logic" ); - gzprintf( pFile, " %s", pModel->attrComb? "comb" : "seq" ); -// gzprintf( pFile, " %s", pModel->attrKeep? "keep" : "sweep" ); - gzprintf( pFile, "\n" ); - } - if ( pModel->attrNoMerge ) - gzprintf( pFile, ".no_merge\n" ); - gzprintf( pFile, ".inputs" ); - Ntl_ModelForEachPi( pModel, pObj, i ) - gzprintf( pFile, " %s", Ntl_ObjFanout0(pObj)->pName ); - gzprintf( pFile, "\n" ); - gzprintf( pFile, ".outputs" ); - Ntl_ModelForEachPo( pModel, pObj, i ) - gzprintf( pFile, " %s", Ntl_ObjFanin0(pObj)->pName ); - gzprintf( pFile, "\n" ); - // write delays - if ( pModel->vDelays ) - { - for ( i = 0; i < Vec_IntSize(pModel->vDelays); i += 3 ) - { - gzprintf( pFile, ".delay" ); - if ( Vec_IntEntry(pModel->vDelays,i) != -1 ) - gzprintf( pFile, " %s", Ntl_ObjFanout0(Ntl_ModelPi(pModel, Vec_IntEntry(pModel->vDelays,i)))->pName ); - if ( Vec_IntEntry(pModel->vDelays,i+1) != -1 ) - gzprintf( pFile, " %s", Ntl_ObjFanin0(Ntl_ModelPo(pModel, Vec_IntEntry(pModel->vDelays,i+1)))->pName ); - gzprintf( pFile, " %.3f", Aig_Int2Float(Vec_IntEntry(pModel->vDelays,i+2)) ); - gzprintf( pFile, "\n" ); - } - } - if ( pModel->vTimeInputs ) - { - for ( i = 0; i < Vec_IntSize(pModel->vTimeInputs); i += 2 ) - { - if ( fMain ) - gzprintf( pFile, ".input_arrival" ); - else - gzprintf( pFile, ".input_required" ); - if ( Vec_IntEntry(pModel->vTimeInputs,i) != -1 ) - gzprintf( pFile, " %s", Ntl_ObjFanout0(Ntl_ModelPi(pModel, Vec_IntEntry(pModel->vTimeInputs,i)))->pName ); - Delay = Aig_Int2Float(Vec_IntEntry(pModel->vTimeInputs,i+1)); - if ( Delay == -TIM_ETERNITY ) - gzprintf( pFile, " -inf" ); - else if ( Delay == TIM_ETERNITY ) - gzprintf( pFile, " inf" ); - else - gzprintf( pFile, " %.3f", Delay ); - gzprintf( pFile, "\n" ); - } - } - if ( pModel->vTimeOutputs ) - { - for ( i = 0; i < Vec_IntSize(pModel->vTimeOutputs); i += 2 ) - { - if ( fMain ) - gzprintf( pFile, ".output_required" ); - else - gzprintf( pFile, ".output_arrival" ); - if ( Vec_IntEntry(pModel->vTimeOutputs,i) != -1 ) - gzprintf( pFile, " %s", Ntl_ObjFanin0(Ntl_ModelPo(pModel, Vec_IntEntry(pModel->vTimeOutputs,i)))->pName ); - Delay = Aig_Int2Float(Vec_IntEntry(pModel->vTimeOutputs,i+1)); - if ( Delay == -TIM_ETERNITY ) - gzprintf( pFile, " -inf" ); - else if ( Delay == TIM_ETERNITY ) - gzprintf( pFile, " inf" ); - else - gzprintf( pFile, " %.3f", Delay ); - gzprintf( pFile, "\n" ); - } - } - // write objects - Ntl_ModelForEachObj( pModel, pObj, i ) - { - if ( Ntl_ObjIsNode(pObj) ) - { - gzprintf( pFile, ".names" ); - Ntl_ObjForEachFanin( pObj, pNet, k ) - gzprintf( pFile, " %s", pNet->pName ); - gzprintf( pFile, " %s\n", Ntl_ObjFanout0(pObj)->pName ); - gzprintf( pFile, "%s", pObj->pSop ); - if ( *pObj->pSop == '\"' ) - gzprintf( pFile, "\n" ); - } - else if ( Ntl_ObjIsLatch(pObj) ) - { - gzprintf( pFile, ".latch" ); - gzprintf( pFile, " %s", Ntl_ObjFanin0(pObj)->pName ); - gzprintf( pFile, " %s", Ntl_ObjFanout0(pObj)->pName ); - assert( pObj->LatchId.regType == 0 || pObj->LatchId.regClass == 0 ); - if ( pObj->LatchId.regType ) - { - if ( pObj->LatchId.regType == 1 ) - gzprintf( pFile, " fe" ); - else if ( pObj->LatchId.regType == 2 ) - gzprintf( pFile, " re" ); - else if ( pObj->LatchId.regType == 3 ) - gzprintf( pFile, " ah" ); - else if ( pObj->LatchId.regType == 4 ) - gzprintf( pFile, " al" ); - else if ( pObj->LatchId.regType == 5 ) - gzprintf( pFile, " as" ); - else - assert( 0 ); - } - else if ( pObj->LatchId.regClass ) - gzprintf( pFile, " %d", pObj->LatchId.regClass ); - if ( pObj->pClock ) - gzprintf( pFile, " %s", pObj->pClock->pName ); - gzprintf( pFile, " %d", pObj->LatchId.regInit ); - gzprintf( pFile, "\n" ); - } - else if ( Ntl_ObjIsBox(pObj) ) - { - gzprintf( pFile, ".subckt %s", pObj->pImplem->pName ); - Ntl_ObjForEachFanin( pObj, pNet, k ) - gzprintf( pFile, " %s=%s", Ntl_ModelPiName(pObj->pImplem, k), pNet->pName ); - Ntl_ObjForEachFanout( pObj, pNet, k ) - gzprintf( pFile, " %s=%s", Ntl_ModelPoName(pObj->pImplem, k), pNet->pName ); - gzprintf( pFile, "\n" ); - } - } - gzprintf( pFile, ".end\n\n" ); -} - -/**Function************************************************************* - - Synopsis [Writes the logic network into the BLIF file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManWriteBlifGz( Ntl_Man_t * p, char * pFileName ) -{ - Ntl_Mod_t * pModel; - int i; - gzFile pFile; - - // start the output stream - pFile = gzopen( pFileName, "wb" ); // if pFileName doesn't end in ".gz" then this acts as a passthrough to fopen - if ( pFile == NULL ) - { - fprintf( stdout, "Ntl_ManWriteBlif(): Cannot open the output file \"%s\".\n", pFileName ); - return; - } - - gzprintf( pFile, "# Benchmark \"%s\" written by ABC-8 on %s\n", p->pName, Aig_TimeStamp() ); - // write the models - Ntl_ManForEachModel( p, pModel, i ) - Ntl_ManWriteBlifModelGz( pFile, pModel, i==0 ); - // close the file - gzclose( pFile ); -} - - -/**Function************************************************************* - - Synopsis [Writes one model into the BLIF file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManWriteBlifModelBz2( bz2file * b, Ntl_Mod_t * pModel, int fMain ) -{ - Ntl_Obj_t * pObj; - Ntl_Net_t * pNet; - float Delay; - int i, k; - fprintfBz2( b, ".model %s\n", pModel->pName ); - if ( pModel->attrWhite || pModel->attrBox || pModel->attrComb || pModel->attrKeep ) - { - fprintfBz2( b, ".attrib" ); - fprintfBz2( b, " %s", pModel->attrWhite? "white": "black" ); - fprintfBz2( b, " %s", pModel->attrBox? "box" : "logic" ); - fprintfBz2( b, " %s", pModel->attrComb? "comb" : "seq" ); -// fprintfBz2( b, " %s", pModel->attrKeep? "keep" : "sweep" ); - fprintfBz2( b, "\n" ); - } - if ( pModel->attrNoMerge ) - fprintfBz2( b, ".no_merge\n" ); - fprintfBz2( b, ".inputs" ); - Ntl_ModelForEachPi( pModel, pObj, i ) - fprintfBz2( b, " %s", Ntl_ObjFanout0(pObj)->pName ); - fprintfBz2( b, "\n" ); - fprintfBz2( b, ".outputs" ); - Ntl_ModelForEachPo( pModel, pObj, i ) - fprintfBz2( b, " %s", Ntl_ObjFanin0(pObj)->pName ); - fprintfBz2( b, "\n" ); - // write delays - if ( pModel->vDelays ) - { - for ( i = 0; i < Vec_IntSize(pModel->vDelays); i += 3 ) - { - fprintfBz2( b, ".delay" ); - if ( Vec_IntEntry(pModel->vDelays,i) != -1 ) - fprintfBz2( b, " %s", Ntl_ObjFanout0(Ntl_ModelPi(pModel, Vec_IntEntry(pModel->vDelays,i)))->pName ); - if ( Vec_IntEntry(pModel->vDelays,i+1) != -1 ) - fprintfBz2( b, " %s", Ntl_ObjFanin0(Ntl_ModelPo(pModel, Vec_IntEntry(pModel->vDelays,i+1)))->pName ); - fprintfBz2( b, " %.3f", Aig_Int2Float(Vec_IntEntry(pModel->vDelays,i+2)) ); - fprintfBz2( b, "\n" ); - } - } - if ( pModel->vTimeInputs ) - { - for ( i = 0; i < Vec_IntSize(pModel->vTimeInputs); i += 2 ) - { - if ( fMain ) - fprintfBz2( b, ".input_arrival" ); - else - fprintfBz2( b, ".input_required" ); - if ( Vec_IntEntry(pModel->vTimeInputs,i) != -1 ) - fprintfBz2( b, " %s", Ntl_ObjFanout0(Ntl_ModelPi(pModel, Vec_IntEntry(pModel->vTimeInputs,i)))->pName ); - Delay = Aig_Int2Float(Vec_IntEntry(pModel->vTimeInputs,i+1)); - if ( Delay == -TIM_ETERNITY ) - fprintfBz2( b, " -inf" ); - else if ( Delay == TIM_ETERNITY ) - fprintfBz2( b, " inf" ); - else - fprintfBz2( b, " %.3f", Delay ); - fprintfBz2( b, "\n" ); - } - } - if ( pModel->vTimeOutputs ) - { - for ( i = 0; i < Vec_IntSize(pModel->vTimeOutputs); i += 2 ) - { - if ( fMain ) - fprintfBz2( b, ".output_required" ); - else - fprintfBz2( b, ".output_arrival" ); - if ( Vec_IntEntry(pModel->vTimeOutputs,i) != -1 ) - fprintfBz2( b, " %s", Ntl_ObjFanin0(Ntl_ModelPo(pModel, Vec_IntEntry(pModel->vTimeOutputs,i)))->pName ); - Delay = Aig_Int2Float(Vec_IntEntry(pModel->vTimeOutputs,i+1)); - if ( Delay == -TIM_ETERNITY ) - fprintfBz2( b, " -inf" ); - else if ( Delay == TIM_ETERNITY ) - fprintfBz2( b, " inf" ); - else - fprintfBz2( b, " %.3f", Delay ); - fprintfBz2( b, "\n" ); - } - } - // write objects - Ntl_ModelForEachObj( pModel, pObj, i ) - { - if ( Ntl_ObjIsNode(pObj) ) - { - fprintfBz2( b, ".names" ); - Ntl_ObjForEachFanin( pObj, pNet, k ) - fprintfBz2( b, " %s", pNet->pName ); - fprintfBz2( b, " %s\n", Ntl_ObjFanout0(pObj)->pName ); - fprintfBz2( b, "%s", pObj->pSop ); - if ( *pObj->pSop == '\"' ) - fprintfBz2( b, "\n" ); - } - else if ( Ntl_ObjIsLatch(pObj) ) - { - fprintfBz2( b, ".latch" ); - fprintfBz2( b, " %s", Ntl_ObjFanin0(pObj)->pName ); - fprintfBz2( b, " %s", Ntl_ObjFanout0(pObj)->pName ); - assert( pObj->LatchId.regType == 0 || pObj->LatchId.regClass == 0 ); - if ( pObj->LatchId.regType ) - { - if ( pObj->LatchId.regType == 1 ) - fprintfBz2( b, " fe" ); - else if ( pObj->LatchId.regType == 2 ) - fprintfBz2( b, " re" ); - else if ( pObj->LatchId.regType == 3 ) - fprintfBz2( b, " ah" ); - else if ( pObj->LatchId.regType == 4 ) - fprintfBz2( b, " al" ); - else if ( pObj->LatchId.regType == 5 ) - fprintfBz2( b, " as" ); - else - assert( 0 ); - } - else if ( pObj->LatchId.regClass ) - fprintfBz2( b, " %d", pObj->LatchId.regClass ); - if ( pObj->pClock ) - fprintfBz2( b, " %s", pObj->pClock->pName ); - fprintfBz2( b, " %d", pObj->LatchId.regInit ); - fprintfBz2( b, "\n" ); - } - else if ( Ntl_ObjIsBox(pObj) ) - { - fprintfBz2( b, ".subckt %s", pObj->pImplem->pName ); - Ntl_ObjForEachFanin( pObj, pNet, k ) - fprintfBz2( b, " %s=%s", Ntl_ModelPiName(pObj->pImplem, k), pNet->pName ); - Ntl_ObjForEachFanout( pObj, pNet, k ) - fprintfBz2( b, " %s=%s", Ntl_ModelPoName(pObj->pImplem, k), pNet->pName ); - fprintfBz2( b, "\n" ); - } - } - fprintfBz2( b, ".end\n\n" ); -} - -/**Function************************************************************* - - Synopsis [Writes the logic network into the BLIF file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntl_ManWriteBlif( Ntl_Man_t * p, char * pFileName ) -{ - Ntl_Mod_t * pModel; - int i, bzError; - bz2file b; - if ( p->pNal && !Ntl_FileIsType(pFileName, ".blif", ".blif.gz", ".blif.bz2") ) - { - p->pNalW( p, pFileName ); - return; - } - // write the GZ file - if (!strncmp(pFileName+strlen(pFileName)-3,".gz",3)) - { - Ntl_ManWriteBlifGz( p, pFileName ); - return; - } - - memset(&b,0,sizeof(b)); - b.nBytesMax = (1<<12); - b.buf = ABC_ALLOC( char,b.nBytesMax ); - - // start the output stream - b.f = fopen( pFileName, "wb" ); - if ( b.f == NULL ) - { - fprintf( stdout, "Ntl_ManWriteBlif(): Cannot open the output file \"%s\".\n", pFileName ); - ABC_FREE(b.buf); - return; - } - if (!strncmp(pFileName+strlen(pFileName)-4,".bz2",4)) { - b.b = BZ2_bzWriteOpen( &bzError, b.f, 9, 0, 0 ); - if ( bzError != BZ_OK ) { - BZ2_bzWriteClose( &bzError, b.b, 0, NULL, NULL ); - fprintf( stdout, "Ntl_ManWriteBlif(): Cannot start compressed stream.\n" ); - fclose( b.f ); - ABC_FREE(b.buf); - return; - } - } - - fprintfBz2( &b, "# Benchmark \"%s\" written by ABC-8 on %s\n", p->pName, Aig_TimeStamp() ); - // write the models - Ntl_ManForEachModel( p, pModel, i ) - Ntl_ManWriteBlifModelBz2( &b, pModel, i==0 ); - // close the file - if (b.b) { - BZ2_bzWriteClose( &bzError, b.b, 0, NULL, NULL ); - if (bzError == BZ_IO_ERROR) { - fprintf( stdout, "Ntl_ManWriteBlif(): I/O error closing compressed stream.\n" ); - fclose( b.f ); - ABC_FREE(b.buf); - return; - } - } - fclose( b.f ); - ABC_FREE(b.buf); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ntl/ntl_.c b/src/aig/ntl/ntl_.c deleted file mode 100644 index 9b0b1d0a..00000000 --- a/src/aig/ntl/ntl_.c +++ /dev/null @@ -1,52 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ntl/ntlnwk.h b/src/aig/ntl/ntlnwk.h deleted file mode 100644 index 0b07f243..00000000 --- a/src/aig/ntl/ntlnwk.h +++ /dev/null @@ -1,113 +0,0 @@ -/**CFile**************************************************************** - - FileName [ntlnwk.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Netlist and network representation.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ntlnwk.h,v 1.3 2008/10/24 14:18:44 mjarvin Exp $] - -***********************************************************************/ - -#ifndef __NTLNWK_H__ -#define __NTLNWK_H__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Ntl_Man_t_ Ntl_Man_t; -typedef struct Nwk_Man_t_ Nwk_Man_t; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// INLINED FUNCTIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -extern ABC_DLL Ntl_Man_t * Ntl_ManReadBlif( char * pFileName, int fCheck ); -extern ABC_DLL void Ntl_ManWriteBlif( Ntl_Man_t * p, char * pFileName ); - -extern ABC_DLL Tim_Man_t * Ntl_ManReadTimeMan( Ntl_Man_t * p ); -extern ABC_DLL Ntl_Man_t * Ntl_ManDup( Ntl_Man_t * p ); -extern ABC_DLL void Ntl_ManFree( Ntl_Man_t * p ); -extern ABC_DLL int Ntl_ManIsComb( Ntl_Man_t * p ); -extern ABC_DLL void Ntl_ManPrintStats( Ntl_Man_t * p ); -extern ABC_DLL int Ntl_ManSweep( Ntl_Man_t * p, int fVerbose ); -extern ABC_DLL Ntl_Man_t * Ntl_ManInsertNtk( Ntl_Man_t * p, Nwk_Man_t * pNtk ); -extern ABC_DLL Ntl_Man_t * Ntl_ManInsertAig( Ntl_Man_t * p, Aig_Man_t * pAig ); -extern ABC_DLL Aig_Man_t * Ntl_ManExtract( Ntl_Man_t * p ); -extern ABC_DLL Aig_Man_t * Ntl_ManCollapse( Ntl_Man_t * p, int fSeq ); -extern ABC_DLL Aig_Man_t * Ntl_ManCollapseSeq( Ntl_Man_t * p, int nMinDomSize, int fVerbose ); -extern ABC_DLL Ntl_Man_t * Ntl_ManDupCollapseLuts( Ntl_Man_t * p ); -extern ABC_DLL Ntl_Man_t * Ntl_ManFraig( Ntl_Man_t * p, int nPartSize, int nConfLimit, int nLevelMax, int fUseCSat, int fVerbose ); -extern ABC_DLL void Ntl_ManPrepareCecMans( Ntl_Man_t * pMan1, Ntl_Man_t * pMan2, Aig_Man_t ** ppAig1, Aig_Man_t ** ppAig2 ); -extern ABC_DLL Vec_Ptr_t * Ntl_ManCollectCiNames( Ntl_Man_t * p ); -extern ABC_DLL Vec_Ptr_t * Ntl_ManCollectCoNames( Ntl_Man_t * p ); -extern ABC_DLL Ntl_Man_t * Ntl_ManScl( Ntl_Man_t * p, int fLatchConst, int fLatchEqual, int fVerbose ); -extern ABC_DLL Ntl_Man_t * Ntl_ManLcorr( Ntl_Man_t * p, int nConfMax, int fScorrGia, int fUseCSat, int fVerbose ); -extern ABC_DLL Ntl_Man_t * Ntl_ManSsw( Ntl_Man_t * p, Fra_Ssw_t * pPars ); -extern ABC_DLL Ntl_Man_t * Ntl_ManScorr( Ntl_Man_t * p, Ssw_Pars_t * pPars ); -extern ABC_DLL void Ntl_ManTransformInitValues( Ntl_Man_t * p ); - -extern ABC_DLL void Ntl_ManPrepareCec( char * pFileName1, char * pFileName2, Aig_Man_t ** ppMan1, Aig_Man_t ** ppMan2 ); -extern ABC_DLL Aig_Man_t * Ntl_ManPrepareSec( char * pFileName1, char * pFileName2 ); - -extern ABC_DLL Nwk_Man_t * Ntl_ManExtractNwk( Ntl_Man_t * p, Aig_Man_t * pAig, Tim_Man_t * pManTime ); -extern ABC_DLL Nwk_Man_t * Ntl_ManReadNwk( char * pFileName, Aig_Man_t * pAig, Tim_Man_t * pManTime ); -extern ABC_DLL void Nwk_ManPrintStats( Nwk_Man_t * p, If_Lib_t * pLutLib, int fSaveBest, int fDumpResult, int fPower, Ntl_Man_t * pNtl ); -extern ABC_DLL void Nwk_ManPrintStatsShort( Ntl_Man_t * p, Aig_Man_t * pAig, Nwk_Man_t * pNtk ); -extern ABC_DLL void Nwk_ManPrintFanioNew( Nwk_Man_t * p ); -extern ABC_DLL Nwk_Man_t * Nwk_MappingIf( Aig_Man_t * p, Tim_Man_t * pManTime, If_Par_t * pPars ); -extern ABC_DLL void Nwk_ManSetIfParsDefault( If_Par_t * pPars ); -extern ABC_DLL void Nwk_ManBidecResyn( Nwk_Man_t * p, int fVerbose ); -extern ABC_DLL Aig_Man_t * Nwk_ManSpeedup( Nwk_Man_t * p, int fUseLutLib, int Percentage, int Degree, int fVerbose, int fVeryVerbose ); -extern ABC_DLL Aig_Man_t * Nwk_ManStrash( Nwk_Man_t * p ); -extern ABC_DLL Vec_Int_t * Nwk_ManLutMerge( Nwk_Man_t * p, void * pPars ); -extern ABC_DLL int Nwk_ManCheck( Nwk_Man_t * p ); -extern ABC_DLL void Nwk_ManDumpBlif( Nwk_Man_t * p, char * pFileName, Vec_Ptr_t * vCiNames, Vec_Ptr_t * vCoNames ); -extern ABC_DLL void Nwk_ManFree( Nwk_Man_t * p ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/nwk/module.make b/src/aig/nwk/module.make deleted file mode 100644 index f4b19e1a..00000000 --- a/src/aig/nwk/module.make +++ /dev/null @@ -1,14 +0,0 @@ -SRC += src/aig/nwk/nwkAig.c \ - src/aig/nwk/nwkCheck.c \ - src/aig/nwk/nwkBidec.c \ - src/aig/nwk/nwkDfs.c \ - src/aig/nwk/nwkFanio.c \ - src/aig/nwk/nwkFlow.c \ - src/aig/nwk/nwkMan.c \ - src/aig/nwk/nwkMap.c \ - src/aig/nwk/nwkMerge.c \ - src/aig/nwk/nwkObj.c \ - src/aig/nwk/nwkSpeedup.c \ - src/aig/nwk/nwkStrash.c \ - src/aig/nwk/nwkTiming.c \ - src/aig/nwk/nwkUtil.c diff --git a/src/aig/nwk/nwk.h b/src/aig/nwk/nwk.h deleted file mode 100644 index acbcbf4a..00000000 --- a/src/aig/nwk/nwk.h +++ /dev/null @@ -1,307 +0,0 @@ -/**CFile**************************************************************** - - FileName [nwk.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Logic network representation.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: nwk.h,v 1.1 2008/05/14 22:13:09 wudenni Exp $] - -***********************************************************************/ - -#ifndef __NWK_H__ -#define __NWK_H__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "aig.h" -#include "hop.h" -#include "tim.h" -#include "if.h" -#include "bdc.h" - -#include "fra.h" -#include "ssw.h" -#include "ntlnwk.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -ABC_NAMESPACE_HEADER_START - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Nwk_Obj_t_ Nwk_Obj_t; - -// object types -typedef enum { - NWK_OBJ_NONE, // 0: non-existant object - NWK_OBJ_CI, // 1: combinational input - NWK_OBJ_CO, // 2: combinational output - NWK_OBJ_NODE, // 3: logic node - NWK_OBJ_LATCH, // 4: register - NWK_OBJ_VOID // 5: unused object -} Nwk_Type_t; - -struct Nwk_Man_t_ -{ - // models of this design - char * pName; // the name of this design - char * pSpec; // the name of input file - // node 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 * vObjs; // the objects in the topological order - int nObjs[NWK_OBJ_VOID]; // counter of objects of each type - int nFanioPlus; // the number of extra fanins/fanouts alloc by default - // functionality, timing, memory, etc - Hop_Man_t * pManHop; // the functionality representation - Tim_Man_t * pManTime; // the timing manager - If_Lib_t * pLutLib; // the LUT library - Aig_MmFlex_t * pMemObjs; // memory for objects - Vec_Ptr_t * vTemp; // array used for incremental updates - int nTravIds; // the counter of traversal IDs - int nRealloced; // the number of realloced nodes - // sequential information - int nLatches; // the total number of latches - int nTruePis; // the number of true primary inputs - int nTruePos; // the number of true primary outputs -}; - -struct Nwk_Obj_t_ -{ - Nwk_Man_t * pMan; // the manager - Hop_Obj_t * pFunc; // functionality - void * pCopy; // temporary pointer - union { - void * pNext; // temporary pointer - int iTemp; // temporary number - }; - // node information - unsigned Type : 3; // object type - unsigned fInvert : 1; // complemented attribute - unsigned MarkA : 1; // temporary mark - unsigned MarkB : 1; // temporary mark - unsigned MarkC : 1; // temporary mark - unsigned PioId : 25; // number of this node in the PI/PO list - int Id; // unique ID - int TravId; // traversal ID - // timing information - int Level; // the topological level - float tArrival; // the arrival time - float tRequired; // the required time - float tSlack; // the slack - // fanin/fanout representation - int nFanins; // the number of fanins - int nFanouts; // the number of fanouts - int nFanioAlloc; // the number of allocated fanins/fanouts - Nwk_Obj_t ** pFanio; // fanins/fanouts -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////// -/// INLINED FUNCTIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline int Nwk_ManCiNum( Nwk_Man_t * p ) { return p->nObjs[NWK_OBJ_CI]; } -static inline int Nwk_ManCoNum( Nwk_Man_t * p ) { return p->nObjs[NWK_OBJ_CO]; } -static inline int Nwk_ManNodeNum( Nwk_Man_t * p ) { return p->nObjs[NWK_OBJ_NODE]; } -static inline int Nwk_ManLatchNum( Nwk_Man_t * p ) { return p->nObjs[NWK_OBJ_LATCH]; } -static inline int Nwk_ManObjNumMax( Nwk_Man_t * p ) { return Vec_PtrSize(p->vObjs); } - -static inline Nwk_Obj_t * Nwk_ManCi( Nwk_Man_t * p, int i ) { return (Nwk_Obj_t *)Vec_PtrEntry( p->vCis, i ); } -static inline Nwk_Obj_t * Nwk_ManCo( Nwk_Man_t * p, int i ) { return (Nwk_Obj_t *)Vec_PtrEntry( p->vCos, i ); } -static inline Nwk_Obj_t * Nwk_ManObj( Nwk_Man_t * p, int i ) { return (Nwk_Obj_t *)Vec_PtrEntry( p->vObjs, i ); } - -static inline int Nwk_ObjId( Nwk_Obj_t * p ) { return p->Id; } -static inline int Nwk_ObjPioNum( Nwk_Obj_t * p ) { return p->PioId; } -static inline int Nwk_ObjFaninNum( Nwk_Obj_t * p ) { return p->nFanins; } -static inline int Nwk_ObjFanoutNum( Nwk_Obj_t * p ) { return p->nFanouts; } - -static inline Nwk_Obj_t * Nwk_ObjFanin0( Nwk_Obj_t * p ) { return p->pFanio[0]; } -static inline Nwk_Obj_t * Nwk_ObjFanout0( Nwk_Obj_t * p ) { return p->pFanio[p->nFanins]; } -static inline Nwk_Obj_t * Nwk_ObjFanin( Nwk_Obj_t * p, int i ) { return p->pFanio[i]; } -static inline Nwk_Obj_t * Nwk_ObjFanout( Nwk_Obj_t * p, int i ) { return p->pFanio[p->nFanins+1]; } - -static inline int Nwk_ObjIsNone( Nwk_Obj_t * p ) { return p->Type == NWK_OBJ_NONE; } -static inline int Nwk_ObjIsCi( Nwk_Obj_t * p ) { return p->Type == NWK_OBJ_CI; } -static inline int Nwk_ObjIsCo( Nwk_Obj_t * p ) { return p->Type == NWK_OBJ_CO; } -static inline int Nwk_ObjIsNode( Nwk_Obj_t * p ) { return p->Type == NWK_OBJ_NODE; } -static inline int Nwk_ObjIsLatch( Nwk_Obj_t * p ) { return p->Type == NWK_OBJ_LATCH; } -static inline int Nwk_ObjIsPi( Nwk_Obj_t * p ) { return Nwk_ObjIsCi(p) && (p->pMan->pManTime == NULL || Tim_ManBoxForCi(p->pMan->pManTime, p->PioId) == -1); } -static inline int Nwk_ObjIsPo( Nwk_Obj_t * p ) { return Nwk_ObjIsCo(p) && (p->pMan->pManTime == NULL || Tim_ManBoxForCo(p->pMan->pManTime, p->PioId) == -1); } -static inline int Nwk_ObjIsLi( Nwk_Obj_t * p ) { return p->pMan->nTruePos && Nwk_ObjIsCo(p) && (int)p->PioId >= p->pMan->nTruePos; } -static inline int Nwk_ObjIsLo( Nwk_Obj_t * p ) { return p->pMan->nTruePis && Nwk_ObjIsCi(p) && (int)p->PioId >= p->pMan->nTruePis; } - -static inline float Nwk_ObjArrival( Nwk_Obj_t * pObj ) { return pObj->tArrival; } -static inline float Nwk_ObjRequired( Nwk_Obj_t * pObj ) { return pObj->tRequired; } -static inline float Nwk_ObjSlack( Nwk_Obj_t * pObj ) { return pObj->tSlack; } -static inline void Nwk_ObjSetArrival( Nwk_Obj_t * pObj, float Time ) { pObj->tArrival = Time; } -static inline void Nwk_ObjSetRequired( Nwk_Obj_t * pObj, float Time ) { pObj->tRequired = Time; } -static inline void Nwk_ObjSetSlack( Nwk_Obj_t * pObj, float Time ) { pObj->tSlack = Time; } - -static inline int Nwk_ObjLevel( Nwk_Obj_t * pObj ) { return pObj->Level; } -static inline void Nwk_ObjSetLevel( Nwk_Obj_t * pObj, int Level ) { pObj->Level = Level; } - -static inline void Nwk_ObjSetTravId( Nwk_Obj_t * pObj, int TravId ) { pObj->TravId = TravId; } -static inline void Nwk_ObjSetTravIdCurrent( Nwk_Obj_t * pObj ) { pObj->TravId = pObj->pMan->nTravIds; } -static inline void Nwk_ObjSetTravIdPrevious( Nwk_Obj_t * pObj ) { pObj->TravId = pObj->pMan->nTravIds - 1; } -static inline int Nwk_ObjIsTravIdCurrent( Nwk_Obj_t * pObj ) { return pObj->TravId == pObj->pMan->nTravIds; } -static inline int Nwk_ObjIsTravIdPrevious( Nwk_Obj_t * pObj ) { return pObj->TravId == pObj->pMan->nTravIds - 1; } - -static inline int Nwk_ManTimeEqual( float f1, float f2, float Eps ) { return (f1 < f2 + Eps) && (f2 < f1 + Eps); } -static inline int Nwk_ManTimeLess( float f1, float f2, float Eps ) { return (f1 < f2 + Eps); } -static inline int Nwk_ManTimeMore( float f1, float f2, float Eps ) { return (f1 + Eps > f2); } - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -#define Nwk_ManForEachCi( p, pObj, i ) \ - Vec_PtrForEachEntry( Nwk_Obj_t *, p->vCis, pObj, i ) -#define Nwk_ManForEachCo( p, pObj, i ) \ - Vec_PtrForEachEntry( Nwk_Obj_t *, p->vCos, pObj, i ) -#define Nwk_ManForEachPi( p, pObj, i ) \ - Vec_PtrForEachEntry( Nwk_Obj_t *, p->vCis, pObj, i ) \ - if ( !Nwk_ObjIsPi(pObj) ) {} else -#define Nwk_ManForEachPo( p, pObj, i ) \ - Vec_PtrForEachEntry( Nwk_Obj_t *, p->vCos, pObj, i ) \ - if ( !Nwk_ObjIsPo(pObj) ) {} else -#define Nwk_ManForEachObj( p, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize(p->vObjs)) && (((pObj) = (Nwk_Obj_t *)Vec_PtrEntry(p->vObjs, i)), 1); i++ ) \ - if ( pObj == NULL ) {} else -#define Nwk_ManForEachNode( p, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize(p->vObjs)) && (((pObj) = (Nwk_Obj_t *)Vec_PtrEntry(p->vObjs, i)), 1); i++ ) \ - if ( (pObj) == NULL || !Nwk_ObjIsNode(pObj) ) {} else -#define Nwk_ManForEachLatch( p, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize(p->vObjs)) && (((pObj) = (Nwk_Obj_t *)Vec_PtrEntry(p->vObjs, i)), 1); i++ ) \ - if ( (pObj) == NULL || !Nwk_ObjIsLatch(pObj) ) {} else - -#define Nwk_ObjForEachFanin( pObj, pFanin, i ) \ - for ( i = 0; (i < (int)(pObj)->nFanins) && ((pFanin) = (pObj)->pFanio[i]); i++ ) -#define Nwk_ObjForEachFanout( pObj, pFanout, i ) \ - for ( i = 0; (i < (int)(pObj)->nFanouts) && ((pFanout) = (pObj)->pFanio[(pObj)->nFanins+i]); i++ ) - -// sequential iterators -#define Nwk_ManForEachPiSeq( p, pObj, i ) \ - Vec_PtrForEachEntryStop( Nwk_Obj_t *, p->vCis, pObj, i, (p)->nTruePis ) -#define Nwk_ManForEachPoSeq( p, pObj, i ) \ - Vec_PtrForEachEntryStop( Nwk_Obj_t *, p->vCos, pObj, i, (p)->nTruePos ) -#define Nwk_ManForEachLoSeq( p, pObj, i ) \ - for ( i = 0; (i < (p)->nLatches) && (((pObj) = (Nwk_Obj_t *)Vec_PtrEntry(p->vCis, i+(p)->nTruePis)), 1); i++ ) -#define Nwk_ManForEachLiSeq( p, pObj, i ) \ - for ( i = 0; (i < (p)->nLatches) && (((pObj) = (Nwk_Obj_t *)Vec_PtrEntry(p->vCos, i+(p)->nTruePos)), 1); i++ ) -#define Nwk_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) \ - for ( i = 0; (i < (p)->nLatches) && (((pObjLi) = Nwk_ManCo(p, i+(p)->nTruePos)), 1) \ - && (((pObjLo) = Nwk_ManCi(p, i+(p)->nTruePis)), 1); i++ ) - - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== nwkAig.c ==========================================================*/ -extern ABC_DLL Vec_Ptr_t * Nwk_ManDeriveRetimingCut( Aig_Man_t * p, int fForward, int fVerbose ); -/*=== nwkBidec.c ==========================================================*/ -extern ABC_DLL void Nwk_ManBidecResyn( Nwk_Man_t * pNtk, int fVerbose ); -extern ABC_DLL Hop_Obj_t * Nwk_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare, float dProb ); -/*=== nwkCheck.c ==========================================================*/ -extern ABC_DLL int Nwk_ManCheck( Nwk_Man_t * p ); -/*=== nwkDfs.c ==========================================================*/ -extern ABC_DLL int Nwk_ManVerifyTopoOrder( Nwk_Man_t * pNtk ); -extern ABC_DLL int Nwk_ManLevelBackup( Nwk_Man_t * pNtk ); -extern ABC_DLL int Nwk_ManLevel( Nwk_Man_t * pNtk ); -extern ABC_DLL int Nwk_ManLevelMax( Nwk_Man_t * pNtk ); -extern ABC_DLL Vec_Vec_t * Nwk_ManLevelize( Nwk_Man_t * pNtk ); -extern ABC_DLL Vec_Ptr_t * Nwk_ManDfs( Nwk_Man_t * pNtk ); -extern ABC_DLL Vec_Ptr_t * Nwk_ManDfsNodes( Nwk_Man_t * pNtk, Nwk_Obj_t ** ppNodes, int nNodes ); -extern ABC_DLL Vec_Ptr_t * Nwk_ManDfsReverse( Nwk_Man_t * pNtk ); -extern ABC_DLL Vec_Ptr_t * Nwk_ManSupportNodes( Nwk_Man_t * pNtk, Nwk_Obj_t ** ppNodes, int nNodes ); -extern ABC_DLL void Nwk_ManSupportSum( Nwk_Man_t * pNtk ); -extern ABC_DLL int Nwk_ObjMffcLabel( Nwk_Obj_t * pNode ); -/*=== nwkFanio.c ==========================================================*/ -extern ABC_DLL void Nwk_ObjCollectFanins( Nwk_Obj_t * pNode, Vec_Ptr_t * vNodes ); -extern ABC_DLL void Nwk_ObjCollectFanouts( Nwk_Obj_t * pNode, Vec_Ptr_t * vNodes ); -extern ABC_DLL int Nwk_ObjFindFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanin ); -extern ABC_DLL int Nwk_ObjFindFanout( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanout ); -extern ABC_DLL void Nwk_ObjAddFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanin ); -extern ABC_DLL void Nwk_ObjDeleteFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanin ); -extern ABC_DLL void Nwk_ObjPatchFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFaninOld, Nwk_Obj_t * pFaninNew ); -extern ABC_DLL void Nwk_ObjTransferFanout( Nwk_Obj_t * pNodeFrom, Nwk_Obj_t * pNodeTo ); -extern ABC_DLL void Nwk_ObjReplace( Nwk_Obj_t * pNodeOld, Nwk_Obj_t * pNodeNew ); -/*=== nwkFlow.c ============================================================*/ -extern ABC_DLL Vec_Ptr_t * Nwk_ManRetimeCutForward( Nwk_Man_t * pMan, int nLatches, int fVerbose ); -extern ABC_DLL Vec_Ptr_t * Nwk_ManRetimeCutBackward( Nwk_Man_t * pMan, int nLatches, int fVerbose ); -/*=== nwkMan.c ============================================================*/ -extern ABC_DLL Nwk_Man_t * Nwk_ManAlloc(); -extern ABC_DLL void Nwk_ManFree( Nwk_Man_t * p ); -extern ABC_DLL float Nwl_ManComputeTotalSwitching( Nwk_Man_t * pNtk ); -extern ABC_DLL void Nwk_ManPrintStats( Nwk_Man_t * p, If_Lib_t * pLutLib, int fSaveBest, int fDumpResult, int fPower, Ntl_Man_t * pNtl ); -/*=== nwkMap.c ============================================================*/ -extern ABC_DLL Nwk_Man_t * Nwk_MappingIf( Aig_Man_t * p, Tim_Man_t * pManTime, If_Par_t * pPars ); -/*=== nwkObj.c ============================================================*/ -extern ABC_DLL Nwk_Obj_t * Nwk_ManCreateCi( Nwk_Man_t * pMan, int nFanouts ); -extern ABC_DLL Nwk_Obj_t * Nwk_ManCreateCo( Nwk_Man_t * pMan ); -extern ABC_DLL Nwk_Obj_t * Nwk_ManCreateNode( Nwk_Man_t * pMan, int nFanins, int nFanouts ); -extern ABC_DLL Nwk_Obj_t * Nwk_ManCreateBox( Nwk_Man_t * pMan, int nFanins, int nFanouts ); -extern ABC_DLL Nwk_Obj_t * Nwk_ManCreateLatch( Nwk_Man_t * pMan ); -extern ABC_DLL void Nwk_ManDeleteNode( Nwk_Obj_t * pObj ); -extern ABC_DLL void Nwk_ManDeleteNode_rec( Nwk_Obj_t * pObj ); -/*=== nwkSpeedup.c ============================================================*/ -extern ABC_DLL Aig_Man_t * Nwk_ManSpeedup( Nwk_Man_t * pNtk, int fUseLutLib, int Percentage, int Degree, int fVerbose, int fVeryVerbose ); -/*=== nwkStrash.c ============================================================*/ -extern ABC_DLL Aig_Man_t * Nwk_ManStrash( Nwk_Man_t * pNtk ); -/*=== nwkTiming.c ============================================================*/ -extern ABC_DLL int Nwk_ManVerifyTiming( Nwk_Man_t * pNtk ); -extern ABC_DLL void Nwk_ManDelayTraceSortPins( Nwk_Obj_t * pNode, int * pPinPerm, float * pPinDelays ); -extern ABC_DLL float Nwk_ManDelayTraceLut( Nwk_Man_t * pNtk ); -extern ABC_DLL void Nwk_ManDelayTracePrint( Nwk_Man_t * pNtk ); -extern ABC_DLL void Nwk_ManUpdate( Nwk_Obj_t * pObj, Nwk_Obj_t * pObjNew, Vec_Vec_t * vLevels ); -extern ABC_DLL int Nwk_ManVerifyLevel( Nwk_Man_t * pNtk ); -/*=== nwkUtil.c ============================================================*/ -extern ABC_DLL void Nwk_ManIncrementTravId( Nwk_Man_t * pNtk ); -extern ABC_DLL int Nwk_ManGetFaninMax( Nwk_Man_t * pNtk ); -extern ABC_DLL int Nwk_ManGetTotalFanins( Nwk_Man_t * pNtk ); -extern ABC_DLL int Nwk_ManPiNum( Nwk_Man_t * pNtk ); -extern ABC_DLL int Nwk_ManPoNum( Nwk_Man_t * pNtk ); -extern ABC_DLL int Nwk_ManGetAigNodeNum( Nwk_Man_t * pNtk ); -extern ABC_DLL int Nwk_NodeCompareLevelsIncrease( Nwk_Obj_t ** pp1, Nwk_Obj_t ** pp2 ); -extern ABC_DLL int Nwk_NodeCompareLevelsDecrease( Nwk_Obj_t ** pp1, Nwk_Obj_t ** pp2 ); -extern ABC_DLL void Nwk_ObjPrint( Nwk_Obj_t * pObj ); -extern ABC_DLL void Nwk_ManDumpBlif( Nwk_Man_t * pNtk, char * pFileName, Vec_Ptr_t * vCiNames, Vec_Ptr_t * vCoNames ); -extern ABC_DLL void Nwk_ManPrintFanioNew( Nwk_Man_t * pNtk ); -extern ABC_DLL void Nwk_ManCleanMarks( Nwk_Man_t * pNtk ); -extern ABC_DLL void Nwk_ManMinimumBase( Nwk_Man_t * pNtk, int fVerbose ); -extern ABC_DLL void Nwk_ManRemoveDupFanins( Nwk_Man_t * pNtk, int fVerbose ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/nwk/nwkAig.c b/src/aig/nwk/nwkAig.c deleted file mode 100644 index b38fbdfa..00000000 --- a/src/aig/nwk/nwkAig.c +++ /dev/null @@ -1,112 +0,0 @@ -/**CFile**************************************************************** - - FileName [nwkAig.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Netlist representation.] - - Synopsis [Translating of AIG into the network.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: nwkAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "nwk.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Converts AIG into the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Nwk_Man_t * Nwk_ManDeriveFromAig( Aig_Man_t * p ) -{ - Nwk_Man_t * pNtk; - Aig_Obj_t * pObj; - int i; - pNtk = Nwk_ManAlloc(); - pNtk->nFanioPlus = 0; - Hop_ManStop( pNtk->pManHop ); - pNtk->pManHop = NULL; - pNtk->pName = Aig_UtilStrsav( p->pName ); - pNtk->pSpec = Aig_UtilStrsav( p->pSpec ); - pObj = Aig_ManConst1(p); - pObj->pData = Nwk_ManCreateNode( pNtk, 0, pObj->nRefs ); - Aig_ManForEachPi( p, pObj, i ) - pObj->pData = Nwk_ManCreateCi( pNtk, pObj->nRefs ); - Aig_ManForEachNode( p, pObj, i ) - { - pObj->pData = Nwk_ManCreateNode( pNtk, 2, pObj->nRefs ); - Nwk_ObjAddFanin( (Nwk_Obj_t *)pObj->pData, (Nwk_Obj_t *)Aig_ObjFanin0(pObj)->pData ); - Nwk_ObjAddFanin( (Nwk_Obj_t *)pObj->pData, (Nwk_Obj_t *)Aig_ObjFanin1(pObj)->pData ); - } - Aig_ManForEachPo( p, pObj, i ) - { - pObj->pData = Nwk_ManCreateCo( pNtk ); - Nwk_ObjAddFanin( (Nwk_Obj_t *)pObj->pData, (Nwk_Obj_t *)Aig_ObjFanin0(pObj)->pData ); - } - return pNtk; -} - -/**Function************************************************************* - - Synopsis [Converts AIG into the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Nwk_ManDeriveRetimingCut( Aig_Man_t * p, int fForward, int fVerbose ) -{ - Vec_Ptr_t * vNodes; - Nwk_Man_t * pNtk; - Nwk_Obj_t * pNode; - Aig_Obj_t * pObj; - int i; - pNtk = Nwk_ManDeriveFromAig( p ); - if ( fForward ) - vNodes = Nwk_ManRetimeCutForward( pNtk, Aig_ManRegNum(p), fVerbose ); - else - vNodes = Nwk_ManRetimeCutBackward( pNtk, Aig_ManRegNum(p), fVerbose ); - Aig_ManForEachObj( p, pObj, i ) - ((Nwk_Obj_t *)pObj->pData)->pCopy = pObj; - Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pNode, i ) - Vec_PtrWriteEntry( vNodes, i, pNode->pCopy ); - Nwk_ManFree( pNtk ); -// assert( Vec_PtrSize(vNodes) <= Aig_ManRegNum(p) ); - return vNodes; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/nwk/nwkBidec.c b/src/aig/nwk/nwkBidec.c deleted file mode 100644 index 567b904b..00000000 --- a/src/aig/nwk/nwkBidec.c +++ /dev/null @@ -1,177 +0,0 @@ -/**CFile**************************************************************** - - FileName [nwkBidec.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Logic network representation.] - - Synopsis [Bi-decomposition of local functions.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: nwkBidec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "nwk.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline int Extra_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } -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_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 Hop_Obj_t * Bdc_FunCopyHop( Bdc_Fun_t * pObj ) { return Hop_NotCond( (Hop_Obj_t *)Bdc_FuncCopy(Bdc_Regular(pObj)), Bdc_IsComplement(pObj) ); } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Resynthesizes nodes using bi-decomposition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Nwk_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare, float dProb ) -{ - unsigned * pTruth; - Bdc_Fun_t * pFunc; - int nNodes, i; - assert( nVars <= 16 ); - // derive truth table - pTruth = Hop_ManConvertAigToTruth( pHop, Hop_Regular(pRoot), nVars, vTruth, 0 ); - if ( Hop_IsComplement(pRoot) ) - for ( i = Aig_TruthWordNum(nVars)-1; i >= 0; i-- ) - pTruth[i] = ~pTruth[i]; - // perform power-aware decomposition - if ( dProb >= 0.0 ) - { - float Prob = (float)2.0 * dProb * (1.0 - dProb); - assert( Prob >= 0.0 && Prob <= 0.5 ); - if ( Prob >= 0.4 ) - { - Extra_TruthNot( puCare, puCare, nVars ); - if ( dProb > 0.5 ) // more 1s than 0s - Extra_TruthOr( pTruth, pTruth, puCare, nVars ); - else - Extra_TruthSharp( pTruth, pTruth, puCare, nVars ); - Extra_TruthNot( puCare, puCare, nVars ); - // decompose truth table - Bdc_ManDecompose( p, pTruth, NULL, nVars, NULL, 1000 ); - } - else - { - // decompose truth table - Bdc_ManDecompose( p, pTruth, puCare, nVars, NULL, 1000 ); - } - } - else - { - // decompose truth table - Bdc_ManDecompose( p, pTruth, puCare, nVars, NULL, 1000 ); - } - // convert back into HOP - Bdc_FuncSetCopy( Bdc_ManFunc( p, 0 ), Hop_ManConst1( pHop ) ); - for ( i = 0; i < nVars; i++ ) - Bdc_FuncSetCopy( Bdc_ManFunc( p, i+1 ), Hop_ManPi( pHop, i ) ); - nNodes = Bdc_ManNodeNum(p); - for ( i = nVars + 1; i < nNodes; i++ ) - { - pFunc = Bdc_ManFunc( p, i ); - Bdc_FuncSetCopy( pFunc, Hop_And( pHop, Bdc_FunCopyHop(Bdc_FuncFanin0(pFunc)), Bdc_FunCopyHop(Bdc_FuncFanin1(pFunc)) ) ); - } - return Bdc_FunCopyHop( Bdc_ManRoot(p) ); -} - -/**Function************************************************************* - - Synopsis [Resynthesizes nodes using bi-decomposition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManBidecResyn( Nwk_Man_t * pNtk, int fVerbose ) -{ - Bdc_Par_t Pars = {0}, * pPars = &Pars; - Bdc_Man_t * p; - Nwk_Obj_t * pObj; - Vec_Int_t * vTruth; - int i, nGainTotal = 0, nNodes1, nNodes2; - int clk = clock(); - pPars->nVarsMax = Nwk_ManGetFaninMax( pNtk ); - pPars->fVerbose = fVerbose; - if ( pPars->nVarsMax < 2 ) - { - printf( "Resynthesis is not performed for networks whose nodes are less than 2 inputs.\n" ); - return; - } - if ( pPars->nVarsMax > 15 ) - { - if ( fVerbose ) - printf( "Resynthesis is not performed for nodes with more than 15 inputs.\n" ); - pPars->nVarsMax = 15; - } - vTruth = Vec_IntAlloc( 0 ); - p = Bdc_ManAlloc( pPars ); - Nwk_ManForEachNode( pNtk, pObj, i ) - { - if ( Nwk_ObjFaninNum(pObj) > 15 ) - continue; - nNodes1 = Hop_DagSize(pObj->pFunc); - pObj->pFunc = Nwk_NodeIfNodeResyn( p, pNtk->pManHop, pObj->pFunc, Nwk_ObjFaninNum(pObj), vTruth, NULL, -1.0 ); - nNodes2 = Hop_DagSize(pObj->pFunc); - nGainTotal += nNodes1 - nNodes2; - } - Bdc_ManFree( p ); - Vec_IntFree( vTruth ); - if ( fVerbose ) - { - printf( "Total gain in AIG nodes = %d. ", nGainTotal ); - ABC_PRT( "Total runtime", clock() - clk ); - } -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/nwk/nwkCheck.c b/src/aig/nwk/nwkCheck.c deleted file mode 100644 index 24a0d513..00000000 --- a/src/aig/nwk/nwkCheck.c +++ /dev/null @@ -1,76 +0,0 @@ -/**CFile**************************************************************** - - FileName [nwkCheck.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Logic network representation.] - - Synopsis [Consistency checking procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: nwkCheck.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "nwk.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Checking the logic network for consistency.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManCheck( Nwk_Man_t * p ) -{ - Nwk_Obj_t * pObj, * pNext; - int i, k, m; - // check if the nodes have duplicated fanins - Nwk_ManForEachNode( p, pObj, i ) - { - for ( k = 0; k < pObj->nFanins; k++ ) - for ( m = k + 1; m < pObj->nFanins; m++ ) - if ( pObj->pFanio[k] == pObj->pFanio[m] ) - printf( "Node %d has duplicated fanin %d.\n", pObj->Id, pObj->pFanio[k]->Id ); - } - // check if all nodes are in the correct fanin/fanout relationship - Nwk_ManForEachObj( p, pObj, i ) - { - Nwk_ObjForEachFanin( pObj, pNext, k ) - if ( Nwk_ObjFanoutNum(pNext) < 100 && Nwk_ObjFindFanout( pNext, pObj ) == -1 ) - printf( "Nwk_ManCheck(): Object %d has fanin %d which does not have a corresponding fanout.\n", pObj->Id, pNext->Id ); - Nwk_ObjForEachFanout( pObj, pNext, k ) - if ( Nwk_ObjFindFanin( pNext, pObj ) == -1 ) - printf( "Nwk_ManCheck(): Object %d has fanout %d which does not have a corresponding fanin.\n", pObj->Id, pNext->Id ); - } - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/nwk/nwkDfs.c b/src/aig/nwk/nwkDfs.c deleted file mode 100644 index 59752c59..00000000 --- a/src/aig/nwk/nwkDfs.c +++ /dev/null @@ -1,664 +0,0 @@ -/**CFile**************************************************************** - - FileName [nwkDfs.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Logic network representation.] - - Synopsis [DFS traversals.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: nwkDfs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "nwk.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Verifies that the objects are in a topo order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManVerifyTopoOrder( Nwk_Man_t * pNtk ) -{ - Nwk_Obj_t * pObj, * pNext; - int i, k, iBox, iTerm1, nTerms; - Nwk_ManIncrementTravId( pNtk ); - Nwk_ManForEachObj( pNtk, pObj, i ) - { - if ( Nwk_ObjIsNode(pObj) || Nwk_ObjIsCo(pObj) ) - { - Nwk_ObjForEachFanin( pObj, pNext, k ) - { - if ( !Nwk_ObjIsTravIdCurrent(pNext) ) - { - printf( "Node %d has fanin %d that is not in a topological order.\n", pObj->Id, pNext->Id ); - return 0; - } - } - } - else if ( Nwk_ObjIsCi(pObj) ) - { - if ( pNtk->pManTime ) - { - iBox = Tim_ManBoxForCi( pNtk->pManTime, pObj->PioId ); - if ( iBox >= 0 ) // this is not a true PI - { - iTerm1 = Tim_ManBoxInputFirst( pNtk->pManTime, iBox ); - nTerms = Tim_ManBoxInputNum( pNtk->pManTime, iBox ); - for ( k = 0; k < nTerms; k++ ) - { - pNext = Nwk_ManCo( pNtk, iTerm1 + k ); - if ( !Nwk_ObjIsTravIdCurrent(pNext) ) - { - printf( "Box %d has input %d that is not in a topological order.\n", iBox, pNext->Id ); - return 0; - } - } - } - } - } - else - assert( 0 ); - Nwk_ObjSetTravIdCurrent( pObj ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Computes the number of logic levels not counting PIs/POs.] - - Description [Assumes that white boxes have unit level.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManLevelBackup( Nwk_Man_t * pNtk ) -{ - Tim_Man_t * pManTimeUnit; - Nwk_Obj_t * pObj, * pFanin; - int i, k, LevelMax, Level; - assert( Nwk_ManVerifyTopoOrder(pNtk) ); - // clean the levels - Nwk_ManForEachObj( pNtk, pObj, i ) - Nwk_ObjSetLevel( pObj, 0 ); - // perform level computation - LevelMax = 0; - pManTimeUnit = pNtk->pManTime ? Tim_ManDupUnit( pNtk->pManTime ) : NULL; - if ( pManTimeUnit ) - Tim_ManIncrementTravId( pManTimeUnit ); - Nwk_ManForEachObj( pNtk, pObj, i ) - { - if ( Nwk_ObjIsCi(pObj) ) - { - Level = pManTimeUnit? (int)Tim_ManGetCiArrival( pManTimeUnit, pObj->PioId ) : 0; - Nwk_ObjSetLevel( pObj, Level ); - } - else if ( Nwk_ObjIsCo(pObj) ) - { - Level = Nwk_ObjLevel( Nwk_ObjFanin0(pObj) ); - if ( pManTimeUnit ) - Tim_ManSetCoArrival( pManTimeUnit, pObj->PioId, (float)Level ); - Nwk_ObjSetLevel( pObj, Level ); - if ( LevelMax < Nwk_ObjLevel(pObj) ) - LevelMax = Nwk_ObjLevel(pObj); - } - else if ( Nwk_ObjIsNode(pObj) ) - { - Level = 0; - Nwk_ObjForEachFanin( pObj, pFanin, k ) - if ( Level < Nwk_ObjLevel(pFanin) ) - Level = Nwk_ObjLevel(pFanin); - Nwk_ObjSetLevel( pObj, Level + 1 ); - } - else - assert( 0 ); - } - // set the old timing manager - if ( pManTimeUnit ) - Tim_ManStop( pManTimeUnit ); - return LevelMax; -} - -/**Function************************************************************* - - Synopsis [Computes the number of logic levels not counting PIs/POs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManLevel_rec( Nwk_Obj_t * pObj ) -{ - Tim_Man_t * pManTime = pObj->pMan->pManTime; - Nwk_Obj_t * pNext; - int i, iBox, iTerm1, nTerms, LevelMax = 0; - if ( Nwk_ObjIsTravIdCurrent( pObj ) ) - return; - Nwk_ObjSetTravIdCurrent( pObj ); - if ( Nwk_ObjIsCi(pObj) ) - { - if ( pManTime ) - { - iBox = Tim_ManBoxForCi( pManTime, pObj->PioId ); - if ( iBox >= 0 ) // this is not a true PI - { - iTerm1 = Tim_ManBoxInputFirst( pManTime, iBox ); - nTerms = Tim_ManBoxInputNum( pManTime, iBox ); - for ( i = 0; i < nTerms; i++ ) - { - pNext = Nwk_ManCo(pObj->pMan, iTerm1 + i); - Nwk_ManLevel_rec( pNext ); - if ( LevelMax < Nwk_ObjLevel(pNext) ) - LevelMax = Nwk_ObjLevel(pNext); - } - LevelMax++; - } - } - } - else if ( Nwk_ObjIsNode(pObj) || Nwk_ObjIsCo(pObj) ) - { - Nwk_ObjForEachFanin( pObj, pNext, i ) - { - Nwk_ManLevel_rec( pNext ); - if ( LevelMax < Nwk_ObjLevel(pNext) ) - LevelMax = Nwk_ObjLevel(pNext); - } - if ( Nwk_ObjIsNode(pObj) && Nwk_ObjFaninNum(pObj) > 0 ) - LevelMax++; - } - else - assert( 0 ); - Nwk_ObjSetLevel( pObj, LevelMax ); -} - -/**Function************************************************************* - - Synopsis [Computes the number of logic levels not counting PIs/POs.] - - Description [Does not assume that the objects are in a topo order.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManLevel( Nwk_Man_t * pNtk ) -{ - Nwk_Obj_t * pObj; - int i, LevelMax = 0; - Nwk_ManForEachObj( pNtk, pObj, i ) - Nwk_ObjSetLevel( pObj, 0 ); - Nwk_ManIncrementTravId( pNtk ); - Nwk_ManForEachPo( pNtk, pObj, i ) - { - Nwk_ManLevel_rec( pObj ); - if ( LevelMax < Nwk_ObjLevel(pObj) ) - LevelMax = Nwk_ObjLevel(pObj); - } - Nwk_ManForEachCi( pNtk, pObj, i ) - { - Nwk_ManLevel_rec( pObj ); - if ( LevelMax < Nwk_ObjLevel(pObj) ) - LevelMax = Nwk_ObjLevel(pObj); - } - return LevelMax; -} - -/**Function************************************************************* - - Synopsis [Computes the number of logic levels not counting PIs/POs.] - - Description [Does not assume that the objects are in a topo order.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManLevelMax( Nwk_Man_t * pNtk ) -{ - Nwk_Obj_t * pObj; - int i, LevelMax = 0; - Nwk_ManForEachPo( pNtk, pObj, i ) - if ( LevelMax < Nwk_ObjLevel(pObj) ) - LevelMax = Nwk_ObjLevel(pObj); - return LevelMax; -} - -/**Function************************************************************* - - Synopsis [Returns the array of objects in the AIG manager ordered by level.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Vec_t * Nwk_ManLevelize( Nwk_Man_t * pNtk ) -{ - Nwk_Obj_t * pObj; - Vec_Vec_t * vLevels; - int nLevels, i; - assert( Nwk_ManVerifyLevel(pNtk) ); - nLevels = Nwk_ManLevelMax( pNtk ); - vLevels = Vec_VecStart( nLevels + 1 ); - Nwk_ManForEachNode( pNtk, pObj, i ) - { - assert( Nwk_ObjLevel(pObj) <= nLevels ); - Vec_VecPush( vLevels, Nwk_ObjLevel(pObj), pObj ); - } - return vLevels; -} - - - -/**Function************************************************************* - - Synopsis [Performs DFS for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManDfs_rec( Nwk_Obj_t * pObj, Vec_Ptr_t * vNodes ) -{ - Nwk_Obj_t * pNext; - int i; - if ( Nwk_ObjIsTravIdCurrent( pObj ) ) - return; - Nwk_ObjSetTravIdCurrent( pObj ); - Nwk_ObjForEachFanin( pObj, pNext, i ) - Nwk_ManDfs_rec( pNext, vNodes ); - Vec_PtrPush( vNodes, pObj ); -} - -/**Function************************************************************* - - Synopsis [Returns the DFS ordered array of all objects except latches.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Nwk_ManDfs( Nwk_Man_t * pNtk ) -{ - Vec_Ptr_t * vNodes; - Nwk_Obj_t * pObj; - int i; - Nwk_ManIncrementTravId( pNtk ); - vNodes = Vec_PtrAlloc( 100 ); - Nwk_ManForEachObj( pNtk, pObj, i ) - { - if ( Nwk_ObjIsCi(pObj) ) - { - Nwk_ObjSetTravIdCurrent( pObj ); - Vec_PtrPush( vNodes, pObj ); - } - else if ( Nwk_ObjIsCo(pObj) ) - Nwk_ManDfs_rec( pObj, vNodes ); - } - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Performs DFS for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManDfsNodes_rec( Nwk_Obj_t * pObj, Vec_Ptr_t * vNodes ) -{ - Nwk_Obj_t * pNext; - int i; - if ( Nwk_ObjIsTravIdCurrent( pObj ) ) - return; - Nwk_ObjSetTravIdCurrent( pObj ); - if ( Nwk_ObjIsCi(pObj) ) - return; - assert( Nwk_ObjIsNode(pObj) ); - Nwk_ObjForEachFanin( pObj, pNext, i ) - Nwk_ManDfsNodes_rec( pNext, vNodes ); - Vec_PtrPush( vNodes, pObj ); -} - -/**Function************************************************************* - - Synopsis [Returns the set of internal nodes rooted in the given nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Nwk_ManDfsNodes( Nwk_Man_t * pNtk, Nwk_Obj_t ** ppNodes, int nNodes ) -{ - Vec_Ptr_t * vNodes; - int i; - // set the traversal ID - Nwk_ManIncrementTravId( 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 ( Nwk_ObjIsCo(ppNodes[i]) ) - Nwk_ManDfsNodes_rec( Nwk_ObjFanin0(ppNodes[i]), vNodes ); - else - Nwk_ManDfsNodes_rec( ppNodes[i], vNodes ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Performs DFS for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManDfsReverse_rec( Nwk_Obj_t * pObj, Vec_Ptr_t * vNodes ) -{ - Nwk_Obj_t * pNext; - int i, iBox, iTerm1, nTerms; - if ( Nwk_ObjIsTravIdCurrent( pObj ) ) - return; - Nwk_ObjSetTravIdCurrent( pObj ); - if ( Nwk_ObjIsCo(pObj) ) - { - if ( pObj->pMan->pManTime ) - { - iBox = Tim_ManBoxForCo( pObj->pMan->pManTime, pObj->PioId ); - if ( iBox >= 0 ) // this is not a true PO - { - iTerm1 = Tim_ManBoxOutputFirst( pObj->pMan->pManTime, iBox ); - nTerms = Tim_ManBoxOutputNum( pObj->pMan->pManTime, iBox ); - for ( i = 0; i < nTerms; i++ ) - { - pNext = Nwk_ManCi(pObj->pMan, iTerm1 + i); - Nwk_ManDfsReverse_rec( pNext, vNodes ); - } - } - } - } - else if ( Nwk_ObjIsNode(pObj) || Nwk_ObjIsCi(pObj) ) - { - Nwk_ObjForEachFanout( pObj, pNext, i ) - Nwk_ManDfsReverse_rec( pNext, vNodes ); - } - else - assert( 0 ); - Vec_PtrPush( vNodes, pObj ); -} - -/**Function************************************************************* - - Synopsis [Returns the DFS ordered array of all objects except latches.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Nwk_ManDfsReverse( Nwk_Man_t * pNtk ) -{ - Vec_Ptr_t * vNodes; - Nwk_Obj_t * pObj; - int i; - Nwk_ManIncrementTravId( pNtk ); - vNodes = Vec_PtrAlloc( 100 ); - Nwk_ManForEachPi( pNtk, pObj, i ) - Nwk_ManDfsReverse_rec( pObj, vNodes ); - // add nodes without fanins - Nwk_ManForEachNode( pNtk, pObj, i ) - if ( Nwk_ObjFaninNum(pObj) == 0 && !Nwk_ObjIsTravIdCurrent(pObj) ) - Vec_PtrPush( vNodes, pObj ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Performs DFS for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManSupportNodes_rec( Nwk_Obj_t * pNode, Vec_Ptr_t * vNodes ) -{ - Nwk_Obj_t * pFanin; - int i; - // if this node is already visited, skip - if ( Nwk_ObjIsTravIdCurrent( pNode ) ) - return; - // mark the node as visited - Nwk_ObjSetTravIdCurrent( pNode ); - // collect the CI - if ( Nwk_ObjIsCi(pNode) ) - { - Vec_PtrPush( vNodes, pNode ); - return; - } - assert( Nwk_ObjIsNode( pNode ) ); - // visit the transitive fanin of the node - Nwk_ObjForEachFanin( pNode, pFanin, i ) - Nwk_ManSupportNodes_rec( pFanin, vNodes ); -} - -/**Function************************************************************* - - Synopsis [Returns the set of CI nodes in the support of the given nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Nwk_ManSupportNodes( Nwk_Man_t * pNtk, Nwk_Obj_t ** ppNodes, int nNodes ) -{ - Vec_Ptr_t * vNodes; - int i; - // set the traversal ID - Nwk_ManIncrementTravId( 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 ( Nwk_ObjIsCo(ppNodes[i]) ) - Nwk_ManSupportNodes_rec( Nwk_ObjFanin0(ppNodes[i]), vNodes ); - else - Nwk_ManSupportNodes_rec( ppNodes[i], vNodes ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Computes the sum total of supports of all outputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManSupportSum( Nwk_Man_t * pNtk ) -{ - Vec_Ptr_t * vSupp; - Nwk_Obj_t * pObj; - int i, nTotalSupps = 0; - Nwk_ManForEachCo( pNtk, pObj, i ) - { - vSupp = Nwk_ManSupportNodes( pNtk, &pObj, 1 ); - nTotalSupps += Vec_PtrSize( vSupp ); - Vec_PtrFree( vSupp ); - } - printf( "Total supports = %d.\n", nTotalSupps ); -} - - -/**Function************************************************************* - - Synopsis [Dereferences the node's MFFC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ObjDeref_rec( Nwk_Obj_t * pNode ) -{ - Nwk_Obj_t * pFanin; - int i, Counter = 1; - if ( Nwk_ObjIsCi(pNode) ) - return 0; - Nwk_ObjForEachFanin( pNode, pFanin, i ) - { - assert( pFanin->nFanouts > 0 ); - if ( --pFanin->nFanouts == 0 ) - Counter += Nwk_ObjDeref_rec( pFanin ); - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [References the node's MFFC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ObjRef_rec( Nwk_Obj_t * pNode ) -{ - Nwk_Obj_t * pFanin; - int i, Counter = 1; - if ( Nwk_ObjIsCi(pNode) ) - return 0; - Nwk_ObjForEachFanin( pNode, pFanin, i ) - { - if ( pFanin->nFanouts++ == 0 ) - Counter += Nwk_ObjRef_rec( pFanin ); - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Collects the internal and boundary nodes in the derefed MFFC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ObjMffcLabel_rec( Nwk_Obj_t * pNode, int fTopmost ) -{ - Nwk_Obj_t * pFanin; - int i; - // add to the new support nodes - if ( !fTopmost && (Nwk_ObjIsCi(pNode) || pNode->nFanouts > 0) ) - return; - // skip visited nodes - if ( Nwk_ObjIsTravIdCurrent(pNode) ) - return; - Nwk_ObjSetTravIdCurrent(pNode); - // recur on the children - Nwk_ObjForEachFanin( pNode, pFanin, i ) - Nwk_ObjMffcLabel_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 Nwk_ObjMffcLabel( Nwk_Obj_t * pNode ) -{ - int Count1, Count2; - // dereference the node - Count1 = Nwk_ObjDeref_rec( pNode ); - // collect the nodes inside the MFFC - Nwk_ManIncrementTravId( pNode->pMan ); - Nwk_ObjMffcLabel_rec( pNode, 1 ); - // reference it back - Count2 = Nwk_ObjRef_rec( pNode ); - assert( Count1 == Count2 ); - return Count1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/nwk/nwkFanio.c b/src/aig/nwk/nwkFanio.c deleted file mode 100644 index 2a12f5bf..00000000 --- a/src/aig/nwk/nwkFanio.c +++ /dev/null @@ -1,320 +0,0 @@ -/**CFile**************************************************************** - - FileName [nwkFanio.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Logic network representation.] - - Synopsis [Manipulation of fanins/fanouts.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: nwkFanio.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "nwk.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Collects fanins of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ObjCollectFanins( Nwk_Obj_t * pNode, Vec_Ptr_t * vNodes ) -{ - Nwk_Obj_t * pFanin; - int i; - Vec_PtrClear(vNodes); - Nwk_ObjForEachFanin( pNode, pFanin, i ) - Vec_PtrPush( vNodes, pFanin ); -} - -/**Function************************************************************* - - Synopsis [Collects fanouts of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ObjCollectFanouts( Nwk_Obj_t * pNode, Vec_Ptr_t * vNodes ) -{ - Nwk_Obj_t * pFanout; - int i; - Vec_PtrClear(vNodes); - Nwk_ObjForEachFanout( pNode, pFanout, i ) - Vec_PtrPush( vNodes, pFanout ); -} - -/**Function************************************************************* - - Synopsis [Returns the number of the fanin of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ObjFindFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanin ) -{ - Nwk_Obj_t * pTemp; - int i; - Nwk_ObjForEachFanin( pObj, pTemp, i ) - if ( pTemp == pFanin ) - return i; - return -1; -} - -/**Function************************************************************* - - Synopsis [Returns the number of the fanout of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ObjFindFanout( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanout ) -{ - Nwk_Obj_t * pTemp; - int i; - Nwk_ObjForEachFanout( pObj, pTemp, i ) - if ( pTemp == pFanout ) - return i; - return -1; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the node has to be reallocated.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Nwk_ObjReallocIsNeeded( Nwk_Obj_t * pObj ) -{ - return pObj->nFanins + pObj->nFanouts == pObj->nFanioAlloc; -} - -/**Function************************************************************* - - Synopsis [Reallocates the object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static Nwk_Obj_t * Nwk_ManReallocNode( Nwk_Obj_t * pObj ) -{ - Nwk_Obj_t ** pFanioOld = pObj->pFanio; - assert( Nwk_ObjReallocIsNeeded(pObj) ); - pObj->pFanio = (Nwk_Obj_t **)Aig_MmFlexEntryFetch( pObj->pMan->pMemObjs, 2 * pObj->nFanioAlloc * sizeof(Nwk_Obj_t *) ); - memmove( pObj->pFanio, pFanioOld, pObj->nFanioAlloc * sizeof(Nwk_Obj_t *) ); - pObj->nFanioAlloc *= 2; - pObj->pMan->nRealloced++; - return NULL; -} - -/**Function************************************************************* - - Synopsis [Creates fanout/fanin relationship between the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ObjAddFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanin ) -{ - int i; - assert( pObj->pMan == pFanin->pMan ); - assert( pObj->Id >= 0 && pFanin->Id >= 0 ); - if ( Nwk_ObjReallocIsNeeded(pObj) ) - Nwk_ManReallocNode( pObj ); - if ( Nwk_ObjReallocIsNeeded(pFanin) ) - Nwk_ManReallocNode( pFanin ); - for ( i = pObj->nFanins + pObj->nFanouts; i > pObj->nFanins; i-- ) - pObj->pFanio[i] = pObj->pFanio[i-1]; - pObj->pFanio[pObj->nFanins++] = pFanin; - pFanin->pFanio[pFanin->nFanins + pFanin->nFanouts++] = pObj; - pObj->Level = ABC_MAX( pObj->Level, pFanin->Level + Nwk_ObjIsNode(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Removes fanout/fanin relationship between the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ObjDeleteFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanin ) -{ - int i, k, Limit, fFound; - // remove pFanin from the fanin list of pObj - Limit = pObj->nFanins + pObj->nFanouts; - fFound = 0; - for ( k = i = 0; i < Limit; i++ ) - if ( fFound || pObj->pFanio[i] != pFanin ) - pObj->pFanio[k++] = pObj->pFanio[i]; - else - fFound = 1; - assert( i == k + 1 ); // if it fails, likely because of duplicated fanin - pObj->nFanins--; - // remove pObj from the fanout list of pFanin - Limit = pFanin->nFanins + pFanin->nFanouts; - fFound = 0; - for ( k = i = pFanin->nFanins; i < Limit; i++ ) - if ( fFound || pFanin->pFanio[i] != pObj ) - pFanin->pFanio[k++] = pFanin->pFanio[i]; - else - fFound = 1; - assert( i == k + 1 ); // if it fails, likely because of duplicated fanout - pFanin->nFanouts--; -} - -/**Function************************************************************* - - Synopsis [Replaces a fanin of the node.] - - Description [The node is pObj. An old fanin of this node (pFaninOld) has to be - replaced by a new fanin (pFaninNew). Assumes that the node and the old fanin - are not complemented. The new fanin can be complemented. In this case, the - polarity of the new fanin will change, compared to the polarity of the old fanin.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ObjPatchFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFaninOld, Nwk_Obj_t * pFaninNew ) -{ - int i, k, iFanin, Limit; - assert( pFaninOld != pFaninNew ); - assert( pObj != pFaninOld ); - assert( pObj != pFaninNew ); - assert( pObj->pMan == pFaninOld->pMan ); - assert( pObj->pMan == pFaninNew->pMan ); - // update the fanin - iFanin = Nwk_ObjFindFanin( pObj, pFaninOld ); - if ( iFanin == -1 ) - { - printf( "Nwk_ObjPatchFanin(); Error! Node %d is not among", pFaninOld->Id ); - printf( " the fanins of node %d...\n", pObj->Id ); - return; - } - pObj->pFanio[iFanin] = pFaninNew; - // remove pObj from the fanout list of pFaninOld - Limit = pFaninOld->nFanins + pFaninOld->nFanouts; - for ( k = i = pFaninOld->nFanins; i < Limit; i++ ) - if ( pFaninOld->pFanio[i] != pObj ) - pFaninOld->pFanio[k++] = pFaninOld->pFanio[i]; - pFaninOld->nFanouts--; - // add pObj to the fanout list of pFaninNew - if ( Nwk_ObjReallocIsNeeded(pFaninNew) ) - Nwk_ManReallocNode( pFaninNew ); - pFaninNew->pFanio[pFaninNew->nFanins + pFaninNew->nFanouts++] = pObj; -} - - -/**Function************************************************************* - - Synopsis [Transfers fanout from the old node to the new node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ObjTransferFanout( Nwk_Obj_t * pNodeFrom, Nwk_Obj_t * pNodeTo ) -{ - Vec_Ptr_t * vFanouts = pNodeFrom->pMan->vTemp; - Nwk_Obj_t * pTemp; - int nFanoutsOld, i; - assert( !Nwk_ObjIsCo(pNodeFrom) && !Nwk_ObjIsCo(pNodeTo) ); - assert( pNodeFrom->pMan == pNodeTo->pMan ); - assert( pNodeFrom != pNodeTo ); - assert( Nwk_ObjFanoutNum(pNodeFrom) > 0 ); - // get the fanouts of the old node - nFanoutsOld = Nwk_ObjFanoutNum(pNodeTo); - Nwk_ObjCollectFanouts( pNodeFrom, vFanouts ); - // patch the fanin of each of them - Vec_PtrForEachEntry( Nwk_Obj_t *, vFanouts, pTemp, i ) - Nwk_ObjPatchFanin( pTemp, pNodeFrom, pNodeTo ); - assert( Nwk_ObjFanoutNum(pNodeFrom) == 0 ); - assert( Nwk_ObjFanoutNum(pNodeTo) == nFanoutsOld + Vec_PtrSize(vFanouts) ); -} - -/**Function************************************************************* - - Synopsis [Replaces the node by a new node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ObjReplace( Nwk_Obj_t * pNodeOld, Nwk_Obj_t * pNodeNew ) -{ - assert( pNodeOld->pMan == pNodeNew->pMan ); - assert( pNodeOld != pNodeNew ); - assert( Nwk_ObjFanoutNum(pNodeOld) > 0 ); - // transfer the fanouts to the old node - Nwk_ObjTransferFanout( pNodeOld, pNodeNew ); - // remove the old node - Nwk_ManDeleteNode_rec( pNodeOld ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/nwk/nwkFlow.c b/src/aig/nwk/nwkFlow.c deleted file mode 100644 index 3961e5c2..00000000 --- a/src/aig/nwk/nwkFlow.c +++ /dev/null @@ -1,606 +0,0 @@ -/**CFile**************************************************************** - - FileName [nwkFlow.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Netlist representation.] - - Synopsis [Max-flow/min-cut computation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: nwkFlow.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "nwk.h" - -ABC_NAMESPACE_IMPL_START - - -/* - This code is based on the papers: - A. Hurst, A. Mishchenko, and R. Brayton, "Fast minimum-register retiming - via binary maximum-flow", Proc. FMCAD '07, pp. 181-187. - A. Hurst, A. Mishchenko, and R. Brayton, "Scalable min-area retiming - under simultaneous delay and initial state constraints". Proc. DAC'08. -*/ - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// predecessors -static inline Nwk_Obj_t * Nwk_ObjPred( Nwk_Obj_t * pObj ) { return (Nwk_Obj_t *)pObj->pCopy; } -static inline int Nwk_ObjSetPred( Nwk_Obj_t * pObj, Nwk_Obj_t * p ) { pObj->pCopy = p; return 1; } -// sink -static inline int Nwk_ObjIsSink( Nwk_Obj_t * pObj ) { return pObj->MarkA; } -static inline void Nwk_ObjSetSink( Nwk_Obj_t * pObj ) { pObj->MarkA = 1; } -// flow -static inline int Nwk_ObjHasFlow( Nwk_Obj_t * pObj ) { return pObj->MarkB; } -static inline void Nwk_ObjSetFlow( Nwk_Obj_t * pObj ) { pObj->MarkB = 1; } -static inline void Nwk_ObjClearFlow( Nwk_Obj_t * pObj ) { pObj->MarkB = 0; } - -// representation of visited nodes -// pObj->TravId < pNtk->nTravIds-2 --- not visited -// pObj->TravId == pNtk->nTravIds-2 --- visited bot only -// pObj->TravId == pNtk->nTravIds-1 --- visited top only -// pObj->TravId == pNtk->nTravIds --- visited bot and top -static inline int Nwk_ObjVisitedBotOnly( Nwk_Obj_t * pObj ) -{ - return pObj->TravId == pObj->pMan->nTravIds - 2; -} -static inline int Nwk_ObjVisitedBot( Nwk_Obj_t * pObj ) -{ - return pObj->TravId == pObj->pMan->nTravIds - 2 || pObj->TravId == pObj->pMan->nTravIds; -} -static inline int Nwk_ObjVisitedTop( Nwk_Obj_t * pObj ) -{ - return pObj->TravId == pObj->pMan->nTravIds - 1 || pObj->TravId == pObj->pMan->nTravIds; -} -static inline void Nwk_ObjSetVisitedBot( Nwk_Obj_t * pObj ) -{ - if ( pObj->TravId < pObj->pMan->nTravIds - 2 ) - pObj->TravId = pObj->pMan->nTravIds - 2; - else if ( pObj->TravId == pObj->pMan->nTravIds - 1 ) - pObj->TravId = pObj->pMan->nTravIds; - else - assert( 0 ); -} -static inline void Nwk_ObjSetVisitedTop( Nwk_Obj_t * pObj ) -{ - if ( pObj->TravId < pObj->pMan->nTravIds - 2 ) - pObj->TravId = pObj->pMan->nTravIds - 1; - else if ( pObj->TravId == pObj->pMan->nTravIds - 2 ) - pObj->TravId = pObj->pMan->nTravIds; - else - assert( 0 ); -} -static inline void Nwk_ManIncrementTravIdFlow( Nwk_Man_t * pMan ) -{ - Nwk_ManIncrementTravId( pMan ); - Nwk_ManIncrementTravId( pMan ); - Nwk_ManIncrementTravId( pMan ); -} - -static int Nwk_ManPushForwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ); -static int Nwk_ManPushForwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ); - -static int Nwk_ManPushBackwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ); -static int Nwk_ManPushBackwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Marks TFI of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManMarkTfiCone_rec( Nwk_Obj_t * pObj ) -{ - Nwk_Obj_t * pNext; - int i; - if ( pObj->MarkA ) - return; - pObj->MarkA = 1; - Nwk_ObjForEachFanin( pObj, pNext, i ) - Nwk_ManMarkTfiCone_rec( pNext ); -} - -/**Function************************************************************* - - Synopsis [Marks TFO of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManMarkTfoCone_rec( Nwk_Obj_t * pObj ) -{ - Nwk_Obj_t * pNext; - int i; - if ( pObj->MarkA ) - return; - pObj->MarkA = 1; - Nwk_ObjForEachFanout( pObj, pNext, i ) - Nwk_ManMarkTfoCone_rec( pNext ); -} - -/**Function************************************************************* - - Synopsis [Fast forward flow pushing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManPushForwardFast_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) -{ - Nwk_Obj_t * pNext; - int i; - if ( Nwk_ObjIsTravIdCurrent( pObj ) ) - return 0; - Nwk_ObjSetTravIdCurrent( pObj ); - if ( Nwk_ObjHasFlow(pObj) ) - return 0; - if ( Nwk_ObjIsSink(pObj) ) - { - Nwk_ObjSetFlow(pObj); - return Nwk_ObjSetPred( pObj, pPred ); - } - Nwk_ObjForEachFanout( pObj, pNext, i ) - if ( Nwk_ManPushForwardFast_rec( pNext, pObj ) ) - { - Nwk_ObjSetFlow(pObj); - return Nwk_ObjSetPred( pObj, pPred ); - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Fast backward flow pushing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManPushBackwardFast_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) -{ - Nwk_Obj_t * pNext; - int i; - if ( Nwk_ObjIsTravIdCurrent( pObj ) ) - return 0; - Nwk_ObjSetTravIdCurrent( pObj ); - if ( Nwk_ObjHasFlow(pObj) ) - return 0; - if ( Nwk_ObjIsSink(pObj) ) - { - Nwk_ObjSetFlow(pObj); - return Nwk_ObjSetPred( pObj, pPred ); - } - Nwk_ObjForEachFanin( pObj, pNext, i ) - if ( Nwk_ManPushBackwardFast_rec( pNext, pObj ) ) - { - Nwk_ObjSetFlow(pObj); - return Nwk_ObjSetPred( pObj, pPred ); - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Pushing the flow through the bottom part of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManPushForwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) -{ - Nwk_Obj_t * pNext; - int i; - if ( Nwk_ObjVisitedBot(pObj) ) - return 0; - Nwk_ObjSetVisitedBot(pObj); - // propagate through the internal edge - if ( Nwk_ObjHasFlow(pObj) ) - { - if ( Nwk_ObjPred(pObj) ) - if ( Nwk_ManPushForwardTop_rec( Nwk_ObjPred(pObj), Nwk_ObjPred(pObj) ) ) - return Nwk_ObjSetPred( pObj, pPred ); - } - else if ( Nwk_ManPushForwardTop_rec(pObj, pObj) ) - { - Nwk_ObjSetFlow( pObj ); - return Nwk_ObjSetPred( pObj, pPred ); - } - // try to push through the fanins - Nwk_ObjForEachFanin( pObj, pNext, i ) - if ( Nwk_ManPushForwardBot_rec( pNext, pPred ) ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Pushing the flow through the top part of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManPushForwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) -{ - Nwk_Obj_t * pNext; - int i; - if ( Nwk_ObjVisitedTop(pObj) ) - return 0; - Nwk_ObjSetVisitedTop(pObj); - // check if this is the sink - if ( Nwk_ObjIsSink(pObj) ) - return 1; - // try to push through the fanouts - Nwk_ObjForEachFanout( pObj, pNext, i ) - if ( Nwk_ManPushForwardBot_rec( pNext, pPred ) ) - return 1; - // redirect the flow - if ( Nwk_ObjHasFlow(pObj) && !Nwk_ObjIsCi(pObj) ) - if ( Nwk_ManPushForwardBot_rec( pObj, Nwk_ObjPred(pObj) ) ) - { - Nwk_ObjClearFlow( pObj ); - return Nwk_ObjSetPred( pObj, NULL ); - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Pushing the flow through the bottom part of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManPushBackwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) -{ - if ( Nwk_ObjVisitedBot(pObj) ) - return 0; - Nwk_ObjSetVisitedBot(pObj); - // propagate through the internal edge - if ( Nwk_ObjHasFlow(pObj) ) - { - if ( Nwk_ObjPred(pObj) ) - if ( Nwk_ManPushBackwardTop_rec( Nwk_ObjPred(pObj), Nwk_ObjPred(pObj) ) ) - return Nwk_ObjSetPred( pObj, pPred ); - } - else if ( Nwk_ManPushBackwardTop_rec(pObj, pObj) ) - { - Nwk_ObjSetFlow( pObj ); - return Nwk_ObjSetPred( pObj, pPred ); - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Pushing the flow through the top part of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManPushBackwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) -{ - Nwk_Obj_t * pNext; - int i; - if ( Nwk_ObjVisitedTop(pObj) ) - return 0; - Nwk_ObjSetVisitedTop(pObj); - // check if this is the sink - if ( Nwk_ObjIsSink(pObj) ) - return 1; - // try to push through the fanins - Nwk_ObjForEachFanin( pObj, pNext, i ) - if ( Nwk_ManPushBackwardBot_rec( pNext, pPred ) ) - return 1; - // try to push through the fanouts - Nwk_ObjForEachFanout( pObj, pNext, i ) - if ( !Nwk_ObjIsCo(pObj) && Nwk_ManPushBackwardTop_rec( pNext, pPred ) ) - return 1; - // redirect the flow - if ( Nwk_ObjHasFlow(pObj) ) - if ( Nwk_ObjPred(pObj) && Nwk_ManPushBackwardBot_rec( pObj, Nwk_ObjPred(pObj) ) ) - { - Nwk_ObjClearFlow( pObj ); - return Nwk_ObjSetPred( pObj, NULL ); - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Returns 0 if there is an unmarked path to a CI.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManVerifyCut_rec( Nwk_Obj_t * pObj ) -{ - Nwk_Obj_t * pNext; - int i; - if ( pObj->MarkA ) - return 1; - if ( Nwk_ObjIsLo(pObj) ) - return 0; - if ( Nwk_ObjIsTravIdCurrent( pObj ) ) - return 1; - Nwk_ObjSetTravIdCurrent( pObj ); - Nwk_ObjForEachFanin( pObj, pNext, i ) - if ( !Nwk_ManVerifyCut_rec( pNext ) ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Verifies the forward cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManRetimeVerifyCutForward( Nwk_Man_t * pMan, Vec_Ptr_t * vNodes ) -{ - Nwk_Obj_t * pObj; - int i; - // mark the nodes - Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i ) - { - assert( pObj->MarkA == 0 ); - pObj->MarkA = 1; - } - // traverse from the COs - Nwk_ManIncrementTravId( pMan ); - Nwk_ManForEachCo( pMan, pObj, i ) - if ( !Nwk_ManVerifyCut_rec( pObj ) ) - printf( "Nwk_ManRetimeVerifyCutForward(): Internal cut verification failed.\n" ); - // unmark the nodes - Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i ) - pObj->MarkA = 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Verifies the forward cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManRetimeVerifyCutBackward( Nwk_Man_t * pMan, Vec_Ptr_t * vNodes ) -{ - return 1; -} - -/**Function************************************************************* - - Synopsis [Computes minimum cut for forward retiming.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Nwk_ManRetimeCutForward( Nwk_Man_t * pMan, int nLatches, int fVerbose ) -{ - Vec_Ptr_t * vNodes; - Nwk_Obj_t * pObj; - int i, RetValue, Counter = 0, Counter2 = 0; - int clk = clock(); - // set the sequential parameters - pMan->nLatches = nLatches; - pMan->nTruePis = Nwk_ManCiNum(pMan) - nLatches; - pMan->nTruePos = Nwk_ManCoNum(pMan) - nLatches; - // mark the COs and the TFO of PIs - Nwk_ManForEachCo( pMan, pObj, i ) - pObj->MarkA = 1; - Nwk_ManForEachPiSeq( pMan, pObj, i ) - Nwk_ManMarkTfoCone_rec( pObj ); - // start flow computation from each LO - Nwk_ManIncrementTravIdFlow( pMan ); - Nwk_ManForEachLoSeq( pMan, pObj, i ) - { - if ( !Nwk_ManPushForwardFast_rec( pObj, NULL ) ) - continue; - Nwk_ManIncrementTravIdFlow( pMan ); - Counter++; - } - if ( fVerbose ) - printf( "Forward: Max-flow = %4d -> ", Counter ); - // continue flow computation from each LO - Nwk_ManIncrementTravIdFlow( pMan ); - Nwk_ManForEachLoSeq( pMan, pObj, i ) - { - if ( !Nwk_ManPushForwardBot_rec( pObj, NULL ) ) - continue; - Nwk_ManIncrementTravIdFlow( pMan ); - Counter2++; - } - if ( fVerbose ) - printf( "%4d. ", Counter+Counter2 ); - // repeat flow computation from each LO - if ( Counter2 > 0 ) - { - Nwk_ManIncrementTravIdFlow( pMan ); - Nwk_ManForEachLoSeq( pMan, pObj, i ) - { - RetValue = Nwk_ManPushForwardBot_rec( pObj, NULL ); - assert( !RetValue ); - } - } - // cut is a set of nodes whose bottom is visited but top is not visited - vNodes = Vec_PtrAlloc( Counter+Counter2 ); - Counter = 0; - Nwk_ManForEachObj( pMan, pObj, i ) - { - if ( Nwk_ObjVisitedBotOnly(pObj) ) - { - assert( Nwk_ObjHasFlow(pObj) ); - assert( !Nwk_ObjIsCo(pObj) ); - Vec_PtrPush( vNodes, pObj ); - Counter += Nwk_ObjIsCi(pObj); - } - } - Nwk_ManCleanMarks( pMan ); -// assert( Nwk_ManRetimeVerifyCutForward(pMan, vNodes) ); - if ( fVerbose ) - { - printf( "Min-cut = %4d. Unmoved = %4d. ", Vec_PtrSize(vNodes), Counter ); - ABC_PRT( "Time", clock() - clk ); - } - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Computes minimum cut for backward retiming.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Nwk_ManRetimeCutBackward( Nwk_Man_t * pMan, int nLatches, int fVerbose ) -{ - Vec_Ptr_t * vNodes; - Nwk_Obj_t * pObj; - int i, RetValue, Counter = 0, Counter2 = 0; - int clk = clock(); - // set the sequential parameters - pMan->nLatches = nLatches; - pMan->nTruePis = Nwk_ManCiNum(pMan) - nLatches; - pMan->nTruePos = Nwk_ManCoNum(pMan) - nLatches; - // mark the CIs, the TFI of POs, and the constant nodes - Nwk_ManForEachCi( pMan, pObj, i ) - pObj->MarkA = 1; - Nwk_ManForEachPoSeq( pMan, pObj, i ) - Nwk_ManMarkTfiCone_rec( pObj ); - Nwk_ManForEachNode( pMan, pObj, i ) - if ( Nwk_ObjFaninNum(pObj) == 0 ) - pObj->MarkA = 1; - // start flow computation from each LI driver - Nwk_ManIncrementTravIdFlow( pMan ); - Nwk_ManForEachLiSeq( pMan, pObj, i ) - { - if ( !Nwk_ManPushBackwardFast_rec( Nwk_ObjFanin0(pObj), NULL ) ) - continue; - Nwk_ManIncrementTravIdFlow( pMan ); - Counter++; - } - if ( fVerbose ) - printf( "Backward: Max-flow = %4d -> ", Counter ); - // continue flow computation from each LI driver - Nwk_ManIncrementTravIdFlow( pMan ); - Nwk_ManForEachLiSeq( pMan, pObj, i ) - { - if ( !Nwk_ManPushBackwardBot_rec( Nwk_ObjFanin0(pObj), NULL ) ) - continue; - Nwk_ManIncrementTravIdFlow( pMan ); - Counter2++; - } - if ( fVerbose ) - printf( "%4d. ", Counter+Counter2 ); - // repeat flow computation from each LI driver - if ( Counter2 > 0 ) - { - Nwk_ManIncrementTravIdFlow( pMan ); - Nwk_ManForEachLiSeq( pMan, pObj, i ) - { - RetValue = Nwk_ManPushBackwardBot_rec( Nwk_ObjFanin0(pObj), NULL ); - assert( !RetValue ); - } - } - // cut is a set of nodes whose bottom is visited but top is not visited - vNodes = Vec_PtrAlloc( Counter+Counter2 ); - Nwk_ManForEachObj( pMan, pObj, i ) - { - if ( Nwk_ObjVisitedBotOnly(pObj) ) - { - assert( Nwk_ObjHasFlow(pObj) ); - assert( !Nwk_ObjIsCo(pObj) ); - Vec_PtrPush( vNodes, pObj ); - } - } - // count CO drivers - Counter = 0; - Nwk_ManForEachLiSeq( pMan, pObj, i ) - if ( Nwk_ObjVisitedBotOnly( Nwk_ObjFanin0(pObj) ) ) - Counter++; - Nwk_ManCleanMarks( pMan ); -// assert( Nwk_ManRetimeVerifyCutBackward(pMan, vNodes) ); - if ( fVerbose ) - { - printf( "Min-cut = %4d. Unmoved = %4d. ", Vec_PtrSize(vNodes), Counter ); - ABC_PRT( "Time", clock() - clk ); - } - return vNodes; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/nwk/nwkFlow_depth.c b/src/aig/nwk/nwkFlow_depth.c deleted file mode 100644 index 6c2e7eb9..00000000 --- a/src/aig/nwk/nwkFlow_depth.c +++ /dev/null @@ -1,631 +0,0 @@ -/**CFile**************************************************************** - - FileName [nwkFlow.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Netlist representation.] - - Synopsis [Max-flow/min-cut computation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: nwkFlow.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "nwk.h" - -ABC_NAMESPACE_IMPL_START - - -/* - This code is based on the papers: - A. Hurst, A. Mishchenko, and R. Brayton, "Fast minimum-register retiming - via binary maximum-flow", Proc. FMCAD '07, pp. 181-187. - A. Hurst, A. Mishchenko, and R. Brayton, "Scalable min-area retiming - under simultaneous delay and initial state constraints". Proc. DAC'08. -*/ - -int DepthFwd, DepthBwd, DepthFwdMax, DepthBwdMax; - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// predecessors -static inline Nwk_Obj_t * Nwk_ObjPred( Nwk_Obj_t * pObj ) { return pObj->pCopy; } -static inline int Nwk_ObjSetPred( Nwk_Obj_t * pObj, Nwk_Obj_t * p ) { pObj->pCopy = p; return 1; } -// sink -static inline int Nwk_ObjIsSink( Nwk_Obj_t * pObj ) { return pObj->MarkA; } -static inline void Nwk_ObjSetSink( Nwk_Obj_t * pObj ) { pObj->MarkA = 1; } -// flow -static inline int Nwk_ObjHasFlow( Nwk_Obj_t * pObj ) { return pObj->MarkB; } -static inline void Nwk_ObjSetFlow( Nwk_Obj_t * pObj ) { pObj->MarkB = 1; } -static inline void Nwk_ObjClearFlow( Nwk_Obj_t * pObj ) { pObj->MarkB = 0; } - -// representation of visited nodes -// pObj->TravId < pNtk->nTravIds-2 --- not visited -// pObj->TravId == pNtk->nTravIds-2 --- visited bot only -// pObj->TravId == pNtk->nTravIds-1 --- visited top only -// pObj->TravId == pNtk->nTravIds --- visited bot and top -static inline int Nwk_ObjVisitedBotOnly( Nwk_Obj_t * pObj ) -{ - return pObj->TravId == pObj->pMan->nTravIds - 2; -} -static inline int Nwk_ObjVisitedBot( Nwk_Obj_t * pObj ) -{ - return pObj->TravId == pObj->pMan->nTravIds - 2 || pObj->TravId == pObj->pMan->nTravIds; -} -static inline int Nwk_ObjVisitedTop( Nwk_Obj_t * pObj ) -{ - return pObj->TravId == pObj->pMan->nTravIds - 1 || pObj->TravId == pObj->pMan->nTravIds; -} -static inline void Nwk_ObjSetVisitedBot( Nwk_Obj_t * pObj ) -{ - if ( pObj->TravId < pObj->pMan->nTravIds - 2 ) - pObj->TravId = pObj->pMan->nTravIds - 2; - else if ( pObj->TravId == pObj->pMan->nTravIds - 1 ) - pObj->TravId = pObj->pMan->nTravIds; - else - assert( 0 ); -} -static inline void Nwk_ObjSetVisitedTop( Nwk_Obj_t * pObj ) -{ - if ( pObj->TravId < pObj->pMan->nTravIds - 2 ) - pObj->TravId = pObj->pMan->nTravIds - 1; - else if ( pObj->TravId == pObj->pMan->nTravIds - 2 ) - pObj->TravId = pObj->pMan->nTravIds; - else - assert( 0 ); -} -static inline Nwk_ManIncrementTravIdFlow( Nwk_Man_t * pMan ) -{ - Nwk_ManIncrementTravId( pMan ); - Nwk_ManIncrementTravId( pMan ); - Nwk_ManIncrementTravId( pMan ); -} - -static int Nwk_ManPushForwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ); -static int Nwk_ManPushForwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ); - -static int Nwk_ManPushBackwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ); -static int Nwk_ManPushBackwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Marks TFI of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManMarkTfiCone_rec( Nwk_Obj_t * pObj ) -{ - Nwk_Obj_t * pNext; - int i; - if ( pObj->MarkA ) - return; - pObj->MarkA = 1; - Nwk_ObjForEachFanin( pObj, pNext, i ) - Nwk_ManMarkTfiCone_rec( pNext ); -} - -/**Function************************************************************* - - Synopsis [Marks TFO of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManMarkTfoCone_rec( Nwk_Obj_t * pObj ) -{ - Nwk_Obj_t * pNext; - int i; - if ( pObj->MarkA ) - return; - pObj->MarkA = 1; - Nwk_ObjForEachFanout( pObj, pNext, i ) - Nwk_ManMarkTfoCone_rec( pNext ); -} - -/**Function************************************************************* - - Synopsis [Fast forward flow pushing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManPushForwardFast_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) -{ - Nwk_Obj_t * pNext; - int i; - if ( Nwk_ObjIsTravIdCurrent( pObj ) ) - return 0; - Nwk_ObjSetTravIdCurrent( pObj ); - if ( Nwk_ObjHasFlow(pObj) ) - return 0; - if ( Nwk_ObjIsSink(pObj) ) - { - Nwk_ObjSetFlow(pObj); - return Nwk_ObjSetPred( pObj, pPred ); - } - Nwk_ObjForEachFanout( pObj, pNext, i ) - if ( Nwk_ManPushForwardFast_rec( pNext, pObj ) ) - { - Nwk_ObjSetFlow(pObj); - return Nwk_ObjSetPred( pObj, pPred ); - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Fast backward flow pushing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManPushBackwardFast_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) -{ - Nwk_Obj_t * pNext; - int i; - if ( Nwk_ObjIsTravIdCurrent( pObj ) ) - return 0; - Nwk_ObjSetTravIdCurrent( pObj ); - if ( Nwk_ObjHasFlow(pObj) ) - return 0; - if ( Nwk_ObjIsSink(pObj) ) - { - Nwk_ObjSetFlow(pObj); - return Nwk_ObjSetPred( pObj, pPred ); - } - Nwk_ObjForEachFanin( pObj, pNext, i ) - if ( Nwk_ManPushBackwardFast_rec( pNext, pObj ) ) - { - Nwk_ObjSetFlow(pObj); - return Nwk_ObjSetPred( pObj, pPred ); - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Pushing the flow through the bottom part of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManPushForwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) -{ - Nwk_Obj_t * pNext; - int i; - if ( Nwk_ObjVisitedBot(pObj) ) - return 0; - Nwk_ObjSetVisitedBot(pObj); - DepthFwd++; - if ( DepthFwdMax < DepthFwd ) - DepthFwdMax = DepthFwd; - // propagate through the internal edge - if ( Nwk_ObjHasFlow(pObj) ) - { - if ( Nwk_ObjPred(pObj) ) - if ( Nwk_ManPushForwardTop_rec( Nwk_ObjPred(pObj), Nwk_ObjPred(pObj) ) ) - { - DepthFwd--; - return Nwk_ObjSetPred( pObj, pPred ); - } - } - else if ( Nwk_ManPushForwardTop_rec(pObj, pObj) ) - { - DepthFwd--; - Nwk_ObjSetFlow( pObj ); - return Nwk_ObjSetPred( pObj, pPred ); - } - // try to push through the fanins - Nwk_ObjForEachFanin( pObj, pNext, i ) - if ( Nwk_ManPushForwardBot_rec( pNext, pPred ) ) - { - DepthFwd--; - return 1; - } - DepthFwd--; - return 0; -} - -/**Function************************************************************* - - Synopsis [Pushing the flow through the top part of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManPushForwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) -{ - Nwk_Obj_t * pNext; - int i; - if ( Nwk_ObjVisitedTop(pObj) ) - return 0; - Nwk_ObjSetVisitedTop(pObj); - // check if this is the sink - if ( Nwk_ObjIsSink(pObj) ) - return 1; - DepthFwd++; - if ( DepthFwdMax < DepthFwd ) - DepthFwdMax = DepthFwd; - // try to push through the fanouts - Nwk_ObjForEachFanout( pObj, pNext, i ) - if ( Nwk_ManPushForwardBot_rec( pNext, pPred ) ) - { - DepthFwd--; - return 1; - } - // redirect the flow - if ( Nwk_ObjHasFlow(pObj) && !Nwk_ObjIsCi(pObj) ) - if ( Nwk_ManPushForwardBot_rec( pObj, Nwk_ObjPred(pObj) ) ) - { - DepthFwd--; - Nwk_ObjClearFlow( pObj ); - return Nwk_ObjSetPred( pObj, NULL ); - } - DepthFwd--; - return 0; -} - -/**Function************************************************************* - - Synopsis [Pushing the flow through the bottom part of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManPushBackwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) -{ - if ( Nwk_ObjVisitedBot(pObj) ) - return 0; - Nwk_ObjSetVisitedBot(pObj); - // propagate through the internal edge - if ( Nwk_ObjHasFlow(pObj) ) - { - if ( Nwk_ObjPred(pObj) ) - if ( Nwk_ManPushBackwardTop_rec( Nwk_ObjPred(pObj), Nwk_ObjPred(pObj) ) ) - return Nwk_ObjSetPred( pObj, pPred ); - } - else if ( Nwk_ManPushBackwardTop_rec(pObj, pObj) ) - { - Nwk_ObjSetFlow( pObj ); - return Nwk_ObjSetPred( pObj, pPred ); - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Pushing the flow through the top part of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManPushBackwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) -{ - Nwk_Obj_t * pNext; - int i; - if ( Nwk_ObjVisitedTop(pObj) ) - return 0; - Nwk_ObjSetVisitedTop(pObj); - // check if this is the sink - if ( Nwk_ObjIsSink(pObj) ) - return 1; - // try to push through the fanins - Nwk_ObjForEachFanin( pObj, pNext, i ) - if ( Nwk_ManPushBackwardBot_rec( pNext, pPred ) ) - return 1; - // try to push through the fanouts - Nwk_ObjForEachFanout( pObj, pNext, i ) - if ( !Nwk_ObjIsCo(pObj) && Nwk_ManPushBackwardTop_rec( pNext, pPred ) ) - return 1; - // redirect the flow - if ( Nwk_ObjHasFlow(pObj) ) - if ( Nwk_ObjPred(pObj) && Nwk_ManPushBackwardBot_rec( pObj, Nwk_ObjPred(pObj) ) ) - { - Nwk_ObjClearFlow( pObj ); - return Nwk_ObjSetPred( pObj, NULL ); - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Returns 0 if there is an unmarked path to a CI.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManVerifyCut_rec( Nwk_Obj_t * pObj ) -{ - Nwk_Obj_t * pNext; - int i; - if ( pObj->MarkA ) - return 1; - if ( Nwk_ObjIsLo(pObj) ) - return 0; - if ( Nwk_ObjIsTravIdCurrent( pObj ) ) - return 1; - Nwk_ObjSetTravIdCurrent( pObj ); - Nwk_ObjForEachFanin( pObj, pNext, i ) - if ( !Nwk_ManVerifyCut_rec( pNext ) ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Verifies the forward cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManRetimeVerifyCutForward( Nwk_Man_t * pMan, Vec_Ptr_t * vNodes ) -{ - Nwk_Obj_t * pObj; - int i; - // mark the nodes - Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i ) - { - assert( pObj->MarkA == 0 ); - pObj->MarkA = 1; - } - // traverse from the COs - Nwk_ManIncrementTravId( pMan ); - Nwk_ManForEachCo( pMan, pObj, i ) - if ( !Nwk_ManVerifyCut_rec( pObj ) ) - printf( "Nwk_ManRetimeVerifyCutForward(): Internal cut verification failed.\n" ); - // unmark the nodes - Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i ) - pObj->MarkA = 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Verifies the forward cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManRetimeVerifyCutBackward( Nwk_Man_t * pMan, Vec_Ptr_t * vNodes ) -{ - return 1; -} - -/**Function************************************************************* - - Synopsis [Computes minimum cut for forward retiming.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Nwk_ManRetimeCutForward( Nwk_Man_t * pMan, int nLatches, int fVerbose ) -{ - Vec_Ptr_t * vNodes; - Nwk_Obj_t * pObj; - int i, RetValue, Counter = 0, Counter2 = 0; - int clk = clock(); - // set the sequential parameters - pMan->nLatches = nLatches; - pMan->nTruePis = Nwk_ManCiNum(pMan) - nLatches; - pMan->nTruePos = Nwk_ManCoNum(pMan) - nLatches; - // mark the COs and the TFO of PIs - Nwk_ManForEachCo( pMan, pObj, i ) - pObj->MarkA = 1; - Nwk_ManForEachPiSeq( pMan, pObj, i ) - Nwk_ManMarkTfoCone_rec( pObj ); - // start flow computation from each LO - Nwk_ManIncrementTravIdFlow( pMan ); - Nwk_ManForEachLoSeq( pMan, pObj, i ) - { - if ( !Nwk_ManPushForwardFast_rec( pObj, NULL ) ) - continue; - Nwk_ManIncrementTravIdFlow( pMan ); - Counter++; - } - if ( fVerbose ) - printf( "Forward: Max-flow = %4d -> ", Counter ); - // continue flow computation from each LO - DepthFwdMax = DepthFwd = 0; - Nwk_ManIncrementTravIdFlow( pMan ); - Nwk_ManForEachLoSeq( pMan, pObj, i ) - { - printf( "%d ", DepthFwdMax ); - if ( !Nwk_ManPushForwardBot_rec( pObj, NULL ) ) - continue; - assert( DepthFwd == 0 ); - Nwk_ManIncrementTravIdFlow( pMan ); - Counter2++; - } - printf( "DepthMax = %d.\n", DepthFwdMax ); - if ( fVerbose ) - printf( "%4d. ", Counter+Counter2 ); - // repeat flow computation from each LO - if ( Counter2 > 0 ) - { - Nwk_ManIncrementTravIdFlow( pMan ); - Nwk_ManForEachLoSeq( pMan, pObj, i ) - { - RetValue = Nwk_ManPushForwardBot_rec( pObj, NULL ); - assert( !RetValue ); - } - } - // cut is a set of nodes whose bottom is visited but top is not visited - vNodes = Vec_PtrAlloc( Counter+Counter2 ); - Counter = 0; - Nwk_ManForEachObj( pMan, pObj, i ) - { - if ( Nwk_ObjVisitedBotOnly(pObj) ) - { - assert( Nwk_ObjHasFlow(pObj) ); - assert( !Nwk_ObjIsCo(pObj) ); - Vec_PtrPush( vNodes, pObj ); - Counter += Nwk_ObjIsCi(pObj); - } - } - Nwk_ManCleanMarks( pMan ); - assert( Nwk_ManRetimeVerifyCutForward(pMan, vNodes) ); - if ( fVerbose ) - { - printf( "Min-cut = %4d. Unmoved = %4d. ", Vec_PtrSize(vNodes), Counter ); - PRT( "Time", clock() - clk ); - } - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Computes minimum cut for backward retiming.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Nwk_ManRetimeCutBackward( Nwk_Man_t * pMan, int nLatches, int fVerbose ) -{ - Vec_Ptr_t * vNodes; - Nwk_Obj_t * pObj; - int i, RetValue, Counter = 0, Counter2 = 0; - int clk = clock(); - // set the sequential parameters - pMan->nLatches = nLatches; - pMan->nTruePis = Nwk_ManCiNum(pMan) - nLatches; - pMan->nTruePos = Nwk_ManCoNum(pMan) - nLatches; - // mark the CIs, the TFI of POs, and the constant nodes - Nwk_ManForEachCi( pMan, pObj, i ) - pObj->MarkA = 1; - Nwk_ManForEachPoSeq( pMan, pObj, i ) - Nwk_ManMarkTfiCone_rec( pObj ); - Nwk_ManForEachNode( pMan, pObj, i ) - if ( Nwk_ObjFaninNum(pObj) == 0 ) - pObj->MarkA = 1; - // start flow computation from each LI driver - Nwk_ManIncrementTravIdFlow( pMan ); - Nwk_ManForEachLiSeq( pMan, pObj, i ) - { - if ( !Nwk_ManPushBackwardFast_rec( Nwk_ObjFanin0(pObj), NULL ) ) - continue; - Nwk_ManIncrementTravIdFlow( pMan ); - Counter++; - } - if ( fVerbose ) - printf( "Backward: Max-flow = %4d -> ", Counter ); - // continue flow computation from each LI driver - Nwk_ManIncrementTravIdFlow( pMan ); - Nwk_ManForEachLiSeq( pMan, pObj, i ) - { - if ( !Nwk_ManPushBackwardBot_rec( Nwk_ObjFanin0(pObj), NULL ) ) - continue; - Nwk_ManIncrementTravIdFlow( pMan ); - Counter2++; - } - if ( fVerbose ) - printf( "%4d. ", Counter+Counter2 ); - // repeat flow computation from each LI driver - if ( Counter2 > 0 ) - { - Nwk_ManIncrementTravIdFlow( pMan ); - Nwk_ManForEachLiSeq( pMan, pObj, i ) - { - RetValue = Nwk_ManPushBackwardBot_rec( Nwk_ObjFanin0(pObj), NULL ); - assert( !RetValue ); - } - } - // cut is a set of nodes whose bottom is visited but top is not visited - vNodes = Vec_PtrAlloc( Counter+Counter2 ); - Nwk_ManForEachObj( pMan, pObj, i ) - { - if ( Nwk_ObjVisitedBotOnly(pObj) ) - { - assert( Nwk_ObjHasFlow(pObj) ); - assert( !Nwk_ObjIsCo(pObj) ); - Vec_PtrPush( vNodes, pObj ); - } - } - // count CO drivers - Counter = 0; - Nwk_ManForEachLiSeq( pMan, pObj, i ) - if ( Nwk_ObjVisitedBotOnly( Nwk_ObjFanin0(pObj) ) ) - Counter++; - Nwk_ManCleanMarks( pMan ); - assert( Nwk_ManRetimeVerifyCutBackward(pMan, vNodes) ); - if ( fVerbose ) - { - printf( "Min-cut = %4d. Unmoved = %4d. ", Vec_PtrSize(vNodes), Counter ); - PRT( "Time", clock() - clk ); - } - return vNodes; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/nwk/nwkMan.c b/src/aig/nwk/nwkMan.c deleted file mode 100644 index 2e2a3e56..00000000 --- a/src/aig/nwk/nwkMan.c +++ /dev/null @@ -1,278 +0,0 @@ -/**CFile**************************************************************** - - FileName [nwkMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Logic network representation.] - - Synopsis [Network manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: nwkMan.c,v 1.1 2008/10/10 14:09:30 mjarvin Exp $] - -***********************************************************************/ - -#include "nwk.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Nwk_Man_t * Nwk_ManAlloc() -{ - Nwk_Man_t * p; - p = ABC_ALLOC( Nwk_Man_t, 1 ); - memset( p, 0, sizeof(Nwk_Man_t) ); - p->vCis = Vec_PtrAlloc( 1000 ); - p->vCos = Vec_PtrAlloc( 1000 ); - p->vObjs = Vec_PtrAlloc( 1000 ); - p->vTemp = Vec_PtrAlloc( 1000 ); - p->nFanioPlus = 2; - p->pMemObjs = Aig_MmFlexStart(); - p->pManHop = Hop_ManStart(); - return p; -} - -/**Function************************************************************* - - Synopsis [Deallocates the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManFree( Nwk_Man_t * p ) -{ -// printf( "The number of realloced nodes = %d.\n", p->nRealloced ); - if ( p->pName ) ABC_FREE( p->pName ); - if ( p->pSpec ) ABC_FREE( p->pSpec ); - if ( p->vCis ) Vec_PtrFree( p->vCis ); - if ( p->vCos ) Vec_PtrFree( p->vCos ); - if ( p->vObjs ) Vec_PtrFree( p->vObjs ); - if ( p->vTemp ) Vec_PtrFree( p->vTemp ); - if ( p->pManTime ) Tim_ManStop( p->pManTime ); - if ( p->pMemObjs ) Aig_MmFlexStop( p->pMemObjs, 0 ); - if ( p->pManHop ) Hop_ManStop( p->pManHop ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Prints stats of the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManPrintLutSizes( Nwk_Man_t * p, If_Lib_t * pLutLib ) -{ - Nwk_Obj_t * pObj; - int i, Counters[256] = {0}; - Nwk_ManForEachNode( p, pObj, i ) - Counters[Nwk_ObjFaninNum(pObj)]++; - printf( "LUTs by size: " ); - for ( i = 0; i <= pLutLib->LutMax; i++ ) - printf( "%d:%d ", i, Counters[i] ); -} - -/**Function************************************************************* - - Synopsis [If the network is best, saves it in "best.blif" and returns 1.] - - Description [If the networks are incomparable, saves the new network, - returns its parameters in the internal parameter structure, and returns 1. - If the new network is not a logic network, quits without saving and returns 0.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManCompareAndSaveBest( Nwk_Man_t * pNtk, void * pNtl ) -{ -// extern void Ntl_WriteBlifLogic( Nwk_Man_t * pNtk, void * pNtl, char * pFileName ); - extern void Nwk_ManDumpBlif( Nwk_Man_t * pNtk, char * pFileName, Vec_Ptr_t * vPiNames, Vec_Ptr_t * vPoNames ); - static struct ParStruct { - char * pName; // name of the best saved network - int Depth; // depth of the best saved network - int Flops; // flops in the best saved network - int Nodes; // nodes in the best saved network - int nPis; // the number of primary inputs - int nPos; // the number of primary outputs - } ParsNew, ParsBest = { 0 }; - // free storage for the name - if ( pNtk == NULL ) - { - ABC_FREE( ParsBest.pName ); - return 0; - } - // get the parameters - ParsNew.Depth = Nwk_ManLevel( pNtk ); - ParsNew.Flops = Nwk_ManLatchNum( pNtk ); - ParsNew.Nodes = Nwk_ManNodeNum( pNtk ); - ParsNew.nPis = Nwk_ManPiNum( pNtk ); - ParsNew.nPos = Nwk_ManPoNum( pNtk ); - // reset the parameters if the network has the same name - if ( ParsBest.pName == NULL || - strcmp(ParsBest.pName, pNtk->pName) || - ParsBest.Depth > ParsNew.Depth || - (ParsBest.Depth == ParsNew.Depth && ParsBest.Flops > ParsNew.Flops) || - (ParsBest.Depth == ParsNew.Depth && ParsBest.Flops == ParsNew.Flops && ParsBest.Nodes > ParsNew.Nodes) ) - { - ABC_FREE( ParsBest.pName ); - ParsBest.pName = Aig_UtilStrsav( pNtk->pName ); - ParsBest.Depth = ParsNew.Depth; - ParsBest.Flops = ParsNew.Flops; - ParsBest.Nodes = ParsNew.Nodes; - ParsBest.nPis = ParsNew.nPis; - ParsBest.nPos = ParsNew.nPos; - // write the network -// Ntl_WriteBlifLogic( pNtk, pNtl, "best.blif" ); -// Nwk_ManDumpBlif( pNtk, "best_map.blif", NULL, NULL ); - return 1; - } - return 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Nwk_FileNameGeneric( char * FileName ) -{ - char * pDot, * pRes; - pRes = Aig_UtilStrsav( FileName ); - if ( (pDot = strrchr( pRes, '.' )) ) - *pDot = 0; - return pRes; -} - -/**Function************************************************************* - - Synopsis [Marks nodes for power-optimization.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Nwl_ManComputeTotalSwitching( Nwk_Man_t * pNtk ) -{ - extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ); - Vec_Int_t * vSwitching; - float * pSwitching; - Aig_Man_t * pAig; - Aig_Obj_t * pObjAig; - Nwk_Obj_t * pObjAbc; - float Result = (float)0; - int i; - // strash the network - // map network into an AIG - pAig = Nwk_ManStrash( pNtk ); - vSwitching = Saig_ManComputeSwitchProbs( pAig, 48, 16, 0 ); - pSwitching = (float *)vSwitching->pArray; - Nwk_ManForEachObj( pNtk, pObjAbc, i ) - { - if ( (pObjAig = Aig_Regular((Aig_Obj_t *)pObjAbc->pCopy)) ) - Result += Nwk_ObjFanoutNum(pObjAbc) * pSwitching[pObjAig->Id]; - } - Vec_IntFree( vSwitching ); - Aig_ManStop( pAig ); - return Result; -} - -/**Function************************************************************* - - Synopsis [Prints stats of the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManPrintStats( Nwk_Man_t * pNtk, If_Lib_t * pLutLib, int fSaveBest, int fDumpResult, int fPower, Ntl_Man_t * pNtl ) -{ -// extern int Ntl_ManLatchNum( Ntl_Man_t * p ); -// extern void Ntl_ManWriteBlifLogic( Nwk_Man_t * pNtk, void * pNtl, char * pFileName ); - if ( fSaveBest ) - Nwk_ManCompareAndSaveBest( pNtk, pNtl ); - if ( fDumpResult ) - { - char Buffer[1000] = {0}; - const char * pNameGen = pNtk->pSpec? Nwk_FileNameGeneric( pNtk->pSpec ) : "nameless_"; - sprintf( Buffer, "%s_dump.blif", pNameGen ); -// Ntl_ManWriteBlifLogic( pNtk, pNtl, Buffer ); -// sprintf( Buffer, "%s_dump_map.blif", pNameGen ); -// Nwk_ManDumpBlif( pNtk, Buffer, NULL, NULL ); - if ( pNtk->pSpec ) ABC_FREE( pNameGen ); - } - - pNtk->pLutLib = pLutLib; - printf( "%-15s : ", pNtk->pName ); - printf( "pi = %5d ", Nwk_ManPiNum(pNtk) ); - printf( "po = %5d ", Nwk_ManPoNum(pNtk) ); - printf( "ci = %5d ", Nwk_ManCiNum(pNtk) ); - printf( "co = %5d ", Nwk_ManCoNum(pNtk) ); -// printf( "lat = %5d ", Ntl_ManLatchNum(pNtl) ); - printf( "node = %5d ", Nwk_ManNodeNum(pNtk) ); - printf( "edge = %5d ", Nwk_ManGetTotalFanins(pNtk) ); - printf( "aig = %6d ", Nwk_ManGetAigNodeNum(pNtk) ); - printf( "lev = %3d ", Nwk_ManLevel(pNtk) ); -// printf( "lev2 = %3d ", Nwk_ManLevelBackup(pNtk) ); - printf( "delay = %5.2f ", Nwk_ManDelayTraceLut(pNtk) ); - if ( fPower ) - printf( "power = %7.2f ", Nwl_ManComputeTotalSwitching(pNtk) ); - Nwk_ManPrintLutSizes( pNtk, pLutLib ); - printf( "\n" ); -// Nwk_ManDelayTracePrint( pNtk, pLutLib ); - fflush( stdout ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/nwk/nwkMap.c b/src/aig/nwk/nwkMap.c deleted file mode 100644 index 22f25dbc..00000000 --- a/src/aig/nwk/nwkMap.c +++ /dev/null @@ -1,396 +0,0 @@ -/**CFile**************************************************************** - - FileName [nwkMap.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Logic network representation.] - - Synopsis [Interface to technology mapping.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: nwkMap.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "nwk.h" -#include "if.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Load the network into FPGA manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_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->Epsilon = (float)0.005; - pPars->fPreprocess = 1; - pPars->fArea = 0; - pPars->fFancy = 0; - pPars->fExpRed = 1; //// - pPars->fLatchPaths = 0; - pPars->fEdge = 1; - pPars->fPower = 0; - pPars->fCutMin = 0; - pPars->fSeqMap = 0; - pPars->fVerbose = 0; - // internal parameters - pPars->fTruth = 0; - 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 * Nwk_ManToIf( Aig_Man_t * p, If_Par_t * pPars, Vec_Ptr_t * vAigToIf ) -{ - extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ); - Vec_Int_t * vSwitching = NULL, * vSwitching2 = NULL; - float * pSwitching, * pSwitching2; - If_Man_t * pIfMan; - If_Obj_t * pIfObj; - Aig_Obj_t * pNode, * pFanin, * pPrev; - int i, clk = clock(); - // set the number of registers (switch activity will be combinational) - Aig_ManSetRegNum( p, 0 ); - if ( pPars->fPower ) - { - vSwitching = Saig_ManComputeSwitchProbs( p, 48, 16, 0 ); - if ( pPars->fVerbose ) - { - ABC_PRT( "Computing switching activity", clock() - clk ); - } - pSwitching = (float *)vSwitching->pArray; - vSwitching2 = Vec_IntStart( Aig_ManObjNumMax(p) ); - pSwitching2 = (float *)vSwitching2->pArray; - } - // start the mapping manager and set its parameters - pIfMan = If_ManStart( pPars ); - pIfMan->vSwitching = vSwitching2; - // load the AIG into the mapper - Aig_ManForEachObj( p, pNode, i ) - { - if ( Aig_ObjIsAnd(pNode) ) - { - pIfObj = 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) ) ); -// printf( "no%d=%d\n ", If_ObjId(pIfObj), If_ObjLevel(pIfObj) ); - } - else if ( Aig_ObjIsPi(pNode) ) - { - pIfObj = If_ManCreateCi( pIfMan ); - If_ObjSetLevel( pIfObj, Aig_ObjLevel(pNode) ); -// printf( "pi%d=%d\n ", If_ObjId(pIfObj), If_ObjLevel(pIfObj) ); - if ( pIfMan->nLevelMax < (int)pIfObj->Level ) - pIfMan->nLevelMax = (int)pIfObj->Level; - } - else if ( Aig_ObjIsPo(pNode) ) - { - pIfObj = If_ManCreateCo( pIfMan, If_NotCond( (If_Obj_t *)Aig_ObjFanin0(pNode)->pData, Aig_ObjFaninC0(pNode) ) ); -// printf( "po%d=%d\n ", If_ObjId(pIfObj), If_ObjLevel(pIfObj) ); - } - else if ( Aig_ObjIsConst1(pNode) ) - pIfObj = If_ManConst1( pIfMan ); - else // add the node to the mapper - assert( 0 ); - // save the result - assert( Vec_PtrEntry(vAigToIf, i) == NULL ); - Vec_PtrWriteEntry( vAigToIf, i, pIfObj ); - pNode->pData = pIfObj; - if ( vSwitching2 ) - pSwitching2[pIfObj->Id] = pSwitching[pNode->Id]; - // set up the choice node - if ( Aig_ObjIsChoice( p, pNode ) ) - { - pIfMan->nChoices++; - for ( pPrev = pNode, pFanin = Aig_ObjEquiv(p, pNode); pFanin; pPrev = pFanin, pFanin = Aig_ObjEquiv(p, pFanin) ) - If_ObjSetChoice( (If_Obj_t *)pPrev->pData, (If_Obj_t *)pFanin->pData ); - If_ManCreateChoice( pIfMan, (If_Obj_t *)pNode->pData ); - } -// assert( If_ObjLevel(pIfObj) == Aig_ObjLevel(pNode) ); - } - if ( vSwitching ) - Vec_IntFree( vSwitching ); - return pIfMan; -} - - -/**Function************************************************************* - - Synopsis [Recursively derives the local AIG for the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Nwk_NodeIfToHop2_rec( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited ) -{ - If_Cut_t * pCut; - If_Obj_t * pTemp; - 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 (Hop_Obj_t *)If_CutData(pCut); - // mark the node as visited - Vec_PtrPush( vVisited, pCut ); - // insert the worst case - If_CutSetData( pCut, (void *)1 ); - // skip in case of primary input - if ( If_ObjIsCi(pIfObj) ) - return (Hop_Obj_t *)If_CutData(pCut); - // compute the functions of the children - for ( pTemp = pIfObj; pTemp; pTemp = pTemp->pEquiv ) - { - gFunc0 = Nwk_NodeIfToHop2_rec( pHopMan, pIfMan, pTemp->pFanin0, vVisited ); - if ( gFunc0 == (void *)1 ) - continue; - gFunc1 = Nwk_NodeIfToHop2_rec( pHopMan, pIfMan, pTemp->pFanin1, vVisited ); - if ( gFunc1 == (void *)1 ) - continue; - // both branches are solved - gFunc = Hop_And( pHopMan, Hop_NotCond(gFunc0, pTemp->fCompl0), Hop_NotCond(gFunc1, pTemp->fCompl1) ); - if ( pTemp->fPhase != pIfObj->fPhase ) - gFunc = Hop_Not(gFunc); - If_CutSetData( pCut, gFunc ); - break; - } - return (Hop_Obj_t *)If_CutData(pCut); -} - -/**Function************************************************************* - - Synopsis [Derives the local AIG for the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Nwk_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 = Nwk_NodeIfToHop2_rec( pHopMan, pIfMan, pIfObj, pIfMan->vTemp ); - if ( gFunc == (void *)1 ) - { - printf( "Nwk_NodeIfToHop(): Computing local AIG has failed.\n" ); - return NULL; - } -// printf( "%d ", Vec_PtrSize(p->vTemp) ); - // clean the cuts - If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) - If_CutSetData( If_ObjCutBest(pLeaf), NULL ); - Vec_PtrForEachEntry( If_Cut_t *, pIfMan->vTemp, pCut, i ) - If_CutSetData( pCut, NULL ); - return gFunc; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Nwk_Man_t * Nwk_ManFromIf( If_Man_t * pIfMan, Aig_Man_t * p, Vec_Ptr_t * vAigToIf ) -{ - Vec_Ptr_t * vIfToAig; - Nwk_Man_t * pNtk; - Nwk_Obj_t * pObjNew; - Aig_Obj_t * pObj, * pObjRepr; - If_Obj_t * pIfObj; - If_Cut_t * pCutBest; - int i, k, nLeaves, * ppLeaves; - assert( Aig_ManPiNum(p) == If_ManCiNum(pIfMan) ); - assert( Aig_ManPoNum(p) == If_ManCoNum(pIfMan) ); - assert( Aig_ManNodeNum(p) == If_ManAndNum(pIfMan) ); - Aig_ManCleanData( p ); - If_ManCleanCutData( pIfMan ); - // create mapping of IF to AIG - vIfToAig = Vec_PtrStart( If_ManObjNum(pIfMan) ); - Aig_ManForEachObj( p, pObj, i ) - { - pIfObj = (If_Obj_t *)Vec_PtrEntry( vAigToIf, i ); - Vec_PtrWriteEntry( vIfToAig, pIfObj->Id, pObj ); - } - // construct the network - pNtk = Nwk_ManAlloc(); - pNtk->pName = Aig_UtilStrsav( p->pName ); - pNtk->pSpec = Aig_UtilStrsav( p->pSpec ); -// pNtk->nLatches = Aig_ManRegNum(p); -// pNtk->nTruePis = Nwk_ManCiNum(pNtk) - pNtk->nLatches; -// pNtk->nTruePos = Nwk_ManCoNum(pNtk) - pNtk->nLatches; - Aig_ManForEachObj( p, pObj, i ) - { - pIfObj = (If_Obj_t *)Vec_PtrEntry( vAigToIf, i ); - if ( pIfObj->nRefs == 0 && !If_ObjIsTerm(pIfObj) ) - continue; - if ( Aig_ObjIsNode(pObj) ) - { - pCutBest = If_ObjCutBest( pIfObj ); - nLeaves = If_CutLeaveNum( pCutBest ); - ppLeaves = If_CutLeaves( pCutBest ); - // create node - pObjNew = Nwk_ManCreateNode( pNtk, nLeaves, pIfObj->nRefs ); - for ( k = 0; k < nLeaves; k++ ) - { - pObjRepr = (Aig_Obj_t *)Vec_PtrEntry( vIfToAig, ppLeaves[k] ); - Nwk_ObjAddFanin( pObjNew, (Nwk_Obj_t *)pObjRepr->pData ); - } - // get the functionality - pObjNew->pFunc = Nwk_NodeIfToHop( pNtk->pManHop, pIfMan, pIfObj ); - } - else if ( Aig_ObjIsPi(pObj) ) - pObjNew = Nwk_ManCreateCi( pNtk, pIfObj->nRefs ); - else if ( Aig_ObjIsPo(pObj) ) - { - pObjNew = Nwk_ManCreateCo( pNtk ); - pObjNew->fInvert = Aig_ObjFaninC0(pObj); - Nwk_ObjAddFanin( pObjNew, (Nwk_Obj_t *)Aig_ObjFanin0(pObj)->pData ); -//printf( "%d ", pObjNew->Id ); - } - else if ( Aig_ObjIsConst1(pObj) ) - { - pObjNew = Nwk_ManCreateNode( pNtk, 0, pIfObj->nRefs ); - pObjNew->pFunc = Hop_ManConst1( pNtk->pManHop ); - } - else - assert( 0 ); - pObj->pData = pObjNew; - } -//printf( "\n" ); - Vec_PtrFree( vIfToAig ); - pNtk->pManTime = Tim_ManDup( pIfMan->pManTim, 0 ); - Nwk_ManMinimumBase( pNtk, 0 ); - assert( Nwk_ManCheck( pNtk ) ); - return pNtk; -} - -/**Function************************************************************* - - Synopsis [Interface with the FPGA mapping package.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Nwk_Man_t * Nwk_MappingIf( Aig_Man_t * p, Tim_Man_t * pManTime, If_Par_t * pPars ) -{ - Nwk_Man_t * pNtk; - If_Man_t * pIfMan; - Vec_Ptr_t * vAigToIf; - // set the arrival times - pPars->pTimesArr = ABC_ALLOC( float, Aig_ManPiNum(p) ); - memset( pPars->pTimesArr, 0, sizeof(float) * Aig_ManPiNum(p) ); - // translate into the mapper - vAigToIf = Vec_PtrStart( Aig_ManObjNumMax(p) ); - pIfMan = Nwk_ManToIf( p, pPars, vAigToIf ); - if ( pIfMan == NULL ) - return NULL; - pIfMan->pManTim = Tim_ManDup( pManTime, 0 ); - pIfMan->pPars->fCutMin = 0; // is not compatible with deriving result - if ( !If_ManPerformMapping( pIfMan ) ) - { - If_ManStop( pIfMan ); - return NULL; - } - // transform the result of mapping into the new network - pNtk = Nwk_ManFromIf( pIfMan, p, vAigToIf ); - if ( pPars->fBidec && pPars->nLutSize <= 8 ) - Nwk_ManBidecResyn( pNtk, 0 ); - If_ManStop( pIfMan ); - Vec_PtrFree( vAigToIf ); - return pNtk; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/nwk/nwkMerge.c b/src/aig/nwk/nwkMerge.c deleted file mode 100644 index 9a4f2f8c..00000000 --- a/src/aig/nwk/nwkMerge.c +++ /dev/null @@ -1,1044 +0,0 @@ -/**CFile**************************************************************** - - FileName [nwkMerge.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Netlist representation.] - - Synopsis [LUT merging algorithm.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: nwkMerge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "nwk.h" -#include "nwkMerge.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates the graph.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Nwk_Grf_t * Nwk_ManGraphAlloc( int nVertsMax ) -{ - Nwk_Grf_t * p; - p = ABC_ALLOC( Nwk_Grf_t, 1 ); - memset( p, 0, sizeof(Nwk_Grf_t) ); - p->nVertsMax = nVertsMax; - p->nEdgeHash = Aig_PrimeCudd( 3 * nVertsMax ); - p->pEdgeHash = ABC_CALLOC( Nwk_Edg_t *, p->nEdgeHash ); - p->pMemEdges = Aig_MmFixedStart( sizeof(Nwk_Edg_t), p->nEdgeHash ); - p->vPairs = Vec_IntAlloc( 1000 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Deallocates the graph.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManGraphFree( Nwk_Grf_t * p ) -{ - if ( p->vPairs ) Vec_IntFree( p->vPairs ); - if ( p->pMemEdges ) Aig_MmFixedStop( p->pMemEdges, 0 ); - if ( p->pMemVerts ) Aig_MmFlexStop( p->pMemVerts, 0 ); - ABC_FREE( p->pVerts ); - ABC_FREE( p->pEdgeHash ); - ABC_FREE( p->pMapLut2Id ); - ABC_FREE( p->pMapId2Lut ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Prepares the graph for solving the problem.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManGraphReportMemoryUsage( Nwk_Grf_t * p ) -{ - p->nMemBytes1 = - sizeof(Nwk_Grf_t) + - sizeof(void *) * p->nEdgeHash + - sizeof(int) * (p->nObjs + p->nVertsMax) + - sizeof(Nwk_Edg_t) * p->nEdges; - p->nMemBytes2 = - sizeof(Nwk_Vrt_t) * p->nVerts + - sizeof(int) * 2 * p->nEdges; - printf( "Memory usage stats: Preprocessing = %.2f Mb. Solving = %.2f Mb.\n", - 1.0 * p->nMemBytes1 / (1<<20), 1.0 * p->nMemBytes2 / (1<<20) ); -} - - -/**Function************************************************************* - - Synopsis [Finds or adds the edge to the graph.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManGraphHashEdge( Nwk_Grf_t * p, int iLut1, int iLut2 ) -{ - Nwk_Edg_t * pEntry; - unsigned Key; - if ( iLut1 == iLut2 ) - return; - if ( iLut1 > iLut2 ) - { - Key = iLut1; - iLut1 = iLut2; - iLut2 = Key; - } - assert( iLut1 < iLut2 ); - if ( p->nObjs < iLut2 ) - p->nObjs = iLut2; - Key = (unsigned)(741457 * iLut1 + 4256249 * iLut2) % p->nEdgeHash; - for ( pEntry = p->pEdgeHash[Key]; pEntry; pEntry = pEntry->pNext ) - if ( pEntry->iNode1 == iLut1 && pEntry->iNode2 == iLut2 ) - return; - pEntry = (Nwk_Edg_t *)Aig_MmFixedEntryFetch( p->pMemEdges ); - pEntry->iNode1 = iLut1; - pEntry->iNode2 = iLut2; - pEntry->pNext = p->pEdgeHash[Key]; - p->pEdgeHash[Key] = pEntry; - p->nEdges++; -} - -/**Function************************************************************* - - Synopsis [Adds one entry to the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Nwk_ManGraphListAdd( Nwk_Grf_t * p, int * pList, Nwk_Vrt_t * pVertex ) -{ - if ( *pList ) - { - Nwk_Vrt_t * pHead; - pHead = p->pVerts[*pList]; - pVertex->iPrev = 0; - pVertex->iNext = pHead->Id; - pHead->iPrev = pVertex->Id; - } - *pList = pVertex->Id; -} - -/**Function************************************************************* - - Synopsis [Deletes one entry from the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Nwk_ManGraphListDelete( Nwk_Grf_t * p, int * pList, Nwk_Vrt_t * pVertex ) -{ - assert( *pList ); - if ( pVertex->iPrev ) - { -// assert( p->pVerts[pVertex->iPrev]->iNext == pVertex->Id ); - p->pVerts[pVertex->iPrev]->iNext = pVertex->iNext; - } - if ( pVertex->iNext ) - { -// assert( p->pVerts[pVertex->iNext]->iPrev == pVertex->Id ); - p->pVerts[pVertex->iNext]->iPrev = pVertex->iPrev; - } - if ( *pList == pVertex->Id ) - *pList = pVertex->iNext; - pVertex->iPrev = pVertex->iNext = 0; -} - -/**Function************************************************************* - - Synopsis [Inserts the edge into one of the linked lists.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Nwk_ManGraphListInsert( Nwk_Grf_t * p, Nwk_Vrt_t * pVertex ) -{ - Nwk_Vrt_t * pNext; - assert( pVertex->nEdges > 0 ); - - if ( pVertex->nEdges == 1 ) - { - pNext = p->pVerts[ pVertex->pEdges[0] ]; - if ( pNext->nEdges >= NWK_MAX_LIST ) - Nwk_ManGraphListAdd( p, p->pLists1 + NWK_MAX_LIST, pVertex ); - else - Nwk_ManGraphListAdd( p, p->pLists1 + pNext->nEdges, pVertex ); - } - else - { - if ( pVertex->nEdges >= NWK_MAX_LIST ) - Nwk_ManGraphListAdd( p, p->pLists2 + NWK_MAX_LIST, pVertex ); - else - Nwk_ManGraphListAdd( p, p->pLists2 + pVertex->nEdges, pVertex ); - } -} - -/**Function************************************************************* - - Synopsis [Extracts the edge from one of the linked lists.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Nwk_ManGraphListExtract( Nwk_Grf_t * p, Nwk_Vrt_t * pVertex ) -{ - Nwk_Vrt_t * pNext; - assert( pVertex->nEdges > 0 ); - - if ( pVertex->nEdges == 1 ) - { - pNext = p->pVerts[ pVertex->pEdges[0] ]; - if ( pNext->nEdges >= NWK_MAX_LIST ) - Nwk_ManGraphListDelete( p, p->pLists1 + NWK_MAX_LIST, pVertex ); - else - Nwk_ManGraphListDelete( p, p->pLists1 + pNext->nEdges, pVertex ); - } - else - { - if ( pVertex->nEdges >= NWK_MAX_LIST ) - Nwk_ManGraphListDelete( p, p->pLists2 + NWK_MAX_LIST, pVertex ); - else - Nwk_ManGraphListDelete( p, p->pLists2 + pVertex->nEdges, pVertex ); - } -} - -/**Function************************************************************* - - Synopsis [Prepares the graph for solving the problem.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManGraphPrepare( Nwk_Grf_t * p ) -{ - Nwk_Edg_t * pEntry; - Nwk_Vrt_t * pVertex; - int * pnEdges, nBytes, i; - // allocate memory for the present objects - p->pMapLut2Id = ABC_ALLOC( int, p->nObjs+1 ); - p->pMapId2Lut = ABC_ALLOC( int, p->nVertsMax+1 ); - memset( p->pMapLut2Id, 0xff, sizeof(int) * (p->nObjs+1) ); - memset( p->pMapId2Lut, 0xff, sizeof(int) * (p->nVertsMax+1) ); - // mark present objects - Nwk_GraphForEachEdge( p, pEntry, i ) - { - assert( pEntry->iNode1 <= p->nObjs ); - assert( pEntry->iNode2 <= p->nObjs ); - p->pMapLut2Id[ pEntry->iNode1 ] = 0; - p->pMapLut2Id[ pEntry->iNode2 ] = 0; - } - // map objects - p->nVerts = 0; - for ( i = 0; i <= p->nObjs; i++ ) - { - if ( p->pMapLut2Id[i] == 0 ) - { - p->pMapLut2Id[i] = ++p->nVerts; - p->pMapId2Lut[p->nVerts] = i; - } - } - // count the edges and mark present objects - pnEdges = ABC_CALLOC( int, p->nVerts+1 ); - Nwk_GraphForEachEdge( p, pEntry, i ) - { - // translate into vertices - assert( pEntry->iNode1 <= p->nObjs ); - assert( pEntry->iNode2 <= p->nObjs ); - pEntry->iNode1 = p->pMapLut2Id[pEntry->iNode1]; - pEntry->iNode2 = p->pMapLut2Id[pEntry->iNode2]; - // count the edges - assert( pEntry->iNode1 <= p->nVerts ); - assert( pEntry->iNode2 <= p->nVerts ); - pnEdges[pEntry->iNode1]++; - pnEdges[pEntry->iNode2]++; - } - // allocate the real graph - p->pMemVerts = Aig_MmFlexStart(); - p->pVerts = ABC_ALLOC( Nwk_Vrt_t *, p->nVerts + 1 ); - p->pVerts[0] = NULL; - for ( i = 1; i <= p->nVerts; i++ ) - { - assert( pnEdges[i] > 0 ); - nBytes = sizeof(Nwk_Vrt_t) + sizeof(int) * pnEdges[i]; - p->pVerts[i] = (Nwk_Vrt_t *)Aig_MmFlexEntryFetch( p->pMemVerts, nBytes ); - memset( p->pVerts[i], 0, nBytes ); - p->pVerts[i]->Id = i; - } - // add edges to the real graph - Nwk_GraphForEachEdge( p, pEntry, i ) - { - pVertex = p->pVerts[pEntry->iNode1]; - pVertex->pEdges[ pVertex->nEdges++ ] = pEntry->iNode2; - pVertex = p->pVerts[pEntry->iNode2]; - pVertex->pEdges[ pVertex->nEdges++ ] = pEntry->iNode1; - } - // put vertices into the data structure - for ( i = 1; i <= p->nVerts; i++ ) - { - assert( p->pVerts[i]->nEdges == pnEdges[i] ); - Nwk_ManGraphListInsert( p, p->pVerts[i] ); - } - // clean up - Aig_MmFixedStop( p->pMemEdges, 0 ); p->pMemEdges = NULL; - ABC_FREE( p->pEdgeHash ); -// p->nEdgeHash = 0; - ABC_FREE( pnEdges ); -} - -/**Function************************************************************* - - Synopsis [Sort pairs by the first vertex in the topological order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManGraphSortPairs( Nwk_Grf_t * p ) -{ - int nSize = Vec_IntSize(p->vPairs); - int * pIdToPair, i; - // allocate storage - pIdToPair = ABC_ALLOC( int, p->nObjs+1 ); - for ( i = 0; i <= p->nObjs; i++ ) - pIdToPair[i] = -1; - // create mapping - for ( i = 0; i < p->vPairs->nSize; i += 2 ) - { - assert( pIdToPair[ p->vPairs->pArray[i] ] == -1 ); - pIdToPair[ p->vPairs->pArray[i] ] = p->vPairs->pArray[i+1]; - } - // recreate pairs - Vec_IntClear( p->vPairs ); - for ( i = 0; i <= p->nObjs; i++ ) - if ( pIdToPair[i] >= 0 ) - { - assert( i < pIdToPair[i] ); - Vec_IntPush( p->vPairs, i ); - Vec_IntPush( p->vPairs, pIdToPair[i] ); - } - assert( nSize == Vec_IntSize(p->vPairs) ); - ABC_FREE( pIdToPair ); -} - - -/**Function************************************************************* - - Synopsis [Updates the problem after pulling out one edge.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManGraphCheckLists( Nwk_Grf_t * p ) -{ - Nwk_Vrt_t * pVertex, * pNext; - int i, j; - assert( p->pLists1[0] == 0 ); - for ( i = 1; i <= NWK_MAX_LIST; i++ ) - if ( p->pLists1[i] ) - { - pVertex = p->pVerts[ p->pLists1[i] ]; - assert( pVertex->nEdges == 1 ); - pNext = p->pVerts[ pVertex->pEdges[0] ]; - assert( pNext->nEdges == i || pNext->nEdges > NWK_MAX_LIST ); - } - // find the next vertext to extract - assert( p->pLists2[0] == 0 ); - assert( p->pLists2[1] == 0 ); - for ( j = 2; j <= NWK_MAX_LIST; j++ ) - if ( p->pLists2[j] ) - { - pVertex = p->pVerts[ p->pLists2[j] ]; - assert( pVertex->nEdges == j || pVertex->nEdges > NWK_MAX_LIST ); - } -} - -/**Function************************************************************* - - Synopsis [Extracts the edge from one of the linked lists.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Nwk_ManGraphVertexRemoveEdge( Nwk_Vrt_t * pThis, Nwk_Vrt_t * pNext ) -{ - int k; - for ( k = 0; k < pThis->nEdges; k++ ) - if ( pThis->pEdges[k] == pNext->Id ) - break; - assert( k < pThis->nEdges ); - pThis->nEdges--; - for ( ; k < pThis->nEdges; k++ ) - pThis->pEdges[k] = pThis->pEdges[k+1]; -} - -/**Function************************************************************* - - Synopsis [Updates the problem after pulling out one edge.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManGraphUpdate( Nwk_Grf_t * p, Nwk_Vrt_t * pVertex, Nwk_Vrt_t * pNext ) -{ - Nwk_Vrt_t * pChanged, * pOther; - int i, k; -// Nwk_ManGraphCheckLists( p ); - Nwk_ManGraphListExtract( p, pVertex ); - Nwk_ManGraphListExtract( p, pNext ); - // update neihbors of pVertex - Nwk_VertexForEachAdjacent( p, pVertex, pChanged, i ) - { - if ( pChanged == pNext ) - continue; - Nwk_ManGraphListExtract( p, pChanged ); - // move those that use this one - if ( pChanged->nEdges > 1 ) - Nwk_VertexForEachAdjacent( p, pChanged, pOther, k ) - { - if ( pOther == pVertex || pOther->nEdges > 1 ) - continue; - assert( pOther->nEdges == 1 ); - Nwk_ManGraphListExtract( p, pOther ); - pChanged->nEdges--; - Nwk_ManGraphListInsert( p, pOther ); - pChanged->nEdges++; - } - // remove the edge - Nwk_ManGraphVertexRemoveEdge( pChanged, pVertex ); - // add the changed vertex back - if ( pChanged->nEdges > 0 ) - Nwk_ManGraphListInsert( p, pChanged ); - } - // update neihbors of pNext - Nwk_VertexForEachAdjacent( p, pNext, pChanged, i ) - { - if ( pChanged == pVertex ) - continue; - Nwk_ManGraphListExtract( p, pChanged ); - // move those that use this one - if ( pChanged->nEdges > 1 ) - Nwk_VertexForEachAdjacent( p, pChanged, pOther, k ) - { - if ( pOther == pNext || pOther->nEdges > 1 ) - continue; - assert( pOther->nEdges == 1 ); - Nwk_ManGraphListExtract( p, pOther ); - pChanged->nEdges--; - Nwk_ManGraphListInsert( p, pOther ); - pChanged->nEdges++; - } - // remove the edge - Nwk_ManGraphVertexRemoveEdge( pChanged, pNext ); - // add the changed vertex back - if ( pChanged->nEdges > 0 ) - Nwk_ManGraphListInsert( p, pChanged ); - } - // add to the result - if ( pVertex->Id < pNext->Id ) - { - Vec_IntPush( p->vPairs, p->pMapId2Lut[pVertex->Id] ); - Vec_IntPush( p->vPairs, p->pMapId2Lut[pNext->Id] ); - } - else - { - Vec_IntPush( p->vPairs, p->pMapId2Lut[pNext->Id] ); - Vec_IntPush( p->vPairs, p->pMapId2Lut[pVertex->Id] ); - } -// Nwk_ManGraphCheckLists( p ); -} - -/**Function************************************************************* - - Synopsis [Counts the number of entries in the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManGraphListLength( Nwk_Grf_t * p, int List ) -{ - Nwk_Vrt_t * pThis; - int fVerbose = 0; - int Counter = 0; - Nwk_ListForEachVertex( p, List, pThis ) - { - if ( fVerbose && Counter < 20 ) - printf( "%d ", p->pVerts[pThis->pEdges[0]]->nEdges ); - Counter++; - } - if ( fVerbose ) - printf( "\n" ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Returns the adjacent vertex with the mininum number of edges.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Nwk_Vrt_t * Nwk_ManGraphListFindMinEdge( Nwk_Grf_t * p, Nwk_Vrt_t * pVert ) -{ - Nwk_Vrt_t * pThis, * pMinCost = NULL; - int k; - Nwk_VertexForEachAdjacent( p, pVert, pThis, k ) - { - if ( pMinCost == NULL || pMinCost->nEdges > pThis->nEdges ) - pMinCost = pThis; - } - return pMinCost; -} - -/**Function************************************************************* - - Synopsis [Finds the best vertext in the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Nwk_Vrt_t * Nwk_ManGraphListFindMin( Nwk_Grf_t * p, int List ) -{ - Nwk_Vrt_t * pThis, * pMinCost = NULL; - int k, Counter = 10000, BestCost = 1000000; - Nwk_ListForEachVertex( p, List, pThis ) - { - for ( k = 0; k < pThis->nEdges; k++ ) - { - if ( pMinCost == NULL || BestCost > p->pVerts[pThis->pEdges[k]]->nEdges ) - { - BestCost = p->pVerts[pThis->pEdges[k]]->nEdges; - pMinCost = pThis; - } - } - if ( --Counter == 0 ) - break; - } - return pMinCost; -} - -/**Function************************************************************* - - Synopsis [Solves the problem by extracting one edge at a time.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManGraphSolve( Nwk_Grf_t * p ) -{ - Nwk_Vrt_t * pVertex, * pNext; - int i, j; - Nwk_ManGraphPrepare( p ); - while ( 1 ) - { - // find the next vertex to extract - assert( p->pLists1[0] == 0 ); - for ( i = 1; i <= NWK_MAX_LIST; i++ ) - if ( p->pLists1[i] ) - { -// printf( "%d ", i ); -// printf( "ListA = %2d. Length = %5d.\n", i, Nwk_ManGraphListLength(p,p->pLists1[i]) ); - pVertex = p->pVerts[ p->pLists1[i] ]; - assert( pVertex->nEdges == 1 ); - pNext = p->pVerts[ pVertex->pEdges[0] ]; - Nwk_ManGraphUpdate( p, pVertex, pNext ); - break; - } - if ( i < NWK_MAX_LIST + 1 ) - continue; - // find the next vertex to extract - assert( p->pLists2[0] == 0 ); - assert( p->pLists2[1] == 0 ); - for ( j = 2; j <= NWK_MAX_LIST; j++ ) - if ( p->pLists2[j] ) - { -// printf( "***%d ", j ); -// printf( "ListB = %2d. Length = %5d.\n", j, Nwk_ManGraphListLength(p,p->pLists2[j]) ); - pVertex = Nwk_ManGraphListFindMin( p, p->pLists2[j] ); - assert( pVertex->nEdges == j || j == NWK_MAX_LIST ); - pNext = Nwk_ManGraphListFindMinEdge( p, pVertex ); - Nwk_ManGraphUpdate( p, pVertex, pNext ); - break; - } - if ( j == NWK_MAX_LIST + 1 ) - break; - } - Nwk_ManGraphSortPairs( p ); -} - -/**Function************************************************************* - - Synopsis [Reads graph from file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Nwk_Grf_t * Nwk_ManLutMergeReadGraph( char * pFileName ) -{ - Nwk_Grf_t * p; - FILE * pFile; - char Buffer[100]; - int nNodes, nEdges, iNode1, iNode2; - pFile = fopen( pFileName, "r" ); - fscanf( pFile, "%s %d", Buffer, &nNodes ); - fscanf( pFile, "%s %d", Buffer, &nEdges ); - p = Nwk_ManGraphAlloc( nNodes ); - while ( fscanf( pFile, "%s %d %d", Buffer, &iNode1, &iNode2 ) == 3 ) - Nwk_ManGraphHashEdge( p, iNode1, iNode2 ); - assert( p->nEdges == nEdges ); - fclose( pFile ); - return p; -} - -/**Function************************************************************* - - Synopsis [Solves the graph coming from file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManLutMergeGraphTest( char * pFileName ) -{ - int nPairs; - Nwk_Grf_t * p; - int clk = clock(); - p = Nwk_ManLutMergeReadGraph( pFileName ); - ABC_PRT( "Reading", clock() - clk ); - clk = clock(); - Nwk_ManGraphSolve( p ); - printf( "GRAPH: Nodes = %6d. Edges = %6d. Pairs = %6d. ", - p->nVerts, p->nEdges, Vec_IntSize(p->vPairs)/2 ); - ABC_PRT( "Solving", clock() - clk ); - nPairs = Vec_IntSize(p->vPairs)/2; - Nwk_ManGraphReportMemoryUsage( p ); - Nwk_ManGraphFree( p ); - return nPairs; -} - - - - -/**Function************************************************************* - - Synopsis [Marks the fanins of the node with the current trav ID.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManMarkFanins_rec( Nwk_Obj_t * pLut, int nLevMin ) -{ - Nwk_Obj_t * pNext; - int i; - if ( !Nwk_ObjIsNode(pLut) ) - return; - if ( Nwk_ObjIsTravIdCurrent( pLut ) ) - return; - Nwk_ObjSetTravIdCurrent( pLut ); - if ( Nwk_ObjLevel(pLut) < nLevMin ) - return; - Nwk_ObjForEachFanin( pLut, pNext, i ) - Nwk_ManMarkFanins_rec( pNext, nLevMin ); -} - -/**Function************************************************************* - - Synopsis [Marks the fanouts of the node with the current trav ID.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManMarkFanouts_rec( Nwk_Obj_t * pLut, int nLevMax, int nFanMax ) -{ - Nwk_Obj_t * pNext; - int i; - if ( !Nwk_ObjIsNode(pLut) ) - return; - if ( Nwk_ObjIsTravIdCurrent( pLut ) ) - return; - Nwk_ObjSetTravIdCurrent( pLut ); - if ( Nwk_ObjLevel(pLut) > nLevMax ) - return; - if ( Nwk_ObjFanoutNum(pLut) > nFanMax ) - return; - Nwk_ObjForEachFanout( pLut, pNext, i ) - Nwk_ManMarkFanouts_rec( pNext, nLevMax, nFanMax ); -} - -/**Function************************************************************* - - Synopsis [Collects the circle of nodes around the given set.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManCollectCircle( Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, int nFanMax ) -{ - Nwk_Obj_t * pObj, * pNext; - int i, k; - Vec_PtrClear( vNext ); - Vec_PtrForEachEntry( Nwk_Obj_t *, vStart, pObj, i ) - { - Nwk_ObjForEachFanin( pObj, pNext, k ) - { - if ( !Nwk_ObjIsNode(pNext) ) - continue; - if ( Nwk_ObjIsTravIdCurrent( pNext ) ) - continue; - Nwk_ObjSetTravIdCurrent( pNext ); - Vec_PtrPush( vNext, pNext ); - } - Nwk_ObjForEachFanout( pObj, pNext, k ) - { - if ( !Nwk_ObjIsNode(pNext) ) - continue; - if ( Nwk_ObjIsTravIdCurrent( pNext ) ) - continue; - Nwk_ObjSetTravIdCurrent( pNext ); - if ( Nwk_ObjFanoutNum(pNext) > nFanMax ) - continue; - Vec_PtrPush( vNext, pNext ); - } - } -} - -/**Function************************************************************* - - Synopsis [Collects the circle of nodes removes from the given one.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManCollectNonOverlapCands( Nwk_Obj_t * pLut, Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars ) -{ - Vec_Ptr_t * vTemp; - Nwk_Obj_t * pObj; - int i, k; - Vec_PtrClear( vCands ); - if ( pPars->nMaxSuppSize - Nwk_ObjFaninNum(pLut) <= 1 ) - return; - - // collect nodes removed by this distance - assert( pPars->nMaxDistance > 0 ); - Vec_PtrClear( vStart ); - Vec_PtrPush( vStart, pLut ); - Nwk_ManIncrementTravId( pLut->pMan ); - Nwk_ObjSetTravIdCurrent( pLut ); - for ( i = 1; i <= pPars->nMaxDistance; i++ ) - { - Nwk_ManCollectCircle( vStart, vNext, pPars->nMaxFanout ); - vTemp = vStart; - vStart = vNext; - vNext = vTemp; - // collect the nodes in vStart - Vec_PtrForEachEntry( Nwk_Obj_t *, vStart, pObj, k ) - Vec_PtrPush( vCands, pObj ); - } - - // mark the TFI/TFO nodes - Nwk_ManIncrementTravId( pLut->pMan ); - if ( pPars->fUseTfiTfo ) - Nwk_ObjSetTravIdCurrent( pLut ); - else - { - Nwk_ObjSetTravIdPrevious( pLut ); - Nwk_ManMarkFanins_rec( pLut, Nwk_ObjLevel(pLut) - pPars->nMaxDistance ); - Nwk_ObjSetTravIdPrevious( pLut ); - Nwk_ManMarkFanouts_rec( pLut, Nwk_ObjLevel(pLut) + pPars->nMaxDistance, pPars->nMaxFanout ); - } - - // collect nodes satisfying the following conditions: - // - they are close enough in terms of distance - // - they are not in the TFI/TFO of the LUT - // - they have no more than the given number of fanins - // - they have no more than the given diff in delay - k = 0; - Vec_PtrForEachEntry( Nwk_Obj_t *, vCands, pObj, i ) - { - if ( Nwk_ObjIsTravIdCurrent(pObj) ) - continue; - if ( Nwk_ObjFaninNum(pLut) + Nwk_ObjFaninNum(pObj) > pPars->nMaxSuppSize ) - continue; - if ( Nwk_ObjLevel(pLut) - Nwk_ObjLevel(pObj) > pPars->nMaxLevelDiff || - Nwk_ObjLevel(pObj) - Nwk_ObjLevel(pLut) > pPars->nMaxLevelDiff ) - continue; - Vec_PtrWriteEntry( vCands, k++, pObj ); - } - Vec_PtrShrink( vCands, k ); -} - - -/**Function************************************************************* - - Synopsis [Count the total number of fanins.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManCountTotalFanins( Nwk_Obj_t * pLut, Nwk_Obj_t * pCand ) -{ - Nwk_Obj_t * pFanin; - int i, nCounter = Nwk_ObjFaninNum(pLut); - Nwk_ObjForEachFanin( pCand, pFanin, i ) - nCounter += !pFanin->MarkC; - return nCounter; -} - -/**Function************************************************************* - - Synopsis [Collects overlapping candidates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManCollectOverlapCands( Nwk_Obj_t * pLut, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars ) -{ - Nwk_Obj_t * pFanin, * pObj; - int i, k; - // mark fanins of pLut - Nwk_ObjForEachFanin( pLut, pFanin, i ) - pFanin->MarkC = 1; - // collect the matching fanouts of each fanin of the node - Vec_PtrClear( vCands ); - Nwk_ManIncrementTravId( pLut->pMan ); - Nwk_ObjSetTravIdCurrent( pLut ); - Nwk_ObjForEachFanin( pLut, pFanin, i ) - { - if ( !Nwk_ObjIsNode(pFanin) ) - continue; - if ( Nwk_ObjFanoutNum(pFanin) > pPars->nMaxFanout ) - continue; - Nwk_ObjForEachFanout( pFanin, pObj, k ) - { - if ( !Nwk_ObjIsNode(pObj) ) - continue; - if ( Nwk_ObjIsTravIdCurrent( pObj ) ) - continue; - Nwk_ObjSetTravIdCurrent( pObj ); - // check the difference in delay - if ( Nwk_ObjLevel(pLut) - Nwk_ObjLevel(pObj) > pPars->nMaxLevelDiff || - Nwk_ObjLevel(pObj) - Nwk_ObjLevel(pLut) > pPars->nMaxLevelDiff ) - continue; - // check the total number of fanins of the node - if ( Nwk_ManCountTotalFanins(pLut, pObj) > pPars->nMaxSuppSize ) - continue; - Vec_PtrPush( vCands, pObj ); - } - } - // unmark fanins of pLut - Nwk_ObjForEachFanin( pLut, pFanin, i ) - pFanin->MarkC = 0; -} - -/**Function************************************************************* - - Synopsis [Performs LUT merging with parameters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Nwk_ManLutMerge( Nwk_Man_t * pNtk, void * pParsInit ) -{ - Nwk_LMPars_t * pPars = (Nwk_LMPars_t *)pParsInit; - Nwk_Grf_t * p; - Vec_Int_t * vResult; - Vec_Ptr_t * vStart, * vNext, * vCands1, * vCands2; - Nwk_Obj_t * pLut, * pCand; - int i, k, nVertsMax, nCands, clk = clock(); - // count the number of vertices - nVertsMax = 0; - Nwk_ManForEachNode( pNtk, pLut, i ) - nVertsMax += (int)(Nwk_ObjFaninNum(pLut) <= pPars->nMaxLutSize); - p = Nwk_ManGraphAlloc( nVertsMax ); - // create graph - vStart = Vec_PtrAlloc( 1000 ); - vNext = Vec_PtrAlloc( 1000 ); - vCands1 = Vec_PtrAlloc( 1000 ); - vCands2 = Vec_PtrAlloc( 1000 ); - nCands = 0; - Nwk_ManForEachNode( pNtk, pLut, i ) - { - if ( Nwk_ObjFaninNum(pLut) > pPars->nMaxLutSize ) - continue; - Nwk_ManCollectOverlapCands( pLut, vCands1, pPars ); - if ( pPars->fUseDiffSupp ) - Nwk_ManCollectNonOverlapCands( pLut, vStart, vNext, vCands2, pPars ); - if ( Vec_PtrSize(vCands1) == 0 && Vec_PtrSize(vCands2) == 0 ) - continue; - nCands += Vec_PtrSize(vCands1) + Vec_PtrSize(vCands2); - // save candidates - Vec_PtrForEachEntry( Nwk_Obj_t *, vCands1, pCand, k ) - Nwk_ManGraphHashEdge( p, Nwk_ObjId(pLut), Nwk_ObjId(pCand) ); - Vec_PtrForEachEntry( Nwk_Obj_t *, vCands2, pCand, k ) - Nwk_ManGraphHashEdge( p, Nwk_ObjId(pLut), Nwk_ObjId(pCand) ); - // print statistics about this node - if ( pPars->fVeryVerbose ) - printf( "Node %6d : Fanins = %d. Fanouts = %3d. Cand1 = %3d. Cand2 = %3d.\n", - Nwk_ObjId(pLut), Nwk_ObjFaninNum(pLut), Nwk_ObjFaninNum(pLut), - Vec_PtrSize(vCands1), Vec_PtrSize(vCands2) ); - } - Vec_PtrFree( vStart ); - Vec_PtrFree( vNext ); - Vec_PtrFree( vCands1 ); - Vec_PtrFree( vCands2 ); - if ( pPars->fVerbose ) - { - printf( "Mergable LUTs = %6d. Total cands = %6d. ", p->nVertsMax, nCands ); - ABC_PRT( "Deriving graph", clock() - clk ); - } - // solve the graph problem - clk = clock(); - Nwk_ManGraphSolve( p ); - if ( pPars->fVerbose ) - { - printf( "GRAPH: Nodes = %6d. Edges = %6d. Pairs = %6d. ", - p->nVerts, p->nEdges, Vec_IntSize(p->vPairs)/2 ); - ABC_PRT( "Solving", clock() - clk ); - Nwk_ManGraphReportMemoryUsage( p ); - } - vResult = p->vPairs; p->vPairs = NULL; -/* - for ( i = 0; i < vResult->nSize; i += 2 ) - printf( "(%d,%d) ", vResult->pArray[i], vResult->pArray[i+1] ); - printf( "\n" ); -*/ - Nwk_ManGraphFree( p ); - return vResult; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/nwk/nwkMerge.h b/src/aig/nwk/nwkMerge.h deleted file mode 100644 index f6be760f..00000000 --- a/src/aig/nwk/nwkMerge.h +++ /dev/null @@ -1,153 +0,0 @@ -/**CFile**************************************************************** - - FileName [nwkMerge.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Logic network representation.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: nwkMerge.h,v 1.1 2008/05/14 22:13:09 wudenni Exp $] - -***********************************************************************/ - -#ifndef __NWK_MERGE_H__ -#define __NWK_MERGE_H__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -#define NWK_MAX_LIST 16 - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -// the LUT merging parameters -typedef struct Nwk_LMPars_t_ Nwk_LMPars_t; -struct Nwk_LMPars_t_ -{ - int nMaxLutSize; // the max LUT size for merging (N=5) - int nMaxSuppSize; // the max total support size after merging (S=5) - int nMaxDistance; // the max number of nodes separating LUTs - int nMaxLevelDiff; // the max difference in levels - int nMaxFanout; // the max number of fanouts to traverse - int fUseDiffSupp; // enables the use of nodes with different support - int fUseTfiTfo; // enables the use of TFO/TFO nodes as candidates - int fVeryVerbose; // enables additional verbose output - int fVerbose; // enables verbose output -}; - -// edge of the graph -typedef struct Nwk_Edg_t_ Nwk_Edg_t; -struct Nwk_Edg_t_ -{ - int iNode1; // the first node - int iNode2; // the second node - Nwk_Edg_t * pNext; // the next edge -}; - -// vertex of the graph -typedef struct Nwk_Vrt_t_ Nwk_Vrt_t; -struct Nwk_Vrt_t_ -{ - int Id; // the vertex number - int iPrev; // the previous vertex in the list - int iNext; // the next vertex in the list - int nEdges; // the number of edges - int pEdges[0]; // the array of edges -}; - -// the connectivity graph -typedef struct Nwk_Grf_t_ Nwk_Grf_t; -struct Nwk_Grf_t_ -{ - // preliminary graph representation - int nObjs; // the number of objects - int nVertsMax; // the upper bound on the number of vertices - int nEdgeHash; // an approximate number of edges - Nwk_Edg_t ** pEdgeHash; // hash table for edges - Aig_MmFixed_t * pMemEdges; // memory for edges - // graph representation - int nEdges; // the number of edges - int nVerts; // the number of vertices - Nwk_Vrt_t ** pVerts; // the array of vertices - Aig_MmFlex_t * pMemVerts; // memory for vertices - // intermediate data - int pLists1[NWK_MAX_LIST+1]; // lists of nodes with one edge - int pLists2[NWK_MAX_LIST+1]; // lists of nodes with more than one edge - // the results of matching - Vec_Int_t * vPairs; // pairs matched in the graph - // object mappings - int * pMapLut2Id; // LUT numbers into vertex IDs - int * pMapId2Lut; // vertex IDs into LUT numbers - // other things - int nMemBytes1; // memory usage in bytes - int nMemBytes2; // memory usage in bytes -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#define Nwk_GraphForEachEdge( p, pEdge, k ) \ - for ( k = 0; k < p->nEdgeHash; k++ ) \ - for ( pEdge = p->pEdgeHash[k]; pEdge; pEdge = pEdge->pNext ) - -#define Nwk_ListForEachVertex( p, List, pVrt ) \ - for ( pVrt = List? p->pVerts[List] : NULL; pVrt; \ - pVrt = pVrt->iNext? p->pVerts[pVrt->iNext] : NULL ) - -#define Nwk_VertexForEachAdjacent( p, pVrt, pNext, k ) \ - for ( k = 0; (k < pVrt->nEdges) && (((pNext) = p->pVerts[pVrt->pEdges[k]]), 1); k++ ) - -//////////////////////////////////////////////////////////////////////// -/// INLINED FUNCTIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== nwkMerge.c ==========================================================*/ -extern ABC_DLL Nwk_Grf_t * Nwk_ManGraphAlloc( int nVertsMax ); -extern ABC_DLL void Nwk_ManGraphFree( Nwk_Grf_t * p ); -extern ABC_DLL void Nwk_ManGraphReportMemoryUsage( Nwk_Grf_t * p ); -extern ABC_DLL void Nwk_ManGraphHashEdge( Nwk_Grf_t * p, int iLut1, int iLut2 ); -extern ABC_DLL void Nwk_ManGraphSolve( Nwk_Grf_t * p ); -extern ABC_DLL int Nwk_ManLutMergeGraphTest( char * pFileName ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/nwk/nwkObj.c b/src/aig/nwk/nwkObj.c deleted file mode 100644 index e5930087..00000000 --- a/src/aig/nwk/nwkObj.c +++ /dev/null @@ -1,204 +0,0 @@ -/**CFile**************************************************************** - - FileName [nwkObj.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Logic network representation.] - - Synopsis [Manipulation of objects.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: nwkObj.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "nwk.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates an object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Nwk_Obj_t * Nwk_ManCreateObj( Nwk_Man_t * p, int nFanins, int nFanouts ) -{ - Nwk_Obj_t * pObj; - pObj = (Nwk_Obj_t *)Aig_MmFlexEntryFetch( p->pMemObjs, sizeof(Nwk_Obj_t) + (nFanins + nFanouts + p->nFanioPlus) * sizeof(Nwk_Obj_t *) ); - memset( pObj, 0, sizeof(Nwk_Obj_t) ); - pObj->pFanio = (Nwk_Obj_t **)((char *)pObj + sizeof(Nwk_Obj_t)); - pObj->Id = Vec_PtrSize( p->vObjs ); - Vec_PtrPush( p->vObjs, pObj ); - pObj->pMan = p; - pObj->nFanioAlloc = nFanins + nFanouts + p->nFanioPlus; - return pObj; -} - - -/**Function************************************************************* - - Synopsis [Creates a primary input.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Nwk_Obj_t * Nwk_ManCreateCi( Nwk_Man_t * p, int nFanouts ) -{ - Nwk_Obj_t * pObj; - pObj = Nwk_ManCreateObj( p, 1, nFanouts ); - pObj->PioId = Vec_PtrSize( p->vCis ); - Vec_PtrPush( p->vCis, pObj ); - pObj->Type = NWK_OBJ_CI; - p->nObjs[NWK_OBJ_CI]++; - return pObj; -} - -/**Function************************************************************* - - Synopsis [Creates a primary output.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Nwk_Obj_t * Nwk_ManCreateCo( Nwk_Man_t * p ) -{ - Nwk_Obj_t * pObj; - pObj = Nwk_ManCreateObj( p, 1, 1 ); - pObj->PioId = Vec_PtrSize( p->vCos ); - Vec_PtrPush( p->vCos, pObj ); - pObj->Type = NWK_OBJ_CO; - p->nObjs[NWK_OBJ_CO]++; - return pObj; -} - -/**Function************************************************************* - - Synopsis [Creates a latch.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Nwk_Obj_t * Nwk_ManCreateLatch( Nwk_Man_t * p ) -{ - Nwk_Obj_t * pObj; - pObj = Nwk_ManCreateObj( p, 1, 1 ); - pObj->Type = NWK_OBJ_LATCH; - p->nObjs[NWK_OBJ_LATCH]++; - return pObj; -} - -/**Function************************************************************* - - Synopsis [Creates a node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Nwk_Obj_t * Nwk_ManCreateNode( Nwk_Man_t * p, int nFanins, int nFanouts ) -{ - Nwk_Obj_t * pObj; - pObj = Nwk_ManCreateObj( p, nFanins, nFanouts ); - pObj->Type = NWK_OBJ_NODE; - p->nObjs[NWK_OBJ_NODE]++; - return pObj; -} - - -/**Function************************************************************* - - Synopsis [Deletes the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManDeleteNode( Nwk_Obj_t * pObj ) -{ - Vec_Ptr_t * vNodes = pObj->pMan->vTemp; - Nwk_Obj_t * pTemp; - int i; - assert( Nwk_ObjFanoutNum(pObj) == 0 ); - // delete fanins - Nwk_ObjCollectFanins( pObj, vNodes ); - Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pTemp, i ) - Nwk_ObjDeleteFanin( pObj, pTemp ); - // remove from the list of objects - Vec_PtrWriteEntry( pObj->pMan->vObjs, pObj->Id, NULL ); - pObj->pMan->nObjs[pObj->Type]--; - memset( pObj, 0, sizeof(Nwk_Obj_t) ); - pObj->Id = -1; -} - -/**Function************************************************************* - - Synopsis [Deletes the node and MFFC of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManDeleteNode_rec( Nwk_Obj_t * pObj ) -{ - Vec_Ptr_t * vNodes; - int i; - assert( !Nwk_ObjIsCi(pObj) ); - assert( Nwk_ObjFanoutNum(pObj) == 0 ); - vNodes = Vec_PtrAlloc( 100 ); - Nwk_ObjCollectFanins( pObj, vNodes ); - Nwk_ManDeleteNode( pObj ); - Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i ) - if ( Nwk_ObjIsNode(pObj) && Nwk_ObjFanoutNum(pObj) == 0 ) - Nwk_ManDeleteNode_rec( pObj ); - Vec_PtrFree( vNodes ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/nwk/nwkSpeedup.c b/src/aig/nwk/nwkSpeedup.c deleted file mode 100644 index 335d50f8..00000000 --- a/src/aig/nwk/nwkSpeedup.c +++ /dev/null @@ -1,382 +0,0 @@ -/**CFile**************************************************************** - - FileName [nwkSpeedup.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Netlist representation.] - - Synopsis [Global delay optimization using structural choices.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: nwkSpeedup.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "nwk.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Adds strashed nodes for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManSpeedupNode_rec( Aig_Man_t * pAig, Aig_Obj_t * pNode, Vec_Ptr_t * vNodes ) -{ - if ( Aig_ObjIsTravIdCurrent(pAig, pNode) ) - return 1; - if ( Aig_ObjIsPi(pNode) ) - return 0; - assert( Aig_ObjIsNode(pNode) ); - Aig_ObjSetTravIdCurrent( pAig, pNode ); - if ( !Aig_ManSpeedupNode_rec( pAig, Aig_ObjFanin0(pNode), vNodes ) ) - return 0; - if ( !Aig_ManSpeedupNode_rec( pAig, Aig_ObjFanin1(pNode), vNodes ) ) - return 0; - Vec_PtrPush( vNodes, pNode ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Adds strashed nodes for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManSpeedupNode( Nwk_Man_t * pNtk, Aig_Man_t * pAig, Nwk_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vTimes ) -{ - Vec_Ptr_t * vNodes; - Nwk_Obj_t * pObj, * pObj2; - Aig_Obj_t * ppCofs[32], * pAnd, * pTemp; - int nCofs, i, k, nSkip; - - // quit of regulars are the same - Vec_PtrForEachEntry( Nwk_Obj_t *, vLeaves, pObj, i ) - Vec_PtrForEachEntry( Nwk_Obj_t *, vLeaves, pObj2, k ) - if ( i != k && Aig_Regular((Aig_Obj_t *)pObj->pCopy) == Aig_Regular((Aig_Obj_t *)pObj2->pCopy) ) - { -// printf( "Identical after structural hashing!!!\n" ); - return; - } - - // collect the AIG nodes - vNodes = Vec_PtrAlloc( 100 ); - Aig_ManIncrementTravId( pAig ); - Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) ); - Vec_PtrForEachEntry( Nwk_Obj_t *, vLeaves, pObj, i ) - { - pAnd = (Aig_Obj_t *)pObj->pCopy; - Aig_ObjSetTravIdCurrent( pAig, Aig_Regular(pAnd) ); - } - // traverse from the root node - pAnd = (Aig_Obj_t *)pNode->pCopy; - if ( !Aig_ManSpeedupNode_rec( pAig, Aig_Regular(pAnd), vNodes ) ) - { -// printf( "Bad node!!!\n" ); - Vec_PtrFree( vNodes ); - return; - } - - // derive cofactors - nCofs = (1 << Vec_PtrSize(vTimes)); - for ( i = 0; i < nCofs; i++ ) - { - Vec_PtrForEachEntry( Nwk_Obj_t *, vLeaves, pObj, k ) - { - pAnd = (Aig_Obj_t *)pObj->pCopy; - Aig_Regular(pAnd)->pData = Aig_Regular(pAnd); - } - Vec_PtrForEachEntry( Nwk_Obj_t *, vTimes, pObj, k ) - { - pAnd = (Aig_Obj_t *)pObj->pCopy; - Aig_Regular(pAnd)->pData = Aig_NotCond( Aig_ManConst1(pAig), ((i & (1<pData = Aig_And( pAig, Aig_ObjChild0Copy(pTemp), Aig_ObjChild1Copy(pTemp) ); - // save the result - pAnd = (Aig_Obj_t *)pNode->pCopy; - ppCofs[i] = Aig_NotCond( (Aig_Obj_t *)Aig_Regular(pAnd)->pData, Aig_IsComplement(pAnd) ); - } - Vec_PtrFree( vNodes ); - -//Nwk_ObjAddFanin( Nwk_ManCreatePo(pAig), ppCofs[0] ); -//Nwk_ObjAddFanin( Nwk_ManCreatePo(pAig), ppCofs[1] ); - - // collect the resulting tree - Vec_PtrForEachEntry( Nwk_Obj_t *, vTimes, pObj, k ) - for ( nSkip = (1<pCopy; - ppCofs[i] = Aig_Mux( pAig, Aig_Regular(pAnd), ppCofs[i+nSkip], ppCofs[i] ); - } -//Nwk_ObjAddFanin( Nwk_ManCreatePo(pAig), ppCofs[0] ); - - // create choice node - pAnd = Aig_Regular((Aig_Obj_t *)pNode->pCopy); // repr - pTemp = Aig_Regular(ppCofs[0]); // new - if ( Aig_ObjEquiv(pAig, pAnd) == NULL && Aig_ObjEquiv(pAig, pTemp) == NULL && !Aig_ObjCheckTfi(pAig, pTemp, pAnd) ) - pAig->pEquivs[pAnd->Id] = pTemp; -} - -/**Function************************************************************* - - Synopsis [Determines timing-critical edges of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Nwk_ManDelayTraceTCEdges( Nwk_Man_t * pNtk, Nwk_Obj_t * pNode, float tDelta, int fUseLutLib ) -{ - int pPinPerm[32]; - float pPinDelays[32]; - If_Lib_t * pLutLib = fUseLutLib? pNtk->pLutLib : NULL; - Nwk_Obj_t * pFanin; - unsigned uResult = 0; - float tRequired, * pDelays; - int k; - tRequired = Nwk_ObjRequired(pNode); - if ( pLutLib == NULL ) - { - Nwk_ObjForEachFanin( pNode, pFanin, k ) - if ( tRequired < Nwk_ObjArrival(pFanin) + 1.0 + tDelta ) - uResult |= (1 << k); - } - else if ( !pLutLib->fVarPinDelays ) - { - pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pNode)]; - Nwk_ObjForEachFanin( pNode, pFanin, k ) - if ( tRequired < Nwk_ObjArrival(pFanin) + pDelays[0] + tDelta ) - uResult |= (1 << k); - } - else - { - pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pNode)]; - Nwk_ManDelayTraceSortPins( pNode, pPinPerm, pPinDelays ); - Nwk_ObjForEachFanin( pNode, pFanin, k ) - if ( tRequired < Nwk_ObjArrival(Nwk_ObjFanin(pNode,pPinPerm[k])) + pDelays[k] + tDelta ) - uResult |= (1 << pPinPerm[k]); - } - return uResult; -} - -/**Function************************************************************* - - Synopsis [Adds choices to speed up the network by the given percentage.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Nwk_ManSpeedup( Nwk_Man_t * pNtk, int fUseLutLib, int Percentage, int Degree, int fVerbose, int fVeryVerbose ) -{ - Aig_Man_t * pAig, * pTemp; - Vec_Ptr_t * vTimeCries, * vTimeFanins; - Nwk_Obj_t * pNode, * pFanin, * pFanin2; - Aig_Obj_t * pAnd; - If_Lib_t * pTempLib = pNtk->pLutLib; - Tim_Man_t * pTempTim = NULL; - float tDelta, tArrival; - int i, k, k2, Counter, CounterRes, nTimeCris; - unsigned * puTCEdges; - // perform delay trace - if ( !fUseLutLib ) - { - pNtk->pLutLib = NULL; - if ( pNtk->pManTime ) - { - pTempTim = pNtk->pManTime; - pNtk->pManTime = Tim_ManDup( pTempTim, 1 ); - } - } - tArrival = Nwk_ManDelayTraceLut( pNtk ); - tDelta = fUseLutLib ? tArrival*Percentage/100.0 : 1.0; - if ( fVerbose ) - { - printf( "Max delay = %.2f. Delta = %.2f. ", tArrival, tDelta ); - printf( "Using %s model. ", fUseLutLib? "LUT library" : "unit-delay" ); - if ( fUseLutLib ) - printf( "Percentage = %d. ", Percentage ); - printf( "\n" ); - } - // mark the timing critical nodes and edges - puTCEdges = ABC_ALLOC( unsigned, Nwk_ManObjNumMax(pNtk) ); - memset( puTCEdges, 0, sizeof(unsigned) * Nwk_ManObjNumMax(pNtk) ); - Nwk_ManForEachNode( pNtk, pNode, i ) - { - if ( Nwk_ObjSlack(pNode) >= tDelta ) - continue; - puTCEdges[pNode->Id] = Nwk_ManDelayTraceTCEdges( pNtk, pNode, tDelta, fUseLutLib ); - } - if ( fVerbose ) - { - Counter = CounterRes = 0; - Nwk_ManForEachNode( pNtk, pNode, i ) - { - Nwk_ObjForEachFanin( pNode, pFanin, k ) - if ( !Nwk_ObjIsCi(pFanin) && Nwk_ObjSlack(pFanin) < tDelta ) - Counter++; - CounterRes += Aig_WordCountOnes( puTCEdges[pNode->Id] ); - } - printf( "Edges: Total = %7d. 0-slack = %7d. Critical = %7d. Ratio = %4.2f\n", - Nwk_ManGetTotalFanins(pNtk), Counter, CounterRes, Counter? 1.0*CounterRes/Counter : 0.0 ); - } - // start the resulting network - pAig = Nwk_ManStrash( pNtk ); - pAig->pEquivs = ABC_ALLOC( Aig_Obj_t *, 3 * Aig_ManObjNumMax(pAig) ); - memset( pAig->pEquivs, 0, sizeof(Aig_Obj_t *) * 3 * Aig_ManObjNumMax(pAig) ); - - // collect nodes to be used for resynthesis - Counter = CounterRes = 0; - vTimeCries = Vec_PtrAlloc( 16 ); - vTimeFanins = Vec_PtrAlloc( 16 ); - Nwk_ManForEachNode( pNtk, pNode, i ) - { - if ( Nwk_ObjSlack(pNode) >= tDelta ) - continue; - // count the number of non-PI timing-critical nodes - nTimeCris = 0; - Nwk_ObjForEachFanin( pNode, pFanin, k ) - if ( !Nwk_ObjIsCi(pFanin) && (puTCEdges[pNode->Id] & (1<Id] & (1<Id] & (1< Degree) ) - if ( (Vec_PtrSize(vTimeCries) == 0 || Vec_PtrSize(vTimeCries) > Degree) ) - continue; - CounterRes++; - // collect second generation nodes - Vec_PtrClear( vTimeFanins ); - Nwk_ObjForEachFanin( pNode, pFanin, k ) - { - if ( Nwk_ObjIsCi(pFanin) ) - Vec_PtrPushUnique( vTimeFanins, pFanin ); - else - Nwk_ObjForEachFanin( pFanin, pFanin2, k2 ) - Vec_PtrPushUnique( vTimeFanins, pFanin2 ); - } - // print the results - if ( fVeryVerbose ) - { - printf( "%5d Node %5d : %d %2d %2d ", Counter, pNode->Id, - nTimeCris, Vec_PtrSize(vTimeCries), Vec_PtrSize(vTimeFanins) ); - Nwk_ObjForEachFanin( pNode, pFanin, k ) - printf( "%d(%.2f)%s ", pFanin->Id, Nwk_ObjSlack(pFanin), (puTCEdges[pNode->Id] & (1< Degree ) - continue; - // order the fanins in the increasing order of criticalily - if ( Vec_PtrSize(vTimeCries) > 1 ) - { - pFanin = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 0 ); - pFanin2 = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 1 ); - if ( Nwk_ObjSlack(pFanin) < Nwk_ObjSlack(pFanin2) ) - { - Vec_PtrWriteEntry( vTimeCries, 0, pFanin2 ); - Vec_PtrWriteEntry( vTimeCries, 1, pFanin ); - } - } - if ( Vec_PtrSize(vTimeCries) > 2 ) - { - pFanin = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 1 ); - pFanin2 = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 2 ); - if ( Nwk_ObjSlack(pFanin) < Nwk_ObjSlack(pFanin2) ) - { - Vec_PtrWriteEntry( vTimeCries, 1, pFanin2 ); - Vec_PtrWriteEntry( vTimeCries, 2, pFanin ); - } - pFanin = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 0 ); - pFanin2 = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 1 ); - if ( Nwk_ObjSlack(pFanin) < Nwk_ObjSlack(pFanin2) ) - { - Vec_PtrWriteEntry( vTimeCries, 0, pFanin2 ); - Vec_PtrWriteEntry( vTimeCries, 1, pFanin ); - } - } - // add choice - Aig_ManSpeedupNode( pNtk, pAig, pNode, vTimeFanins, vTimeCries ); - } - Vec_PtrFree( vTimeCries ); - Vec_PtrFree( vTimeFanins ); - ABC_FREE( puTCEdges ); - if ( fVerbose ) - printf( "Nodes: Total = %7d. 0-slack = %7d. Workable = %7d. Ratio = %4.2f\n", - Nwk_ManNodeNum(pNtk), Counter, CounterRes, Counter? 1.0*CounterRes/Counter : 0.0 ); - - // remove invalid choice nodes - Aig_ManForEachNode( pAig, pAnd, i ) - if ( Aig_ObjEquiv(pAig, pAnd) ) - { - if ( Aig_ObjRefs(Aig_ObjEquiv(pAig, pAnd)) > 0 ) - pAig->pEquivs[pAnd->Id] = NULL; - } - - // put back the library - if ( !fUseLutLib ) - pNtk->pLutLib = pTempLib; - if ( pTempTim ) - { - Tim_ManStop( pNtk->pManTime ); - pNtk->pManTime = pTempTim; - } - - // reconstruct the network - pAig = Aig_ManDupDfs( pTemp = pAig ); - Aig_ManStop( pTemp ); - // reset levels - Aig_ManChoiceLevel( pAig ); - return pAig; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/nwk/nwkStrash.c b/src/aig/nwk/nwkStrash.c deleted file mode 100644 index 54f1f027..00000000 --- a/src/aig/nwk/nwkStrash.c +++ /dev/null @@ -1,149 +0,0 @@ -/**CFile**************************************************************** - - FileName [nwkStrash.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Logic network representation.] - - Synopsis [Performs structural hashing for the network.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: nwkStrash.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "nwk.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Derives AIG from the local functions of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManStrashNode_rec( Aig_Man_t * p, Hop_Obj_t * pObj ) -{ - assert( !Hop_IsComplement(pObj) ); - if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) - return; - Nwk_ManStrashNode_rec( p, Hop_ObjFanin0(pObj) ); - Nwk_ManStrashNode_rec( p, Hop_ObjFanin1(pObj) ); - pObj->pData = Aig_And( p, (Aig_Obj_t *)Hop_ObjChild0Copy(pObj), (Aig_Obj_t *)Hop_ObjChild1Copy(pObj) ); - assert( !Hop_ObjIsMarkA(pObj) ); // loop detection - Hop_ObjSetMarkA( pObj ); -} - -/**Function************************************************************* - - Synopsis [Derives AIG from the local functions of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Nwk_ManStrashNode( Aig_Man_t * p, Nwk_Obj_t * pObj ) -{ - Hop_Man_t * pMan = pObj->pMan->pManHop; - Hop_Obj_t * pRoot = pObj->pFunc; - Nwk_Obj_t * pFanin; - int i; - assert( Nwk_ObjIsNode(pObj) ); - // check the constant case - if ( Hop_Regular(pRoot) == Hop_ManConst1(pMan) ) - return Aig_NotCond( Aig_ManConst1(p), Hop_IsComplement(pRoot) ); - // set elementary variables - Nwk_ObjForEachFanin( pObj, pFanin, i ) - Hop_IthVar(pMan, i)->pData = pFanin->pCopy; - // strash the AIG of this node - Nwk_ManStrashNode_rec( p, Hop_Regular(pRoot) ); - Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); - // return the final node - return Aig_NotCond( (Aig_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); -} - -/**Function************************************************************* - - Synopsis [Derives AIG from the logic network.] - - Description [Assumes topological ordering of nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Nwk_ManStrash( Nwk_Man_t * pNtk ) -{ - Vec_Ptr_t * vObjs; - Aig_Man_t * pMan; - Aig_Obj_t * pObjNew; - Nwk_Obj_t * pObj; - int i, Level; - pMan = Aig_ManStart( Nwk_ManGetAigNodeNum(pNtk) ); - pMan->pName = Aig_UtilStrsav( pNtk->pName ); - pMan->pSpec = Aig_UtilStrsav( pNtk->pSpec ); - pMan->pManTime = Tim_ManDup( (Tim_Man_t *)pNtk->pManTime, 1 ); - Tim_ManIncrementTravId( (Tim_Man_t *)pMan->pManTime ); - Nwk_ManForEachObj( pNtk, pObj, i ) - pObj->pCopy = NULL; -// Nwk_ManForEachObj( pNtk, pObj, i ) - vObjs = Nwk_ManDfs( pNtk ); - Vec_PtrForEachEntry( Nwk_Obj_t *, vObjs, pObj, i ) - { - if ( Nwk_ObjIsCi(pObj) ) - { - pObjNew = Aig_ObjCreatePi(pMan); - Level = Tim_ManGetCiArrival( (Tim_Man_t *)pMan->pManTime, pObj->PioId ); - Aig_ObjSetLevel( pObjNew, Level ); - } - else if ( Nwk_ObjIsCo(pObj) ) - { - pObjNew = Aig_ObjCreatePo( pMan, Aig_NotCond((Aig_Obj_t *)Nwk_ObjFanin0(pObj)->pCopy, pObj->fInvert) ); - Level = Aig_ObjLevel( pObjNew ); - Tim_ManSetCoArrival( (Tim_Man_t *)pMan->pManTime, pObj->PioId, (float)Level ); - } - else if ( Nwk_ObjIsNode(pObj) ) - { - pObjNew = Nwk_ManStrashNode( pMan, pObj ); - } - else - assert( 0 ); - pObj->pCopy = pObjNew; - } - Vec_PtrFree( vObjs ); - Aig_ManCleanup( pMan ); - Aig_ManSetRegNum( pMan, 0 ); - return pMan; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/nwk/nwkTiming.c b/src/aig/nwk/nwkTiming.c deleted file mode 100644 index 53591ee8..00000000 --- a/src/aig/nwk/nwkTiming.c +++ /dev/null @@ -1,894 +0,0 @@ -/**CFile**************************************************************** - - FileName [nwkTiming.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Logic network representation.] - - Synopsis [Manipulation of timing information.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: nwkTiming.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "nwk.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Cleans timing information for all nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManCleanTiming( Nwk_Man_t * pNtk ) -{ - Nwk_Obj_t * pObj; - int i; - Nwk_ManForEachObj( pNtk, pObj, i ) - { - pObj->tArrival = pObj->tSlack = 0.0; - pObj->tRequired = TIM_ETERNITY; - } -} - -/**Function************************************************************* - - Synopsis [Sorts the pins in the decreasing order of delays.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManDelayTraceSortPins( Nwk_Obj_t * pNode, int * pPinPerm, float * pPinDelays ) -{ - Nwk_Obj_t * pFanin; - int i, j, best_i, temp; - // start the trivial permutation and collect pin delays - Nwk_ObjForEachFanin( pNode, pFanin, i ) - { - pPinPerm[i] = i; - pPinDelays[i] = Nwk_ObjArrival(pFanin); - } - // 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 < Nwk_ObjFaninNum(pNode)-1; i++ ) - { - best_i = i; - for ( j = i+1; j < Nwk_ObjFaninNum(pNode); 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( Nwk_ObjFaninNum(pNode) == 0 || pPinPerm[0] < Nwk_ObjFaninNum(pNode) ); - for ( i = 1; i < Nwk_ObjFaninNum(pNode); i++ ) - { - assert( pPinPerm[i] < Nwk_ObjFaninNum(pNode) ); - assert( pPinDelays[pPinPerm[i-1]] >= pPinDelays[pPinPerm[i]] ); - } -} - -/**Function************************************************************* - - Synopsis [Sorts the pins in the decreasing order of delays.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManWhereIsPin( Nwk_Obj_t * pFanout, Nwk_Obj_t * pFanin, int * pPinPerm ) -{ - int i; - for ( i = 0; i < Nwk_ObjFaninNum(pFanout); i++ ) - if ( Nwk_ObjFanin(pFanout, pPinPerm[i]) == pFanin ) - return i; - return -1; -} - -/**Function************************************************************* - - Synopsis [Computes the arrival times for the given object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Nwk_NodeComputeArrival( Nwk_Obj_t * pObj, int fUseSorting ) -{ - If_Lib_t * pLutLib = pObj->pMan->pLutLib; - int pPinPerm[32]; - float pPinDelays[32]; - Nwk_Obj_t * pFanin; - float tArrival, * pDelays; - int k; - assert( Nwk_ObjIsNode(pObj) || Nwk_ObjIsCi(pObj) || Nwk_ObjIsCo(pObj) ); - if ( Nwk_ObjIsCi(pObj) ) - return Nwk_ObjArrival(pObj); - if ( Nwk_ObjIsCo(pObj) ) - return Nwk_ObjArrival( Nwk_ObjFanin0(pObj) ); - tArrival = -TIM_ETERNITY; - if ( pLutLib == NULL ) - { - Nwk_ObjForEachFanin( pObj, pFanin, k ) - if ( tArrival < Nwk_ObjArrival(pFanin) + 1.0 ) - tArrival = Nwk_ObjArrival(pFanin) + 1.0; - } - else if ( !pLutLib->fVarPinDelays ) - { - pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pObj)]; - Nwk_ObjForEachFanin( pObj, pFanin, k ) - if ( tArrival < Nwk_ObjArrival(pFanin) + pDelays[0] ) - tArrival = Nwk_ObjArrival(pFanin) + pDelays[0]; - } - else - { - pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pObj)]; - if ( fUseSorting ) - { - Nwk_ManDelayTraceSortPins( pObj, pPinPerm, pPinDelays ); - Nwk_ObjForEachFanin( pObj, pFanin, k ) - if ( tArrival < Nwk_ObjArrival(Nwk_ObjFanin(pObj,pPinPerm[k])) + pDelays[k] ) - tArrival = Nwk_ObjArrival(Nwk_ObjFanin(pObj,pPinPerm[k])) + pDelays[k]; - } - else - { - Nwk_ObjForEachFanin( pObj, pFanin, k ) - if ( tArrival < Nwk_ObjArrival(pFanin) + pDelays[k] ) - tArrival = Nwk_ObjArrival(pFanin) + pDelays[k]; - } - } - if ( Nwk_ObjFaninNum(pObj) == 0 ) - tArrival = 0.0; - return tArrival; -} - -/**Function************************************************************* - - Synopsis [Computes the required times for the given node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Nwk_NodeComputeRequired( Nwk_Obj_t * pObj, int fUseSorting ) -{ - If_Lib_t * pLutLib = pObj->pMan->pLutLib; - int pPinPerm[32]; - float pPinDelays[32]; - Nwk_Obj_t * pFanout; - float tRequired, tDelay, * pDelays; - int k, iFanin; - assert( Nwk_ObjIsNode(pObj) || Nwk_ObjIsCi(pObj) || Nwk_ObjIsCo(pObj) ); - if ( Nwk_ObjIsCo(pObj) ) - return Nwk_ObjRequired(pObj); - tRequired = TIM_ETERNITY; - if ( pLutLib == NULL ) - { - Nwk_ObjForEachFanout( pObj, pFanout, k ) - { - tDelay = Nwk_ObjIsCo(pFanout)? 0.0 : 1.0; - if ( tRequired > Nwk_ObjRequired(pFanout) - tDelay ) - tRequired = Nwk_ObjRequired(pFanout) - tDelay; - } - } - else if ( !pLutLib->fVarPinDelays ) - { - Nwk_ObjForEachFanout( pObj, pFanout, k ) - { - pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pFanout)]; - tDelay = Nwk_ObjIsCo(pFanout)? 0.0 : pDelays[0]; - if ( tRequired > Nwk_ObjRequired(pFanout) - tDelay ) - tRequired = Nwk_ObjRequired(pFanout) - tDelay; - } - } - else - { - if ( fUseSorting ) - { - Nwk_ObjForEachFanout( pObj, pFanout, k ) - { - pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pFanout)]; - Nwk_ManDelayTraceSortPins( pFanout, pPinPerm, pPinDelays ); - iFanin = Nwk_ManWhereIsPin( pFanout, pObj, pPinPerm ); - assert( Nwk_ObjFanin(pFanout,pPinPerm[iFanin]) == pObj ); - tDelay = Nwk_ObjIsCo(pFanout)? 0.0 : pDelays[iFanin]; - if ( tRequired > Nwk_ObjRequired(pFanout) - tDelay ) - tRequired = Nwk_ObjRequired(pFanout) - tDelay; - } - } - else - { - Nwk_ObjForEachFanout( pObj, pFanout, k ) - { - pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pFanout)]; - iFanin = Nwk_ObjFindFanin( pFanout, pObj ); - assert( Nwk_ObjFanin(pFanout,iFanin) == pObj ); - tDelay = Nwk_ObjIsCo(pFanout)? 0.0 : pDelays[iFanin]; - if ( tRequired > Nwk_ObjRequired(pFanout) - tDelay ) - tRequired = Nwk_ObjRequired(pFanout) - tDelay; - } - } - } - return tRequired; -} - -/**Function************************************************************* - - Synopsis [Propagates the required times through the given node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Nwk_NodePropagateRequired( Nwk_Obj_t * pObj, int fUseSorting ) -{ - If_Lib_t * pLutLib = pObj->pMan->pLutLib; - int pPinPerm[32]; - float pPinDelays[32]; - Nwk_Obj_t * pFanin; - float tRequired = 0.0; // Suppress "might be used uninitialized" - float * pDelays; - int k; - assert( Nwk_ObjIsNode(pObj) ); - if ( pLutLib == NULL ) - { - tRequired = Nwk_ObjRequired(pObj) - (float)1.0; - Nwk_ObjForEachFanin( pObj, pFanin, k ) - if ( Nwk_ObjRequired(pFanin) > tRequired ) - Nwk_ObjSetRequired( pFanin, tRequired ); - } - else if ( !pLutLib->fVarPinDelays ) - { - pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pObj)]; - tRequired = Nwk_ObjRequired(pObj) - pDelays[0]; - Nwk_ObjForEachFanin( pObj, pFanin, k ) - if ( Nwk_ObjRequired(pFanin) > tRequired ) - Nwk_ObjSetRequired( pFanin, tRequired ); - } - else - { - pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pObj)]; - if ( fUseSorting ) - { - Nwk_ManDelayTraceSortPins( pObj, pPinPerm, pPinDelays ); - Nwk_ObjForEachFanin( pObj, pFanin, k ) - { - tRequired = Nwk_ObjRequired(pObj) - pDelays[k]; - if ( Nwk_ObjRequired(Nwk_ObjFanin(pObj,pPinPerm[k])) > tRequired ) - Nwk_ObjSetRequired( Nwk_ObjFanin(pObj,pPinPerm[k]), tRequired ); - } - } - else - { - Nwk_ObjForEachFanin( pObj, pFanin, k ) - { - tRequired = Nwk_ObjRequired(pObj) - pDelays[k]; - if ( Nwk_ObjRequired(pFanin) > tRequired ) - Nwk_ObjSetRequired( pFanin, tRequired ); - } - } - } - return tRequired; -} - -/**Function************************************************************* - - Synopsis [Computes the delay trace of the given network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Nwk_ManDelayTraceLut( Nwk_Man_t * pNtk ) -{ - Vec_Ptr_t * vObjs; - int fUseSorting = 1; - If_Lib_t * pLutLib = pNtk->pLutLib; - Vec_Ptr_t * vNodes; - Nwk_Obj_t * pObj; - float tArrival, tRequired, tSlack; - int i; - - // get the library - if ( pLutLib && pLutLib->LutMax < Nwk_ManGetFaninMax(pNtk) ) - { - printf( "The max LUT size (%d) is less than the max fanin count (%d).\n", - pLutLib->LutMax, Nwk_ManGetFaninMax(pNtk) ); - return -TIM_ETERNITY; - } - - // compute the reverse order of all objects - vNodes = Nwk_ManDfsReverse( pNtk ); - - // initialize the arrival times - Nwk_ManCleanTiming( pNtk ); - - // propagate arrival times - if ( pNtk->pManTime ) - Tim_ManIncrementTravId( pNtk->pManTime ); -// Nwk_ManForEachObj( pNtk, pObj, i ) - vObjs = Nwk_ManDfs( pNtk ); - Vec_PtrForEachEntry( Nwk_Obj_t *, vObjs, pObj, i ) - { - tArrival = Nwk_NodeComputeArrival( pObj, fUseSorting ); - if ( Nwk_ObjIsCi(pObj) && pNtk->pManTime ) - tArrival = Tim_ManGetCiArrival( pNtk->pManTime, pObj->PioId ); - if ( Nwk_ObjIsCo(pObj) && pNtk->pManTime ) - Tim_ManSetCoArrival( pNtk->pManTime, pObj->PioId, tArrival ); - Nwk_ObjSetArrival( pObj, tArrival ); - } - Vec_PtrFree( vObjs ); - - // get the latest arrival times - tArrival = -TIM_ETERNITY; - Nwk_ManForEachPo( pNtk, pObj, i ) - if ( tArrival < Nwk_ObjArrival(pObj) ) - tArrival = Nwk_ObjArrival(pObj); - - // initialize the required times - if ( pNtk->pManTime ) - { - Tim_ManIncrementTravId( pNtk->pManTime ); - Tim_ManSetCoRequiredAll( pNtk->pManTime, tArrival ); - } - else - { - Nwk_ManForEachCo( pNtk, pObj, i ) - Nwk_ObjSetRequired( pObj, tArrival ); - } - - // propagate the required times - Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i ) - { - if ( Nwk_ObjIsNode(pObj) ) - { - Nwk_NodePropagateRequired( pObj, fUseSorting ); - } - else if ( Nwk_ObjIsCi(pObj) ) - { - if ( pNtk->pManTime ) - Tim_ManSetCiRequired( pNtk->pManTime, pObj->PioId, Nwk_ObjRequired(pObj) ); - } - else if ( Nwk_ObjIsCo(pObj) ) - { - if ( pNtk->pManTime ) - { - tRequired = Tim_ManGetCoRequired( pNtk->pManTime, pObj->PioId ); - Nwk_ObjSetRequired( pObj, tRequired ); - } - if ( Nwk_ObjRequired(Nwk_ObjFanin0(pObj)) > Nwk_ObjRequired(pObj) ) - Nwk_ObjSetRequired( Nwk_ObjFanin0(pObj), Nwk_ObjRequired(pObj) ); - } - - // set slack for this object - tSlack = Nwk_ObjRequired(pObj) - Nwk_ObjArrival(pObj); - assert( tSlack + 0.01 > 0.0 ); - Nwk_ObjSetSlack( pObj, tSlack < 0.0 ? 0.0 : tSlack ); - } - Vec_PtrFree( vNodes ); - return tArrival; -} - -/**Function************************************************************* - - Synopsis [Computes the arrival times for the given node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManVerifyTiming( Nwk_Man_t * pNtk ) -{ - Nwk_Obj_t * pObj; - float tArrival, tRequired; - int i; - Nwk_ManForEachObj( pNtk, pObj, i ) - { - if ( Nwk_ObjIsCi(pObj) && Nwk_ObjFanoutNum(pObj) == 0 ) - continue; - tArrival = Nwk_NodeComputeArrival( pObj, 1 ); - tRequired = Nwk_NodeComputeRequired( pObj, 1 ); - if ( !Nwk_ManTimeEqual( tArrival, Nwk_ObjArrival(pObj), (float)0.01 ) ) - printf( "Nwk_ManVerifyTiming(): Object %d has different arrival time (%.2f) from computed (%.2f).\n", - pObj->Id, Nwk_ObjArrival(pObj), tArrival ); - if ( !Nwk_ManTimeEqual( tRequired, Nwk_ObjRequired(pObj), (float)0.01 ) ) - printf( "Nwk_ManVerifyTiming(): Object %d has different required time (%.2f) from computed (%.2f).\n", - pObj->Id, Nwk_ObjRequired(pObj), tRequired ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Prints the delay trace for the given network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManDelayTracePrint( Nwk_Man_t * pNtk ) -{ - If_Lib_t * pLutLib = pNtk->pLutLib; - Nwk_Obj_t * pNode; - int i, Nodes, * pCounters; - float tArrival, tDelta, nSteps, Num; - // get the library - if ( pLutLib && pLutLib->LutMax < Nwk_ManGetFaninMax(pNtk) ) - { - printf( "The max LUT size (%d) is less than the max fanin count (%d).\n", - pLutLib->LutMax, Nwk_ManGetFaninMax(pNtk) ); - return; - } - // decide how many steps - nSteps = pLutLib ? 20 : Nwk_ManLevelMax(pNtk); - pCounters = ABC_ALLOC( int, nSteps + 1 ); - memset( pCounters, 0, sizeof(int)*(nSteps + 1) ); - // perform delay trace - tArrival = Nwk_ManDelayTraceLut( pNtk ); - tDelta = tArrival / nSteps; - // count how many nodes have slack in the corresponding intervals - Nwk_ManForEachNode( pNtk, pNode, i ) - { - if ( Nwk_ObjFaninNum(pNode) == 0 ) - continue; - Num = Nwk_ObjSlack(pNode) / tDelta; - if ( Num > nSteps ) - continue; - assert( Num >=0 && Num <= nSteps ); - pCounters[(int)Num]++; - } - // print the results - printf( "Max delay = %6.2f. Delay trace using %s model:\n", tArrival, pLutLib? "LUT library" : "unit-delay" ); - Nodes = 0; - for ( i = 0; i < nSteps; i++ ) - { - Nodes += pCounters[i]; - printf( "%3d %s : %5d (%6.2f %%)\n", pLutLib? 5*(i+1) : i+1, - pLutLib? "%":"lev", Nodes, 100.0*Nodes/Nwk_ManNodeNum(pNtk) ); - } - ABC_FREE( pCounters ); -} - - -/**Function************************************************************* - - Synopsis [Inserts node into the queue of nodes sorted by level.] - - Description [The inserted node should not go before the current position - given by iCurrent. If the arrival times are computed, the nodes are sorted - in the increasing order of levels. If the required times are computed, - the nodes are sorted in the decreasing order of levels.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_NodeUpdateAddToQueue( Vec_Ptr_t * vQueue, Nwk_Obj_t * pObj, int iCurrent, int fArrival ) -{ - Nwk_Obj_t * pTemp1, * pTemp2; - int i; - Vec_PtrPush( vQueue, pObj ); - for ( i = Vec_PtrSize(vQueue) - 1; i > iCurrent + 1; i-- ) - { - pTemp1 = (Nwk_Obj_t *)vQueue->pArray[i]; - pTemp2 = (Nwk_Obj_t *)vQueue->pArray[i-1]; - if ( fArrival ) - { - if ( Nwk_ObjLevel(pTemp2) <= Nwk_ObjLevel(pTemp1) ) - break; - } - else - { - if ( Nwk_ObjLevel(pTemp2) >= Nwk_ObjLevel(pTemp1) ) - break; - } - vQueue->pArray[i-1] = pTemp1; - vQueue->pArray[i] = pTemp2; - } - // verification - for ( i = iCurrent + 1; i < Vec_PtrSize(vQueue) - 1; i++ ) - { - pTemp1 = (Nwk_Obj_t *)vQueue->pArray[i]; - pTemp2 = (Nwk_Obj_t *)vQueue->pArray[i+1]; - if ( fArrival ) - assert( Nwk_ObjLevel(pTemp1) <= Nwk_ObjLevel(pTemp2) ); - else - assert( Nwk_ObjLevel(pTemp1) >= Nwk_ObjLevel(pTemp2) ); - } -} - -/**Function************************************************************* - - Synopsis [Incrementally updates arrival times of the node.] - - Description [Supports variable-pin delay model and white-boxes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_NodeUpdateArrival( Nwk_Obj_t * pObj ) -{ - Tim_Man_t * pManTime = pObj->pMan->pManTime; - Vec_Ptr_t * vQueue = pObj->pMan->vTemp; - Nwk_Obj_t * pTemp; - Nwk_Obj_t * pNext = NULL; // Suppress "might be used uninitialized" - float tArrival; - int iCur, k, iBox, iTerm1, nTerms; - assert( Nwk_ObjIsNode(pObj) ); - // verify the arrival time - tArrival = Nwk_NodeComputeArrival( pObj, 1 ); - assert( Nwk_ManTimeLess( tArrival, Nwk_ObjRequired(pObj), (float)0.01 ) ); - // initialize the queue with the node - Vec_PtrClear( vQueue ); - Vec_PtrPush( vQueue, pObj ); - pObj->MarkA = 1; - // process objects - if ( pManTime ) - Tim_ManIncrementTravId( pManTime ); - Vec_PtrForEachEntry( Nwk_Obj_t *, vQueue, pTemp, iCur ) - { - pTemp->MarkA = 0; - tArrival = Nwk_NodeComputeArrival( pTemp, 1 ); - if ( Nwk_ObjIsCi(pTemp) && pManTime ) - tArrival = Tim_ManGetCiArrival( pManTime, pTemp->PioId ); - if ( Nwk_ManTimeEqual( tArrival, Nwk_ObjArrival(pTemp), (float)0.01 ) ) - continue; - Nwk_ObjSetArrival( pTemp, tArrival ); - // add the fanouts to the queue - if ( Nwk_ObjIsCo(pTemp) ) - { - if ( pManTime ) - { - iBox = Tim_ManBoxForCo( pManTime, pTemp->PioId ); - if ( iBox >= 0 ) // this CO is an input of the box - { - // it may happen that a box-input (CO) was already marked as visited - // when some other box-input of the same box was visited - here we undo this - if ( Tim_ManIsCoTravIdCurrent( pManTime, pTemp->PioId ) ) - Tim_ManSetPreviousTravIdBoxInputs( pManTime, iBox ); - Tim_ManSetCoArrival( pManTime, pTemp->PioId, tArrival ); - Tim_ManSetCurrentTravIdBoxInputs( pManTime, iBox ); - iTerm1 = Tim_ManBoxOutputFirst( pManTime, iBox ); - nTerms = Tim_ManBoxOutputNum( pManTime, iBox ); - for ( k = 0; k < nTerms; k++ ) - { - pNext = Nwk_ManCi(pNext->pMan, iTerm1 + k); - if ( pNext->MarkA ) - continue; - Nwk_NodeUpdateAddToQueue( vQueue, pNext, iCur, 1 ); - pNext->MarkA = 1; - } - } - } - } - else - { - Nwk_ObjForEachFanout( pTemp, pNext, k ) - { - if ( pNext->MarkA ) - continue; - Nwk_NodeUpdateAddToQueue( vQueue, pNext, iCur, 1 ); - pNext->MarkA = 1; - } - } - } -} - -/**Function************************************************************* - - Synopsis [Incrementally updates required times of the node.] - - Description [Supports variable-pin delay model and white-boxes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_NodeUpdateRequired( Nwk_Obj_t * pObj ) -{ - Tim_Man_t * pManTime = pObj->pMan->pManTime; - Vec_Ptr_t * vQueue = pObj->pMan->vTemp; - Nwk_Obj_t * pTemp; - Nwk_Obj_t * pNext = NULL; // Suppress "might be used uninitialized" - float tRequired; - int iCur, k, iBox, iTerm1, nTerms; - assert( Nwk_ObjIsNode(pObj) ); - // make sure the node's required time remained the same - tRequired = Nwk_NodeComputeRequired( pObj, 1 ); - assert( Nwk_ManTimeEqual( tRequired, Nwk_ObjRequired(pObj), (float)0.01 ) ); - // initialize the queue with the node's faninsa and the old node's fanins - Vec_PtrClear( vQueue ); - Nwk_ObjForEachFanin( pObj, pNext, k ) - { - if ( pNext->MarkA ) - continue; - Nwk_NodeUpdateAddToQueue( vQueue, pNext, -1, 0 ); - pNext->MarkA = 1; - } - // process objects - if ( pManTime ) - Tim_ManIncrementTravId( pManTime ); - Vec_PtrForEachEntry( Nwk_Obj_t *, vQueue, pTemp, iCur ) - { - pTemp->MarkA = 0; - tRequired = Nwk_NodeComputeRequired( pTemp, 1 ); - if ( Nwk_ObjIsCo(pTemp) && pManTime ) - tRequired = Tim_ManGetCoRequired( pManTime, pTemp->PioId ); - if ( Nwk_ManTimeEqual( tRequired, Nwk_ObjRequired(pTemp), (float)0.01 ) ) - continue; - Nwk_ObjSetRequired( pTemp, tRequired ); - // add the fanins to the queue - if ( Nwk_ObjIsCi(pTemp) ) - { - if ( pManTime ) - { - iBox = Tim_ManBoxForCi( pManTime, pTemp->PioId ); - if ( iBox >= 0 ) // this CI is an output of the box - { - // it may happen that a box-output (CI) was already marked as visited - // when some other box-output of the same box was visited - here we undo this - if ( Tim_ManIsCiTravIdCurrent( pManTime, pTemp->PioId ) ) - Tim_ManSetPreviousTravIdBoxOutputs( pManTime, iBox ); - Tim_ManSetCiRequired( pManTime, pTemp->PioId, tRequired ); - Tim_ManSetCurrentTravIdBoxOutputs( pManTime, iBox ); - iTerm1 = Tim_ManBoxInputFirst( pManTime, iBox ); - nTerms = Tim_ManBoxInputNum( pManTime, iBox ); - for ( k = 0; k < nTerms; k++ ) - { - pNext = Nwk_ManCo(pNext->pMan, iTerm1 + k); - if ( pNext->MarkA ) - continue; - Nwk_NodeUpdateAddToQueue( vQueue, pNext, iCur, 0 ); - pNext->MarkA = 1; - } - } - } - } - else - { - Nwk_ObjForEachFanin( pTemp, pNext, k ) - { - if ( pNext->MarkA ) - continue; - Nwk_NodeUpdateAddToQueue( vQueue, pNext, iCur, 0 ); - pNext->MarkA = 1; - } - } - } -} - -/**Function************************************************************* - - Synopsis [Computes the level of the node using its fanin levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ObjLevelNew( Nwk_Obj_t * pObj ) -{ - Tim_Man_t * pManTime = pObj->pMan->pManTime; - Nwk_Obj_t * pFanin; - int i, iBox, iTerm1, nTerms, Level = 0; - if ( Nwk_ObjIsCi(pObj) || Nwk_ObjIsLatch(pObj) ) - { - if ( pManTime ) - { - iBox = Tim_ManBoxForCi( pManTime, pObj->PioId ); - if ( iBox >= 0 ) // this CI is an output of the box - { - iTerm1 = Tim_ManBoxInputFirst( pManTime, iBox ); - nTerms = Tim_ManBoxInputNum( pManTime, iBox ); - for ( i = 0; i < nTerms; i++ ) - { - pFanin = Nwk_ManCo(pObj->pMan, iTerm1 + i); - Level = ABC_MAX( Level, Nwk_ObjLevel(pFanin) ); - } - Level++; - } - } - return Level; - } - assert( Nwk_ObjIsNode(pObj) || Nwk_ObjIsCo(pObj) ); - Nwk_ObjForEachFanin( pObj, pFanin, i ) - Level = ABC_MAX( Level, Nwk_ObjLevel(pFanin) ); - return Level + (Nwk_ObjIsNode(pObj) && Nwk_ObjFaninNum(pObj) > 0); -} - -/**Function************************************************************* - - Synopsis [Incrementally updates level of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManUpdateLevel( Nwk_Obj_t * pObj ) -{ - Tim_Man_t * pManTime = pObj->pMan->pManTime; - Vec_Ptr_t * vQueue = pObj->pMan->vTemp; - Nwk_Obj_t * pTemp; - Nwk_Obj_t * pNext = NULL; // Suppress "might be used uninitialized" - int LevelNew, iCur, k, iBox, iTerm1, nTerms; - assert( Nwk_ObjIsNode(pObj) ); - // initialize the queue with the node - Vec_PtrClear( vQueue ); - Vec_PtrPush( vQueue, pObj ); - pObj->MarkA = 1; - // process objects - Vec_PtrForEachEntry( Nwk_Obj_t *, vQueue, pTemp, iCur ) - { - pTemp->MarkA = 0; - LevelNew = Nwk_ObjLevelNew( pTemp ); - if ( LevelNew == Nwk_ObjLevel(pTemp) ) - continue; - Nwk_ObjSetLevel( pTemp, LevelNew ); - // add the fanouts to the queue - if ( Nwk_ObjIsCo(pTemp) ) - { - if ( pManTime ) - { - iBox = Tim_ManBoxForCo( pManTime, pTemp->PioId ); - if ( iBox >= 0 ) // this is not a true PO - { - Tim_ManSetCurrentTravIdBoxInputs( pManTime, iBox ); - iTerm1 = Tim_ManBoxOutputFirst( pManTime, iBox ); - nTerms = Tim_ManBoxOutputNum( pManTime, iBox ); - for ( k = 0; k < nTerms; k++ ) - { - pNext = Nwk_ManCi(pNext->pMan, iTerm1 + k); - if ( pNext->MarkA ) - continue; - Nwk_NodeUpdateAddToQueue( vQueue, pNext, iCur, 1 ); - pNext->MarkA = 1; - } - } - } - } - else - { - Nwk_ObjForEachFanout( pTemp, pNext, k ) - { - if ( pNext->MarkA ) - continue; - Nwk_NodeUpdateAddToQueue( vQueue, pNext, iCur, 1 ); - pNext->MarkA = 1; - } - } - } -} - -/**Function************************************************************* - - Synopsis [Computes the level of the node using its fanin levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManVerifyLevel( Nwk_Man_t * pNtk ) -{ - Nwk_Obj_t * pObj; - int LevelNew, i; - Nwk_ManForEachObj( pNtk, pObj, i ) - { - assert( pObj->MarkA == 0 ); - LevelNew = Nwk_ObjLevelNew( pObj ); - if ( Nwk_ObjLevel(pObj) != LevelNew ) - { - printf( "Object %6d: Mismatch betweeh levels: Actual = %d. Correct = %d.\n", - i, Nwk_ObjLevel(pObj), LevelNew ); - } - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Replaces the node and incrementally updates levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManUpdate( Nwk_Obj_t * pObj, Nwk_Obj_t * pObjNew, Vec_Vec_t * vLevels ) -{ - assert( pObj->pMan == pObjNew->pMan ); - assert( pObj != pObjNew ); - assert( Nwk_ObjFanoutNum(pObj) > 0 ); - assert( Nwk_ObjIsNode(pObj) && !Nwk_ObjIsCo(pObjNew) ); - // transfer fanouts to the old node - Nwk_ObjTransferFanout( pObj, pObjNew ); - // transfer the timing information - // (this is needed because updating level happens if the level has changed; - // when we set the old level, it will be recomputed by the level updating - // procedure, which will update level of other nodes if there is a difference) - pObjNew->Level = pObj->Level; - pObjNew->tArrival = pObj->tArrival; - pObjNew->tRequired = pObj->tRequired; - // update required times of the old fanins - pObj->tRequired = TIM_ETERNITY; - Nwk_NodeUpdateRequired( pObj ); - // remove the old node - Nwk_ManDeleteNode_rec( pObj ); - // update the information of the new node - Nwk_ManUpdateLevel( pObjNew ); - Nwk_NodeUpdateArrival( pObjNew ); - Nwk_NodeUpdateRequired( pObjNew ); -//Nwk_ManVerifyTiming( pObjNew->pMan ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/nwk/nwkUtil.c b/src/aig/nwk/nwkUtil.c deleted file mode 100644 index a1948031..00000000 --- a/src/aig/nwk/nwkUtil.c +++ /dev/null @@ -1,643 +0,0 @@ -/**CFile**************************************************************** - - FileName [nwkUtil.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Logic network representation.] - - Synopsis [Various utilities.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: nwkUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include -#include "nwk.h" -#include "kit.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Increments the current traversal ID of the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManIncrementTravId( Nwk_Man_t * pNtk ) -{ - Nwk_Obj_t * pObj; - int i; - if ( pNtk->nTravIds >= (1<<26)-1 ) - { - pNtk->nTravIds = 0; - Nwk_ManForEachObj( pNtk, pObj, i ) - pObj->TravId = 0; - } - pNtk->nTravIds++; -} - -/**Function************************************************************* - - Synopsis [Reads the maximum number of fanins of a node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManGetFaninMax( Nwk_Man_t * pNtk ) -{ - Nwk_Obj_t * pNode; - int i, nFaninsMax = 0; - Nwk_ManForEachNode( pNtk, pNode, i ) - { - if ( nFaninsMax < Nwk_ObjFaninNum(pNode) ) - nFaninsMax = Nwk_ObjFaninNum(pNode); - } - return nFaninsMax; -} - -/**Function************************************************************* - - Synopsis [Reads the total number of all fanins.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManGetTotalFanins( Nwk_Man_t * pNtk ) -{ - Nwk_Obj_t * pNode; - int i, nFanins = 0; - Nwk_ManForEachNode( pNtk, pNode, i ) - nFanins += Nwk_ObjFaninNum(pNode); - return nFanins; -} - - -/**Function************************************************************* - - Synopsis [Returns the number of true PIs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManPiNum( Nwk_Man_t * pNtk ) -{ - Nwk_Obj_t * pNode; - int i, Counter = 0; - Nwk_ManForEachCi( pNtk, pNode, i ) - Counter += Nwk_ObjIsPi( pNode ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Returns the number of true POs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManPoNum( Nwk_Man_t * pNtk ) -{ - Nwk_Obj_t * pNode; - int i, Counter = 0; - Nwk_ManForEachCo( pNtk, pNode, i ) - Counter += Nwk_ObjIsPo( pNode ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Reads the number of AIG nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManGetAigNodeNum( Nwk_Man_t * pNtk ) -{ - Nwk_Obj_t * pNode; - int i, nNodes = 0; - Nwk_ManForEachNode( pNtk, pNode, i ) - { - if ( pNode->pFunc == NULL ) - { - printf( "Nwk_ManGetAigNodeNum(): Local AIG of node %d is not assigned.\n", pNode->Id ); - continue; - } - if ( Nwk_ObjFaninNum(pNode) < 2 ) - continue; - nNodes += Hop_DagSize( pNode->pFunc ); - } - return nNodes; -} - -/**Function************************************************************* - - Synopsis [Procedure used for sorting the nodes in increasing order of levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_NodeCompareLevelsIncrease( Nwk_Obj_t ** pp1, Nwk_Obj_t ** pp2 ) -{ - int Diff = (*pp1)->Level - (*pp2)->Level; - if ( Diff < 0 ) - return -1; - if ( Diff > 0 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_NodeCompareLevelsDecrease( Nwk_Obj_t ** pp1, Nwk_Obj_t ** pp2 ) -{ - int Diff = (*pp1)->Level - (*pp2)->Level; - if ( Diff > 0 ) - return -1; - if ( Diff < 0 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Prints the objects.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ObjPrint( Nwk_Obj_t * pObj ) -{ - Nwk_Obj_t * pNext; - int i; - printf( "ObjId = %5d. ", pObj->Id ); - if ( Nwk_ObjIsPi(pObj) ) - printf( "PI" ); - if ( Nwk_ObjIsPo(pObj) ) - printf( "PO" ); - if ( Nwk_ObjIsNode(pObj) ) - printf( "Node" ); - printf( " Fanins = " ); - Nwk_ObjForEachFanin( pObj, pNext, i ) - printf( "%d ", pNext->Id ); - printf( " Fanouts = " ); - Nwk_ObjForEachFanout( pObj, pNext, i ) - printf( "%d ", pNext->Id ); - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Dumps the BLIF file for the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManDumpBlif( Nwk_Man_t * pNtk, char * pFileName, Vec_Ptr_t * vPiNames, Vec_Ptr_t * vPoNames ) -{ - FILE * pFile; - Vec_Ptr_t * vNodes; - Vec_Int_t * vTruth; - Vec_Int_t * vCover; - Nwk_Obj_t * pObj, * pFanin; - Aig_MmFlex_t * pMem; - char * pSop = NULL; - unsigned * pTruth; - int i, k, nDigits; - if ( Nwk_ManPoNum(pNtk) == 0 ) - { - printf( "Nwk_ManDumpBlif(): Network does not have POs.\n" ); - return; - } - // collect nodes in the DFS order - nDigits = Aig_Base10Log( Nwk_ManObjNumMax(pNtk) ); - // write the file - pFile = fopen( pFileName, "w" ); - fprintf( pFile, "# BLIF file written by procedure Nwk_ManDumpBlif()\n" ); -// fprintf( pFile, "# http://www.eecs.berkeley.edu/~alanmi/abc/\n" ); - fprintf( pFile, ".model %s\n", pNtk->pName ); - // write PIs - fprintf( pFile, ".inputs" ); - Nwk_ManForEachCi( pNtk, pObj, i ) - if ( vPiNames ) - fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPiNames, i) ); - else - fprintf( pFile, " n%0*d", nDigits, pObj->Id ); - fprintf( pFile, "\n" ); - // write POs - fprintf( pFile, ".outputs" ); - Nwk_ManForEachCo( pNtk, pObj, i ) - if ( vPoNames ) - fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPoNames, i) ); - else - fprintf( pFile, " n%0*d", nDigits, pObj->Id ); - fprintf( pFile, "\n" ); - // write nodes - pMem = Aig_MmFlexStart(); - vTruth = Vec_IntAlloc( 1 << 16 ); - vCover = Vec_IntAlloc( 1 << 16 ); - vNodes = Nwk_ManDfs( pNtk ); - Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i ) - { - if ( !Nwk_ObjIsNode(pObj) ) - continue; - // derive SOP for the AIG - pTruth = Hop_ManConvertAigToTruth( pNtk->pManHop, Hop_Regular(pObj->pFunc), Nwk_ObjFaninNum(pObj), vTruth, 0 ); - if ( Hop_IsComplement(pObj->pFunc) ) - Kit_TruthNot( pTruth, pTruth, Nwk_ObjFaninNum(pObj) ); - pSop = Kit_PlaFromTruth( pMem, pTruth, Nwk_ObjFaninNum(pObj), vCover ); - // write the node - fprintf( pFile, ".names" ); - if ( !Kit_TruthIsConst0(pTruth, Nwk_ObjFaninNum(pObj)) && !Kit_TruthIsConst1(pTruth, Nwk_ObjFaninNum(pObj)) ) - { - Nwk_ObjForEachFanin( pObj, pFanin, k ) - if ( vPiNames && Nwk_ObjIsPi(pFanin) ) - fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPiNames, Nwk_ObjPioNum(pFanin)) ); - else - fprintf( pFile, " n%0*d", nDigits, pFanin->Id ); - } - fprintf( pFile, " n%0*d\n", nDigits, pObj->Id ); - // write the function - fprintf( pFile, "%s", pSop ); - } - Vec_IntFree( vCover ); - Vec_IntFree( vTruth ); - Vec_PtrFree( vNodes ); - Aig_MmFlexStop( pMem, 0 ); - // write POs - Nwk_ManForEachCo( pNtk, pObj, i ) - { - fprintf( pFile, ".names" ); - if ( vPiNames && Nwk_ObjIsPi(Nwk_ObjFanin0(pObj)) ) - fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPiNames, Nwk_ObjPioNum(Nwk_ObjFanin0(pObj))) ); - else - fprintf( pFile, " n%0*d", nDigits, Nwk_ObjFanin0(pObj)->Id ); - if ( vPoNames ) - fprintf( pFile, " %s\n", (char*)Vec_PtrEntry(vPoNames, Nwk_ObjPioNum(pObj)) ); - else - fprintf( pFile, " n%0*d\n", nDigits, pObj->Id ); - fprintf( pFile, "%d 1\n", !pObj->fInvert ); - } - fprintf( pFile, ".end\n\n" ); - fclose( pFile ); -} - -/**Function************************************************************* - - Synopsis [Prints the distribution of fanins/fanouts in the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManPrintFanioNew( Nwk_Man_t * pNtk ) -{ - char Buffer[100]; - Nwk_Obj_t * pNode; - Vec_Int_t * vFanins, * vFanouts; - int nFanins, nFanouts, nFaninsMax, nFanoutsMax, nFaninsAll, nFanoutsAll; - int i, k, nSizeMax; - - // determine the largest fanin and fanout - nFaninsMax = nFanoutsMax = 0; - nFaninsAll = nFanoutsAll = 0; - Nwk_ManForEachNode( pNtk, pNode, i ) - { - nFanins = Nwk_ObjFaninNum(pNode); - nFanouts = Nwk_ObjFanoutNum(pNode); - nFaninsAll += nFanins; - nFanoutsAll += nFanouts; - nFaninsMax = ABC_MAX( nFaninsMax, nFanins ); - nFanoutsMax = ABC_MAX( nFanoutsMax, nFanouts ); - } - - // allocate storage for fanin/fanout numbers - nSizeMax = ABC_MAX( 10 * (Aig_Base10Log(nFaninsMax) + 1), 10 * (Aig_Base10Log(nFanoutsMax) + 1) ); - vFanins = Vec_IntStart( nSizeMax ); - vFanouts = Vec_IntStart( nSizeMax ); - - // count the number of fanins and fanouts - Nwk_ManForEachNode( pNtk, pNode, i ) - { - nFanins = Nwk_ObjFaninNum(pNode); - nFanouts = Nwk_ObjFanoutNum(pNode); -// nFanouts = Nwk_NodeMffcSize(pNode); - - if ( nFanins < 10 ) - Vec_IntAddToEntry( vFanins, nFanins, 1 ); - else if ( nFanins < 100 ) - Vec_IntAddToEntry( vFanins, 10 + nFanins/10, 1 ); - else if ( nFanins < 1000 ) - Vec_IntAddToEntry( vFanins, 20 + nFanins/100, 1 ); - else if ( nFanins < 10000 ) - Vec_IntAddToEntry( vFanins, 30 + nFanins/1000, 1 ); - else if ( nFanins < 100000 ) - Vec_IntAddToEntry( vFanins, 40 + nFanins/10000, 1 ); - else if ( nFanins < 1000000 ) - Vec_IntAddToEntry( vFanins, 50 + nFanins/100000, 1 ); - else if ( nFanins < 10000000 ) - Vec_IntAddToEntry( vFanins, 60 + nFanins/1000000, 1 ); - - if ( nFanouts < 10 ) - Vec_IntAddToEntry( vFanouts, nFanouts, 1 ); - else if ( nFanouts < 100 ) - Vec_IntAddToEntry( vFanouts, 10 + nFanouts/10, 1 ); - else if ( nFanouts < 1000 ) - Vec_IntAddToEntry( vFanouts, 20 + nFanouts/100, 1 ); - else if ( nFanouts < 10000 ) - Vec_IntAddToEntry( vFanouts, 30 + nFanouts/1000, 1 ); - else if ( nFanouts < 100000 ) - Vec_IntAddToEntry( vFanouts, 40 + nFanouts/10000, 1 ); - else if ( nFanouts < 1000000 ) - Vec_IntAddToEntry( vFanouts, 50 + nFanouts/100000, 1 ); - else if ( nFanouts < 10000000 ) - Vec_IntAddToEntry( vFanouts, 60 + nFanouts/1000000, 1 ); - } - - printf( "The distribution of fanins and fanouts in the network:\n" ); - printf( " Number Nodes with fanin Nodes with fanout\n" ); - for ( k = 0; k < nSizeMax; k++ ) - { - if ( vFanins->pArray[k] == 0 && vFanouts->pArray[k] == 0 ) - continue; - if ( k < 10 ) - printf( "%15d : ", k ); - else - { - sprintf( Buffer, "%d - %d", (int)pow((double)10, k/10) * (k%10), (int)pow((double)10, k/10) * (k%10+1) - 1 ); - printf( "%15s : ", Buffer ); - } - if ( vFanins->pArray[k] == 0 ) - printf( " " ); - else - printf( "%12d ", vFanins->pArray[k] ); - printf( " " ); - if ( vFanouts->pArray[k] == 0 ) - printf( " " ); - else - printf( "%12d ", vFanouts->pArray[k] ); - printf( "\n" ); - } - Vec_IntFree( vFanins ); - Vec_IntFree( vFanouts ); - - printf( "Fanins: Max = %d. Ave = %.2f. Fanouts: Max = %d. Ave = %.2f.\n", - nFaninsMax, 1.0*nFaninsAll/Nwk_ManNodeNum(pNtk), - nFanoutsMax, 1.0*nFanoutsAll/Nwk_ManNodeNum(pNtk) ); -} - -/**Function************************************************************* - - Synopsis [Cleans the temporary marks of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManCleanMarks( Nwk_Man_t * pMan ) -{ - Nwk_Obj_t * pObj; - int i; - Nwk_ManForEachObj( pMan, pObj, i ) - pObj->MarkA = pObj->MarkB = 0; -} - -/**Function************************************************************* - - Synopsis [Minimizes the support of all nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManMinimumBaseNode( Nwk_Obj_t * pObj, Vec_Int_t * vTruth, int fVerbose ) -{ - unsigned * pTruth; - Nwk_Obj_t * pFanin, * pObjNew; - Nwk_Man_t * pNtk = pObj->pMan; - int uSupp, nSuppSize, k, Counter = 0; - pTruth = Hop_ManConvertAigToTruth( pNtk->pManHop, Hop_Regular(pObj->pFunc), Nwk_ObjFaninNum(pObj), vTruth, 0 ); - nSuppSize = Kit_TruthSupportSize(pTruth, Nwk_ObjFaninNum(pObj)); - if ( nSuppSize == Nwk_ObjFaninNum(pObj) ) - return 0; - Counter++; - uSupp = Kit_TruthSupport( pTruth, Nwk_ObjFaninNum(pObj) ); - // create new node with the given support - pObjNew = Nwk_ManCreateNode( pNtk, nSuppSize, Nwk_ObjFanoutNum(pObj) ); - Nwk_ObjForEachFanin( pObj, pFanin, k ) - if ( uSupp & (1 << k) ) - Nwk_ObjAddFanin( pObjNew, pFanin ); - pObjNew->pFunc = Hop_Remap( pNtk->pManHop, pObj->pFunc, uSupp, Nwk_ObjFaninNum(pObj) ); - if ( fVerbose ) - printf( "Reducing node %d fanins from %d to %d.\n", - pObj->Id, Nwk_ObjFaninNum(pObj), Nwk_ObjFaninNum(pObjNew) ); - Nwk_ObjReplace( pObj, pObjNew ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Minimizes the support of all nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nwk_ManMinimumBaseInt( Nwk_Man_t * pNtk, int fVerbose ) -{ - Vec_Int_t * vTruth; - Nwk_Obj_t * pObj; - int i, Counter = 0; - vTruth = Vec_IntAlloc( 1 << 16 ); - Nwk_ManForEachNode( pNtk, pObj, i ) - Counter += Nwk_ManMinimumBaseNode( pObj, vTruth, fVerbose ); - if ( fVerbose && Counter ) - printf( "Support minimization reduced support of %d nodes.\n", Counter ); - Vec_IntFree( vTruth ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Minimizes the support of all nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManMinimumBaseRec( Nwk_Man_t * pNtk, int fVerbose ) -{ - int i, clk = clock(); - for ( i = 0; Nwk_ManMinimumBaseInt( pNtk, fVerbose ); i++ ); - ABC_PRT( "Minbase", clock() - clk ); -} - -/**Function************************************************************* - - Synopsis [Minimizes the support of all nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManMinimumBase( Nwk_Man_t * pNtk, int fVerbose ) -{ - Vec_Int_t * vTruth; - Nwk_Obj_t * pObj; - int i, Counter = 0; - vTruth = Vec_IntAlloc( 1 << 16 ); - Nwk_ManForEachNode( pNtk, pObj, i ) - Counter += Nwk_ManMinimumBaseNode( pObj, vTruth, fVerbose ); - if ( fVerbose && Counter ) - printf( "Support minimization reduced support of %d nodes.\n", Counter ); - Vec_IntFree( vTruth ); -} - -/**Function************************************************************* - - Synopsis [Minimizes the support of all nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManRemoveDupFaninsNode( Nwk_Obj_t * pObj, int iFan0, int iFan1, Vec_Int_t * vTruth ) -{ - Hop_Man_t * pManHop = pObj->pMan->pManHop; -// Nwk_Obj_t * pFanin0 = pObj->pFanio[iFan0]; -// Nwk_Obj_t * pFanin1 = pObj->pFanio[iFan1]; - assert( pObj->pFanio[iFan0] == pObj->pFanio[iFan1] ); - pObj->pFunc = Hop_Compose( pManHop, pObj->pFunc, Hop_IthVar(pManHop,iFan0), iFan1 ); - Nwk_ManMinimumBaseNode( pObj, vTruth, 0 ); -} - -/**Function************************************************************* - - Synopsis [Minimizes the support of all nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nwk_ManRemoveDupFanins( Nwk_Man_t * pNtk, int fVerbose ) -{ - Vec_Int_t * vTruth; - Nwk_Obj_t * pObj; - int i, k, m, fFound; - // check if the nodes have duplicated fanins - vTruth = Vec_IntAlloc( 1 << 16 ); - Nwk_ManForEachNode( pNtk, pObj, i ) - { - fFound = 0; - for ( k = 0; k < pObj->nFanins; k++ ) - { - for ( m = k + 1; m < pObj->nFanins; m++ ) - if ( pObj->pFanio[k] == pObj->pFanio[m] ) - { - if ( fVerbose ) - printf( "Removing duplicated fanins of node %d (fanins %d and %d).\n", - pObj->Id, pObj->pFanio[k]->Id, pObj->pFanio[m]->Id ); - Nwk_ManRemoveDupFaninsNode( pObj, k, m, vTruth ); - fFound = 1; - break; - } - if ( fFound ) - break; - } - } - Vec_IntFree( vTruth ); -// Nwk_ManMinimumBase( pNtk, fVerbose ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/nwk/nwk_.c b/src/aig/nwk/nwk_.c deleted file mode 100644 index 882b077c..00000000 --- a/src/aig/nwk/nwk_.c +++ /dev/null @@ -1,52 +0,0 @@ -/**CFile**************************************************************** - - FileName [nwk_.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: nwk_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "nwk.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - 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 5410c9de..00000000 --- a/src/aig/rwt/rwt.h +++ /dev/null @@ -1,165 +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__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include - -#include "vec.h" -#include "extra.h" -#include "mem.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// 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)(((ABC_PTRUINT_T)p) & 01); } -static inline Rwt_Node_t * Rwt_Regular( Rwt_Node_t * p ) { return (Rwt_Node_t *)((ABC_PTRUINT_T)(p) & ~01); } -static inline Rwt_Node_t * Rwt_Not( Rwt_Node_t * p ) { return (Rwt_Node_t *)((ABC_PTRUINT_T)(p) ^ 01); } -static inline Rwt_Node_t * Rwt_NotCond( Rwt_Node_t * p, int c ) { return (Rwt_Node_t *)((ABC_PTRUINT_T)(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 ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/rwt/rwtDec.c b/src/aig/rwt/rwtDec.c deleted file mode 100644 index a26e474d..00000000 --- a/src/aig/rwt/rwtDec.c +++ /dev/null @@ -1,155 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 = ABC_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] < 222 ); // Always >= 0 b/c unsigned. - 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( Rwt_Node_t *, 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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/rwt/rwtMan.c b/src/aig/rwt/rwtMan.c deleted file mode 100644 index 12caa87f..00000000 --- a/src/aig/rwt/rwtMan.c +++ /dev/null @@ -1,363 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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() -{ - ABC_FREE( s_puCanons ); - ABC_FREE( s_pPhases ); - ABC_FREE( s_pPerms ); - ABC_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 = ABC_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 = ABC_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( Rwt_Node_t *, 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 ); - ABC_FREE( p->pMapInv ); - ABC_FREE( p->pTable ); - ABC_FREE( p->pPractical ); - ABC_FREE( p->pPerms4 ); - ABC_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 ); - ABC_PRT( "Start ", p->timeStart ); - ABC_PRT( "Cuts ", p->timeCut ); - ABC_PRT( "Truth ", p->timeTruth ); - ABC_PRT( "Resynthesis ", p->timeRes ); - ABC_PRT( " Mffc ", p->timeMffc ); - ABC_PRT( " Eval ", p->timeEval ); - ABC_PRT( "Update ", p->timeUpdate ); - ABC_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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/rwt/rwtUtil.c b/src/aig/rwt/rwtUtil.c deleted file mode 100644 index 6cdaf657..00000000 --- a/src/aig/rwt/rwtUtil.c +++ /dev/null @@ -1,662 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// precomputed data -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 -}; - - -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 -}; - -//////////////////////////////////////////////////////////////////////// -/// 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( Rwt_Node_t *, 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 = (Rwt_Node_t *)p->vForest->pArray[Entry0 >> 1]; - p1 = (Rwt_Node_t *)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 ); ABC_PRT( "Loading", clock() - clk ); - } -} - -/**Function************************************************************* - - Synopsis [Create practical classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Rwt_ManGetPractical( Rwt_Man_t * p ) -{ - char * pPractical; - int i; - pPractical = ABC_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 -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/saig/saig.h b/src/aig/saig/saig.h index 64bb3b02..b22821ab 100644 --- a/src/aig/saig/saig.h +++ b/src/aig/saig/saig.h @@ -18,16 +18,16 @@ ***********************************************************************/ -#ifndef __SAIG_H__ -#define __SAIG_H__ +#ifndef ABC__aig__saig__saig_h +#define ABC__aig__saig__saig_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// -#include "aig.h" -#include "giaAbs.h" +#include "src/aig/aig/aig.h" +#include "src/aig/gia/giaAbs.h" ABC_NAMESPACE_HEADER_START diff --git a/src/aig/saig/saigAbs.c b/src/aig/saig/saigAbs.c index 01b1e6a6..ffb17db8 100644 --- a/src/aig/saig/saigAbs.c +++ b/src/aig/saig/saigAbs.c @@ -105,8 +105,8 @@ Abc_Cex_t * Saig_ManCexRemap( Aig_Man_t * p, Aig_Man_t * pAbs, Abc_Cex_t * pCexA { if ( i == Saig_ManPiNum(p) ) break; - if ( Aig_InfoHasBit( pCexAbs->pData, pCexAbs->nRegs + pCexAbs->nPis * f + i ) ) - Aig_InfoSetBit( pCex->pData, pCex->nRegs + pCex->nPis * f + i ); + if ( Abc_InfoHasBit( pCexAbs->pData, pCexAbs->nRegs + pCexAbs->nPis * f + i ) ) + Abc_InfoSetBit( pCex->pData, pCex->nRegs + pCex->nPis * f + i ); } } // verify the counter example diff --git a/src/aig/saig/saigAbsCba.c b/src/aig/saig/saigAbsCba.c index f3e55c72..e8b68a6f 100644 --- a/src/aig/saig/saigAbsCba.c +++ b/src/aig/saig/saigAbsCba.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "saig.h" -#include "giaAig.h" -#include "ioa.h" +#include "src/aig/gia/giaAig.h" +#include "src/aig/ioa/ioa.h" ABC_NAMESPACE_IMPL_START @@ -89,7 +89,7 @@ Vec_Int_t * Saig_ManCbaFilterFlops( Aig_Man_t * pAig, Abc_Cex_t * pAbsCex, Vec_I // override the flop values according to the cex iBit = pAbsCex->nRegs + f * pAbsCex->nPis + Saig_ManPiNum(pAig); Vec_IntForEachEntry( vMapEntries, Entry, k ) - Saig_ManLo(pAig, Entry)->fMarkB = Aig_InfoHasBit(pAbsCex->pData, iBit + k); + Saig_ManLo(pAig, Entry)->fMarkB = Abc_InfoHasBit(pAbsCex->pData, iBit + k); // simulate Aig_ManForEachNode( pAig, pObj, k ) pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) & @@ -102,7 +102,7 @@ Vec_Int_t * Saig_ManCbaFilterFlops( Aig_Man_t * pAig, Abc_Cex_t * pAbsCex, Vec_I // compare iBit = pAbsCex->nRegs + (f + 1) * pAbsCex->nPis + Saig_ManPiNum(pAig); Vec_IntForEachEntry( vMapEntries, Entry, k ) - if ( Saig_ManLi(pAig, Entry)->fMarkB != (unsigned)Aig_InfoHasBit(pAbsCex->pData, iBit + k) ) + if ( Saig_ManLi(pAig, Entry)->fMarkB != (unsigned)Abc_InfoHasBit(pAbsCex->pData, iBit + k) ) Vec_IntAddToEntry( vFlopCosts, k, 1 ); } // Vec_IntForEachEntry( vFlopCosts, Entry, i ) @@ -153,7 +153,7 @@ Aig_Man_t * Saig_ManDupWithCubes( Aig_Man_t * pAig, Vec_Vec_t * vReg2Value ) assert( pAig->nConstrs == 0 ); // start the new manager pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) + Vec_VecSizeSize(vReg2Value) ); - pAigNew->pName = Aig_UtilStrsav( pAig->pName ); + pAigNew->pName = Abc_UtilStrsav( pAig->pName ); // map the constant node Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); // create variables for PIs @@ -168,8 +168,8 @@ Aig_Man_t * Saig_ManDupWithCubes( Aig_Man_t * pAig, Vec_Vec_t * vReg2Value ) pMiter = Aig_ManConst1( pAigNew ); Vec_IntForEachEntry( vLevel, Lit, k ) { - pObj = Saig_ManLi( pAig, Aig_Lit2Var(Lit) ); - pMiter = Aig_And( pAigNew, pMiter, Aig_NotCond(Aig_ObjChild0Copy(pObj), Aig_LitIsCompl(Lit)) ); + pObj = Saig_ManLi( pAig, Abc_Lit2Var(Lit) ); + pMiter = Aig_And( pAigNew, pMiter, Aig_NotCond(Aig_ObjChild0Copy(pObj), Abc_LitIsCompl(Lit)) ); } Aig_ObjCreatePo( pAigNew, pMiter ); } @@ -227,20 +227,20 @@ Abc_Cex_t * Saig_ManCbaReason2Cex( Saig_ManCba_t * p, Vec_Int_t * vReasons ) Abc_Cex_t * pCare; int i, Entry, iInput, iFrame; pCare = Abc_CexDup( p->pCex, p->pCex->nRegs ); - memset( pCare->pData, 0, sizeof(unsigned) * Aig_BitWordNum(pCare->nBits) ); + memset( pCare->pData, 0, sizeof(unsigned) * Abc_BitWordNum(pCare->nBits) ); Vec_IntForEachEntry( vReasons, Entry, i ) { assert( Entry >= 0 && Entry < Aig_ManPiNum(p->pFrames) ); iInput = Vec_IntEntry( p->vMapPiF2A, 2*Entry ); iFrame = Vec_IntEntry( p->vMapPiF2A, 2*Entry+1 ); - Aig_InfoSetBit( pCare->pData, pCare->nRegs + pCare->nPis * iFrame + iInput ); + Abc_InfoSetBit( pCare->pData, pCare->nRegs + pCare->nPis * iFrame + iInput ); } /* for ( iFrame = 0; iFrame <= pCare->iFrame; iFrame++ ) { int Count = 0; for ( i = 0; i < pCare->nPis; i++ ) - Count += Aig_InfoHasBit(pCare->pData, pCare->nRegs + pCare->nPis * iFrame + i); + Count += Abc_InfoHasBit(pCare->pData, pCare->nRegs + pCare->nPis * iFrame + i); printf( "%d ", Count ); } printf( "\n" ); @@ -322,7 +322,7 @@ Vec_Int_t * Saig_ManCbaFindReason( Saig_ManCba_t * p ) { int iInput = Vec_IntEntry( p->vMapPiF2A, 2*i ); int iFrame = Vec_IntEntry( p->vMapPiF2A, 2*i+1 ); - pObj->fPhase = Aig_InfoHasBit( p->pCex->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput ); + pObj->fPhase = Abc_InfoHasBit( p->pCex->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput ); Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), i ); } @@ -434,11 +434,11 @@ Aig_Man_t * Saig_ManCbaUnrollWithCex( Aig_Man_t * pAig, Abc_Cex_t * pCex, int nI // derive unrolled timeframes pFrames = Aig_ManStart( 10000 ); - pFrames->pName = Aig_UtilStrsav( pAig->pName ); - pFrames->pSpec = Aig_UtilStrsav( pAig->pSpec ); + pFrames->pName = Abc_UtilStrsav( pAig->pName ); + pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec ); // initialize the flops Saig_ManForEachLo( pAig, pObj, i ) - pObj->pData = Aig_NotCond( Aig_ManConst1(pFrames), !Aig_InfoHasBit(pCex->pData, i) ); + pObj->pData = Aig_NotCond( Aig_ManConst1(pFrames), !Abc_InfoHasBit(pCex->pData, i) ); // iterate through the frames for ( f = 0; f <= pCex->iFrame; f++ ) { @@ -457,7 +457,7 @@ Aig_Man_t * Saig_ManCbaUnrollWithCex( Aig_Man_t * pAig, Abc_Cex_t * pCex, int nI if ( Aig_ObjPioNum(pObj) < nInputs ) { int iBit = pCex->nRegs + f * pCex->nPis + Aig_ObjPioNum(pObj); - pObj->pData = Aig_NotCond( Aig_ManConst1(pFrames), !Aig_InfoHasBit(pCex->pData, iBit) ); + pObj->pData = Aig_NotCond( Aig_ManConst1(pFrames), !Abc_InfoHasBit(pCex->pData, iBit) ); } else { @@ -558,12 +558,12 @@ void Saig_ManCbaShrink( Saig_ManCba_t * p ) { Vec_IntForEachEntryDouble( vLevel, ObjId, Lit, k ) { - pObjFrame = Aig_ManObj( p->pFrames, Aig_Lit2Var(Lit) ); + pObjFrame = Aig_ManObj( p->pFrames, Abc_Lit2Var(Lit) ); if ( pObjFrame == NULL || (!Aig_ObjIsConst1(pObjFrame) && !Aig_ObjIsTravIdCurrent(p->pFrames, pObjFrame)) ) continue; pObjLi = Aig_ManObj( p->pAig, ObjId ); assert( Saig_ObjIsLi(p->pAig, pObjLi) ); - Vec_VecPushInt( p->vReg2Value, f, Aig_Var2Lit( Aig_ObjPioNum(pObjLi) - Saig_ManPoNum(p->pAig), Aig_LitIsCompl(Lit) ^ !pObjFrame->fPhase ) ); + Vec_VecPushInt( p->vReg2Value, f, Abc_Var2Lit( Aig_ObjPioNum(pObjLi) - Saig_ManPoNum(p->pAig), Abc_LitIsCompl(Lit) ^ !pObjFrame->fPhase ) ); } } // print statistics diff --git a/src/aig/saig/saigAbsPba.c b/src/aig/saig/saigAbsPba.c index a42515f3..3c9de875 100644 --- a/src/aig/saig/saigAbsPba.c +++ b/src/aig/saig/saigAbsPba.c @@ -19,9 +19,9 @@ ***********************************************************************/ #include "saig.h" -#include "cnf.h" -#include "satSolver.h" -#include "giaAig.h" +#include "src/sat/cnf/cnf.h" +#include "src/sat/bsat/satSolver.h" +#include "src/aig/gia/giaAig.h" ABC_NAMESPACE_IMPL_START @@ -99,8 +99,8 @@ Aig_Man_t * Saig_ManUnrollForPba( Aig_Man_t * pAig, int nStart, int nFrames, Vec } // derive unrolled timeframes pFrames = Aig_ManStart( 10000 ); - pFrames->pName = Aig_UtilStrsav( pAig->pName ); - pFrames->pSpec = Aig_UtilStrsav( pAig->pSpec ); + pFrames->pName = Abc_UtilStrsav( pAig->pName ); + pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec ); // create activation variables Saig_ManForEachLo( pAig, pObj, i ) Aig_ObjCreatePi( pFrames ); @@ -186,19 +186,19 @@ Abc_Cex_t * Saig_ManPbaDeriveCex( Aig_Man_t * pAig, sat_solver * pSat, Cnf_Dat_t { int iSatVar = pCnf->pVarNums[ Aig_ObjId(Aig_ManPi(pCnf->pMan, Entry)) ]; if ( sat_solver_var_value( pSat, iSatVar ) ) - Aig_InfoSetBit( pCex->pData, Aig_ManRegNum(pAig) + i ); + Abc_InfoSetBit( pCex->pData, Aig_ManRegNum(pAig) + i ); } } // check what frame has failed Aig_ManCleanMarkB(pAig); Aig_ManConst1(pAig)->fMarkB = 1; Saig_ManForEachLo( pAig, pObj, i ) - pObj->fMarkB = Aig_InfoHasBit(pCex->pData, iBit++); + pObj->fMarkB = Abc_InfoHasBit(pCex->pData, iBit++); for ( f = 0; f < nFrames; f++ ) { // compute new state Saig_ManForEachPi( pAig, pObj, i ) - pObj->fMarkB = Aig_InfoHasBit(pCex->pData, iBit++); + pObj->fMarkB = Abc_InfoHasBit(pCex->pData, iBit++); Aig_ManForEachNode( pAig, pObj, i ) pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) & (Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj)); diff --git a/src/aig/saig/saigAbsStart.c b/src/aig/saig/saigAbsStart.c index 71ef98d5..a5ec7dac 100644 --- a/src/aig/saig/saigAbsStart.c +++ b/src/aig/saig/saigAbsStart.c @@ -19,10 +19,10 @@ ***********************************************************************/ #include "saig.h" -#include "ssw.h" -#include "fra.h" -#include "bbr.h" -#include "pdr.h" +#include "src/proof/ssw/ssw.h" +#include "src/proof/fra/fra.h" +#include "src/proof/bbr/bbr.h" +#include "src/proof/pdr/pdr.h" ABC_NAMESPACE_IMPL_START diff --git a/src/aig/saig/saigAbsVfa.c b/src/aig/saig/saigAbsVfa.c index 4226ba51..c3243b0e 100644 --- a/src/aig/saig/saigAbsVfa.c +++ b/src/aig/saig/saigAbsVfa.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "saig.h" -#include "cnf.h" -#include "satSolver.h" +#include "src/sat/cnf/cnf.h" +#include "src/sat/bsat/satSolver.h" ABC_NAMESPACE_IMPL_START diff --git a/src/aig/saig/saigBmc.c b/src/aig/saig/saigBmc.c index 011a746e..814c445f 100644 --- a/src/aig/saig/saigBmc.c +++ b/src/aig/saig/saigBmc.c @@ -19,9 +19,9 @@ ***********************************************************************/ #include "saig.h" -#include "fra.h" -#include "cnf.h" -#include "satStore.h" +#include "src/proof/fra/fra.h" +#include "src/sat/cnf/cnf.h" +#include "src/sat/bsat/satStore.h" ABC_NAMESPACE_IMPL_START @@ -167,7 +167,7 @@ Aig_Man_t * Saig_ManFramesBmcLimit( Aig_Man_t * pAig, int nFrames, int nSizeMax ABC_NAMESPACE_IMPL_END -#include "utilMem.h" +#include "src/misc/util/utilMem.h" ABC_NAMESPACE_IMPL_START diff --git a/src/aig/saig/saigBmc2.c b/src/aig/saig/saigBmc2.c index 169b9404..2586a457 100644 --- a/src/aig/saig/saigBmc2.c +++ b/src/aig/saig/saigBmc2.c @@ -19,9 +19,9 @@ ***********************************************************************/ #include "saig.h" -#include "cnf.h" -#include "satStore.h" -#include "ssw.h" +#include "src/sat/cnf/cnf.h" +#include "src/sat/bsat/satStore.h" +#include "src/proof/ssw/ssw.h" ABC_NAMESPACE_IMPL_START @@ -180,8 +180,8 @@ Vec_Ptr_t * Abs_ManTernarySimulate( Aig_Man_t * p, int nFramesMax, int fVerbose assert( Aig_ManRegNum(p) > 0 ); // the maximum number of frames will be determined to use at most 200Mb of RAM nFramesLimit = 1 + (200000000 * 4)/Aig_ManObjNum(p); - nFramesLimit = ABC_MIN( nFramesLimit, nFramesMax ); - nFrameWords = Aig_BitWordNum( 2 * Aig_ManObjNum(p) ); + nFramesLimit = Abc_MinInt( nFramesLimit, nFramesMax ); + nFrameWords = Abc_BitWordNum( 2 * Aig_ManObjNum(p) ); // allocate simulation info vSimInfo = Vec_PtrAlloc( nFramesLimit ); for ( f = 0; f < nFramesLimit; f++ ) @@ -652,7 +652,7 @@ Abc_Cex_t * Saig_BmcGenerateCounterExample( Saig_Bmc_t * p ) if ( iVarNum == 0 ) continue; if ( sat_solver_var_value( p->pSat, iVarNum ) ) - Aig_InfoSetBit( pCex->pData, pCex->nRegs + Saig_ManPiNum(p->pAig) * f + i ); + Abc_InfoSetBit( pCex->pData, pCex->nRegs + Saig_ManPiNum(p->pAig) * f + i ); } } // verify the counter example diff --git a/src/aig/saig/saigBmc3.c b/src/aig/saig/saigBmc3.c index 2035ac72..27393f32 100644 --- a/src/aig/saig/saigBmc3.c +++ b/src/aig/saig/saigBmc3.c @@ -19,9 +19,9 @@ ***********************************************************************/ #include "saig.h" -#include "fra.h" -#include "cnf.h" -#include "satStore.h" +#include "src/proof/fra/fra.h" +#include "src/sat/cnf/cnf.h" +#include "src/sat/bsat/satStore.h" ABC_NAMESPACE_IMPL_START @@ -130,7 +130,7 @@ unsigned * Saig_ManBmcTerSimOne( Aig_Man_t * p, unsigned * pPrev ) Aig_Obj_t * pObj, * pObjLi; unsigned * pInfo; int i, Val0, Val1; - pInfo = ABC_CALLOC( unsigned, Aig_BitWordNum(2 * Aig_ManObjNumMax(p)) ); + pInfo = ABC_CALLOC( unsigned, Abc_BitWordNum(2 * Aig_ManObjNumMax(p)) ); Saig_ManBmcSimInfoSet( pInfo, Aig_ManConst1(p), SAIG_TER_ONE ); Saig_ManForEachPi( p, pObj, i ) Saig_ManBmcSimInfoSet( pInfo, pObj, SAIG_TER_UND ); @@ -1105,7 +1105,7 @@ int Saig_ManBmcScalable( Aig_Man_t * pAig, Saig_ParBmc_t * pPars ) Gia_ManBmc_t * p; Aig_Obj_t * pObj; int RetValue = -1, fFirst = 1, nJumpFrame = 0, fUnfinished = 0; - int nOutDigits = Aig_Base10Log( Saig_ManPoNum(pAig) - Saig_ManConstrNum(pAig) ); + int nOutDigits = Abc_Base10Log( Saig_ManPoNum(pAig) - Saig_ManConstrNum(pAig) ); int i, f, Lit, status, clk, clk2, clkOther = 0, clkTotal = clock(); int nTimeToStop = time(NULL) + pPars->nTimeOut; if ( pPars->fVerbose && Aig_ManConstrNum(pAig) > 0 ) diff --git a/src/aig/saig/saigCexMin.c b/src/aig/saig/saigCexMin.c index 824f9eb3..f1826f50 100644 --- a/src/aig/saig/saigCexMin.c +++ b/src/aig/saig/saigCexMin.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "saig.h" -#include "ioa.h" +#include "src/aig/ioa/ioa.h" ABC_NAMESPACE_IMPL_START @@ -151,18 +151,18 @@ void Saig_ManCexMinDerivePhasePriority_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj ) Saig_ManCexMinDerivePhasePriority_rec( pAig, Aig_ObjFanin1(pObj) ); assert( Aig_ObjFanin0(pObj)->iData >= 0 ); assert( Aig_ObjFanin1(pObj)->iData >= 0 ); - fPhase0 = Aig_LitIsCompl( Aig_ObjFanin0(pObj)->iData ) ^ Aig_ObjFaninC0(pObj); - fPhase1 = Aig_LitIsCompl( Aig_ObjFanin1(pObj)->iData ) ^ Aig_ObjFaninC1(pObj); - iPrio0 = Aig_Lit2Var( Aig_ObjFanin0(pObj)->iData ); - iPrio1 = Aig_Lit2Var( Aig_ObjFanin1(pObj)->iData ); + fPhase0 = Abc_LitIsCompl( Aig_ObjFanin0(pObj)->iData ) ^ Aig_ObjFaninC0(pObj); + fPhase1 = Abc_LitIsCompl( Aig_ObjFanin1(pObj)->iData ) ^ Aig_ObjFaninC1(pObj); + iPrio0 = Abc_Lit2Var( Aig_ObjFanin0(pObj)->iData ); + iPrio1 = Abc_Lit2Var( Aig_ObjFanin1(pObj)->iData ); if ( fPhase0 && fPhase1 ) // both are one - pObj->iData = Aig_Var2Lit( Abc_MinInt(iPrio0, iPrio1), 1 ); + pObj->iData = Abc_Var2Lit( Abc_MinInt(iPrio0, iPrio1), 1 ); else if ( !fPhase0 && fPhase1 ) - pObj->iData = Aig_Var2Lit( iPrio0, 0 ); + pObj->iData = Abc_Var2Lit( iPrio0, 0 ); else if ( fPhase0 && !fPhase1 ) - pObj->iData = Aig_Var2Lit( iPrio1, 0 ); + pObj->iData = Abc_Var2Lit( iPrio1, 0 ); else // both are zero - pObj->iData = Aig_Var2Lit( Abc_MaxInt(iPrio0, iPrio1), 0 ); + pObj->iData = Abc_Var2Lit( Abc_MaxInt(iPrio0, iPrio1), 0 ); } } @@ -183,7 +183,7 @@ void Saig_ManCexMinVerifyPhase( Aig_Man_t * pAig, Abc_Cex_t * pCex, int f ) int i; Aig_ManConst1(pAig)->fPhase = 1; Saig_ManForEachPi( pAig, pObj, i ) - pObj->fPhase = Aig_InfoHasBit(pCex->pData, pCex->nRegs + f * pCex->nPis + i); + pObj->fPhase = Abc_InfoHasBit(pCex->pData, pCex->nRegs + f * pCex->nPis + i); if ( f == 0 ) { Saig_ManForEachLo( pAig, pObj, i ) @@ -266,7 +266,7 @@ Vec_Vec_t * Saig_ManCexMinCollectPhasePriority_( Aig_Man_t * pAig, Abc_Cex_t * p // set the constant node to higher priority than the flops vFramePPs = Vec_VecStart( pCex->iFrame+1 ); nPrioOffset = (pCex->iFrame + 1) * pCex->nPis; - Aig_ManConst1(pAig)->iData = Aig_Var2Lit( nPrioOffset + pCex->nRegs, 1 ); + Aig_ManConst1(pAig)->iData = Abc_Var2Lit( nPrioOffset + pCex->nRegs, 1 ); vRoots = Vec_IntAlloc( 1000 ); //printf( "Const1 = %d Offset = %d\n", Aig_ManConst1(pAig)->iData, nPrioOffset ); for ( f = 0; f <= pCex->iFrame; f++ ) @@ -280,9 +280,9 @@ Vec_Vec_t * Saig_ManCexMinCollectPhasePriority_( Aig_Man_t * pAig, Abc_Cex_t * p { assert( Aig_ObjIsPi(pObj) ); if ( Saig_ObjIsPi(pAig, pObj) ) - Vec_IntPush( vFramePPsOne, Aig_Var2Lit( (f+1) * pCex->nPis - nPiCount++, Aig_InfoHasBit(pCex->pData, pCex->nRegs + f * pCex->nPis + Aig_ObjPioNum(pObj)) ) ); + Vec_IntPush( vFramePPsOne, Abc_Var2Lit( (f+1) * pCex->nPis - nPiCount++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + f * pCex->nPis + Aig_ObjPioNum(pObj)) ) ); else if ( f == 0 ) - Vec_IntPush( vFramePPsOne, Aig_Var2Lit( nPrioOffset + Saig_ObjRegId(pAig, pObj), 0 ) ); + Vec_IntPush( vFramePPsOne, Abc_Var2Lit( nPrioOffset + Saig_ObjRegId(pAig, pObj), 0 ) ); else { Aig_Obj_t * pObj0 = Saig_ObjLoToLi(pAig, pObj); @@ -298,7 +298,7 @@ Vec_Vec_t * Saig_ManCexMinCollectPhasePriority_( Aig_Man_t * pAig, Abc_Cex_t * p Vec_IntFree( vRoots ); // check the output pObj = Aig_ManPo( pAig, pCex->iPo ); - assert( Aig_LitIsCompl(pObj->iData) ); + assert( Abc_LitIsCompl(pObj->iData) ); return vFramePPs; } @@ -327,7 +327,7 @@ Vec_Vec_t * Saig_ManCexMinCollectPhasePriority( Aig_Man_t * pAig, Abc_Cex_t * pC // set the constant node to higher priority than the flops vFramePPs = Vec_VecStart( pCex->iFrame+1 ); nPrioOffset = pCex->nRegs; - Aig_ManConst1(pAig)->iData = Aig_Var2Lit( nPrioOffset + (pCex->iFrame + 1) * pCex->nPis, 1 ); + Aig_ManConst1(pAig)->iData = Abc_Var2Lit( nPrioOffset + (pCex->iFrame + 1) * pCex->nPis, 1 ); vRoots = Vec_IntAlloc( 1000 ); //printf( "Const1 = %d Offset = %d\n", Aig_ManConst1(pAig)->iData, nPrioOffset ); for ( f = 0; f <= pCex->iFrame; f++ ) @@ -341,9 +341,9 @@ Vec_Vec_t * Saig_ManCexMinCollectPhasePriority( Aig_Man_t * pAig, Abc_Cex_t * pC { assert( Aig_ObjIsPi(pObj) ); if ( Saig_ObjIsPi(pAig, pObj) ) - Vec_IntPush( vFramePPsOne, Aig_Var2Lit( nPrioOffset + (f+1) * pCex->nPis - 1 - nPiCount++, Aig_InfoHasBit(pCex->pData, pCex->nRegs + f * pCex->nPis + Aig_ObjPioNum(pObj)) ) ); + Vec_IntPush( vFramePPsOne, Abc_Var2Lit( nPrioOffset + (f+1) * pCex->nPis - 1 - nPiCount++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + f * pCex->nPis + Aig_ObjPioNum(pObj)) ) ); else if ( f == 0 ) - Vec_IntPush( vFramePPsOne, Aig_Var2Lit( Saig_ObjRegId(pAig, pObj), 0 ) ); + Vec_IntPush( vFramePPsOne, Abc_Var2Lit( Saig_ObjRegId(pAig, pObj), 0 ) ); else { Aig_Obj_t * pObj0 = Saig_ObjLoToLi(pAig, pObj); @@ -359,7 +359,7 @@ Vec_Vec_t * Saig_ManCexMinCollectPhasePriority( Aig_Man_t * pAig, Abc_Cex_t * pC Vec_IntFree( vRoots ); // check the output pObj = Aig_ManPo( pAig, pCex->iPo ); - assert( Aig_LitIsCompl(pObj->iData) ); + assert( Abc_LitIsCompl(pObj->iData) ); return vFramePPs; } @@ -383,9 +383,9 @@ void Saig_ManCexMinCollectReason_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Int_t if ( Aig_ObjIsPi(pObj) ) { if ( fPiReason && Saig_ObjIsPi(p, pObj) ) - Vec_IntPush( vReason, Aig_Var2Lit( Aig_ObjPioNum(pObj), !Aig_LitIsCompl(pObj->iData) ) ); + Vec_IntPush( vReason, Abc_Var2Lit( Aig_ObjPioNum(pObj), !Abc_LitIsCompl(pObj->iData) ) ); else if ( !fPiReason && Saig_ObjIsLo(p, pObj) ) - Vec_IntPush( vReason, Aig_Var2Lit( Saig_ObjRegId(p, pObj), !Aig_LitIsCompl(pObj->iData) ) ); + Vec_IntPush( vReason, Abc_Var2Lit( Saig_ObjRegId(p, pObj), !Abc_LitIsCompl(pObj->iData) ) ); return; } if ( Aig_ObjIsPo(pObj) ) @@ -396,18 +396,18 @@ void Saig_ManCexMinCollectReason_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Int_t if ( Aig_ObjIsConst1(pObj) ) return; assert( Aig_ObjIsNode(pObj) ); - if ( Aig_LitIsCompl(pObj->iData) ) // value 1 + if ( Abc_LitIsCompl(pObj->iData) ) // value 1 { - int fPhase0 = Aig_LitIsCompl( Aig_ObjFanin0(pObj)->iData ) ^ Aig_ObjFaninC0(pObj); - int fPhase1 = Aig_LitIsCompl( Aig_ObjFanin1(pObj)->iData ) ^ Aig_ObjFaninC1(pObj); + int fPhase0 = Abc_LitIsCompl( Aig_ObjFanin0(pObj)->iData ) ^ Aig_ObjFaninC0(pObj); + int fPhase1 = Abc_LitIsCompl( Aig_ObjFanin1(pObj)->iData ) ^ Aig_ObjFaninC1(pObj); assert( fPhase0 && fPhase1 ); Saig_ManCexMinCollectReason_rec( p, Aig_ObjFanin0(pObj), vReason, fPiReason ); Saig_ManCexMinCollectReason_rec( p, Aig_ObjFanin1(pObj), vReason, fPiReason ); } else { - int fPhase0 = Aig_LitIsCompl( Aig_ObjFanin0(pObj)->iData ) ^ Aig_ObjFaninC0(pObj); - int fPhase1 = Aig_LitIsCompl( Aig_ObjFanin1(pObj)->iData ) ^ Aig_ObjFaninC1(pObj); + int fPhase0 = Abc_LitIsCompl( Aig_ObjFanin0(pObj)->iData ) ^ Aig_ObjFaninC0(pObj); + int fPhase1 = Abc_LitIsCompl( Aig_ObjFanin1(pObj)->iData ) ^ Aig_ObjFaninC1(pObj); assert( !fPhase0 || !fPhase1 ); if ( !fPhase0 && fPhase1 ) Saig_ManCexMinCollectReason_rec( p, Aig_ObjFanin0(pObj), vReason, fPiReason ); @@ -415,8 +415,8 @@ void Saig_ManCexMinCollectReason_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Int_t Saig_ManCexMinCollectReason_rec( p, Aig_ObjFanin1(pObj), vReason, fPiReason ); else { - int iPrio0 = Aig_Lit2Var( Aig_ObjFanin0(pObj)->iData ); - int iPrio1 = Aig_Lit2Var( Aig_ObjFanin1(pObj)->iData ); + int iPrio0 = Abc_Lit2Var( Aig_ObjFanin0(pObj)->iData ); + int iPrio1 = Abc_Lit2Var( Aig_ObjFanin1(pObj)->iData ); if ( iPrio0 >= iPrio1 ) Saig_ManCexMinCollectReason_rec( p, Aig_ObjFanin0(pObj), vReason, fPiReason ); else @@ -514,7 +514,7 @@ Aig_Man_t * Saig_ManCexMinDupWithCubes( Aig_Man_t * pAig, Vec_Vec_t * vReg2Value assert( pAig->nConstrs == 0 ); // start the new manager pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) + Vec_VecSizeSize(vReg2Value) + Vec_VecSize(vReg2Value) ); - pAigNew->pName = Aig_UtilStrsav( pAig->pName ); + pAigNew->pName = Abc_UtilStrsav( pAig->pName ); // map the constant node Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); // create variables for PIs @@ -532,8 +532,8 @@ Aig_Man_t * Saig_ManCexMinDupWithCubes( Aig_Man_t * pAig, Vec_Vec_t * vReg2Value Vec_IntForEachEntry( vLevel, Lit, k ) { assert( Lit >= 0 && Lit < 2 * Aig_ManRegNum(pAig) ); - pObj = Saig_ManLi( pAig, Aig_Lit2Var(Lit) ); - pMiter = Aig_And( pAigNew, pMiter, Aig_NotCond(Aig_ObjChild0Copy(pObj), Aig_LitIsCompl(Lit)) ); + pObj = Saig_ManLi( pAig, Abc_Lit2Var(Lit) ); + pMiter = Aig_And( pAigNew, pMiter, Aig_NotCond(Aig_ObjChild0Copy(pObj), Abc_LitIsCompl(Lit)) ); } Aig_ObjCreatePo( pAigNew, pMiter ); } diff --git a/src/aig/saig/saigConstr.c b/src/aig/saig/saigConstr.c index d58074e3..91bdf46f 100644 --- a/src/aig/saig/saigConstr.c +++ b/src/aig/saig/saigConstr.c @@ -19,10 +19,10 @@ ***********************************************************************/ #include "saig.h" -#include "cnf.h" -#include "satSolver.h" -#include "kit.h" -#include "ioa.h" +#include "src/sat/cnf/cnf.h" +#include "src/sat/bsat/satSolver.h" +#include "src/bool/kit/kit.h" +#include "src/aig/ioa/ioa.h" ABC_NAMESPACE_IMPL_START @@ -64,7 +64,7 @@ Aig_Man_t * Saig_ManDupUnfoldConstrs( Aig_Man_t * pAig ) } // start the new manager pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); - pAigNew->pName = Aig_UtilStrsav( pAig->pName ); + pAigNew->pName = Abc_UtilStrsav( pAig->pName ); // map the constant node Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); // create variables for PIs @@ -113,7 +113,7 @@ Aig_Man_t * Saig_ManDupFoldConstrs( Aig_Man_t * pAig, Vec_Int_t * vConstrs ) assert( Saig_ManRegNum(pAig) > 0 ); // start the new manager pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); - pAigNew->pName = Aig_UtilStrsav( pAig->pName ); + pAigNew->pName = Abc_UtilStrsav( pAig->pName ); // map the constant node Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); // create variables for PIs diff --git a/src/aig/saig/saigConstr2.c b/src/aig/saig/saigConstr2.c index 7f2eab6a..e60d1b82 100644 --- a/src/aig/saig/saigConstr2.c +++ b/src/aig/saig/saigConstr2.c @@ -19,10 +19,10 @@ ***********************************************************************/ #include "saig.h" -#include "cnf.h" -#include "satSolver.h" -#include "kit.h" -#include "bar.h" +#include "src/sat/cnf/cnf.h" +#include "src/sat/bsat/satSolver.h" +#include "src/bool/kit/kit.h" +#include "src/misc/bar/bar.h" ABC_NAMESPACE_IMPL_START @@ -244,8 +244,8 @@ Aig_Man_t * Saig_ManCreateIndMiter( Aig_Man_t * pAig, Vec_Vec_t * vCands ) // start the fraig package pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFrames ); - pFrames->pName = Aig_UtilStrsav( pAig->pName ); - pFrames->pSpec = Aig_UtilStrsav( pAig->pSpec ); + pFrames->pName = Abc_UtilStrsav( pAig->pName ); + pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec ); // map constant nodes for ( f = 0; f < nFrames; f++ ) Aig_ObjSetFrames( pObjMap, nFrames, Aig_ManConst1(pAig), f, Aig_ManConst1(pFrames) ); @@ -437,8 +437,8 @@ Aig_Man_t * Saig_ManUnrollCOI( Aig_Man_t * pAig, int nFrames ) pObjMap = ABC_CALLOC( Aig_Obj_t *, nFrames * Aig_ManObjNumMax(pAig) ); // start the fraig package pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFrames ); - pFrames->pName = Aig_UtilStrsav( pAig->pName ); - pFrames->pSpec = Aig_UtilStrsav( pAig->pSpec ); + pFrames->pName = Abc_UtilStrsav( pAig->pName ); + pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec ); // map constant nodes for ( f = 0; f < nFrames; f++ ) Aig_ObjSetFrames( pObjMap, nFrames, Aig_ManConst1(pAig), f, Aig_ManConst1(pFrames) ); @@ -504,8 +504,8 @@ void Saig_CollectSatValues( sat_solver * pSat, Cnf_Dat_t * pCnf, Vec_Ptr_t * vIn continue; assert( pCnf->pVarNums[i] > 0 ); pInfo = (unsigned *)Vec_PtrEntry( vInfo, i ); - if ( Aig_InfoHasBit(pInfo, *piPat) != sat_solver_var_value(pSat, pCnf->pVarNums[i]) ) - Aig_InfoXorBit(pInfo, *piPat); + if ( Abc_InfoHasBit(pInfo, *piPat) != sat_solver_var_value(pSat, pCnf->pVarNums[i]) ) + Abc_InfoXorBit(pInfo, *piPat); } } @@ -949,8 +949,8 @@ Aig_Man_t * Saig_ManDupFoldConstrsFunc( Aig_Man_t * pAig, int fCompl, int fVerbo assert( Aig_ManConstrNum(pAig) < Saig_ManPoNum(pAig) ); // start the new manager pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); - pAigNew->pName = Aig_UtilStrsav( pAig->pName ); - pAigNew->pSpec = Aig_UtilStrsav( pAig->pSpec ); + pAigNew->pName = Abc_UtilStrsav( pAig->pName ); + pAigNew->pSpec = Abc_UtilStrsav( pAig->pSpec ); // map the constant node Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); // create variables for PIs diff --git a/src/aig/saig/saigDup.c b/src/aig/saig/saigDup.c index ca06398c..fa915f52 100644 --- a/src/aig/saig/saigDup.c +++ b/src/aig/saig/saigDup.c @@ -54,7 +54,7 @@ Aig_Man_t * Saig_ManDupOrpos( Aig_Man_t * pAig ) } // start the new manager pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); - pAigNew->pName = Aig_UtilStrsav( pAig->pName ); + pAigNew->pName = Abc_UtilStrsav( pAig->pName ); pAigNew->nConstrs = pAig->nConstrs; // map the constant node Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); @@ -100,7 +100,7 @@ Aig_Man_t * Saig_ManCreateEquivMiter( Aig_Man_t * pAig, Vec_Int_t * vPairs ) } // start the new manager pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); - pAigNew->pName = Aig_UtilStrsav( pAig->pName ); + pAigNew->pName = Abc_UtilStrsav( pAig->pName ); pAigNew->nConstrs = pAig->nConstrs; // map the constant node Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); @@ -150,7 +150,7 @@ Aig_Man_t * Saig_ManTrimPis( Aig_Man_t * p ) fAllPisHaveNoRefs = 0; // start the new manager pNew = Aig_ManStart( Aig_ManObjNum(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); pNew->nConstrs = p->nConstrs; // start mapping of the CI numbers pNew->vCiNumsOrig = Vec_IntAlloc( Aig_ManPiNum(p) ); @@ -210,7 +210,7 @@ Aig_Man_t * Saig_ManDupAbstraction( Aig_Man_t * p, Vec_Int_t * vFlops ) Aig_ManCleanData( p ); // start the new manager pNew = Aig_ManStart( 5000 ); - pNew->pName = Aig_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); // map the constant node Aig_ManConst1(p)->pData = Aig_ManConst1( pNew ); // label included flops @@ -283,11 +283,11 @@ int Saig_ManVerifyCex( Aig_Man_t * pAig, Abc_Cex_t * p ) Aig_ManCleanMarkB(pAig); Aig_ManConst1(pAig)->fMarkB = 1; Saig_ManForEachLo( pAig, pObj, i ) - pObj->fMarkB = Aig_InfoHasBit(p->pData, iBit++); + pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++); for ( i = 0; i <= p->iFrame; i++ ) { Saig_ManForEachPi( pAig, pObj, k ) - pObj->fMarkB = Aig_InfoHasBit(p->pData, iBit++); + pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++); Aig_ManForEachNode( pAig, pObj, k ) pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) & (Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj)); @@ -328,15 +328,15 @@ Abc_Cex_t * Saig_ManExtendCex( Aig_Man_t * pAig, Abc_Cex_t * p ) Aig_ManCleanMarkB(pAig); Aig_ManConst1(pAig)->fMarkB = 1; Saig_ManForEachLo( pAig, pObj, i ) - pObj->fMarkB = Aig_InfoHasBit(p->pData, iBit++); + pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++); for ( i = 0; i <= p->iFrame; i++ ) { Saig_ManForEachPi( pAig, pObj, k ) - pObj->fMarkB = Aig_InfoHasBit(p->pData, iBit++); + pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++); ///////// write PI+LO values //////////// Aig_ManForEachPi( pAig, pObj, k ) if ( pObj->fMarkB ) - Aig_InfoSetBit(pNew->pData, Aig_ManPiNum(pAig)*i + k); + Abc_InfoSetBit(pNew->pData, Aig_ManPiNum(pAig)*i + k); ///////////////////////////////////////// Aig_ManForEachNode( pAig, pObj, k ) pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) & @@ -374,11 +374,11 @@ int Saig_ManFindFailedPoCex( Aig_Man_t * pAig, Abc_Cex_t * p ) Aig_ManCleanMarkB(pAig); Aig_ManConst1(pAig)->fMarkB = 1; Saig_ManForEachLo( pAig, pObj, i ) - pObj->fMarkB = Aig_InfoHasBit(p->pData, iBit++); + pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++); for ( i = 0; i <= p->iFrame; i++ ) { Saig_ManForEachPi( pAig, pObj, k ) - pObj->fMarkB = Aig_InfoHasBit(p->pData, iBit++); + pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++); Aig_ManForEachNode( pAig, pObj, k ) pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) & (Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj)); @@ -421,7 +421,7 @@ Aig_Man_t * Saig_ManDupWithPhase( Aig_Man_t * pAig, Vec_Int_t * vInit ) assert( Aig_ManRegNum(pAig) <= Vec_IntSize(vInit) ); // start the new manager pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); - pAigNew->pName = Aig_UtilStrsav( pAig->pName ); + pAigNew->pName = Abc_UtilStrsav( pAig->pName ); pAigNew->nConstrs = pAig->nConstrs; // map the constant node Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); diff --git a/src/aig/saig/saigGlaCba.c b/src/aig/saig/saigGlaCba.c index d5a94acb..d6af6e47 100644 --- a/src/aig/saig/saigGlaCba.c +++ b/src/aig/saig/saigGlaCba.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "saig.h" -#include "satSolver.h" -#include "cnf.h" +#include "src/sat/bsat/satSolver.h" +#include "src/sat/cnf/cnf.h" ABC_NAMESPACE_IMPL_START @@ -250,7 +250,7 @@ Aig_Man_t * Aig_Gla1DeriveAbs( Aig_Gla1Man_t * p ) assert( Saig_ManPoNum(p->pAig) == 1 ); // start the new manager pNew = Aig_ManStart( 5000 ); - pNew->pName = Aig_UtilStrsav( p->pAig->pName ); + pNew->pName = Abc_UtilStrsav( p->pAig->pName ); // create constant Aig_ManCleanData( p->pAig ); Aig_ManConst1(p->pAig)->pData = Aig_ManConst1(pNew); @@ -596,7 +596,7 @@ Abc_Cex_t * Aig_Gla1DeriveCex( Aig_Gla1Man_t * p, int iFrame ) continue; assert( iSatId > 0 ); if ( sat_solver_var_value(p->pSat, iSatId) ) - Aig_InfoSetBit( pCex->pData, pCex->nRegs + f * pCex->nPis + i ); + Abc_InfoSetBit( pCex->pData, pCex->nRegs + f * pCex->nPis + i ); } } Aig_ManForEachObjVec( p->vPPis, p->pAig, pObj, i ) @@ -610,7 +610,7 @@ Abc_Cex_t * Aig_Gla1DeriveCex( Aig_Gla1Man_t * p, int iFrame ) continue; assert( iSatId > 0 ); if ( sat_solver_var_value(p->pSat, iSatId) ) - Aig_InfoSetBit( pCex->pData, pCex->nRegs + f * pCex->nPis + Vec_IntSize(p->vPis) + i ); + Abc_InfoSetBit( pCex->pData, pCex->nRegs + f * pCex->nPis + Vec_IntSize(p->vPis) + i ); } } return pCex; diff --git a/src/aig/saig/saigGlaPba.c b/src/aig/saig/saigGlaPba.c index cdbc05c7..c22cf415 100644 --- a/src/aig/saig/saigGlaPba.c +++ b/src/aig/saig/saigGlaPba.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "saig.h" -#include "satSolver.h" -#include "satStore.h" +#include "src/sat/bsat/satSolver.h" +#include "src/sat/bsat/satStore.h" ABC_NAMESPACE_IMPL_START diff --git a/src/aig/saig/saigGlaPba2.c b/src/aig/saig/saigGlaPba2.c index 1daea5d9..8bc2b982 100644 --- a/src/aig/saig/saigGlaPba2.c +++ b/src/aig/saig/saigGlaPba2.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "saig.h" -#include "satSolver2.h" +#include "src/sat/bsat/satSolver2.h" ABC_NAMESPACE_IMPL_START diff --git a/src/aig/saig/saigHaig.c b/src/aig/saig/saigHaig.c index 3ea0a2c6..ee058a3c 100644 --- a/src/aig/saig/saigHaig.c +++ b/src/aig/saig/saigHaig.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "saig.h" -#include "satSolver.h" -#include "cnf.h" +#include "src/sat/bsat/satSolver.h" +#include "src/sat/cnf/cnf.h" ABC_NAMESPACE_IMPL_START @@ -101,8 +101,8 @@ Aig_Man_t * Aig_ManHaigFrames( Aig_Man_t * pHaig, int nFrames ) assert( nFrames == 1 || Saig_ManRegNum(pHaig) > 0 ); // start AIG manager for timeframes pFrames = Aig_ManStart( Aig_ManNodeNum(pHaig) * nFrames ); - pFrames->pName = Aig_UtilStrsav( pHaig->pName ); - pFrames->pSpec = Aig_UtilStrsav( pHaig->pSpec ); + pFrames->pName = Abc_UtilStrsav( pHaig->pName ); + pFrames->pSpec = Abc_UtilStrsav( pHaig->pSpec ); // map the constant node Aig_ManConst1(pHaig)->pData = Aig_ManConst1( pFrames ); // create variables for register outputs diff --git a/src/aig/saig/saigInd.c b/src/aig/saig/saigInd.c index 190d8d25..c9043ba2 100644 --- a/src/aig/saig/saigInd.c +++ b/src/aig/saig/saigInd.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "saig.h" -#include "cnf.h" -#include "satSolver.h" +#include "src/sat/cnf/cnf.h" +#include "src/sat/bsat/satSolver.h" ABC_NAMESPACE_IMPL_START @@ -324,7 +324,7 @@ nextrun: Vec_IntForEachEntryStart( vTopVarIds, VarNum, i, 1 ) { if ( VarNum >= 0 && sat_solver_var_value( pSat, VarNum ) ) - Aig_InfoSetBit( pCex->pData, iBit ); + Abc_InfoSetBit( pCex->pData, iBit ); iBit++; } assert( iBit == pCex->nBits ); diff --git a/src/aig/saig/saigIoa.c b/src/aig/saig/saigIoa.c index c84c37f3..bdd187d9 100644 --- a/src/aig/saig/saigIoa.c +++ b/src/aig/saig/saigIoa.c @@ -47,15 +47,15 @@ char * Saig_ObjName( Aig_Man_t * p, Aig_Obj_t * pObj ) { static char Buffer[16]; if ( Aig_ObjIsNode(pObj) || Aig_ObjIsConst1(pObj) ) - sprintf( Buffer, "n%0*d", Aig_Base10Log(Aig_ManObjNumMax(p)), Aig_ObjId(pObj) ); + sprintf( Buffer, "n%0*d", Abc_Base10Log(Aig_ManObjNumMax(p)), Aig_ObjId(pObj) ); else if ( Saig_ObjIsPi(p, pObj) ) - sprintf( Buffer, "pi%0*d", Aig_Base10Log(Saig_ManPiNum(p)), Aig_ObjPioNum(pObj) ); + sprintf( Buffer, "pi%0*d", Abc_Base10Log(Saig_ManPiNum(p)), Aig_ObjPioNum(pObj) ); else if ( Saig_ObjIsPo(p, pObj) ) - sprintf( Buffer, "po%0*d", Aig_Base10Log(Saig_ManPoNum(p)), Aig_ObjPioNum(pObj) ); + sprintf( Buffer, "po%0*d", Abc_Base10Log(Saig_ManPoNum(p)), Aig_ObjPioNum(pObj) ); else if ( Saig_ObjIsLo(p, pObj) ) - sprintf( Buffer, "lo%0*d", Aig_Base10Log(Saig_ManRegNum(p)), Aig_ObjPioNum(pObj) - Saig_ManPiNum(p) ); + sprintf( Buffer, "lo%0*d", Abc_Base10Log(Saig_ManRegNum(p)), Aig_ObjPioNum(pObj) - Saig_ManPiNum(p) ); else if ( Saig_ObjIsLi(p, pObj) ) - sprintf( Buffer, "li%0*d", Aig_Base10Log(Saig_ManRegNum(p)), Aig_ObjPioNum(pObj) - Saig_ManPoNum(p) ); + sprintf( Buffer, "li%0*d", Abc_Base10Log(Saig_ManRegNum(p)), Aig_ObjPioNum(pObj) - Saig_ManPoNum(p) ); else assert( 0 ); return Buffer; @@ -268,8 +268,8 @@ Aig_Man_t * Saig_ManReadBlif( char * pFileName ) { printf( "Saig_ManReadBlif(): Error 2.\n" ); return NULL; } // start the package p = Aig_ManStart( 10000 ); - p->pName = Aig_UtilStrsav( pToken ); - p->pSpec = Aig_UtilStrsav( pFileName ); + p->pName = Abc_UtilStrsav( pToken ); + p->pSpec = Abc_UtilStrsav( pFileName ); // count PIs pToken = Saig_ManReadToken( pFile ); if ( pToken == NULL || strcmp( pToken, ".inputs" ) ) diff --git a/src/aig/saig/saigMiter.c b/src/aig/saig/saigMiter.c index c50eaac5..20dbeec7 100644 --- a/src/aig/saig/saigMiter.c +++ b/src/aig/saig/saigMiter.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "saig.h" -#include "fra.h" +#include "src/proof/fra/fra.h" ABC_NAMESPACE_IMPL_START @@ -106,7 +106,7 @@ Aig_Man_t * Saig_ManCreateMiter( Aig_Man_t * p0, Aig_Man_t * p1, int Oper ) assert( Saig_ManPiNum(p0) == Saig_ManPiNum(p1) ); assert( Saig_ManPoNum(p0) == Saig_ManPoNum(p1) ); pNew = Aig_ManStart( Aig_ManObjNumMax(p0) + Aig_ManObjNumMax(p1) ); - pNew->pName = Aig_UtilStrsav( "miter" ); + pNew->pName = Abc_UtilStrsav( "miter" ); Aig_ManCleanData( p0 ); Aig_ManCleanData( p1 ); // map constant nodes @@ -168,7 +168,7 @@ Aig_Man_t * Saig_ManCreateMiterComb( Aig_Man_t * p0, Aig_Man_t * p1, int Oper ) assert( Aig_ManPiNum(p0) == Aig_ManPiNum(p1) ); assert( Aig_ManPoNum(p0) == Aig_ManPoNum(p1) ); pNew = Aig_ManStart( Aig_ManObjNumMax(p0) + Aig_ManObjNumMax(p1) ); - pNew->pName = Aig_UtilStrsav( "miter" ); + pNew->pName = Abc_UtilStrsav( "miter" ); // map constant nodes Aig_ManConst1(p0)->pData = Aig_ManConst1(pNew); Aig_ManConst1(p1)->pData = Aig_ManConst1(pNew); @@ -246,8 +246,8 @@ Aig_Man_t * Saig_ManDualRail( Aig_Man_t * p, int fMiter ) Aig_ManCleanNext( p ); // create the new manager pNew = Aig_ManStart( 4*Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->pSpec = Aig_UtilStrsav( p->pSpec ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // create the PIs Aig_ManConst1(p)->pData = Aig_ManConst0(pNew); Aig_ManConst1(p)->pNext = Aig_ManConst1(pNew); @@ -331,8 +331,8 @@ Aig_Man_t * Saig_ManUnrollTwo( Aig_Man_t * pBot, Aig_Man_t * pTop, int nFrames ) assert( Saig_ManRegNum(pBot) == Saig_ManRegNum(pTop) ); assert( Saig_ManRegNum(pBot) > 0 || Saig_ManRegNum(pTop) > 0 ); // start timeframes - p = Aig_ManStart( nFrames * ABC_MAX(Aig_ManObjNumMax(pBot), Aig_ManObjNumMax(pTop)) ); - p->pName = Aig_UtilStrsav( "frames" ); + p = Aig_ManStart( nFrames * Abc_MaxInt(Aig_ManObjNumMax(pBot), Aig_ManObjNumMax(pTop)) ); + p->pName = Abc_UtilStrsav( "frames" ); // create variables for register outputs pAig = pBot; Saig_ManForEachLo( pAig, pObj, i ) @@ -392,7 +392,7 @@ Aig_Man_t * Aig_ManDupNodesAll( Aig_Man_t * p, Vec_Ptr_t * vSet ) Aig_Obj_t * pObj; int i; pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Aig_ManForEachPi( p, pObj, i ) pObj->pData = Aig_ObjCreatePi( pNew ); @@ -430,7 +430,7 @@ Aig_Man_t * Aig_ManDupNodesHalf( Aig_Man_t * p, Vec_Ptr_t * vSet, int iPart ) int i; Aig_ManCleanData( p ); pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Saig_ManForEachPi( p, pObj, i ) pObj->pData = Aig_ObjCreatePi( pNew ); @@ -534,13 +534,13 @@ int Saig_ManDemiterSimple( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAi { *ppAig0 = Aig_ManDupNodesHalf( p, vSet0, 0 ); ABC_FREE( (*ppAig0)->pName ); - (*ppAig0)->pName = Aig_UtilStrsav( "part0" ); + (*ppAig0)->pName = Abc_UtilStrsav( "part0" ); } if ( ppAig1 ) { *ppAig1 = Aig_ManDupNodesHalf( p, vSet1, 1 ); ABC_FREE( (*ppAig1)->pName ); - (*ppAig1)->pName = Aig_UtilStrsav( "part1" ); + (*ppAig1)->pName = Abc_UtilStrsav( "part1" ); } Vec_PtrFree( vSet0 ); Vec_PtrFree( vSet1 ); @@ -682,11 +682,11 @@ int Saig_ManDemiterSimpleDiff( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** // create new AIG *ppAig0 = Aig_ManDupNodesHalf( p, vSet0, 0 ); ABC_FREE( (*ppAig0)->pName ); - (*ppAig0)->pName = Aig_UtilStrsav( "part0" ); + (*ppAig0)->pName = Abc_UtilStrsav( "part0" ); // create new AIGs *ppAig1 = Aig_ManDupNodesHalf( p, vSet1, 1 ); ABC_FREE( (*ppAig1)->pName ); - (*ppAig1)->pName = Aig_UtilStrsav( "part1" ); + (*ppAig1)->pName = Abc_UtilStrsav( "part1" ); // cleanup Vec_PtrFree( vSet0 ); Vec_PtrFree( vSet1 ); @@ -812,13 +812,13 @@ int Saig_ManDemiterSimpleDiff_old( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t { *ppAig0 = Aig_ManDupNodesAll( p, vSet0 ); ABC_FREE( (*ppAig0)->pName ); - (*ppAig0)->pName = Aig_UtilStrsav( "part0" ); + (*ppAig0)->pName = Abc_UtilStrsav( "part0" ); } if ( ppAig1 ) { *ppAig1 = Aig_ManDupNodesAll( p, vSet1 ); ABC_FREE( (*ppAig1)->pName ); - (*ppAig1)->pName = Aig_UtilStrsav( "part1" ); + (*ppAig1)->pName = Abc_UtilStrsav( "part1" ); } Vec_PtrFree( vSet0 ); Vec_PtrFree( vSet1 ); @@ -984,14 +984,14 @@ int Saig_ManDemiter( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 ) assert( 0 ); *ppAig0 = Aig_ManDupNodesHalf( p, vSet0, 0 ); // not ready ABC_FREE( (*ppAig0)->pName ); - (*ppAig0)->pName = Aig_UtilStrsav( "part0" ); + (*ppAig0)->pName = Abc_UtilStrsav( "part0" ); } if ( ppAig1 ) { assert( 0 ); *ppAig1 = Aig_ManDupNodesHalf( p, vSet1, 1 ); // not ready ABC_FREE( (*ppAig1)->pName ); - (*ppAig1)->pName = Aig_UtilStrsav( "part1" ); + (*ppAig1)->pName = Abc_UtilStrsav( "part1" ); } Vec_PtrFree( vSet0 ); Vec_PtrFree( vSet1 ); diff --git a/src/aig/saig/saigOutDec.c b/src/aig/saig/saigOutDec.c index d8cc591e..e72ea132 100644 --- a/src/aig/saig/saigOutDec.c +++ b/src/aig/saig/saigOutDec.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "saig.h" -#include "cnf.h" -#include "satSolver.h" +#include "src/sat/cnf/cnf.h" +#include "src/sat/bsat/satSolver.h" ABC_NAMESPACE_IMPL_START @@ -160,7 +160,7 @@ Aig_Man_t * Saig_ManDecPropertyOutput( Aig_Man_t * pAig, int nLits, int fVerbose // start the new manager pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); - pAigNew->pName = Aig_UtilStrsav( pAig->pName ); + pAigNew->pName = Abc_UtilStrsav( pAig->pName ); pAigNew->nConstrs = pAig->nConstrs; // map the constant node Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); @@ -180,7 +180,7 @@ Aig_Man_t * Saig_ManDecPropertyOutput( Aig_Man_t * pAig, int nLits, int fVerbose pMiter = Aig_ManConst1( pAigNew ); Vec_IntForEachEntry( vCube, Lit, i ) { - pObj = Aig_NotCond( Aig_ObjCopy(Aig_ManObj(pAig, Aig_Lit2Var(Lit))), Aig_LitIsCompl(Lit) ); + pObj = Aig_NotCond( Aig_ObjCopy(Aig_ManObj(pAig, Abc_Lit2Var(Lit))), Abc_LitIsCompl(Lit) ); pMiter = Aig_And( pAigNew, pMiter, pObj ); } Aig_ObjCreatePo( pAigNew, pMiter ); diff --git a/src/aig/saig/saigPhase.c b/src/aig/saig/saigPhase.c index bd7176fa..4107c5a2 100644 --- a/src/aig/saig/saigPhase.c +++ b/src/aig/saig/saigPhase.c @@ -145,10 +145,10 @@ Saig_Tsim_t * Saig_TsiStart( Aig_Man_t * pAig ) p = (Saig_Tsim_t *)ABC_ALLOC( char, sizeof(Saig_Tsim_t) ); memset( p, 0, sizeof(Saig_Tsim_t) ); p->pAig = pAig; - p->nWords = Aig_BitWordNum( 2*Aig_ManRegNum(pAig) ); + p->nWords = Abc_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(TSIM_MAX_ROUNDS/2); + p->nBins = Abc_PrimeCudd(TSIM_MAX_ROUNDS/2); p->pBins = ABC_ALLOC( unsigned *, p->nBins ); memset( p->pBins, 0, sizeof(unsigned *) * p->nBins ); return p; @@ -233,7 +233,7 @@ int Saig_TsiCountNonXValuedRegisters( Saig_Tsim_t * p, int nPref ) { Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, k, nPref ) { - Value = (Aig_InfoHasBit( pState, 2 * i + 1 ) << 1) | Aig_InfoHasBit( pState, 2 * i ); + Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i ); assert( Value != 0 ); if ( Value == SAIG_XVSX ) break; @@ -266,7 +266,7 @@ Vec_Int_t * Saig_TsiComputeTransient( Saig_Tsim_t * p, int nPref ) { Vec_PtrForEachEntry( unsigned *, p->vStates, pState, k ) { - ValueThis = (Aig_InfoHasBit( pState, 2 * i + 1 ) << 1) | Aig_InfoHasBit( pState, 2 * i ); + ValueThis = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i ); //printf( "%s", (ValueThis == 1)? "0" : ((ValueThis == 2)? "1" : "x") ); assert( ValueThis != 0 ); if ( ValuePrev != ValueThis ) @@ -320,7 +320,7 @@ void Saig_TsiPrintTraces( Saig_Tsim_t * p, int nWords, int nPrefix, int nLoop ) /* Vec_PtrForEachEntry( unsigned *, p->vStates, pState, k ) { - Value = (Aig_InfoHasBit( pState, 2 * i + 1 ) << 1) | Aig_InfoHasBit( pState, 2 * i ); + Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i ); if ( Value == SAIG_XVSX ) break; } @@ -335,7 +335,7 @@ void Saig_TsiPrintTraces( Saig_Tsim_t * p, int nWords, int nPrefix, int nLoop ) printf( "%5d : ", Counter++ ); Vec_PtrForEachEntryStop( unsigned *, p->vStates, pState, k, Vec_PtrSize(p->vStates)-1 ) { - Value = (Aig_InfoHasBit( pState, 2 * i + 1 ) << 1) | Aig_InfoHasBit( pState, 2 * i ); + Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i ); if ( Value == SAIG_XVS0 ) printf( "0" ); else if ( Value == SAIG_XVS1 ) @@ -458,7 +458,7 @@ void Saig_TsiStatePrint( Saig_Tsim_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 ); + Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i ); if ( Value == SAIG_XVS0 ) printf( "0" ), nZeros++; else if ( Value == SAIG_XVS1 ) @@ -488,7 +488,7 @@ int Saig_TsiStateCount( Saig_Tsim_t * p, unsigned * pState ) int i, Value, nCounter = 0; Aig_ManForEachLiLoSeq( p->pAig, pObjLi, pObjLo, i ) { - Value = (Aig_InfoHasBit( pState, 2 * i + 1 ) << 1) | Aig_InfoHasBit( pState, 2 * i ); + Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i ); nCounter += (Value == SAIG_XVS0 || Value == SAIG_XVS1); } return nCounter; @@ -559,9 +559,9 @@ Saig_Tsim_t * Saig_ManReachableTernary( Aig_Man_t * p, Vec_Int_t * vInits, int f { Value = Saig_ObjGetXsim(pObjLo); if ( Value & 1 ) - Aig_InfoSetBit( pState, 2 * i ); + Abc_InfoSetBit( pState, 2 * i ); if ( Value & 2 ) - Aig_InfoSetBit( pState, 2 * i + 1 ); + Abc_InfoSetBit( pState, 2 * i + 1 ); } // printf( "%d ", Saig_TsiStateCount(pTsi, pState) ); // Saig_TsiStatePrint( pTsi, pState ); @@ -679,7 +679,7 @@ int Saig_ManFindRegisters( Saig_Tsim_t * pTsi, int nFrames, int fIgnore, int fVe pState = (unsigned *)Vec_PtrEntry( pTsi->vStates, k ); else pState = (unsigned *)Vec_PtrEntry( pTsi->vStates, k - pTsi->nCycle ); - Value = (Aig_InfoHasBit( pState, 2 * Reg + 1 ) << 1) | Aig_InfoHasBit( pState, 2 * Reg ); + Value = (Abc_InfoHasBit( pState, 2 * Reg + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * Reg ); assert( Value == SAIG_XVS0 || Value == SAIG_XVS1 ); if ( k < nFrames || (fIgnore && k == nFrames) ) Values[k % nFrames] = Value; @@ -761,8 +761,8 @@ Aig_Man_t * Saig_ManPerformAbstraction( Saig_Tsim_t * pTsi, int nFrames, int fVe // start the fraig package pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFrames ); - pFrames->pName = Aig_UtilStrsav( pAig->pName ); - pFrames->pSpec = Aig_UtilStrsav( pAig->pSpec ); + pFrames->pName = Abc_UtilStrsav( pAig->pName ); + pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec ); // map constant nodes for ( f = 0; f < nFrames; f++ ) Saig_ObjSetFrames( pObjMap, nFrames, Aig_ManConst1(pAig), f, Aig_ManConst1(pFrames) ); @@ -782,7 +782,7 @@ Aig_Man_t * Saig_ManPerformAbstraction( Saig_Tsim_t * pTsi, int nFrames, int fVe { pObj = Saig_ManLo( pAig, Reg ); pState = (unsigned *)Vec_PtrEntry( pTsi->vStates, f ); - Value = (Aig_InfoHasBit( pState, 2 * Reg + 1 ) << 1) | Aig_InfoHasBit( pState, 2 * Reg ); + Value = (Abc_InfoHasBit( pState, 2 * Reg + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * Reg ); assert( Value == SAIG_XVS0 || Value == SAIG_XVS1 ); pObjNew = (Value == SAIG_XVS1)? Aig_ManConst1(pFrames) : Aig_ManConst0(pFrames); Saig_ObjSetFrames( pObjMap, nFrames, pObj, f, pObjNew ); @@ -922,7 +922,7 @@ Aig_Man_t * Saig_ManPhaseAbstract( Aig_Man_t * p, Vec_Int_t * vInits, int nFrame // derive information pTsi->nPrefix = Saig_TsiComputePrefix( pTsi, (unsigned *)Vec_PtrEntryLast(pTsi->vStates), pTsi->nWords ); pTsi->nCycle = Vec_PtrSize(pTsi->vStates) - 1 - pTsi->nPrefix; - pTsi->nNonXRegs = Saig_TsiCountNonXValuedRegisters(pTsi, ABC_MIN(pTsi->nPrefix,nPref)); + pTsi->nNonXRegs = Saig_TsiCountNonXValuedRegisters(pTsi, Abc_MinInt(pTsi->nPrefix,nPref)); // print statistics if ( fVerbose ) { @@ -1066,8 +1066,8 @@ Abc_Cex_t * Saig_PhaseTranslateCex( Aig_Man_t * p, Abc_Cex_t * pCex ) pNew->iPo = pCex->iPo % Saig_ManPoNum(p); // copy the bit data for ( i = pCex->nRegs, k = pNew->nRegs; k < pNew->nBits; k++, i++ ) - if ( Aig_InfoHasBit( pCex->pData, i ) ) - Aig_InfoSetBit( pNew->pData, k ); + if ( Abc_InfoHasBit( pCex->pData, i ) ) + Abc_InfoSetBit( pNew->pData, k ); assert( i <= pCex->nBits ); return pNew; } diff --git a/src/aig/saig/saigRefSat.c b/src/aig/saig/saigRefSat.c index b2ea80a6..1f862c1a 100644 --- a/src/aig/saig/saigRefSat.c +++ b/src/aig/saig/saigRefSat.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "saig.h" -#include "cnf.h" -#include "satSolver.h" +#include "src/sat/cnf/cnf.h" +#include "src/sat/bsat/satSolver.h" ABC_NAMESPACE_IMPL_START @@ -95,13 +95,13 @@ Abc_Cex_t * Saig_RefManReason2Cex( Saig_RefMan_t * p, Vec_Int_t * vReasons ) Abc_Cex_t * pCare; int i, Entry, iInput, iFrame; pCare = Abc_CexDup( p->pCex, p->pCex->nRegs ); - memset( pCare->pData, 0, sizeof(unsigned) * Aig_BitWordNum(pCare->nBits) ); + memset( pCare->pData, 0, sizeof(unsigned) * Abc_BitWordNum(pCare->nBits) ); Vec_IntForEachEntry( vReasons, Entry, i ) { assert( Entry >= 0 && Entry < Aig_ManPiNum(p->pFrames) ); iInput = Vec_IntEntry( p->vMapPiF2A, 2*Entry ); iFrame = Vec_IntEntry( p->vMapPiF2A, 2*Entry+1 ); - Aig_InfoSetBit( pCare->pData, pCare->nRegs + pCare->nPis * iFrame + iInput ); + Abc_InfoSetBit( pCare->pData, pCare->nRegs + pCare->nPis * iFrame + iInput ); } return pCare; } @@ -181,7 +181,7 @@ Vec_Int_t * Saig_RefManFindReason( Saig_RefMan_t * p ) { int iInput = Vec_IntEntry( p->vMapPiF2A, 2*i ); int iFrame = Vec_IntEntry( p->vMapPiF2A, 2*i+1 ); - pObj->fPhase = Aig_InfoHasBit( p->pCex->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput ); + pObj->fPhase = Abc_InfoHasBit( p->pCex->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput ); // assign priority if ( Vec_IntEntry(vPi2Prio, iInput) == ~0 ) Vec_IntWriteEntry( vPi2Prio, iInput, CountPrios++ ); @@ -295,11 +295,11 @@ Aig_Man_t * Saig_ManUnrollWithCex( Aig_Man_t * pAig, Abc_Cex_t * pCex, int nInpu // derive unrolled timeframes pFrames = Aig_ManStart( 10000 ); - pFrames->pName = Aig_UtilStrsav( pAig->pName ); - pFrames->pSpec = Aig_UtilStrsav( pAig->pSpec ); + pFrames->pName = Abc_UtilStrsav( pAig->pName ); + pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec ); // initialize the flops Saig_ManForEachLo( pAig, pObj, i ) - pObj->pData = Aig_NotCond( Aig_ManConst1(pFrames), !Aig_InfoHasBit(pCex->pData, i) ); + pObj->pData = Aig_NotCond( Aig_ManConst1(pFrames), !Abc_InfoHasBit(pCex->pData, i) ); // iterate through the frames for ( f = 0; f <= pCex->iFrame; f++ ) { @@ -318,7 +318,7 @@ Aig_Man_t * Saig_ManUnrollWithCex( Aig_Man_t * pAig, Abc_Cex_t * pCex, int nInpu if ( Aig_ObjPioNum(pObj) < nInputs ) { int iBit = pCex->nRegs + f * pCex->nPis + Aig_ObjPioNum(pObj); - pObj->pData = Aig_NotCond( Aig_ManConst1(pFrames), !Aig_InfoHasBit(pCex->pData, iBit) ); + pObj->pData = Aig_NotCond( Aig_ManConst1(pFrames), !Abc_InfoHasBit(pCex->pData, iBit) ); } else { @@ -409,9 +409,9 @@ int Saig_RefManSetPhases( Saig_RefMan_t * p, Abc_Cex_t * pCare, int fValue1 ) { iInput = Vec_IntEntry( p->vMapPiF2A, 2*i ); iFrame = Vec_IntEntry( p->vMapPiF2A, 2*i+1 ); - pObj->fPhase = Aig_InfoHasBit( p->pCex->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput ); + pObj->fPhase = Abc_InfoHasBit( p->pCex->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput ); // update value if it is a don't-care - if ( pCare && !Aig_InfoHasBit( pCare->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput ) ) + if ( pCare && !Abc_InfoHasBit( pCare->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput ) ) pObj->fPhase = fValue1; } Aig_ManForEachNode( p->pFrames, pObj, i ) @@ -448,7 +448,7 @@ Vec_Vec_t * Saig_RefManOrderLiterals( Saig_RefMan_t * p, Vec_Int_t * vVar2PiId, assert( iPiNum >= 0 && iPiNum < Aig_ManPiNum(p->pFrames) ); iInput = Vec_IntEntry( p->vMapPiF2A, 2*iPiNum ); iFrame = Vec_IntEntry( p->vMapPiF2A, 2*iPiNum+1 ); -// Aig_InfoSetBit( pCare->pData, pCare->nRegs + pCare->nPis * iFrame + iInput ); +// Abc_InfoSetBit( pCare->pData, pCare->nRegs + pCare->nPis * iFrame + iInput ); if ( Vec_IntEntry( vVar2New, iInput ) == ~0 ) Vec_IntWriteEntry( vVar2New, iInput, Vec_VecSize(vLits) ); Vec_VecPushInt( vLits, Vec_IntEntry( vVar2New, iInput ), Entry ); @@ -475,14 +475,14 @@ Abc_Cex_t * Saig_RefManCreateCex( Saig_RefMan_t * p, Vec_Int_t * vVar2PiId, Vec_ int i, Entry, iInput, iFrame; // create counter-example pCare = Abc_CexDup( p->pCex, p->pCex->nRegs ); - memset( pCare->pData, 0, sizeof(unsigned) * Aig_BitWordNum(pCare->nBits) ); + memset( pCare->pData, 0, sizeof(unsigned) * Abc_BitWordNum(pCare->nBits) ); Vec_IntForEachEntry( vAssumps, Entry, i ) { int iPiNum = Vec_IntEntry( vVar2PiId, lit_var(Entry) ); assert( iPiNum >= 0 && iPiNum < Aig_ManPiNum(p->pFrames) ); iInput = Vec_IntEntry( p->vMapPiF2A, 2*iPiNum ); iFrame = Vec_IntEntry( p->vMapPiF2A, 2*iPiNum+1 ); - Aig_InfoSetBit( pCare->pData, pCare->nRegs + pCare->nPis * iFrame + iInput ); + Abc_InfoSetBit( pCare->pData, pCare->nRegs + pCare->nPis * iFrame + iInput ); } return pCare; } @@ -540,7 +540,7 @@ Abc_Cex_t * Saig_RefManRunSat( Saig_RefMan_t * p, int fNewOrder ) printf( "The problem is trivially UNSAT. The CEX is real.\n" ); // create counter-example pCare = Abc_CexDup( p->pCex, p->pCex->nRegs ); - memset( pCare->pData, 0, sizeof(unsigned) * Aig_BitWordNum(pCare->nBits) ); + memset( pCare->pData, 0, sizeof(unsigned) * Abc_BitWordNum(pCare->nBits) ); return pCare; } // the problem is SAT - it is expected @@ -552,7 +552,7 @@ Abc_Cex_t * Saig_RefManRunSat( Saig_RefMan_t * p, int fNewOrder ) { int iInput = Vec_IntEntry( p->vMapPiF2A, 2*i ); int iFrame = Vec_IntEntry( p->vMapPiF2A, 2*i+1 ); -// RetValue = Aig_InfoHasBit( p->pCex->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput ); +// RetValue = Abc_InfoHasBit( p->pCex->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput ); // Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !RetValue ) ); Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 1 ) ); Vec_IntWriteEntry( vVar2PiId, pCnf->pVarNums[Aig_ObjId(pObj)], i ); @@ -740,7 +740,7 @@ Vec_Int_t * Saig_RefManRefineWithSat( Saig_RefMan_t * p, Vec_Int_t * vAigPis ) int iFrame = Vec_IntEntry( p->vMapPiF2A, 2*i+1 ); if ( Vec_IntEntry(vVisited, iInput) == 0 ) continue; - RetValue = Aig_InfoHasBit( p->pCex->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput ); + RetValue = Abc_InfoHasBit( p->pCex->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput ); Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !RetValue ) ); // Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 1 ) ); Vec_IntWriteEntry( vVar2PiId, pCnf->pVarNums[Aig_ObjId(pObj)], i ); diff --git a/src/aig/saig/saigRetMin.c b/src/aig/saig/saigRetMin.c index cce7dcc6..3f06177c 100644 --- a/src/aig/saig/saigRetMin.c +++ b/src/aig/saig/saigRetMin.c @@ -20,10 +20,10 @@ #include "saig.h" -#include "nwk.h" -#include "cnf.h" -#include "satSolver.h" -#include "satStore.h" +#include "src/opt/nwk/nwk.h" +#include "src/sat/cnf/cnf.h" +#include "src/sat/bsat/satSolver.h" +#include "src/sat/bsat/satStore.h" ABC_NAMESPACE_IMPL_START @@ -287,8 +287,8 @@ Aig_Man_t * Saig_ManRetimeDupForward( Aig_Man_t * p, Vec_Ptr_t * vCut ) // assert( Vec_PtrSize(vCut) == Saig_ManRetimeCountCut(p, vCut) ); // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->pSpec = Aig_UtilStrsav( p->pSpec ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nRegs = Vec_PtrSize(vCut); pNew->nTruePis = p->nTruePis; pNew->nTruePos = p->nTruePos; @@ -346,8 +346,8 @@ Aig_Man_t * Saig_ManRetimeDupBackward( Aig_Man_t * p, Vec_Ptr_t * vCut, Vec_Int_ // assert( Vec_PtrSize(vCut) == Saig_ManRetimeCountCut(p, vCut) ); // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->pSpec = Aig_UtilStrsav( p->pSpec ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nRegs = Vec_PtrSize(vCut); pNew->nTruePis = p->nTruePis; pNew->nTruePos = p->nTruePos; diff --git a/src/aig/saig/saigSimExt.c b/src/aig/saig/saigSimExt.c index ac0fa697..021481b9 100644 --- a/src/aig/saig/saigSimExt.c +++ b/src/aig/saig/saigSimExt.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "saig.h" -#include "ssw.h" +#include "src/proof/ssw/ssw.h" ABC_NAMESPACE_IMPL_START @@ -111,12 +111,12 @@ int Saig_ManSimDataInit( Aig_Man_t * p, Abc_Cex_t * pCex, Vec_Ptr_t * vSimInfo, Aig_Obj_t * pObj, * pObjLi, * pObjLo; int i, f, Entry, iBit = 0; Saig_ManForEachLo( p, pObj, i ) - Saig_ManSimInfoSet( vSimInfo, pObj, 0, Aig_InfoHasBit(pCex->pData, iBit++)?SAIG_ONE:SAIG_ZER ); + Saig_ManSimInfoSet( vSimInfo, pObj, 0, Abc_InfoHasBit(pCex->pData, iBit++)?SAIG_ONE:SAIG_ZER ); for ( f = 0; f <= pCex->iFrame; f++ ) { Saig_ManSimInfoSet( vSimInfo, Aig_ManConst1(p), f, SAIG_ONE ); Saig_ManForEachPi( p, pObj, i ) - Saig_ManSimInfoSet( vSimInfo, pObj, f, Aig_InfoHasBit(pCex->pData, iBit++)?SAIG_ONE:SAIG_ZER ); + Saig_ManSimInfoSet( vSimInfo, pObj, f, Abc_InfoHasBit(pCex->pData, iBit++)?SAIG_ONE:SAIG_ZER ); if ( vRes ) Vec_IntForEachEntry( vRes, Entry, i ) Saig_ManSimInfoSet( vSimInfo, Aig_ManPi(p, Entry), f, SAIG_UND ); @@ -251,7 +251,7 @@ Vec_Int_t * Saig_ManExtendCounterExample0( Aig_Man_t * p, int iFirstFlopPi, Abc_ Vec_Int_t * vRes, * vResInv, * vUndo, * vVis, * vVis2; int i, f, Value; // assert( Aig_ManRegNum(p) > 0 ); - assert( (unsigned *)Vec_PtrEntry(vSimInfo,1) - (unsigned *)Vec_PtrEntry(vSimInfo,0) >= Aig_BitWordNum(2*(pCex->iFrame+1)) ); + assert( (unsigned *)Vec_PtrEntry(vSimInfo,1) - (unsigned *)Vec_PtrEntry(vSimInfo,0) >= Abc_BitWordNum(2*(pCex->iFrame+1)) ); // start simulation data Value = Saig_ManSimDataInit( p, pCex, vSimInfo, NULL ); assert( Value == SAIG_ONE ); @@ -301,7 +301,7 @@ Vec_Int_t * Saig_ManExtendCounterExample1( Aig_Man_t * p, int iFirstFlopPi, Abc_ Vec_Int_t * vRes, * vResInv, * vUndo, * vVis, * vVis2; int i, f, Value; // assert( Aig_ManRegNum(p) > 0 ); - assert( (unsigned *)Vec_PtrEntry(vSimInfo,1) - (unsigned *)Vec_PtrEntry(vSimInfo,0) >= Aig_BitWordNum(2*(pCex->iFrame+1)) ); + assert( (unsigned *)Vec_PtrEntry(vSimInfo,1) - (unsigned *)Vec_PtrEntry(vSimInfo,0) >= Abc_BitWordNum(2*(pCex->iFrame+1)) ); // start simulation data Value = Saig_ManSimDataInit( p, pCex, vSimInfo, NULL ); assert( Value == SAIG_ONE ); @@ -351,7 +351,7 @@ Vec_Int_t * Saig_ManExtendCounterExample2( Aig_Man_t * p, int iFirstFlopPi, Abc_ Vec_Int_t * vRes, * vResInv, * vUndo, * vVis, * vVis2; int i, f, Value; // assert( Aig_ManRegNum(p) > 0 ); - assert( (unsigned *)Vec_PtrEntry(vSimInfo,1) - (unsigned *)Vec_PtrEntry(vSimInfo,0) >= Aig_BitWordNum(2*(pCex->iFrame+1)) ); + assert( (unsigned *)Vec_PtrEntry(vSimInfo,1) - (unsigned *)Vec_PtrEntry(vSimInfo,0) >= Abc_BitWordNum(2*(pCex->iFrame+1)) ); // start simulation data Value = Saig_ManSimDataInit( p, pCex, vSimInfo, NULL ); assert( Value == SAIG_ONE ); @@ -419,7 +419,7 @@ Vec_Int_t * Saig_ManExtendCounterExample3( Aig_Man_t * p, int iFirstFlopPi, Abc_ Vec_Int_t * vRes, * vResInv, * vUndo, * vVis, * vVis2; int i, f, Value; // assert( Aig_ManRegNum(p) > 0 ); - assert( (unsigned *)Vec_PtrEntry(vSimInfo,1) - (unsigned *)Vec_PtrEntry(vSimInfo,0) >= Aig_BitWordNum(2*(pCex->iFrame+1)) ); + assert( (unsigned *)Vec_PtrEntry(vSimInfo,1) - (unsigned *)Vec_PtrEntry(vSimInfo,0) >= Abc_BitWordNum(2*(pCex->iFrame+1)) ); // start simulation data Value = Saig_ManSimDataInit( p, pCex, vSimInfo, NULL ); assert( Value == SAIG_ONE ); @@ -529,8 +529,8 @@ Vec_Int_t * Saig_ManExtendCounterExampleTest( Aig_Man_t * p, int iFirstFlopPi, A return NULL; } Aig_ManFanoutStart( p ); - vSimInfo = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p), Aig_BitWordNum(2*(pCex->iFrame+1)) ); - Vec_PtrCleanSimInfo( vSimInfo, 0, Aig_BitWordNum(2*(pCex->iFrame+1)) ); + vSimInfo = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p), Abc_BitWordNum(2*(pCex->iFrame+1)) ); + Vec_PtrCleanSimInfo( vSimInfo, 0, Abc_BitWordNum(2*(pCex->iFrame+1)) ); clk = clock(); if ( fTryFour ) diff --git a/src/aig/saig/saigSimExt2.c b/src/aig/saig/saigSimExt2.c index 3d9cc88a..858c2b3b 100644 --- a/src/aig/saig/saigSimExt2.c +++ b/src/aig/saig/saigSimExt2.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "saig.h" -#include "ssw.h" +#include "src/proof/ssw/ssw.h" ABC_NAMESPACE_IMPL_START @@ -139,12 +139,12 @@ int Saig_ManSimDataInit2( Aig_Man_t * p, Abc_Cex_t * pCex, Vec_Ptr_t * vSimInfo Aig_Obj_t * pObj, * pObjLi, * pObjLo; int i, f, iBit = 0; Saig_ManForEachLo( p, pObj, i ) - Saig_ManSimInfo2Set( vSimInfo, pObj, 0, Aig_InfoHasBit(pCex->pData, iBit++)?SAIG_ONE_NEW:SAIG_ZER_NEW ); + Saig_ManSimInfo2Set( vSimInfo, pObj, 0, Abc_InfoHasBit(pCex->pData, iBit++)?SAIG_ONE_NEW:SAIG_ZER_NEW ); for ( f = 0; f <= pCex->iFrame; f++ ) { Saig_ManSimInfo2Set( vSimInfo, Aig_ManConst1(p), f, SAIG_ONE_NEW ); Saig_ManForEachPi( p, pObj, i ) - Saig_ManSimInfo2Set( vSimInfo, pObj, f, Aig_InfoHasBit(pCex->pData, iBit++)?SAIG_ONE_NEW:SAIG_ZER_NEW ); + Saig_ManSimInfo2Set( vSimInfo, pObj, f, Abc_InfoHasBit(pCex->pData, iBit++)?SAIG_ONE_NEW:SAIG_ZER_NEW ); Aig_ManForEachNode( p, pObj, i ) Saig_ManExtendOneEval2( vSimInfo, pObj, f ); Aig_ManForEachPo( p, pObj, i ) @@ -284,7 +284,7 @@ Vec_Int_t * Saig_ManProcessCex( Aig_Man_t * p, int iFirstFlopPi, Abc_Cex_t * pCe Vec_Int_t * vRes, * vResInv; int i, f, Value; // assert( Aig_ManRegNum(p) > 0 ); - assert( (unsigned *)Vec_PtrEntry(vSimInfo,1) - (unsigned *)Vec_PtrEntry(vSimInfo,0) >= Aig_BitWordNum(2*(pCex->iFrame+1)) ); + assert( (unsigned *)Vec_PtrEntry(vSimInfo,1) - (unsigned *)Vec_PtrEntry(vSimInfo,0) >= Abc_BitWordNum(2*(pCex->iFrame+1)) ); // start simulation data Value = Saig_ManSimDataInit2( p, pCex, vSimInfo ); assert( Value == SAIG_ONE_NEW ); @@ -345,8 +345,8 @@ Vec_Int_t * Saig_ManExtendCounterExampleTest2( Aig_Man_t * p, int iFirstFlopPi, return NULL; } Aig_ManFanoutStart( p ); - vSimInfo = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p), Aig_BitWordNum(2*(pCex->iFrame+1)) ); - Vec_PtrCleanSimInfo( vSimInfo, 0, Aig_BitWordNum(2*(pCex->iFrame+1)) ); + vSimInfo = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p), Abc_BitWordNum(2*(pCex->iFrame+1)) ); + Vec_PtrCleanSimInfo( vSimInfo, 0, Abc_BitWordNum(2*(pCex->iFrame+1)) ); clk = clock(); vRes = Saig_ManProcessCex( p, iFirstFlopPi, pCex, vSimInfo, fVerbose ); @@ -382,7 +382,7 @@ Abc_Cex_t * Saig_ManDeriveCex( Aig_Man_t * p, int iFirstFlopPi, Abc_Cex_t * pCex Vec_Int_t * vRes, * vResInv; int i, f, Value; // assert( Aig_ManRegNum(p) > 0 ); - assert( (unsigned *)Vec_PtrEntry(vSimInfo,1) - (unsigned *)Vec_PtrEntry(vSimInfo,0) >= Aig_BitWordNum(2*(pCex->iFrame+1)) ); + assert( (unsigned *)Vec_PtrEntry(vSimInfo,1) - (unsigned *)Vec_PtrEntry(vSimInfo,0) >= Abc_BitWordNum(2*(pCex->iFrame+1)) ); // start simulation data Value = Saig_ManSimDataInit2( p, pCex, vSimInfo ); assert( Value == SAIG_ONE_NEW ); @@ -400,7 +400,7 @@ Abc_Cex_t * Saig_ManDeriveCex( Aig_Man_t * p, int iFirstFlopPi, Abc_Cex_t * pCex // create CEX pCare = Abc_CexDup( pCex, pCex->nRegs ); - memset( pCare->pData, 0, sizeof(unsigned) * Aig_BitWordNum(pCare->nBits) ); + memset( pCare->pData, 0, sizeof(unsigned) * Abc_BitWordNum(pCare->nBits) ); // select the result vRes = Vec_IntAlloc( 1000 ); @@ -414,7 +414,7 @@ Abc_Cex_t * Saig_ManDeriveCex( Aig_Man_t * p, int iFirstFlopPi, Abc_Cex_t * pCex if ( Saig_ManSimInfo2IsOld( Value ) ) { fFound = 1; - Aig_InfoSetBit( pCare->pData, pCare->nRegs + pCare->nPis * f + i ); + Abc_InfoSetBit( pCare->pData, pCare->nRegs + pCare->nPis * f + i ); } } if ( fFound ) @@ -454,8 +454,8 @@ Abc_Cex_t * Saig_ManFindCexCareBitsSense( Aig_Man_t * p, Abc_Cex_t * pCex, int i return NULL; } Aig_ManFanoutStart( p ); - vSimInfo = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p), Aig_BitWordNum(2*(pCex->iFrame+1)) ); - Vec_PtrCleanSimInfo( vSimInfo, 0, Aig_BitWordNum(2*(pCex->iFrame+1)) ); + vSimInfo = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p), Abc_BitWordNum(2*(pCex->iFrame+1)) ); + Vec_PtrCleanSimInfo( vSimInfo, 0, Abc_BitWordNum(2*(pCex->iFrame+1)) ); clk = clock(); pCare = Saig_ManDeriveCex( p, iFirstFlopPi, pCex, vSimInfo, fVerbose ); diff --git a/src/aig/saig/saigSimFast.c b/src/aig/saig/saigSimFast.c index 1840eaa7..b8eed19e 100644 --- a/src/aig/saig/saigSimFast.c +++ b/src/aig/saig/saigSimFast.c @@ -20,7 +20,7 @@ #include "saig.h" -#include "main.h" +#include "src/base/main/main.h" ABC_NAMESPACE_IMPL_START diff --git a/src/aig/saig/saigSimMv.c b/src/aig/saig/saigSimMv.c index 7076d07b..6579c37b 100644 --- a/src/aig/saig/saigSimMv.c +++ b/src/aig/saig/saigSimMv.c @@ -184,7 +184,7 @@ static inline int Saig_MvCreateObj( Saig_MvMan_t * p, int iFan0, int iFan1 ) pNode->iFan1 = iFan1; pNode->iNext = 0; if ( iFan0 || iFan1 ) - p->pLevels[p->nObjs] = 1 + ABC_MAX( Saig_MvLev(p, iFan0), Saig_MvLev(p, iFan1) ); + p->pLevels[p->nObjs] = 1 + Abc_MaxInt( Saig_MvLev(p, iFan0), Saig_MvLev(p, iFan1) ); else p->pLevels[p->nObjs] = 0, p->nPis++; return p->nObjs++; @@ -216,7 +216,7 @@ Saig_MvMan_t * Saig_MvManStart( Aig_Man_t * pAig, int nFramesSatur ) p->nFlops = Aig_ManRegNum(pAig); // compacted AIG p->pAigOld = Saig_ManCreateReducedAig( pAig, &p->vFlops ); - p->nTStatesSize = Aig_PrimeCudd( p->nStatesMax ); + p->nTStatesSize = Abc_PrimeCudd( p->nStatesMax ); p->pTStates = ABC_CALLOC( unsigned, p->nTStatesSize ); p->pMemStates = Aig_MmFixedStart( sizeof(int) * (p->nFlops+1), p->nStatesMax ); p->vStates = Vec_PtrAlloc( p->nStatesMax ); @@ -231,7 +231,7 @@ Saig_MvMan_t * Saig_MvManStart( Aig_Man_t * pAig, int nFramesSatur ) // internal AIG p->nObjsAlloc = 1000000; p->pAigNew = ABC_ALLOC( Saig_MvAnd_t, p->nObjsAlloc ); - p->nTNodesSize = Aig_PrimeCudd( p->nObjsAlloc / 3 ); + p->nTNodesSize = Abc_PrimeCudd( p->nObjsAlloc / 3 ); p->pTNodes = ABC_CALLOC( int, p->nTNodesSize ); p->pLevels = ABC_ALLOC( unsigned char, p->nObjsAlloc ); Saig_MvCreateObj( p, 0, 0 ); diff --git a/src/aig/saig/saigSimSeq.c b/src/aig/saig/saigSimSeq.c index cc5a9e05..538afef0 100644 --- a/src/aig/saig/saigSimSeq.c +++ b/src/aig/saig/saigSimSeq.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "saig.h" -#include "ssw.h" +#include "src/proof/ssw/ssw.h" ABC_NAMESPACE_IMPL_START @@ -433,8 +433,8 @@ Abc_Cex_t * Raig_ManGenerateCounter( Aig_Man_t * pAig, int iFrame, int iOut, int continue; for ( w = 0; w < nWords; w++ ) pData[w] = Aig_ManRandom( 0 ); - if ( Aig_InfoHasBit( pData, iPat ) ) - Aig_InfoSetBit( p->pData, Counter + iPioId ); + if ( Abc_InfoHasBit( pData, iPat ) ) + Abc_InfoSetBit( p->pData, Counter + iPioId ); } ABC_FREE( pData ); return p; diff --git a/src/aig/saig/saigStrSim.c b/src/aig/saig/saigStrSim.c index 1d69630f..cdf177d0 100644 --- a/src/aig/saig/saigStrSim.c +++ b/src/aig/saig/saigStrSim.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "saig.h" -#include "ssw.h" +#include "src/proof/ssw/ssw.h" ABC_NAMESPACE_IMPL_START @@ -398,7 +398,7 @@ int Saig_StrSimDetectUnique( Aig_Man_t * p0, Aig_Man_t * p1 ) int i, nTableSize, Counter; // allocate the hash table hashing simulation info into nodes - nTableSize = Aig_PrimeCudd( Aig_ManObjNum(p0)/2 ); + nTableSize = Abc_PrimeCudd( Aig_ManObjNum(p0)/2 ); ppTable = ABC_CALLOC( Aig_Obj_t *, nTableSize ); ppNexts = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p0) ); ppCands = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p0) ); diff --git a/src/aig/saig/saigSwitch.c b/src/aig/saig/saigSwitch.c index bbad9be4..01411c05 100644 --- a/src/aig/saig/saigSwitch.c +++ b/src/aig/saig/saigSwitch.c @@ -20,7 +20,7 @@ #include "saig.h" -#include "main.h" +#include "src/base/main/main.h" ABC_NAMESPACE_IMPL_START diff --git a/src/aig/saig/saigSynch.c b/src/aig/saig/saigSynch.c index 00f7517e..08a10b66 100644 --- a/src/aig/saig/saigSynch.c +++ b/src/aig/saig/saigSynch.c @@ -471,7 +471,7 @@ Aig_Man_t * Saig_ManDupInitZero( Aig_Man_t * p ) Aig_Obj_t * pObj; int i; pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); + pNew->pName = Abc_UtilStrsav( p->pName ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Saig_ManForEachPi( p, pObj, i ) pObj->pData = Aig_ObjCreatePi( pNew ); @@ -619,7 +619,7 @@ Aig_Man_t * Saig_Synchronize( Aig_Man_t * pAig1, Aig_Man_t * pAig2, int nWords, return NULL; } clk = clock(); - vSimInfo = Vec_PtrAllocSimInfo( ABC_MAX( Aig_ManObjNumMax(pAig1), Aig_ManObjNumMax(pAig2) ), 1 ); + vSimInfo = Vec_PtrAllocSimInfo( Abc_MaxInt( Aig_ManObjNumMax(pAig1), Aig_ManObjNumMax(pAig2) ), 1 ); // process Design 1 RetValue = Saig_SynchSequenceRun( pAig1, vSimInfo, vSeq1, 1 ); diff --git a/src/aig/saig/saigTempor.c b/src/aig/saig/saigTempor.c index fc57c1f5..1a6f1919 100644 --- a/src/aig/saig/saigTempor.c +++ b/src/aig/saig/saigTempor.c @@ -50,7 +50,7 @@ Aig_Man_t * Saig_ManTemporFrames( Aig_Man_t * pAig, int nFrames ) // start the frames package Aig_ManCleanData( pAig ); pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFrames ); - pFrames->pName = Aig_UtilStrsav( pAig->pName ); + pFrames->pName = Abc_UtilStrsav( pAig->pName ); // initiliaze the flops Saig_ManForEachLo( pAig, pObj, i ) pObj->pData = Aig_ManConst0(pFrames); @@ -103,7 +103,7 @@ Aig_Man_t * Saig_ManTemporDecompose( Aig_Man_t * pAig, int nFrames ) // start the new manager Aig_ManCleanData( pAig ); pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); - pAigNew->pName = Aig_UtilStrsav( pAig->pName ); + pAigNew->pName = Abc_UtilStrsav( pAig->pName ); // map the constant node and primary inputs Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); Saig_ManForEachPi( pAig, pObj, i ) diff --git a/src/aig/saig/saigTrans.c b/src/aig/saig/saigTrans.c index 09639e27..11e775e5 100644 --- a/src/aig/saig/saigTrans.c +++ b/src/aig/saig/saigTrans.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "saig.h" -#include "fra.h" +#include "src/proof/fra/fra.h" ABC_NAMESPACE_IMPL_START diff --git a/src/aig/saig/saigWnd.c b/src/aig/saig/saigWnd.c index c11798ea..6753370f 100644 --- a/src/aig/saig/saigWnd.c +++ b/src/aig/saig/saigWnd.c @@ -232,7 +232,7 @@ Aig_Man_t * Saig_ManWindowExtractNodes( Aig_Man_t * p, Vec_Ptr_t * vNodes ) Aig_ManCleanData( p ); // create the new manager pNew = Aig_ManStart( Vec_PtrSize(vNodes) ); - pNew->pName = Aig_UtilStrsav( "wnd" ); + pNew->pName = Abc_UtilStrsav( "wnd" ); pNew->pSpec = NULL; // map constant nodes pObj = Aig_ManConst1( p ); @@ -375,8 +375,8 @@ Aig_Man_t * Saig_ManWindowInsertNodes( Aig_Man_t * p, Vec_Ptr_t * vNodes, Aig_Ma Aig_ManCleanData( p ); Aig_ManCleanData( pWnd ); pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->pSpec = Aig_UtilStrsav( p->pSpec ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // map constant nodes pObj = Aig_ManConst1( p ); pObj->pData = Aig_ManConst1( pNew ); @@ -745,7 +745,7 @@ Aig_Man_t * Saig_ManWindowExtractMiter( Aig_Man_t * p0, Aig_Man_t * p1 ) vNodes1 = Saig_ManCollectedDiffNodes( p1, p0 ); // create the new manager pNew = Aig_ManStart( Vec_PtrSize(vNodes0) + Vec_PtrSize(vNodes1) ); - pNew->pName = Aig_UtilStrsav( "wnd" ); + pNew->pName = Abc_UtilStrsav( "wnd" ); pNew->pSpec = NULL; // map constant nodes pObj0 = Aig_ManConst1( p0 ); diff --git a/src/aig/ssw/module.make b/src/aig/ssw/module.make deleted file mode 100644 index b6b813b1..00000000 --- a/src/aig/ssw/module.make +++ /dev/null @@ -1,20 +0,0 @@ -SRC += src/aig/ssw/sswAig.c \ - src/aig/ssw/sswBmc.c \ - src/aig/ssw/sswClass.c \ - src/aig/ssw/sswCnf.c \ - src/aig/ssw/sswConstr.c \ - src/aig/ssw/sswCore.c \ - src/aig/ssw/sswDyn.c \ - src/aig/ssw/sswFilter.c \ - src/aig/ssw/sswIslands.c \ - src/aig/ssw/sswLcorr.c \ - src/aig/ssw/sswMan.c \ - src/aig/ssw/sswPart.c \ - src/aig/ssw/sswPairs.c \ - src/aig/ssw/sswRarity.c \ - src/aig/ssw/sswSat.c \ - src/aig/ssw/sswSemi.c \ - src/aig/ssw/sswSim.c \ - src/aig/ssw/sswSimSat.c \ - src/aig/ssw/sswSweep.c \ - src/aig/ssw/sswUnique.c diff --git a/src/aig/ssw/ssw.h b/src/aig/ssw/ssw.h deleted file mode 100644 index 22b6c6e5..00000000 --- a/src/aig/ssw/ssw.h +++ /dev/null @@ -1,142 +0,0 @@ -/**CFile**************************************************************** - - FileName [ssw.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Inductive prover with constraints.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 1, 2008.] - - Revision [$Id: ssw.h,v 1.00 2008/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __SSW_H__ -#define __SSW_H__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -ABC_NAMESPACE_HEADER_START - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -// choicing parameters -typedef struct Ssw_Pars_t_ Ssw_Pars_t; -struct Ssw_Pars_t_ -{ - int nPartSize; // size of the partition - int nOverSize; // size of the overlap between partitions - int nFramesK; // the induction depth - int nFramesAddSim; // the number of additional frames to simulate - int fConstrs; // treat the last nConstrs POs as seq constraints - int fMergeFull; // enables full merge when constraints are used - int nMaxLevs; // the max number of levels of nodes to consider - int nBTLimit; // conflict limit at a node - int nBTLimitGlobal;// conflict limit for multiple runs - int nMinDomSize; // min clock domain considered for optimization - int nItersStop; // stop after the given number of iterations - int fDumpSRInit; // dumps speculative reduction - int nResimDelta; // the number of nodes to resimulate - int nStepsMax; // (scorr only) the max number of induction steps - int TimeLimit; // time out in seconds - int fPolarFlip; // uses polarity adjustment - int fLatchCorr; // perform register correspondence - int fConstCorr; // perform constant correspondence - int fOutputCorr; // perform 'PO correspondence' - int fSemiFormal; // enable semiformal filtering -// int fUniqueness; // enable uniqueness constraints - int fDynamic; // enable dynamic addition of constraints - int fLocalSim; // enable local simulation simulation - int fPartSigCorr; // uses partial signal correspondence - int nIsleDist; // extends islands by the given distance - int fScorrGia; // new signal correspondence implementation - int fUseCSat; // new SAT solver using when fScorrGia is selected - int fVerbose; // verbose stats - int fFlopVerbose; // verbose printout of redundant flops - int fEquivDump; // enables dumping equivalences - // optimized latch correspondence - int fLatchCorrOpt; // perform register correspondence (optimized) - int nSatVarMax; // max number of SAT vars before recycling SAT solver (optimized latch corr only) - int nRecycleCalls; // calls to perform before recycling SAT solver (optimized latch corr only) - // optimized signal correspondence - int nSatVarMax2; // max number of SAT vars before recycling SAT solver (optimized latch corr only) - int nRecycleCalls2;// calls to perform before recycling SAT solver (optimized latch corr only) - // internal parameters - int nIters; // the number of iterations performed - int nConflicts; // the total number of conflicts performed - // callback - void * pData; - void * pFunc; -}; - -typedef struct Ssw_Sml_t_ Ssw_Sml_t; // sequential simulation manager - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== sswBmc.c ==========================================================*/ -extern int Ssw_BmcDynamic( Aig_Man_t * pAig, int nFramesMax, int nConfLimit, int fVerbose, int * piFrame ); -/*=== sswConstr.c ==========================================================*/ -extern int Ssw_ManSetConstrPhases( Aig_Man_t * p, int nFrames, Vec_Int_t ** pvInits ); -/*=== sswCore.c ==========================================================*/ -extern void Ssw_ManSetDefaultParams( Ssw_Pars_t * p ); -extern void Ssw_ManSetDefaultParamsLcorr( Ssw_Pars_t * p ); -extern Aig_Man_t * Ssw_SignalCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars ); -extern Aig_Man_t * Ssw_LatchCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars ); -/*=== sswIslands.c ==========================================================*/ -extern int Ssw_SecWithSimilarityPairs( Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairs, Ssw_Pars_t * pPars ); -extern int Ssw_SecWithSimilarity( Aig_Man_t * p0, Aig_Man_t * p1, Ssw_Pars_t * pPars ); -/*=== sswMiter.c ===================================================*/ -/*=== sswPart.c ==========================================================*/ -extern Aig_Man_t * Ssw_SignalCorrespondencePart( Aig_Man_t * pAig, Ssw_Pars_t * pPars ); -/*=== sswPairs.c ===================================================*/ -extern int Ssw_MiterStatus( Aig_Man_t * p, int fVerbose ); -extern int Ssw_SecWithPairs( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec_Int_t * vIds1, Vec_Int_t * vIds2, Ssw_Pars_t * pPars ); -extern int Ssw_SecGeneral( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Ssw_Pars_t * pPars ); -extern int Ssw_SecGeneralMiter( Aig_Man_t * pMiter, Ssw_Pars_t * pPars ); -/*=== sswRarity.c ===================================================*/ -extern int Ssw_RarSignalFilter( Aig_Man_t * pAig, int nFrames, int nWords, int nBinSize, int nRounds, int nRandSeed, int TimeOut, int fMiter, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose ); -extern int Ssw_RarSimulate( Aig_Man_t * pAig, int nFrames, int nWords, int nBinSize, int nRounds, int nRandSeed, int TimeOut, int fVerbose ); -/*=== sswSim.c ===================================================*/ -extern Ssw_Sml_t * Ssw_SmlSimulateComb( Aig_Man_t * pAig, int nWords ); -extern Ssw_Sml_t * Ssw_SmlSimulateSeq( Aig_Man_t * pAig, int nPref, int nFrames, int nWords ); -extern void Ssw_SmlUnnormalize( Ssw_Sml_t * p ); -extern void Ssw_SmlStop( Ssw_Sml_t * p ); -extern int Ssw_SmlNumFrames( Ssw_Sml_t * p ); -extern int Ssw_SmlNumWordsTotal( Ssw_Sml_t * p ); -extern unsigned * Ssw_SmlSimInfo( Ssw_Sml_t * p, Aig_Obj_t * pObj ); -extern int Ssw_SmlObjsAreEqualWord( Ssw_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ); -extern void Ssw_SmlInitializeSpecial( Ssw_Sml_t * p, Vec_Int_t * vInit ); -extern int Ssw_SmlCheckNonConstOutputs( Ssw_Sml_t * p ); -extern Vec_Ptr_t * Ssw_SmlSimDataPointers( Ssw_Sml_t * p ); - - -ABC_NAMESPACE_HEADER_END - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/ssw/sswAig.c b/src/aig/ssw/sswAig.c deleted file mode 100644 index f3174470..00000000 --- a/src/aig/ssw/sswAig.c +++ /dev/null @@ -1,259 +0,0 @@ -/**CFile**************************************************************** - - FileName [sswAig.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Inductive prover with constraints.] - - Synopsis [AIG manipulation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 1, 2008.] - - Revision [$Id: sswAig.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "sswInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the SAT manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ssw_Frm_t * Ssw_FrmStart( Aig_Man_t * pAig ) -{ - Ssw_Frm_t * p; - p = ABC_ALLOC( Ssw_Frm_t, 1 ); - memset( p, 0, sizeof(Ssw_Frm_t) ); - p->pAig = pAig; - p->nObjs = Aig_ManObjNumMax( pAig ); - p->nFrames = 0; - p->pFrames = NULL; - p->vAig2Frm = Vec_PtrAlloc( 0 ); - Vec_PtrFill( p->vAig2Frm, 2 * p->nObjs, NULL ); - return p; -} - -/**Function************************************************************* - - Synopsis [Starts the SAT manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_FrmStop( Ssw_Frm_t * p ) -{ - if ( p->pFrames ) - Aig_ManStop( p->pFrames ); - Vec_PtrFree( p->vAig2Frm ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Performs speculative reduction for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Ssw_FramesConstrainNode( Ssw_Man_t * p, Aig_Man_t * pFrames, Aig_Man_t * pAig, Aig_Obj_t * pObj, int iFrame, int fTwoPos ) -{ - Aig_Obj_t * pObjNew, * pObjNew2, * pObjRepr, * pObjReprNew, * pMiter; - // skip nodes without representative - pObjRepr = Aig_ObjRepr(pAig, pObj); - if ( pObjRepr == NULL ) - return; - p->nConstrTotal++; - assert( pObjRepr->Id < pObj->Id ); - // get the new node - pObjNew = Ssw_ObjFrame( p, pObj, iFrame ); - // get the new node of the representative - pObjReprNew = Ssw_ObjFrame( p, pObjRepr, iFrame ); - // if this is the same node, no need to add constraints - if ( pObj->fPhase == pObjRepr->fPhase ) - { - assert( pObjNew != Aig_Not(pObjReprNew) ); - if ( pObjNew == pObjReprNew ) - return; - } - else - { - assert( pObjNew != pObjReprNew ); - if ( pObjNew == Aig_Not(pObjReprNew) ) - return; - } - p->nConstrReduced++; - // these are different nodes - perform speculative reduction - pObjNew2 = Aig_NotCond( pObjReprNew, pObj->fPhase ^ pObjRepr->fPhase ); - // set the new node - Ssw_ObjSetFrame( p, pObj, iFrame, pObjNew2 ); - // add the constraint - if ( fTwoPos ) - { - Aig_ObjCreatePo( pFrames, pObjNew2 ); - Aig_ObjCreatePo( pFrames, pObjNew ); - } - else - { - pMiter = Aig_Exor( pFrames, pObjNew, pObjNew2 ); - Aig_ObjCreatePo( pFrames, Aig_NotCond(pMiter, Aig_ObjPhaseReal(pMiter)) ); - } -} - -/**Function************************************************************* - - Synopsis [Prepares the inductive case with speculative reduction.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Ssw_FramesWithClasses( Ssw_Man_t * p ) -{ - Aig_Man_t * pFrames; - Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew; - int i, f, iLits; - assert( p->pFrames == NULL ); - assert( Aig_ManRegNum(p->pAig) > 0 ); - assert( Aig_ManRegNum(p->pAig) < Aig_ManPiNum(p->pAig) ); - p->nConstrTotal = p->nConstrReduced = 0; - - // start the fraig package - pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->nFrames ); - // create latches for the first frame - Saig_ManForEachLo( p->pAig, pObj, i ) - Ssw_ObjSetFrame( p, pObj, 0, Aig_ObjCreatePi(pFrames) ); - // add timeframes - iLits = 0; - for ( f = 0; f < p->pPars->nFramesK; f++ ) - { - // map constants and PIs - Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(pFrames) ); - Saig_ManForEachPi( p->pAig, pObj, i ) - { - pObjNew = Aig_ObjCreatePi(pFrames); - pObjNew->fPhase = (p->vInits != NULL) && Vec_IntEntry(p->vInits, iLits++); - Ssw_ObjSetFrame( p, pObj, f, pObjNew ); - } - // set the constraints on the latch outputs - Saig_ManForEachLo( p->pAig, pObj, i ) - Ssw_FramesConstrainNode( p, pFrames, p->pAig, pObj, f, 1 ); - // add internal nodes of this frame - Aig_ManForEachNode( p->pAig, pObj, i ) - { - pObjNew = Aig_And( pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); - Ssw_ObjSetFrame( p, pObj, f, pObjNew ); - Ssw_FramesConstrainNode( p, pFrames, p->pAig, pObj, f, 1 ); - } - // transfer to the primary outputs - Aig_ManForEachPo( p->pAig, pObj, i ) - Ssw_ObjSetFrame( p, pObj, f, Ssw_ObjChild0Fra(p, pObj,f) ); - // transfer latch input to the latch outputs - Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) - Ssw_ObjSetFrame( p, pObjLo, f+1, Ssw_ObjFrame(p, pObjLi,f) ); - } - assert( p->vInits == NULL || Vec_IntSize(p->vInits) == iLits + Saig_ManPiNum(p->pAig) ); - // add the POs for the latch outputs of the last frame - Saig_ManForEachLo( p->pAig, pObj, i ) - Aig_ObjCreatePo( pFrames, Ssw_ObjFrame( p, pObj, p->pPars->nFramesK ) ); - - // remove dangling nodes - Aig_ManCleanup( pFrames ); - // make sure the satisfying assignment is node assigned - assert( pFrames->pData == NULL ); -//Aig_ManShow( pFrames, 0, NULL ); - return pFrames; -} - -/**Function************************************************************* - - Synopsis [Prepares the inductive case with speculative reduction.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Ssw_SpeculativeReduction( Ssw_Man_t * p ) -{ - Aig_Man_t * pFrames; - Aig_Obj_t * pObj, * pObjNew; - int i; - assert( p->pFrames == NULL ); - assert( Aig_ManRegNum(p->pAig) > 0 ); - assert( Aig_ManRegNum(p->pAig) < Aig_ManPiNum(p->pAig) ); - p->nConstrTotal = p->nConstrReduced = 0; - - // start the fraig package - pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->nFrames ); - pFrames->pName = Aig_UtilStrsav( p->pAig->pName ); - // map constants and PIs - Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), 0, Aig_ManConst1(pFrames) ); - Saig_ManForEachPi( p->pAig, pObj, i ) - Ssw_ObjSetFrame( p, pObj, 0, Aig_ObjCreatePi(pFrames) ); - // create latches for the first frame - Saig_ManForEachLo( p->pAig, pObj, i ) - Ssw_ObjSetFrame( p, pObj, 0, Aig_ObjCreatePi(pFrames) ); - // set the constraints on the latch outputs - Saig_ManForEachLo( p->pAig, pObj, i ) - Ssw_FramesConstrainNode( p, pFrames, p->pAig, pObj, 0, 0 ); - // add internal nodes of this frame - Aig_ManForEachNode( p->pAig, pObj, i ) - { - pObjNew = Aig_And( pFrames, Ssw_ObjChild0Fra(p, pObj, 0), Ssw_ObjChild1Fra(p, pObj, 0) ); - Ssw_ObjSetFrame( p, pObj, 0, pObjNew ); - Ssw_FramesConstrainNode( p, pFrames, p->pAig, pObj, 0, 0 ); - } - // add the POs for the latch outputs of the last frame - Saig_ManForEachLi( p->pAig, pObj, i ) - Aig_ObjCreatePo( pFrames, Ssw_ObjChild0Fra(p, pObj,0) ); - // remove dangling nodes - Aig_ManCleanup( pFrames ); - Aig_ManSetRegNum( pFrames, Aig_ManRegNum(p->pAig) ); -// printf( "SpecRed: Total constraints = %d. Reduced constraints = %d.\n", -// p->nConstrTotal, p->nConstrReduced ); - return pFrames; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ssw/sswBmc.c b/src/aig/ssw/sswBmc.c deleted file mode 100644 index d565d5d3..00000000 --- a/src/aig/ssw/sswBmc.c +++ /dev/null @@ -1,224 +0,0 @@ -/**CFile**************************************************************** - - FileName [sswBmc.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Inductive prover with constraints.] - - Synopsis [Bounded model checker using dynamic unrolling.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 1, 2008.] - - Revision [$Id: sswBmc.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "sswInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Incrementally unroll the timeframes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Ssw_BmcUnroll_rec( Ssw_Frm_t * pFrm, Aig_Obj_t * pObj, int f ) -{ - Aig_Obj_t * pRes, * pRes0, * pRes1; - if ( (pRes = Ssw_ObjFrame_(pFrm, pObj, f)) ) - return pRes; - if ( Aig_ObjIsConst1(pObj) ) - pRes = Aig_ManConst1( pFrm->pFrames ); - else if ( Saig_ObjIsPi(pFrm->pAig, pObj) ) - pRes = Aig_ObjCreatePi( pFrm->pFrames ); - else if ( Aig_ObjIsPo(pObj) ) - { - Ssw_BmcUnroll_rec( pFrm, Aig_ObjFanin0(pObj), f ); - pRes = Ssw_ObjChild0Fra_( pFrm, pObj, f ); - } - else if ( Saig_ObjIsLo(pFrm->pAig, pObj) ) - { - if ( f == 0 ) - pRes = Aig_ManConst0( pFrm->pFrames ); - else - pRes = Ssw_BmcUnroll_rec( pFrm, Saig_ObjLoToLi(pFrm->pAig, pObj), f-1 ); - } - else - { - assert( Aig_ObjIsNode(pObj) ); - Ssw_BmcUnroll_rec( pFrm, Aig_ObjFanin0(pObj), f ); - Ssw_BmcUnroll_rec( pFrm, Aig_ObjFanin1(pObj), f ); - pRes0 = Ssw_ObjChild0Fra_( pFrm, pObj, f ); - pRes1 = Ssw_ObjChild1Fra_( pFrm, pObj, f ); - pRes = Aig_And( pFrm->pFrames, pRes0, pRes1 ); - } - Ssw_ObjSetFrame_( pFrm, pObj, f, pRes ); - return pRes; -} - -/**Function************************************************************* - - Synopsis [Derives counter-example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Cex_t * Ssw_BmcGetCounterExample( Ssw_Frm_t * pFrm, Ssw_Sat_t * pSat, int iPo, int iFrame ) -{ - Abc_Cex_t * pCex; - Aig_Obj_t * pObj, * pObjFrames; - int f, i, nShift; - assert( Saig_ManRegNum(pFrm->pAig) > 0 ); - // allocate the counter example - pCex = Abc_CexAlloc( Saig_ManRegNum(pFrm->pAig), Saig_ManPiNum(pFrm->pAig), iFrame + 1 ); - pCex->iPo = iPo; - pCex->iFrame = iFrame; - // create data-bits - nShift = Saig_ManRegNum(pFrm->pAig); - for ( f = 0; f <= iFrame; f++, nShift += Saig_ManPiNum(pFrm->pAig) ) - Saig_ManForEachPi( pFrm->pAig, pObj, i ) - { - pObjFrames = Ssw_ObjFrame_(pFrm, pObj, f); - if ( pObjFrames == NULL ) - continue; - if ( Ssw_CnfGetNodeValue( pSat, pObjFrames ) ) - Aig_InfoSetBit( pCex->pData, nShift + i ); - } - return pCex; -} - - -/**Function************************************************************* - - Synopsis [Performs BMC for the given AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_BmcDynamic( Aig_Man_t * pAig, int nFramesMax, int nConfLimit, int fVerbose, int * piFrame ) -{ - Ssw_Frm_t * pFrm; - Ssw_Sat_t * pSat; - Aig_Obj_t * pObj, * pObjFrame; - int status, clkPart, Lit, i, f, RetValue; - - // start managers - assert( Saig_ManRegNum(pAig) > 0 ); - Aig_ManSetPioNumbers( pAig ); - pSat = Ssw_SatStart( 0 ); - pFrm = Ssw_FrmStart( pAig ); - pFrm->pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * 3 ); - // report statistics - if ( fVerbose ) - { - printf( "AIG: PI/PO/Reg = %d/%d/%d. Node = %6d. Lev = %5d.\n", - Saig_ManPiNum(pAig), Saig_ManPoNum(pAig), Saig_ManRegNum(pAig), - Aig_ManNodeNum(pAig), Aig_ManLevelNum(pAig) ); - fflush( stdout ); - } - // perform dynamic unrolling - RetValue = -1; - for ( f = 0; f < nFramesMax; f++ ) - { - clkPart = clock(); - Saig_ManForEachPo( pAig, pObj, i ) - { - // unroll the circuit for this output - Ssw_BmcUnroll_rec( pFrm, pObj, f ); - pObjFrame = Ssw_ObjFrame_( pFrm, pObj, f ); - Ssw_CnfNodeAddToSolver( pSat, Aig_Regular(pObjFrame) ); - status = sat_solver_simplify(pSat->pSat); - assert( status ); - // solve - Lit = toLitCond( Ssw_ObjSatNum(pSat,pObjFrame), Aig_IsComplement(pObjFrame) ); - if ( fVerbose ) - { - printf( "Solving output %2d of frame %3d ... \r", - i % Saig_ManPoNum(pAig), i / Saig_ManPoNum(pAig) ); - } - status = sat_solver_solve( pSat->pSat, &Lit, &Lit + 1, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); - if ( status == l_False ) - { -/* - Lit = lit_neg( Lit ); - RetValue = sat_solver_addclause( pSat->pSat, &Lit, &Lit + 1 ); - assert( RetValue ); - if ( pSat->pSat->qtail != pSat->pSat->qhead ) - { - RetValue = sat_solver_simplify(pSat->pSat); - assert( RetValue ); - } -*/ - RetValue = 1; - continue; - } - else if ( status == l_True ) - { - pAig->pSeqModel = Ssw_BmcGetCounterExample( pFrm, pSat, i, f ); - if ( piFrame ) - *piFrame = f; - RetValue = 0; - break; - } - else - { - if ( piFrame ) - *piFrame = f; - RetValue = -1; - break; - } - } - if ( fVerbose ) - { - printf( "Solved %2d outputs of frame %3d. ", Saig_ManPoNum(pAig), f ); - printf( "Conf =%8.0f. Var =%8d. AIG=%9d. ", - (double)pSat->pSat->stats.conflicts, - pSat->nSatVars, Aig_ManNodeNum(pFrm->pFrames) ); - ABC_PRT( "T", clock() - clkPart ); - clkPart = clock(); - fflush( stdout ); - } - if ( RetValue != 1 ) - break; - } - - Ssw_SatStop( pSat ); - Ssw_FrmStop( pFrm ); - return RetValue; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ssw/sswClass.c b/src/aig/ssw/sswClass.c deleted file mode 100644 index 51514f47..00000000 --- a/src/aig/ssw/sswClass.c +++ /dev/null @@ -1,1170 +0,0 @@ -/**CFile**************************************************************** - - FileName [sswClass.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Inductive prover with constraints.] - - Synopsis [Representation of candidate equivalence classes.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 1, 2008.] - - Revision [$Id: sswClass.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "sswInt.h" - -ABC_NAMESPACE_IMPL_START - - -/* - 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 topo order of their representatives. -*/ - -// internal representation of candidate equivalence classes -struct Ssw_Cla_t_ -{ - // class information - Aig_Man_t * pAig; // original AIG manager - Aig_Obj_t *** pId2Class; // non-const classes by ID of repr node - int * pClassSizes; // sizes of each equivalence class - int fConstCorr; - // statistics - int nClasses; // the total number of non-const classes - int nCands1; // the total number of const candidates - int nLits; // the number of literals in all classes - // memory - Aig_Obj_t ** pMemClasses; // memory allocated for equivalence classes - Aig_Obj_t ** pMemClassesFree; // memory allocated for equivalence classes to be used - // temporary data - Vec_Ptr_t * vClassOld; // old equivalence class after splitting - Vec_Ptr_t * vClassNew; // new equivalence class(es) after splitting - Vec_Ptr_t * vRefined; // the nodes refined since the last iteration - // procedures used for class refinement - void * pManData; - unsigned (*pFuncNodeHash) (void *,Aig_Obj_t *); // returns hash key of the node - int (*pFuncNodeIsConst) (void *,Aig_Obj_t *); // returns 1 if the node is a constant - int (*pFuncNodesAreEqual) (void *,Aig_Obj_t *, Aig_Obj_t *); // returns 1 if nodes are equal up to a complement -}; - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline Aig_Obj_t * Ssw_ObjNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj ) { return ppNexts[pObj->Id]; } -static inline void Ssw_ObjSetNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { ppNexts[pObj->Id] = pNext; } - -// iterator through the equivalence classes -#define Ssw_ManForEachClass( p, ppClass, i ) \ - for ( i = 0; i < Aig_ManObjNumMax(p->pAig); i++ ) \ - if ( ((ppClass) = p->pId2Class[i]) == NULL ) {} else -// iterator through the nodes in one class -#define Ssw_ClassForEachNode( p, pRepr, pNode, i ) \ - for ( i = 0; i < p->pClassSizes[pRepr->Id]; i++ ) \ - if ( ((pNode) = p->pId2Class[pRepr->Id][i]) == NULL ) {} else - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates one equivalence class.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Ssw_ObjAddClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, Aig_Obj_t ** pClass, int nSize ) -{ - assert( p->pId2Class[pRepr->Id] == NULL ); - assert( pClass[0] == pRepr ); - p->pId2Class[pRepr->Id] = pClass; - assert( p->pClassSizes[pRepr->Id] == 0 ); - assert( nSize > 1 ); - p->pClassSizes[pRepr->Id] = nSize; - p->nClasses++; - p->nLits += nSize - 1; -} - -/**Function************************************************************* - - Synopsis [Removes one equivalence class.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Aig_Obj_t ** Ssw_ObjRemoveClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr ) -{ - Aig_Obj_t ** pClass = p->pId2Class[pRepr->Id]; - int nSize; - assert( pClass != NULL ); - p->pId2Class[pRepr->Id] = NULL; - nSize = p->pClassSizes[pRepr->Id]; - assert( nSize > 1 ); - p->nClasses--; - p->nLits -= nSize - 1; - p->pClassSizes[pRepr->Id] = 0; - return pClass; -} - -/**Function************************************************************* - - Synopsis [Starts representation of equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ssw_Cla_t * Ssw_ClassesStart( Aig_Man_t * pAig ) -{ - Ssw_Cla_t * p; - p = ABC_ALLOC( Ssw_Cla_t, 1 ); - memset( p, 0, sizeof(Ssw_Cla_t) ); - p->pAig = pAig; - p->pId2Class = ABC_CALLOC( Aig_Obj_t **, Aig_ManObjNumMax(pAig) ); - p->pClassSizes = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); - p->vClassOld = Vec_PtrAlloc( 100 ); - p->vClassNew = Vec_PtrAlloc( 100 ); - p->vRefined = Vec_PtrAlloc( 1000 ); - if ( pAig->pReprs == NULL ) - Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) ); - return p; -} - -/**Function************************************************************* - - Synopsis [Starts representation of equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ClassesSetData( Ssw_Cla_t * p, void * pManData, - unsigned (*pFuncNodeHash)(void *,Aig_Obj_t *), // returns hash key of the node - int (*pFuncNodeIsConst)(void *,Aig_Obj_t *), // returns 1 if the node is a constant - int (*pFuncNodesAreEqual)(void *,Aig_Obj_t *, Aig_Obj_t *) ) // returns 1 if nodes are equal up to a complement -{ - p->pManData = pManData; - p->pFuncNodeHash = pFuncNodeHash; - p->pFuncNodeIsConst = pFuncNodeIsConst; - p->pFuncNodesAreEqual = pFuncNodesAreEqual; -} - -/**Function************************************************************* - - Synopsis [Stop representation of equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ClassesStop( Ssw_Cla_t * p ) -{ - if ( p->vClassNew ) Vec_PtrFree( p->vClassNew ); - if ( p->vClassOld ) Vec_PtrFree( p->vClassOld ); - Vec_PtrFree( p->vRefined ); - ABC_FREE( p->pId2Class ); - ABC_FREE( p->pClassSizes ); - ABC_FREE( p->pMemClasses ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Stop representation of equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Ssw_ClassesReadAig( Ssw_Cla_t * p ) -{ - return p->pAig; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Ssw_ClassesGetRefined( Ssw_Cla_t * p ) -{ - return p->vRefined; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ClassesClearRefined( Ssw_Cla_t * p ) -{ - Vec_PtrClear( p->vRefined ); -} - -/**Function************************************************************* - - Synopsis [Stop representation of equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ClassesCand1Num( Ssw_Cla_t * p ) -{ - return p->nCands1; -} - -/**Function************************************************************* - - Synopsis [Stop representation of equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ClassesClassNum( Ssw_Cla_t * p ) -{ - return p->nClasses; -} - -/**Function************************************************************* - - Synopsis [Stop representation of equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ClassesLitNum( Ssw_Cla_t * p ) -{ - return p->nLits; -} - -/**Function************************************************************* - - Synopsis [Stop representation of equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t ** Ssw_ClassesReadClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, int * pnSize ) -{ - if ( p->pId2Class[pRepr->Id] == NULL ) - return NULL; - assert( p->pId2Class[pRepr->Id] != NULL ); - assert( p->pClassSizes[pRepr->Id] > 1 ); - *pnSize = p->pClassSizes[pRepr->Id]; - return p->pId2Class[pRepr->Id]; -} - -/**Function************************************************************* - - Synopsis [Stop representation of equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ClassesCollectClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, Vec_Ptr_t * vClass ) -{ - int i; - Vec_PtrClear( vClass ); - if ( p->pId2Class[pRepr->Id] == NULL ) - return; - assert( p->pClassSizes[pRepr->Id] > 1 ); - for ( i = 1; i < p->pClassSizes[pRepr->Id]; i++ ) - Vec_PtrPush( vClass, p->pId2Class[pRepr->Id][i] ); -} - -/**Function************************************************************* - - Synopsis [Checks candidate equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ClassesCheck( Ssw_Cla_t * p ) -{ - Aig_Obj_t * pObj, * pPrev, ** ppClass; - int i, k, nLits, nClasses, nCands1; - nClasses = nLits = 0; - Ssw_ManForEachClass( p, ppClass, k ) - { - pPrev = NULL; - assert( p->pClassSizes[ppClass[0]->Id] >= 2 ); - Ssw_ClassForEachNode( p, ppClass[0], pObj, i ) - { - if ( i == 0 ) - assert( Aig_ObjRepr(p->pAig, pObj) == NULL ); - else - { - assert( Aig_ObjRepr(p->pAig, pObj) == ppClass[0] ); - assert( pPrev->Id < pObj->Id ); - nLits++; - } - pPrev = pObj; - } - nClasses++; - } - nCands1 = 0; - Aig_ManForEachObj( p->pAig, pObj, i ) - nCands1 += Ssw_ObjIsConst1Cand( p->pAig, pObj ); - assert( p->nLits == nLits ); - assert( p->nCands1 == nCands1 ); - assert( p->nClasses == nClasses ); -} - -/**Function************************************************************* - - Synopsis [Prints simulation classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ClassesPrintOne( Ssw_Cla_t * p, Aig_Obj_t * pRepr ) -{ - Aig_Obj_t * pObj; - int i; - printf( "{ " ); - Ssw_ClassForEachNode( p, pRepr, pObj, i ) - printf( "%d(%d,%d,%d) ", pObj->Id, pObj->Level, - Aig_SupportSize(p->pAig,pObj), Aig_NodeMffcSupp(p->pAig,pObj,0,NULL) ); - printf( "}\n" ); -} - -/**Function************************************************************* - - Synopsis [Prints simulation classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ClassesPrint( Ssw_Cla_t * p, int fVeryVerbose ) -{ - Aig_Obj_t ** ppClass; - Aig_Obj_t * pObj; - int i; - printf( "Equiv classes: Const1 = %5d. Class = %5d. Lit = %5d.\n", - p->nCands1, p->nClasses, p->nCands1+p->nLits ); - if ( !fVeryVerbose ) - return; - printf( "Constants { " ); - Aig_ManForEachObj( p->pAig, pObj, i ) - if ( Ssw_ObjIsConst1Cand( p->pAig, pObj ) ) - printf( "%d(%d,%d,%d) ", pObj->Id, pObj->Level, - Aig_SupportSize(p->pAig,pObj), Aig_NodeMffcSupp(p->pAig,pObj,0,NULL) ); - printf( "}\n" ); - Ssw_ManForEachClass( p, ppClass, i ) - { - printf( "%3d (%3d) : ", i, p->pClassSizes[i] ); - Ssw_ClassesPrintOne( p, ppClass[0] ); - } - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Prints simulation classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ClassesRemoveNode( Ssw_Cla_t * p, Aig_Obj_t * pObj ) -{ - Aig_Obj_t * pRepr, * pTemp; - assert( p->pClassSizes[pObj->Id] == 0 ); - assert( p->pId2Class[pObj->Id] == NULL ); - pRepr = Aig_ObjRepr( p->pAig, pObj ); - assert( pRepr != NULL ); -// Vec_PtrPush( p->vRefined, pObj ); - if ( Ssw_ObjIsConst1Cand( p->pAig, pObj ) ) - { - assert( p->pClassSizes[pRepr->Id] == 0 ); - assert( p->pId2Class[pRepr->Id] == NULL ); - Aig_ObjSetRepr( p->pAig, pObj, NULL ); - p->nCands1--; - return; - } -// Vec_PtrPush( p->vRefined, pRepr ); - Aig_ObjSetRepr( p->pAig, pObj, NULL ); - assert( p->pId2Class[pRepr->Id][0] == pRepr ); - assert( p->pClassSizes[pRepr->Id] >= 2 ); - if ( p->pClassSizes[pRepr->Id] == 2 ) - { - p->pId2Class[pRepr->Id] = NULL; - p->nClasses--; - p->pClassSizes[pRepr->Id] = 0; - p->nLits--; - } - else - { - int i, k = 0; - // remove the entry from the class - Ssw_ClassForEachNode( p, pRepr, pTemp, i ) - if ( pTemp != pObj ) - p->pId2Class[pRepr->Id][k++] = pTemp; - assert( k + 1 == p->pClassSizes[pRepr->Id] ); - // reduce the class - p->pClassSizes[pRepr->Id]--; - p->nLits--; - } -} - -/**Function************************************************************* - - Synopsis [Takes the set of const1 cands and rehashes them using sim info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ClassesPrepareRehash( Ssw_Cla_t * p, Vec_Ptr_t * vCands, int fConstCorr ) -{ - Aig_Man_t * pAig = p->pAig; - Aig_Obj_t ** ppTable, ** ppNexts, ** ppClassNew; - Aig_Obj_t * pObj, * pTemp, * pRepr; - int i, k, nTableSize, nNodes, iEntry, nEntries, nEntries2; - - // allocate the hash table hashing simulation info into nodes - nTableSize = Aig_PrimeCudd( Vec_PtrSize(vCands)/2 ); - ppTable = ABC_CALLOC( Aig_Obj_t *, nTableSize ); - ppNexts = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) ); - - // sort through the candidates - nEntries = 0; - p->nCands1 = 0; - Vec_PtrForEachEntry( Aig_Obj_t *, vCands, pObj, i ) - { - assert( p->pClassSizes[pObj->Id] == 0 ); - Aig_ObjSetRepr( p->pAig, pObj, NULL ); - // check if the node belongs to the class of constant 1 - if ( p->pFuncNodeIsConst( p->pManData, pObj ) ) - { - Ssw_ObjSetConst1Cand( p->pAig, pObj ); - p->nCands1++; - continue; - } - if ( fConstCorr ) - continue; - // hash the node by its simulation info - iEntry = p->pFuncNodeHash( p->pManData, pObj ) % nTableSize; - // add the node to the class - if ( ppTable[iEntry] == NULL ) - { - ppTable[iEntry] = pObj; - } - else - { - // set the representative of this node - pRepr = ppTable[iEntry]; - Aig_ObjSetRepr( p->pAig, pObj, pRepr ); - // add node to the table - if ( Ssw_ObjNext( ppNexts, pRepr ) == NULL ) - { // this will be the second entry - p->pClassSizes[pRepr->Id]++; - nEntries++; - } - // add the entry to the list - Ssw_ObjSetNext( ppNexts, pObj, Ssw_ObjNext( ppNexts, pRepr ) ); - Ssw_ObjSetNext( ppNexts, pRepr, pObj ); - p->pClassSizes[pRepr->Id]++; - nEntries++; - } - } - - // copy the entries into storage in the topological order - nEntries2 = 0; - Vec_PtrForEachEntry( Aig_Obj_t *, vCands, pObj, i ) - { - nNodes = p->pClassSizes[pObj->Id]; - // skip the nodes that are not representatives of non-trivial classes - if ( nNodes == 0 ) - continue; - assert( nNodes > 1 ); - // add the nodes to the class in the topological order - ppClassNew = p->pMemClassesFree + nEntries2; - ppClassNew[0] = pObj; - for ( pTemp = Ssw_ObjNext(ppNexts, pObj), k = 1; pTemp; - pTemp = Ssw_ObjNext(ppNexts, pTemp), k++ ) - { - ppClassNew[nNodes-k] = pTemp; - } - // add the class of nodes - p->pClassSizes[pObj->Id] = 0; - Ssw_ObjAddClass( p, pObj, ppClassNew, nNodes ); - // increment the number of entries - nEntries2 += nNodes; - } - p->pMemClassesFree += nEntries2; - assert( nEntries == nEntries2 ); - ABC_FREE( ppTable ); - ABC_FREE( ppNexts ); - // now it is time to refine the classes - return Ssw_ClassesRefine( p, 1 ); -} - -/**Function************************************************************* - - Synopsis [Creates initial simulation classes.] - - Description [Assumes that simulation info is assigned.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ssw_Cla_t * Ssw_ClassesPrepare( Aig_Man_t * pAig, int nFramesK, int fLatchCorr, int fConstCorr, int fOutputCorr, int nMaxLevs, int fVerbose ) -{ -// int nFrames = 4; -// int nWords = 1; -// int nIters = 16; - -// int nFrames = 32; -// int nWords = 4; -// int nIters = 0; - - int nFrames = ABC_MAX( nFramesK, 4 ); - int nWords = 2; - int nIters = 16; - Ssw_Cla_t * p; - Ssw_Sml_t * pSml; - Vec_Ptr_t * vCands; - Aig_Obj_t * pObj; - int i, k, RetValue, clk; - - // start the classes - p = Ssw_ClassesStart( pAig ); - p->fConstCorr = fConstCorr; - - // perform sequential simulation -clk = clock(); - pSml = Ssw_SmlSimulateSeq( pAig, 0, nFrames, nWords ); -if ( fVerbose ) -{ - printf( "Allocated %.2f Mb to store simulation information.\n", - 1.0*(sizeof(unsigned) * Aig_ManObjNumMax(pAig) * nFrames * nWords)/(1<<20) ); - printf( "Initial simulation of %d frames with %d words. ", nFrames, nWords ); - ABC_PRT( "Time", clock() - clk ); -} - - // set comparison procedures -clk = clock(); - Ssw_ClassesSetData( p, pSml, (unsigned(*)(void *,Aig_Obj_t *))Ssw_SmlObjHashWord, (int(*)(void *,Aig_Obj_t *))Ssw_SmlObjIsConstWord, (int(*)(void *,Aig_Obj_t *,Aig_Obj_t *))Ssw_SmlObjsAreEqualWord ); - - // collect nodes to be considered as candidates - vCands = Vec_PtrAlloc( 1000 ); - Aig_ManForEachObj( p->pAig, pObj, i ) - { - if ( fLatchCorr ) - { - if ( !Saig_ObjIsLo(p->pAig, 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; - } - Vec_PtrPush( vCands, pObj ); - } - - // this change will consider all PO drivers - if ( fOutputCorr ) - { - Vec_PtrClear( vCands ); - Aig_ManForEachObj( p->pAig, pObj, i ) - pObj->fMarkB = 0; - Saig_ManForEachPo( p->pAig, pObj, i ) - if ( Aig_ObjIsCand(Aig_ObjFanin0(pObj)) ) - Aig_ObjFanin0(pObj)->fMarkB = 1; - Aig_ManForEachObj( p->pAig, pObj, i ) - if ( pObj->fMarkB ) - Vec_PtrPush( vCands, pObj ); - Aig_ManForEachObj( p->pAig, pObj, i ) - pObj->fMarkB = 0; - } - - // allocate room for classes - p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, Vec_PtrSize(vCands) ); - p->pMemClassesFree = p->pMemClasses; - - // now it is time to refine the classes - Ssw_ClassesPrepareRehash( p, vCands, fConstCorr ); -if ( fVerbose ) -{ - printf( "Collecting candidate equivalence classes. " ); -ABC_PRT( "Time", clock() - clk ); -} - -clk = clock(); - // perform iterative refinement using simulation - for ( i = 1; i < nIters; i++ ) - { - // collect const1 candidates - Vec_PtrClear( vCands ); - Aig_ManForEachObj( p->pAig, pObj, k ) - if ( Ssw_ObjIsConst1Cand( p->pAig, pObj ) ) - Vec_PtrPush( vCands, pObj ); - assert( Vec_PtrSize(vCands) == p->nCands1 ); - // perform new round of simulation - Ssw_SmlResimulateSeq( pSml ); - // check equivalence classes - RetValue = Ssw_ClassesPrepareRehash( p, vCands, fConstCorr ); - if ( RetValue == 0 ) - break; - } - Ssw_SmlStop( pSml ); - Vec_PtrFree( vCands ); -if ( fVerbose ) -{ - printf( "Simulation of %d frames with %d words (%2d rounds). ", - nFrames, nWords, i-1 ); - ABC_PRT( "Time", clock() - clk ); -} - Ssw_ClassesCheck( p ); -// Ssw_ClassesPrint( p, 0 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Creates initial simulation classes.] - - Description [Assumes that simulation info is assigned.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ssw_Cla_t * Ssw_ClassesPrepareSimple( Aig_Man_t * pAig, int fLatchCorr, int nMaxLevs ) -{ - Ssw_Cla_t * p; - Aig_Obj_t * pObj; - int i; - // start the classes - p = Ssw_ClassesStart( pAig ); - // go through the nodes - p->nCands1 = 0; - Aig_ManForEachObj( pAig, pObj, i ) - { - if ( fLatchCorr ) - { - if ( !Saig_ObjIsLo(pAig, pObj) ) - continue; - } - else - { - if ( !Aig_ObjIsNode(pObj) && !Saig_ObjIsLo(pAig, pObj) ) - continue; - // skip the node with more that the given number of levels - if ( nMaxLevs && (int)pObj->Level > nMaxLevs ) - continue; - } - Ssw_ObjSetConst1Cand( pAig, pObj ); - p->nCands1++; - } - // allocate room for classes - p->pMemClassesFree = p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, p->nCands1 ); -// Ssw_ClassesPrint( p, 0 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Creates initial simulation classes.] - - Description [Assumes that simulation info is assigned.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ssw_Cla_t * Ssw_ClassesPrepareFromReprs( Aig_Man_t * pAig ) -{ - Ssw_Cla_t * p; - Aig_Obj_t * pObj, * pRepr; - int * pClassSizes, nEntries, i; - // start the classes - p = Ssw_ClassesStart( pAig ); - // allocate memory for classes - p->pMemClasses = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) ); - // count classes - p->nCands1 = 0; - Aig_ManForEachObj( pAig, pObj, i ) - { - if ( Ssw_ObjIsConst1Cand(pAig, pObj) ) - { - p->nCands1++; - continue; - } - if ( (pRepr = Aig_ObjRepr(pAig, pObj)) ) - { - if ( p->pClassSizes[pRepr->Id]++ == 0 ) - p->pClassSizes[pRepr->Id]++; - } - } - // add nodes - nEntries = 0; - p->nClasses = 0; - pClassSizes = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); - Aig_ManForEachObj( pAig, pObj, i ) - { - if ( p->pClassSizes[i] ) - { - p->pId2Class[i] = p->pMemClasses + nEntries; - nEntries += p->pClassSizes[i]; - p->pId2Class[i][pClassSizes[i]++] = pObj; - p->nClasses++; - continue; - } - if ( Ssw_ObjIsConst1Cand(pAig, pObj) ) - continue; - if ( (pRepr = Aig_ObjRepr(pAig, pObj)) ) - p->pId2Class[pRepr->Id][pClassSizes[pRepr->Id]++] = pObj; - } - p->pMemClassesFree = p->pMemClasses + nEntries; - p->nLits = nEntries - p->nClasses; - assert( memcmp(pClassSizes, p->pClassSizes, sizeof(int)*Aig_ManObjNumMax(pAig)) == 0 ); - ABC_FREE( pClassSizes ); -// printf( "After converting:\n" ); -// Ssw_ClassesPrint( p, 0 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Creates initial simulation classes.] - - Description [Assumes that simulation info is assigned.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ssw_Cla_t * Ssw_ClassesPrepareTargets( Aig_Man_t * pAig ) -{ - Ssw_Cla_t * p; - Aig_Obj_t * pObj; - int i; - // start the classes - p = Ssw_ClassesStart( pAig ); - // go through the nodes - p->nCands1 = 0; - Saig_ManForEachPo( pAig, pObj, i ) - { - Ssw_ObjSetConst1Cand( pAig, Aig_ObjFanin0(pObj) ); - p->nCands1++; - } - // allocate room for classes - p->pMemClassesFree = p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, p->nCands1 ); -// Ssw_ClassesPrint( p, 0 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Creates classes from the temporary representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ssw_Cla_t * Ssw_ClassesPreparePairs( Aig_Man_t * pAig, Vec_Int_t ** pvClasses ) -{ - Ssw_Cla_t * p; - Aig_Obj_t ** ppClassNew; - Aig_Obj_t * pObj, * pRepr, * pPrev; - int i, k, nTotalObjs, nEntries, Entry; - // start the classes - p = Ssw_ClassesStart( pAig ); - // count the number of entries in the classes - nTotalObjs = 0; - for ( i = 0; i < Aig_ManObjNumMax(pAig); i++ ) - nTotalObjs += pvClasses[i] ? Vec_IntSize(pvClasses[i]) : 0; - // allocate memory for classes - p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, nTotalObjs ); - // create constant-1 class - if ( pvClasses[0] ) - Vec_IntForEachEntry( pvClasses[0], Entry, i ) - { - assert( (i == 0) == (Entry == 0) ); - if ( i == 0 ) - continue; - pObj = Aig_ManObj( pAig, Entry ); - Ssw_ObjSetConst1Cand( pAig, pObj ); - p->nCands1++; - } - // create classes - nEntries = 0; - for ( i = 1; i < Aig_ManObjNumMax(pAig); i++ ) - { - if ( pvClasses[i] == NULL ) - continue; - // get room for storing the class - ppClassNew = p->pMemClasses + nEntries; - nEntries += Vec_IntSize( pvClasses[i] ); - // store the nodes of the class - pPrev = pRepr = Aig_ManObj( pAig, Vec_IntEntry(pvClasses[i],0) ); - ppClassNew[0] = pRepr; - Vec_IntForEachEntryStart( pvClasses[i], Entry, k, 1 ) - { - pObj = Aig_ManObj( pAig, Entry ); - assert( pPrev->Id < pObj->Id ); - pPrev = pObj; - ppClassNew[k] = pObj; - Aig_ObjSetRepr( pAig, pObj, pRepr ); - } - // create new class - Ssw_ObjAddClass( p, pRepr, ppClassNew, Vec_IntSize(pvClasses[i]) ); - } - // prepare room for new classes - p->pMemClassesFree = p->pMemClasses + nEntries; - Ssw_ClassesCheck( p ); -// Ssw_ClassesPrint( p, 0 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Creates classes from the temporary representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ssw_Cla_t * Ssw_ClassesPreparePairsSimple( Aig_Man_t * pMiter, Vec_Int_t * vPairs ) -{ - Ssw_Cla_t * p; - Aig_Obj_t ** ppClassNew; - Aig_Obj_t * pObj, * pRepr; - int i; - // start the classes - p = Ssw_ClassesStart( pMiter ); - // allocate memory for classes - p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, Vec_IntSize(vPairs) ); - // create classes - for ( i = 0; i < Vec_IntSize(vPairs); i += 2 ) - { - pRepr = Aig_ManObj( pMiter, Vec_IntEntry(vPairs, i) ); - pObj = Aig_ManObj( pMiter, Vec_IntEntry(vPairs, i+1) ); - assert( Aig_ObjId(pRepr) < Aig_ObjId(pObj) ); - Aig_ObjSetRepr( pMiter, pObj, pRepr ); - // get room for storing the class - ppClassNew = p->pMemClasses + i; - ppClassNew[0] = pRepr; - ppClassNew[1] = pObj; - // create new class - Ssw_ObjAddClass( p, pRepr, ppClassNew, 2 ); - } - // prepare room for new classes - p->pMemClassesFree = NULL; - Ssw_ClassesCheck( p ); -// Ssw_ClassesPrint( p, 0 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Iteratively refines the classes after simulation.] - - Description [Returns the number of refinements performed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ClassesRefineOneClass( Ssw_Cla_t * p, Aig_Obj_t * pReprOld, int fRecursive ) -{ - Aig_Obj_t ** pClassOld, ** pClassNew; - Aig_Obj_t * pObj, * pReprNew; - int i; - - // split the class - Vec_PtrClear( p->vClassOld ); - Vec_PtrClear( p->vClassNew ); - Ssw_ClassForEachNode( p, pReprOld, pObj, i ) - if ( p->pFuncNodesAreEqual(p->pManData, pReprOld, pObj) ) - Vec_PtrPush( p->vClassOld, pObj ); - else - Vec_PtrPush( p->vClassNew, pObj ); - // check if splitting happened - if ( Vec_PtrSize(p->vClassNew) == 0 ) - return 0; - // remember that this class is refined -// Ssw_ClassForEachNode( p, pReprOld, pObj, i ) -// Vec_PtrPush( p->vRefined, pObj ); - - // get the new representative - pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 ); - assert( Vec_PtrSize(p->vClassOld) > 0 ); - assert( Vec_PtrSize(p->vClassNew) > 0 ); - - // create old class - pClassOld = Ssw_ObjRemoveClass( p, pReprOld ); - Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassOld, pObj, i ) - { - pClassOld[i] = pObj; - Aig_ObjSetRepr( p->pAig, pObj, i? pReprOld : NULL ); - } - // create new class - pClassNew = pClassOld + i; - Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i ) - { - pClassNew[i] = pObj; - Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL ); - } - - // put classes back - if ( Vec_PtrSize(p->vClassOld) > 1 ) - Ssw_ObjAddClass( p, pReprOld, pClassOld, Vec_PtrSize(p->vClassOld) ); - if ( Vec_PtrSize(p->vClassNew) > 1 ) - Ssw_ObjAddClass( p, pReprNew, pClassNew, Vec_PtrSize(p->vClassNew) ); - - // check if the class should be recursively refined - if ( fRecursive && Vec_PtrSize(p->vClassNew) > 1 ) - return 1 + Ssw_ClassesRefineOneClass( p, pReprNew, 1 ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Refines the classes after simulation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ClassesRefine( Ssw_Cla_t * p, int fRecursive ) -{ - Aig_Obj_t ** ppClass; - int i, nRefis = 0; - Ssw_ManForEachClass( p, ppClass, i ) - nRefis += Ssw_ClassesRefineOneClass( p, ppClass[0], fRecursive ); - return nRefis; -} - -/**Function************************************************************* - - Synopsis [Refines the classes after simulation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ClassesRefineGroup( Ssw_Cla_t * p, Vec_Ptr_t * vReprs, int fRecursive ) -{ - Aig_Obj_t * pObj; - int i, nRefis = 0; - Vec_PtrForEachEntry( Aig_Obj_t *, vReprs, pObj, i ) - nRefis += Ssw_ClassesRefineOneClass( p, pObj, fRecursive ); - return nRefis; -} - -/**Function************************************************************* - - Synopsis [Refine the group of constant 1 nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ClassesRefineConst1Group( Ssw_Cla_t * p, Vec_Ptr_t * vRoots, int fRecursive ) -{ - Aig_Obj_t * pObj, * pReprNew, ** ppClassNew; - int i; - if ( Vec_PtrSize(vRoots) == 0 ) - return 0; - // collect the nodes to be refined - Vec_PtrClear( p->vClassNew ); - Vec_PtrForEachEntry( Aig_Obj_t *, vRoots, pObj, i ) - if ( !p->pFuncNodeIsConst( p->pManData, pObj ) ) - Vec_PtrPush( p->vClassNew, pObj ); - // check if there is a new class - if ( Vec_PtrSize(p->vClassNew) == 0 ) - return 0; - p->nCands1 -= Vec_PtrSize(p->vClassNew); - pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 ); - Aig_ObjSetRepr( p->pAig, pReprNew, NULL ); - if ( Vec_PtrSize(p->vClassNew) == 1 ) - return 1; - // create a new class composed of these nodes - ppClassNew = p->pMemClassesFree; - p->pMemClassesFree += Vec_PtrSize(p->vClassNew); - Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i ) - { - ppClassNew[i] = pObj; - Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL ); - } - Ssw_ObjAddClass( p, pReprNew, ppClassNew, Vec_PtrSize(p->vClassNew) ); - // refine them recursively - if ( fRecursive ) - return 1 + Ssw_ClassesRefineOneClass( p, pReprNew, 1 ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Refine the group of constant 1 nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ClassesRefineConst1( Ssw_Cla_t * p, int fRecursive ) -{ - Aig_Obj_t * pObj, * pReprNew, ** ppClassNew; - int i; - // collect the nodes to be refined - Vec_PtrClear( p->vClassNew ); - for ( i = 0; i < Vec_PtrSize(p->pAig->vObjs); i++ ) - if ( p->pAig->pReprs[i] == Aig_ManConst1(p->pAig) ) - { - pObj = Aig_ManObj( p->pAig, i ); - if ( !p->pFuncNodeIsConst( p->pManData, pObj ) ) - { - Vec_PtrPush( p->vClassNew, pObj ); -// Vec_PtrPush( p->vRefined, pObj ); - } - } - // check if there is a new class - if ( Vec_PtrSize(p->vClassNew) == 0 ) - return 0; - if ( p->fConstCorr ) - { - Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i ) - Aig_ObjSetRepr( p->pAig, pObj, NULL ); - return 1; - } - p->nCands1 -= Vec_PtrSize(p->vClassNew); - pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 ); - Aig_ObjSetRepr( p->pAig, pReprNew, NULL ); - if ( Vec_PtrSize(p->vClassNew) == 1 ) - return 1; - // create a new class composed of these nodes - ppClassNew = p->pMemClassesFree; - p->pMemClassesFree += Vec_PtrSize(p->vClassNew); - Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i ) - { - ppClassNew[i] = pObj; - Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL ); - } - Ssw_ObjAddClass( p, pReprNew, ppClassNew, Vec_PtrSize(p->vClassNew) ); - // refine them recursively - if ( fRecursive ) - return 1 + Ssw_ClassesRefineOneClass( p, pReprNew, 1 ); - return 1; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ssw/sswCnf.c b/src/aig/ssw/sswCnf.c deleted file mode 100644 index 1970c62f..00000000 --- a/src/aig/ssw/sswCnf.c +++ /dev/null @@ -1,428 +0,0 @@ -/**CFile**************************************************************** - - FileName [sswCnf.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Inductive prover with constraints.] - - Synopsis [Computation of CNF.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 1, 2008.] - - Revision [$Id: sswCnf.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "sswInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the SAT manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ssw_Sat_t * Ssw_SatStart( int fPolarFlip ) -{ - Ssw_Sat_t * p; - int Lit; - p = ABC_ALLOC( Ssw_Sat_t, 1 ); - memset( p, 0, sizeof(Ssw_Sat_t) ); - p->pAig = NULL; - p->fPolarFlip = fPolarFlip; - p->vSatVars = Vec_IntStart( 10000 ); - p->vFanins = Vec_PtrAlloc( 100 ); - p->vUsedPis = Vec_PtrAlloc( 100 ); - p->pSat = sat_solver_new(); - sat_solver_setnvars( p->pSat, 1000 ); - // var 0 is not used - // var 1 is reserved for const1 node - add the clause - p->nSatVars = 1; - Lit = toLit( p->nSatVars ); - if ( fPolarFlip ) - Lit = lit_neg( Lit ); - sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ); -// Ssw_ObjSetSatNum( p, Aig_ManConst1(p->pAig), p->nSatVars++ ); - Vec_IntWriteEntry( p->vSatVars, 0, p->nSatVars++ ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stop the SAT manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SatStop( Ssw_Sat_t * p ) -{ -// printf( "Recycling SAT solver with %d vars and %d restarts.\n", -// p->pSat->size, p->pSat->stats.starts ); - if ( p->pSat ) - sat_solver_delete( p->pSat ); - Vec_IntFree( p->vSatVars ); - Vec_PtrFree( p->vFanins ); - Vec_PtrFree( p->vUsedPis ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Addes clauses to the solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_AddClausesMux( Ssw_Sat_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 = Ssw_ObjSatNum(p,pNode); - VarI = Ssw_ObjSatNum(p,pNodeI); - VarT = Ssw_ObjSatNum(p,Aig_Regular(pNodeT)); - VarE = Ssw_ObjSatNum(p,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); - if ( p->fPolarFlip ) - { - if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); - if ( Aig_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] ); - if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); - } - 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); - if ( p->fPolarFlip ) - { - if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); - if ( Aig_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] ); - if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); - } - 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); - if ( p->fPolarFlip ) - { - if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); - if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); - if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); - } - 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); - if ( p->fPolarFlip ) - { - if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); - if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); - if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); - } - 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); - if ( p->fPolarFlip ) - { - if ( Aig_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] ); - if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); - if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); - } - 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); - if ( p->fPolarFlip ) - { - if ( Aig_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] ); - if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); - if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); - } - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); - assert( RetValue ); -} - -/**Function************************************************************* - - Synopsis [Addes clauses to the solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_AddClausesSuper( Ssw_Sat_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 = ABC_ALLOC( int, nLits ); - // suppose AND-gate is A & B = C - // add !A => !C or A + !C - Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i ) - { - pLits[0] = toLitCond(Ssw_ObjSatNum(p,Aig_Regular(pFanin)), Aig_IsComplement(pFanin)); - pLits[1] = toLitCond(Ssw_ObjSatNum(p,pNode), 1); - if ( p->fPolarFlip ) - { - if ( Aig_Regular(pFanin)->fPhase ) pLits[0] = lit_neg( pLits[0] ); - if ( pNode->fPhase ) pLits[1] = lit_neg( pLits[1] ); - } - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); - assert( RetValue ); - } - // add A & B => C or !A + !B + C - Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i ) - { - pLits[i] = toLitCond(Ssw_ObjSatNum(p,Aig_Regular(pFanin)), !Aig_IsComplement(pFanin)); - if ( p->fPolarFlip ) - { - if ( Aig_Regular(pFanin)->fPhase ) pLits[i] = lit_neg( pLits[i] ); - } - } - pLits[nLits-1] = toLitCond(Ssw_ObjSatNum(p,pNode), 0); - if ( p->fPolarFlip ) - { - if ( pNode->fPhase ) pLits[nLits-1] = lit_neg( pLits[nLits-1] ); - } - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits ); - assert( RetValue ); - ABC_FREE( pLits ); -} - -/**Function************************************************************* - - Synopsis [Collects the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_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; - } -// pObj->fMarkA = 1; - // go through the branches - Ssw_CollectSuper_rec( Aig_ObjChild0(pObj), vSuper, 0, fUseMuxes ); - Ssw_CollectSuper_rec( Aig_ObjChild1(pObj), vSuper, 0, fUseMuxes ); -} - -/**Function************************************************************* - - Synopsis [Collects the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_CollectSuper( Aig_Obj_t * pObj, int fUseMuxes, Vec_Ptr_t * vSuper ) -{ - assert( !Aig_IsComplement(pObj) ); - assert( !Aig_ObjIsPi(pObj) ); - Vec_PtrClear( vSuper ); - Ssw_CollectSuper_rec( pObj, vSuper, 1, fUseMuxes ); -} - -/**Function************************************************************* - - Synopsis [Updates the solver clause database.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ObjAddToFrontier( Ssw_Sat_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vFrontier ) -{ - assert( !Aig_IsComplement(pObj) ); - if ( Ssw_ObjSatNum(p,pObj) ) - return; - assert( Ssw_ObjSatNum(p,pObj) == 0 ); - if ( Aig_ObjIsConst1(pObj) ) - return; -// pObj->fMarkA = 1; - // save PIs (used by register correspondence) - if ( Aig_ObjIsPi(pObj) ) - Vec_PtrPush( p->vUsedPis, pObj ); - Ssw_ObjSetSatNum( p, pObj, p->nSatVars++ ); - sat_solver_setnvars( p->pSat, 100 * (1 + p->nSatVars / 100) ); - if ( Aig_ObjIsNode(pObj) ) - Vec_PtrPush( vFrontier, pObj ); -} - -/**Function************************************************************* - - Synopsis [Updates the solver clause database.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_CnfNodeAddToSolver( Ssw_Sat_t * p, Aig_Obj_t * pObj ) -{ - Vec_Ptr_t * vFrontier; - Aig_Obj_t * pNode, * pFanin; - int i, k, fUseMuxes = 1; - // quit if CNF is ready - if ( Ssw_ObjSatNum(p,pObj) ) - return; - // start the frontier - vFrontier = Vec_PtrAlloc( 100 ); - Ssw_ObjAddToFrontier( p, pObj, vFrontier ); - // explore nodes in the frontier - Vec_PtrForEachEntry( Aig_Obj_t *, vFrontier, pNode, i ) - { - // create the supergate - assert( Ssw_ObjSatNum(p,pNode) ); - if ( fUseMuxes && Aig_ObjIsMuxType(pNode) ) - { - Vec_PtrClear( p->vFanins ); - Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin0( Aig_ObjFanin0(pNode) ) ); - Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin0( Aig_ObjFanin1(pNode) ) ); - Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin1( Aig_ObjFanin0(pNode) ) ); - Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin1( Aig_ObjFanin1(pNode) ) ); - Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanins, pFanin, k ) - Ssw_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier ); - Ssw_AddClausesMux( p, pNode ); - } - else - { - Ssw_CollectSuper( pNode, fUseMuxes, p->vFanins ); - Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanins, pFanin, k ) - Ssw_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier ); - Ssw_AddClausesSuper( p, pNode, p->vFanins ); - } - assert( Vec_PtrSize(p->vFanins) > 1 ); - } - Vec_PtrFree( vFrontier ); -} - - -/**Function************************************************************* - - Synopsis [Copy pattern from the solver into the internal storage.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_CnfGetNodeValue( Ssw_Sat_t * p, Aig_Obj_t * pObj ) -{ - int Value0, Value1, nVarNum; - assert( !Aig_IsComplement(pObj) ); - nVarNum = Ssw_ObjSatNum( p, pObj ); - if ( nVarNum > 0 ) - return sat_solver_var_value( p->pSat, nVarNum ); -// if ( pObj->fMarkA == 1 ) -// return 0; - if ( Aig_ObjIsPi(pObj) ) - return 0; - assert( Aig_ObjIsNode(pObj) ); - Value0 = Ssw_CnfGetNodeValue( p, Aig_ObjFanin0(pObj) ); - Value0 ^= Aig_ObjFaninC0(pObj); - Value1 = Ssw_CnfGetNodeValue( p, Aig_ObjFanin1(pObj) ); - Value1 ^= Aig_ObjFaninC1(pObj); - return Value0 & Value1; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ssw/sswConstr.c b/src/aig/ssw/sswConstr.c deleted file mode 100644 index 6af312ab..00000000 --- a/src/aig/ssw/sswConstr.c +++ /dev/null @@ -1,714 +0,0 @@ -/**CFile**************************************************************** - - FileName [sswConstr.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Inductive prover with constraints.] - - Synopsis [One round of SAT sweeping.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 1, 2008.] - - Revision [$Id: sswConstr.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "sswInt.h" -#include "cnf.h" -#include "bar.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Constructs initialized timeframes with constraints as POs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Ssw_FramesWithConstraints( Aig_Man_t * p, int nFrames ) -{ - Aig_Man_t * pFrames; - Aig_Obj_t * pObj, * pObjLi, * pObjLo; - int i, f; - assert( Saig_ManConstrNum(p) > 0 ); - assert( Aig_ManRegNum(p) > 0 ); - assert( Aig_ManRegNum(p) < Aig_ManPiNum(p) ); - // start the fraig package - pFrames = Aig_ManStart( Aig_ManObjNumMax(p) * nFrames ); - // create latches for the first frame - Saig_ManForEachLo( p, pObj, i ) - Aig_ObjSetCopy( pObj, Aig_ManConst0(pFrames) ); - // add timeframes - for ( f = 0; f < nFrames; f++ ) - { - // map constants and PIs - Aig_ObjSetCopy( Aig_ManConst1(p), Aig_ManConst1(pFrames) ); - Saig_ManForEachPi( p, pObj, i ) - Aig_ObjSetCopy( pObj, Aig_ObjCreatePi(pFrames) ); - // add internal nodes of this frame - Aig_ManForEachNode( p, pObj, i ) - Aig_ObjSetCopy( pObj, Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ) ); - // transfer to the primary output - Aig_ManForEachPo( p, pObj, i ) - Aig_ObjSetCopy( pObj, Aig_ObjChild0Copy(pObj) ); - // create constraint outputs - Saig_ManForEachPo( p, pObj, i ) - { - if ( i < Saig_ManPoNum(p) - Saig_ManConstrNum(p) ) - continue; - Aig_ObjCreatePo( pFrames, Aig_Not( Aig_ObjCopy(pObj) ) ); - } - // transfer latch inputs to the latch outputs - Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) - Aig_ObjSetCopy( pObjLo, Aig_ObjCopy(pObjLi) ); - } - // remove dangling nodes - Aig_ManCleanup( pFrames ); - return pFrames; -} - -/**Function************************************************************* - - Synopsis [Finds one satisfiable assignment of the timeframes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ManSetConstrPhases( Aig_Man_t * p, int nFrames, Vec_Int_t ** pvInits ) -{ - Aig_Man_t * pFrames; - sat_solver * pSat; - Cnf_Dat_t * pCnf; - Aig_Obj_t * pObj; - int i, RetValue; - if ( pvInits ) - *pvInits = NULL; - assert( p->nConstrs > 0 ); - // derive the timeframes - pFrames = Ssw_FramesWithConstraints( p, nFrames ); - // create CNF - pCnf = Cnf_Derive( pFrames, 0 ); - // create SAT solver - pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); - if ( pSat == NULL ) - { - Cnf_DataFree( pCnf ); - Aig_ManStop( pFrames ); - return 1; - } - // solve - RetValue = sat_solver_solve( pSat, NULL, NULL, - (ABC_INT64_T)1000000, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); - if ( RetValue == l_True && pvInits ) - { - *pvInits = Vec_IntAlloc( 1000 ); - Aig_ManForEachPi( pFrames, pObj, i ) - Vec_IntPush( *pvInits, sat_solver_var_value(pSat, pCnf->pVarNums[Aig_ObjId(pObj)]) ); - -// Aig_ManForEachPi( pFrames, pObj, i ) -// printf( "%d", Vec_IntEntry(*pvInits, i) ); -// printf( "\n" ); - } - sat_solver_delete( pSat ); - Cnf_DataFree( pCnf ); - Aig_ManStop( pFrames ); - if ( RetValue == l_False ) - return 1; - if ( RetValue == l_True ) - return 0; - return -1; -} - -/**Function************************************************************* - - Synopsis [Performs fraiging for one node.] - - Description [Returns the fraiged node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ManSetConstrPhases_( Aig_Man_t * p, int nFrames, Vec_Int_t ** pvInits ) -{ - Vec_Int_t * vLits; - sat_solver * pSat; - Cnf_Dat_t * pCnf; - Aig_Obj_t * pObj; - int i, f, iVar, RetValue, nRegs; - if ( pvInits ) - *pvInits = NULL; - assert( p->nConstrs > 0 ); - // create CNF - nRegs = p->nRegs; p->nRegs = 0; - pCnf = Cnf_Derive( p, Aig_ManPoNum(p) ); - p->nRegs = nRegs; - // create SAT solver - pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, nFrames, 0 ); - assert( pSat->size == nFrames * pCnf->nVars ); - // collect constraint literals - vLits = Vec_IntAlloc( 100 ); - Saig_ManForEachLo( p, pObj, i ) - { - assert( pCnf->pVarNums[Aig_ObjId(pObj)] >= 0 ); - Vec_IntPush( vLits, toLitCond(pCnf->pVarNums[Aig_ObjId(pObj)], 1) ); - } - for ( f = 0; f < nFrames; f++ ) - { - Saig_ManForEachPo( p, pObj, i ) - { - if ( i < Saig_ManPoNum(p) - Saig_ManConstrNum(p) ) - continue; - assert( pCnf->pVarNums[Aig_ObjId(pObj)] >= 0 ); - iVar = pCnf->pVarNums[Aig_ObjId(pObj)] + pCnf->nVars*f; - Vec_IntPush( vLits, toLitCond(iVar, 1) ); - } - } - RetValue = sat_solver_solve( pSat, (int *)Vec_IntArray(vLits), - (int *)Vec_IntArray(vLits) + Vec_IntSize(vLits), - (ABC_INT64_T)1000000, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); - if ( RetValue == l_True && pvInits ) - { - *pvInits = Vec_IntAlloc( 1000 ); - for ( f = 0; f < nFrames; f++ ) - { - Saig_ManForEachPi( p, pObj, i ) - { - iVar = pCnf->pVarNums[Aig_ObjId(pObj)] + pCnf->nVars*f; - Vec_IntPush( *pvInits, sat_solver_var_value(pSat, iVar) ); - } - } - } - sat_solver_delete( pSat ); - Vec_IntFree( vLits ); - Cnf_DataFree( pCnf ); - if ( RetValue == l_False ) - return 1; - if ( RetValue == l_True ) - return 0; - return -1; -} - -/**Function************************************************************* - - Synopsis [Performs fraiging for one node.] - - Description [Returns the fraiged node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ManPrintPolarity( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i; - Aig_ManForEachObj( p, pObj, i ) - printf( "%d", pObj->fPhase ); - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Performs fraiging for one node.] - - Description [Returns the fraiged node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ManRefineByConstrSim( Ssw_Man_t * p ) -{ - Aig_Obj_t * pObj, * pObjLi; - int f, i, iLits, RetValue1, RetValue2; - int nFrames = Vec_IntSize(p->vInits) / Saig_ManPiNum(p->pAig); - assert( Vec_IntSize(p->vInits) % Saig_ManPiNum(p->pAig) == 0 ); - // assign register outputs - Saig_ManForEachLi( p->pAig, pObj, i ) - pObj->fMarkB = 0; - // simulate the timeframes - iLits = 0; - for ( f = 0; f < nFrames; f++ ) - { - // set the PI simulation information - Aig_ManConst1(p->pAig)->fMarkB = 1; - Saig_ManForEachPi( p->pAig, pObj, i ) - pObj->fMarkB = Vec_IntEntry( p->vInits, iLits++ ); - Saig_ManForEachLiLo( p->pAig, pObjLi, pObj, i ) - pObj->fMarkB = pObjLi->fMarkB; - // simulate internal nodes - Aig_ManForEachNode( p->pAig, pObj, i ) - pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ) - & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) ); - // assign the COs - Aig_ManForEachPo( p->pAig, pObj, i ) - pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ); - // check the outputs - Saig_ManForEachPo( p->pAig, pObj, i ) - { - if ( i < Saig_ManPoNum(p->pAig) - Saig_ManConstrNum(p->pAig) ) - { - if ( pObj->fMarkB ) - printf( "output %d failed in frame %d.\n", i, f ); - } - else - { - if ( pObj->fMarkB ) - printf( "constraint %d failed in frame %d.\n", i, f ); - } - } - // transfer - if ( f == 0 ) - { // copy markB into phase - Aig_ManForEachObj( p->pAig, pObj, i ) - pObj->fPhase = pObj->fMarkB; - } - else - { // refine classes - RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 0 ); - RetValue2 = Ssw_ClassesRefine( p->ppClasses, 0 ); - } - } - assert( iLits == Vec_IntSize(p->vInits) ); -} - - -/**Function************************************************************* - - Synopsis [Performs fraiging for one node.] - - Description [Returns the fraiged node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ManSweepNodeConstr( Ssw_Man_t * p, Aig_Obj_t * pObj, int f, int fBmc ) -{ - Aig_Obj_t * pObjRepr, * pObjFraig, * pObjFraig2, * pObjReprFraig; - int RetValue; - // get representative of this class - pObjRepr = Aig_ObjRepr( p->pAig, pObj ); - if ( pObjRepr == NULL ) - return 0; - // get the fraiged node - pObjFraig = Ssw_ObjFrame( p, pObj, f ); - // get the fraiged representative - pObjReprFraig = Ssw_ObjFrame( p, pObjRepr, f ); - // check if constant 0 pattern distinquishes these nodes - assert( pObjFraig != NULL && pObjReprFraig != NULL ); - assert( (pObj->fPhase == pObjRepr->fPhase) == (Aig_ObjPhaseReal(pObjFraig) == Aig_ObjPhaseReal(pObjReprFraig)) ); - // if the fraiged nodes are the same, return - if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) ) - return 0; - // call equivalence checking - if ( Aig_Regular(pObjFraig) != Aig_ManConst1(p->pFrames) ) - RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) ); - else - RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjFraig), Aig_Regular(pObjReprFraig) ); - if ( RetValue == 1 ) // proved equivalent - { - pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase ); - Ssw_ObjSetFrame( p, pObj, f, pObjFraig2 ); - return 0; - } - if ( RetValue == -1 ) // timed out - { - Ssw_ClassesRemoveNode( p->ppClasses, pObj ); - return 1; - } - // disproved equivalence - Ssw_SmlSavePatternAig( p, f ); - Ssw_ManResimulateBit( p, pObj, pObjRepr ); - assert( Aig_ObjRepr( p->pAig, pObj ) != pObjRepr ); - if ( Aig_ObjRepr( p->pAig, pObj ) == pObjRepr ) - { - printf( "Ssw_ManSweepNodeConstr(): Failed to refine representative.\n" ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Performs fraiging for the internal nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Ssw_ManSweepBmcConstr_rec( Ssw_Man_t * p, Aig_Obj_t * pObj, int f ) -{ - Aig_Obj_t * pObjNew, * pObjLi; - pObjNew = Ssw_ObjFrame( p, pObj, f ); - if ( pObjNew ) - return pObjNew; - assert( !Saig_ObjIsPi(p->pAig, pObj) ); - if ( Saig_ObjIsLo(p->pAig, pObj) ) - { - assert( f > 0 ); - pObjLi = Saig_ObjLoToLi( p->pAig, pObj ); - pObjNew = Ssw_ManSweepBmcConstr_rec( p, Aig_ObjFanin0(pObjLi), f-1 ); - pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObjLi) ); - } - else - { - assert( Aig_ObjIsNode(pObj) ); - Ssw_ManSweepBmcConstr_rec( p, Aig_ObjFanin0(pObj), f ); - Ssw_ManSweepBmcConstr_rec( p, Aig_ObjFanin1(pObj), f ); - pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); - } - Ssw_ObjSetFrame( p, pObj, f, pObjNew ); - assert( pObjNew != NULL ); - return pObjNew; -} - -/**Function************************************************************* - - Synopsis [Performs fraiging for the internal nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ManSweepBmcConstr_old( Ssw_Man_t * p ) -{ - Bar_Progress_t * pProgress = NULL; - Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo; - int i, f, iLits, clk; -clk = clock(); - - // start initialized timeframes - p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK ); - Saig_ManForEachLo( p->pAig, pObj, i ) - Ssw_ObjSetFrame( p, pObj, 0, Aig_ManConst0(p->pFrames) ); - - // build the constraint outputs - iLits = 0; - for ( f = 0; f < p->pPars->nFramesK; f++ ) - { - // map constants and PIs - Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) ); - Saig_ManForEachPi( p->pAig, pObj, i ) - { - pObjNew = Aig_ObjCreatePi(p->pFrames); - pObjNew->fPhase = Vec_IntEntry( p->vInits, iLits++ ); - Ssw_ObjSetFrame( p, pObj, f, pObjNew ); - } - // build the constraint cones - Saig_ManForEachPo( p->pAig, pObj, i ) - { - if ( i < Saig_ManPoNum(p->pAig) - Saig_ManConstrNum(p->pAig) ) - continue; - pObjNew = Ssw_ManSweepBmcConstr_rec( p, Aig_ObjFanin0(pObj), f ); - pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObj) ); - if ( Aig_Regular(pObjNew) == Aig_ManConst1(p->pFrames) ) - { - assert( Aig_IsComplement(pObjNew) ); - continue; - } - Ssw_NodesAreConstrained( p, pObjNew, Aig_ManConst0(p->pFrames) ); - } - } - assert( Vec_IntSize(p->vInits) == iLits + Saig_ManPiNum(p->pAig) ); - - // sweep internal nodes - p->fRefined = 0; - if ( p->pPars->fVerbose ) - pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK ); - for ( f = 0; f < p->pPars->nFramesK; f++ ) - { - // sweep internal nodes - Aig_ManForEachNode( p->pAig, pObj, i ) - { - if ( p->pPars->fVerbose ) - Bar_ProgressUpdate( pProgress, Aig_ManObjNumMax(p->pAig) * f + i, NULL ); - pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); - Ssw_ObjSetFrame( p, pObj, f, pObjNew ); - p->fRefined |= Ssw_ManSweepNodeConstr( p, pObj, f, 1 ); - } - // quit if this is the last timeframe - if ( f == p->pPars->nFramesK - 1 ) - break; - // transfer latch input to the latch outputs - Aig_ManForEachPo( p->pAig, pObj, i ) - Ssw_ObjSetFrame( p, pObj, f, Ssw_ObjChild0Fra(p, pObj, f) ); - // build logic cones for register outputs - Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) - { - pObjNew = Ssw_ObjFrame( p, pObjLi, f ); - Ssw_ObjSetFrame( p, pObjLo, f+1, pObjNew ); - Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pObjNew) );// - } - } - if ( p->pPars->fVerbose ) - Bar_ProgressStop( pProgress ); - - // cleanup -// Ssw_ClassesCheck( p->ppClasses ); -p->timeBmc += clock() - clk; - return p->fRefined; -} - -/**Function************************************************************* - - Synopsis [Performs fraiging for the internal nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ManSweepBmcConstr( Ssw_Man_t * p ) -{ - Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo; - int i, f, iLits, clk; -clk = clock(); - - // start initialized timeframes - p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK ); - Saig_ManForEachLo( p->pAig, pObj, i ) - Ssw_ObjSetFrame( p, pObj, 0, Aig_ManConst0(p->pFrames) ); - - // build the constraint outputs - iLits = 0; - p->fRefined = 0; - for ( f = 0; f < p->pPars->nFramesK; f++ ) - { - // map constants and PIs - Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) ); - Saig_ManForEachPi( p->pAig, pObj, i ) - { - pObjNew = Aig_ObjCreatePi(p->pFrames); - pObjNew->fPhase = Vec_IntEntry( p->vInits, iLits++ ); - Ssw_ObjSetFrame( p, pObj, f, pObjNew ); - } - // build the constraint cones - Saig_ManForEachPo( p->pAig, pObj, i ) - { - if ( i < Saig_ManPoNum(p->pAig) - Saig_ManConstrNum(p->pAig) ) - continue; - pObjNew = Ssw_ManSweepBmcConstr_rec( p, Aig_ObjFanin0(pObj), f ); - pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObj) ); - if ( Aig_Regular(pObjNew) == Aig_ManConst1(p->pFrames) ) - { - assert( Aig_IsComplement(pObjNew) ); - continue; - } - Ssw_NodesAreConstrained( p, pObjNew, Aig_ManConst0(p->pFrames) ); - } - - // sweep internal nodes - Aig_ManForEachNode( p->pAig, pObj, i ) - { - pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); - Ssw_ObjSetFrame( p, pObj, f, pObjNew ); - p->fRefined |= Ssw_ManSweepNodeConstr( p, pObj, f, 1 ); - } - // quit if this is the last timeframe - if ( f == p->pPars->nFramesK - 1 ) - break; - // transfer latch input to the latch outputs - Aig_ManForEachPo( p->pAig, pObj, i ) - Ssw_ObjSetFrame( p, pObj, f, Ssw_ObjChild0Fra(p, pObj, f) ); - // build logic cones for register outputs - Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) - { - pObjNew = Ssw_ObjFrame( p, pObjLi, f ); - Ssw_ObjSetFrame( p, pObjLo, f+1, pObjNew ); - Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pObjNew) );// - } - } - assert( Vec_IntSize(p->vInits) == iLits + Saig_ManPiNum(p->pAig) ); - - // cleanup -// Ssw_ClassesCheck( p->ppClasses ); -p->timeBmc += clock() - clk; - return p->fRefined; -} - - - - -/**Function************************************************************* - - Synopsis [Performs fraiging for the internal nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Ssw_FramesWithClasses_rec( Ssw_Man_t * p, Aig_Obj_t * pObj, int f ) -{ - Aig_Obj_t * pObjNew, * pObjLi; - pObjNew = Ssw_ObjFrame( p, pObj, f ); - if ( pObjNew ) - return pObjNew; - assert( !Saig_ObjIsPi(p->pAig, pObj) ); - if ( Saig_ObjIsLo(p->pAig, pObj) ) - { - assert( f > 0 ); - pObjLi = Saig_ObjLoToLi( p->pAig, pObj ); - pObjNew = Ssw_FramesWithClasses_rec( p, Aig_ObjFanin0(pObjLi), f-1 ); - pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObjLi) ); - } - else - { - assert( Aig_ObjIsNode(pObj) ); - Ssw_FramesWithClasses_rec( p, Aig_ObjFanin0(pObj), f ); - Ssw_FramesWithClasses_rec( p, Aig_ObjFanin1(pObj), f ); - pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); - } - Ssw_ObjSetFrame( p, pObj, f, pObjNew ); - assert( pObjNew != NULL ); - return pObjNew; -} - - -/**Function************************************************************* - - Synopsis [Performs fraiging for the internal nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ManSweepConstr( Ssw_Man_t * p ) -{ - Bar_Progress_t * pProgress = NULL; - Aig_Obj_t * pObj, * pObj2, * pObjNew; - int nConstrPairs, clk, i, f, iLits; -//Ssw_ManPrintPolarity( p->pAig ); - - // perform speculative reduction -clk = clock(); - // create timeframes - p->pFrames = Ssw_FramesWithClasses( p ); - // add constants - nConstrPairs = Aig_ManPoNum(p->pFrames)-Aig_ManRegNum(p->pAig); - assert( (nConstrPairs & 1) == 0 ); - for ( i = 0; i < nConstrPairs; i += 2 ) - { - pObj = Aig_ManPo( p->pFrames, i ); - pObj2 = Aig_ManPo( p->pFrames, i+1 ); - Ssw_NodesAreConstrained( p, Aig_ObjChild0(pObj), Aig_ObjChild0(pObj2) ); - } - // build logic cones for register inputs - for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ ) - { - pObj = Aig_ManPo( p->pFrames, nConstrPairs + i ); - Ssw_CnfNodeAddToSolver( p->pMSat, Aig_ObjFanin0(pObj) );// - } - - // map constants and PIs of the last frame - f = p->pPars->nFramesK; -// iLits = 0; - iLits = f * Saig_ManPiNum(p->pAig); - Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) ); - Saig_ManForEachPi( p->pAig, pObj, i ) - { - pObjNew = Aig_ObjCreatePi(p->pFrames); - pObjNew->fPhase = (p->vInits != NULL) && Vec_IntEntry(p->vInits, iLits++); - Ssw_ObjSetFrame( p, pObj, f, pObjNew ); - } - assert( Vec_IntSize(p->vInits) == iLits ); -p->timeReduce += clock() - clk; - - // add constraints to all timeframes - for ( f = 0; f <= p->pPars->nFramesK; f++ ) - { - Saig_ManForEachPo( p->pAig, pObj, i ) - { - if ( i < Saig_ManPoNum(p->pAig) - Saig_ManConstrNum(p->pAig) ) - continue; - Ssw_FramesWithClasses_rec( p, Aig_ObjFanin0(pObj), f ); -// if ( Aig_Regular(Ssw_ObjChild0Fra(p,pObj,f)) == Aig_ManConst1(p->pFrames) ) - if ( Ssw_ObjChild0Fra(p,pObj,f) == Aig_ManConst0(p->pFrames) ) - continue; - assert( Ssw_ObjChild0Fra(p,pObj,f) != Aig_ManConst1(p->pFrames) ); - if ( Ssw_ObjChild0Fra(p,pObj,f) == Aig_ManConst1(p->pFrames) ) - { - printf( "Polarity violation.\n" ); - continue; - } - Ssw_NodesAreConstrained( p, Ssw_ObjChild0Fra(p,pObj,f), Aig_ManConst0(p->pFrames) ); - } - } - f = p->pPars->nFramesK; - // clean the solver - sat_solver_simplify( p->pMSat->pSat ); - - - // sweep internal nodes - p->fRefined = 0; - Ssw_ClassesClearRefined( p->ppClasses ); - if ( p->pPars->fVerbose ) - pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) ); - Aig_ManForEachObj( p->pAig, pObj, i ) - { - if ( p->pPars->fVerbose ) - Bar_ProgressUpdate( pProgress, i, NULL ); - if ( Saig_ObjIsLo(p->pAig, pObj) ) - p->fRefined |= Ssw_ManSweepNodeConstr( p, pObj, f, 0 ); - else if ( Aig_ObjIsNode(pObj) ) - { - pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); - Ssw_ObjSetFrame( p, pObj, f, pObjNew ); - p->fRefined |= Ssw_ManSweepNodeConstr( p, pObj, f, 0 ); - } - } - if ( p->pPars->fVerbose ) - Bar_ProgressStop( pProgress ); - // cleanup -// Ssw_ClassesCheck( p->ppClasses ); - return p->fRefined; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ssw/sswCore.c b/src/aig/ssw/sswCore.c deleted file mode 100644 index 0b2393df..00000000 --- a/src/aig/ssw/sswCore.c +++ /dev/null @@ -1,522 +0,0 @@ -/**CFile**************************************************************** - - FileName [sswCore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Inductive prover with constraints.] - - Synopsis [The core procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 1, 2008.] - - Revision [$Id: sswCore.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "sswInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [This procedure sets default parameters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ManSetDefaultParams( Ssw_Pars_t * p ) -{ - memset( p, 0, sizeof(Ssw_Pars_t) ); - p->nPartSize = 0; // size of the partition - p->nOverSize = 0; // size of the overlap between partitions - p->nFramesK = 1; // the induction depth - p->nFramesAddSim = 2; // additional frames to simulate - p->fConstrs = 0; // treat the last nConstrs POs as seq constraints - p->fMergeFull = 0; // enables full merge when constraints are used - p->nBTLimit = 1000; // conflict limit at a node - p->nBTLimitGlobal = 5000000; // conflict limit for all runs - p->nMinDomSize = 100; // min clock domain considered for optimization - p->nItersStop = -1; // stop after the given number of iterations - p->nResimDelta = 1000; // the internal of nodes to resimulate - p->nStepsMax = -1; // (scorr only) the max number of induction steps - p->fPolarFlip = 0; // uses polarity adjustment - p->fLatchCorr = 0; // performs register correspondence - p->fConstCorr = 0; // performs constant correspondence - p->fOutputCorr = 0; // perform 'PO correspondence' - p->fSemiFormal = 0; // enable semiformal filtering - p->fDynamic = 0; // dynamic partitioning - p->fLocalSim = 0; // local simulation - p->fVerbose = 0; // verbose stats - p->fEquivDump = 0; // enables dumping equivalences - - // latch correspondence - p->fLatchCorrOpt = 0; // performs optimized register correspondence - p->nSatVarMax = 1000; // the max number of SAT variables - p->nRecycleCalls = 50; // calls to perform before recycling SAT solver - // signal correspondence - p->nSatVarMax2 = 5000; // the max number of SAT variables - p->nRecycleCalls2 = 250; // calls to perform before recycling SAT solver - // return values - p->nIters = 0; // the number of iterations performed -} - -/**Function************************************************************* - - Synopsis [This procedure sets default parameters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ManSetDefaultParamsLcorr( Ssw_Pars_t * p ) -{ - Ssw_ManSetDefaultParams( p ); - p->fLatchCorrOpt = 1; - p->nBTLimit = 10000; -} - -/**Function************************************************************* - - Synopsis [Reports improvements for property cones.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ReportConeReductions( Ssw_Man_t * p, Aig_Man_t * pAigInit, Aig_Man_t * pAigStop ) -{ - Aig_Man_t * pAig1, * pAig2, * pAux; - pAig1 = Aig_ManDupOneOutput( pAigInit, 0, 1 ); - pAig1 = Aig_ManScl( pAux = pAig1, 1, 1, 0, -1, -1, 0, 0 ); - Aig_ManStop( pAux ); - pAig2 = Aig_ManDupOneOutput( pAigStop, 0, 1 ); - pAig2 = Aig_ManScl( pAux = pAig2, 1, 1, 0, -1, -1, 0, 0 ); - Aig_ManStop( pAux ); - - p->nNodesBegC = Aig_ManNodeNum(pAig1); - p->nNodesEndC = Aig_ManNodeNum(pAig2); - p->nRegsBegC = Aig_ManRegNum(pAig1); - p->nRegsEndC = Aig_ManRegNum(pAig2); - - Aig_ManStop( pAig1 ); - Aig_ManStop( pAig2 ); -} - -/**Function************************************************************* - - Synopsis [Reports one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ReportOneOutput( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - if ( pObj == Aig_ManConst1(p) ) - printf( "1" ); - else if ( pObj == Aig_ManConst0(p) ) - printf( "0" ); - else - printf( "X" ); -} - -/**Function************************************************************* - - Synopsis [Reports improvements for property cones.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ReportOutputs( Aig_Man_t * pAig ) -{ - Aig_Obj_t * pObj; - int i; - Saig_ManForEachPo( pAig, pObj, i ) - { - if ( i < Saig_ManPoNum(pAig)-Saig_ManConstrNum(pAig) ) - printf( "o" ); - else - printf( "c" ); - Ssw_ReportOneOutput( pAig, Aig_ObjChild0(pObj) ); - } - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Remove from-equivs that are in the cone of constraints.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ManUpdateEquivs( Ssw_Man_t * p, Aig_Man_t * pAig, int fVerbose ) -{ - Vec_Ptr_t * vCones; - Aig_Obj_t ** pArray; - Aig_Obj_t * pObj; - int i, nTotal = 0, nRemoved = 0; - // collect the nodes in the cone of constraints - pArray = (Aig_Obj_t **)Vec_PtrArray(pAig->vPos); - pArray += Saig_ManPoNum(pAig) - Saig_ManConstrNum(pAig); - vCones = Aig_ManDfsNodes( pAig, pArray, Saig_ManConstrNum(pAig) ); - // remove all the node that are equiv to something and are in the cones - Aig_ManForEachObj( pAig, pObj, i ) - { - if ( !Aig_ObjIsPi(pObj) && !Aig_ObjIsNode(pObj) ) - continue; - if ( pAig->pReprs[i] != NULL ) - nTotal++; - if ( !Aig_ObjIsTravIdCurrent(pAig, pObj) ) - continue; - if ( pAig->pReprs[i] ) - { - if ( p->pPars->fConstrs && !p->pPars->fMergeFull ) - { - pAig->pReprs[i] = NULL; - nRemoved++; - } - } - } - // collect statistics - p->nConesTotal = Aig_ManPiNum(pAig) + Aig_ManNodeNum(pAig); - p->nConesConstr = Vec_PtrSize(vCones); - p->nEquivsTotal = nTotal; - p->nEquivsConstr = nRemoved; - Vec_PtrFree( vCones ); -} - -/**Function************************************************************* - - Synopsis [Performs computation of signal correspondence with constraints.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Ssw_SignalCorrespondenceRefine( Ssw_Man_t * p ) -{ - int nSatProof, nSatCallsSat, nRecycles, nSatFailsReal, nUniques; - Aig_Man_t * pAigNew; - int RetValue, nIter = -1; - int clk, clkTotal = clock(); - // get the starting stats - p->nLitsBeg = Ssw_ClassesLitNum( p->ppClasses ); - p->nNodesBeg = Aig_ManNodeNum(p->pAig); - p->nRegsBeg = Aig_ManRegNum(p->pAig); - // refine classes using BMC - if ( p->pPars->fVerbose ) - { - printf( "Before BMC: " ); - Ssw_ClassesPrint( p->ppClasses, 0 ); - } - if ( !p->pPars->fLatchCorr ) - { - p->pMSat = Ssw_SatStart( 0 ); - if ( p->pPars->fConstrs ) - Ssw_ManSweepBmcConstr( p ); - else - Ssw_ManSweepBmc( p ); - Ssw_SatStop( p->pMSat ); - p->pMSat = NULL; - Ssw_ManCleanup( p ); - } - if ( p->pPars->fVerbose ) - { - printf( "After BMC: " ); - Ssw_ClassesPrint( p->ppClasses, 0 ); - } - // apply semi-formal filtering -/* - if ( p->pPars->fSemiFormal ) - { - Aig_Man_t * pSRed; - Ssw_FilterUsingSemi( p, 0, 2000, p->pPars->fVerbose ); -// Ssw_FilterUsingSemi( p, 1, 100000, p->pPars->fVerbose ); - pSRed = Ssw_SpeculativeReduction( p ); - Aig_ManDumpBlif( pSRed, "srm.blif", NULL, NULL ); - Aig_ManStop( pSRed ); - } -*/ - if ( p->pPars->pFunc ) - { - ((int (*)(void *))p->pPars->pFunc)( p->pPars->pData ); - ((int (*)(void *))p->pPars->pFunc)( p->pPars->pData ); - } - if ( p->pPars->nStepsMax == 0 ) - { - printf( "Stopped signal correspondence after BMC.\n" ); - goto finalize; - } - // refine classes using induction - nSatProof = nSatCallsSat = nRecycles = nSatFailsReal = nUniques = 0; - for ( nIter = 0; ; nIter++ ) - { - if ( p->pPars->nStepsMax == nIter ) - { - printf( "Stopped signal correspondence after %d refiment iterations.\n", nIter ); - goto finalize; - } - if ( p->pPars->nItersStop >= 0 && p->pPars->nItersStop == nIter ) - { - Aig_Man_t * pSRed = Ssw_SpeculativeReduction( p ); - Aig_ManDumpBlif( pSRed, "srm.blif", NULL, NULL ); - Aig_ManStop( pSRed ); - printf( "Iterative refinement is stopped before iteration %d.\n", nIter ); - printf( "The network is reduced using candidate equivalences.\n" ); - printf( "Speculatively reduced miter is saved in file \"%s\".\n", "srm.blif" ); - printf( "If the miter is SAT, the reduced result is incorrect.\n" ); - break; - } - -clk = clock(); - p->pMSat = Ssw_SatStart( 0 ); - if ( p->pPars->fLatchCorrOpt ) - { - RetValue = Ssw_ManSweepLatch( p ); - if ( p->pPars->fVerbose ) - { - printf( "%3d : C =%7d. Cl =%7d. Pr =%6d. Cex =%5d. R =%4d. F =%4d. ", - nIter, Ssw_ClassesCand1Num(p->ppClasses), Ssw_ClassesClassNum(p->ppClasses), - p->nSatProof-nSatProof, p->nSatCallsSat-nSatCallsSat, - p->nRecycles-nRecycles, p->nSatFailsReal-nSatFailsReal ); - ABC_PRT( "T", clock() - clk ); - } - } - else - { - if ( p->pPars->fConstrs ) - RetValue = Ssw_ManSweepConstr( p ); - else if ( p->pPars->fDynamic ) - RetValue = Ssw_ManSweepDyn( p ); - else - RetValue = Ssw_ManSweep( p ); - - p->pPars->nConflicts += p->pMSat->pSat->stats.conflicts; - if ( p->pPars->fVerbose ) - { - printf( "%3d : C =%7d. Cl =%7d. LR =%6d. NR =%6d. ", - nIter, Ssw_ClassesCand1Num(p->ppClasses), Ssw_ClassesClassNum(p->ppClasses), - p->nConstrReduced, Aig_ManNodeNum(p->pFrames) ); - if ( p->pPars->fDynamic ) - { - printf( "Cex =%5d. ", p->nSatCallsSat-nSatCallsSat ); - printf( "R =%4d. ", p->nRecycles-nRecycles ); - } - printf( "F =%5d. %s ", p->nSatFailsReal-nSatFailsReal, - (Saig_ManPoNum(p->pAig)==1 && Ssw_ObjIsConst1Cand(p->pAig,Aig_ObjFanin0(Aig_ManPo(p->pAig,0))))? "+" : "-" ); - ABC_PRT( "T", clock() - clk ); - } -// if ( p->pPars->fDynamic && p->nSatCallsSat-nSatCallsSat < 100 ) -// p->pPars->nBTLimit = 10000; - } - nSatProof = p->nSatProof; - nSatCallsSat = p->nSatCallsSat; - nRecycles = p->nRecycles; - nSatFailsReal = p->nSatFailsReal; - nUniques = p->nUniques; - - p->nVarsMax = ABC_MAX( p->nVarsMax, p->pMSat->nSatVars ); - p->nCallsMax = ABC_MAX( p->nCallsMax, p->pMSat->nSolverCalls ); - Ssw_SatStop( p->pMSat ); - p->pMSat = NULL; - Ssw_ManCleanup( p ); - if ( !RetValue ) - break; - if ( p->pPars->pFunc ) - ((int (*)(void *))p->pPars->pFunc)( p->pPars->pData ); - } - -finalize: - p->pPars->nIters = nIter + 1; -p->timeTotal = clock() - clkTotal; - - Ssw_ManUpdateEquivs( p, p->pAig, p->pPars->fVerbose ); - pAigNew = Aig_ManDupRepr( p->pAig, 0 ); - Aig_ManSeqCleanup( pAigNew ); -//Ssw_ClassesPrint( p->ppClasses, 1 ); - // get the final stats - p->nLitsEnd = Ssw_ClassesLitNum( p->ppClasses ); - p->nNodesEnd = Aig_ManNodeNum(pAigNew); - p->nRegsEnd = Aig_ManRegNum(pAigNew); - // cleanup - Aig_ManSetPhase( p->pAig ); - Aig_ManCleanMarkB( p->pAig ); - return pAigNew; -} - -/**Function************************************************************* - - Synopsis [Performs computation of signal correspondence with constraints.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Ssw_SignalCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars ) -{ - Ssw_Pars_t Pars; - Aig_Man_t * pAigNew; - Ssw_Man_t * p; - assert( Aig_ManRegNum(pAig) > 0 ); - // reset random numbers - Aig_ManRandom( 1 ); - // if parameters are not given, create them - if ( pPars == NULL ) - Ssw_ManSetDefaultParams( pPars = &Pars ); - // consider the case of empty AIG - if ( Aig_ManNodeNum(pAig) == 0 ) - { - pPars->nIters = 0; - // Ntl_ManFinalize() needs the following to satisfy an assertion - Aig_ManReprStart( pAig,Aig_ManObjNumMax(pAig) ); - return Aig_ManDupOrdered(pAig); - } - // check and update parameters - if ( pPars->fLatchCorrOpt ) - { - pPars->fLatchCorr = 1; - pPars->nFramesAddSim = 0; - if ( (pAig->vClockDoms && Vec_VecSize(pAig->vClockDoms) > 0) ) - return Ssw_SignalCorrespondencePart( pAig, pPars ); - } - else - { - assert( pPars->nFramesK > 0 ); - // perform partitioning - if ( (pPars->nPartSize > 0 && pPars->nPartSize < Aig_ManRegNum(pAig)) - || (pAig->vClockDoms && Vec_VecSize(pAig->vClockDoms) > 0) ) - return Ssw_SignalCorrespondencePart( pAig, pPars ); - } - - if ( pPars->fScorrGia ) - { - if ( pPars->fLatchCorrOpt ) - { - extern Aig_Man_t * Cec_LatchCorrespondence( Aig_Man_t * pAig, int nConfs, int fUseCSat ); - return Cec_LatchCorrespondence( pAig, pPars->nBTLimit, pPars->fUseCSat ); - } - else - { - extern Aig_Man_t * Cec_SignalCorrespondence( Aig_Man_t * pAig, int nConfs, int fUseCSat ); - return Cec_SignalCorrespondence( pAig, pPars->nBTLimit, pPars->fUseCSat ); - } - } - - // start the induction manager - p = Ssw_ManCreate( pAig, pPars ); - // compute candidate equivalence classes -// p->pPars->nConstrs = 1; - if ( p->pPars->fConstrs ) - { - // create trivial equivalence classes with all nodes being candidates for constant 1 - p->ppClasses = Ssw_ClassesPrepareSimple( pAig, pPars->fLatchCorr, pPars->nMaxLevs ); - Ssw_ClassesSetData( p->ppClasses, NULL, NULL, Ssw_SmlObjIsConstBit, Ssw_SmlObjsAreEqualBit ); - // derive phase bits to satisfy the constraints - if ( Ssw_ManSetConstrPhases( pAig, p->pPars->nFramesK + 1, &p->vInits ) != 0 ) - { - printf( "Ssw_SignalCorrespondence(): The init state does not satisfy the constraints!\n" ); - p->pPars->fVerbose = 0; - Ssw_ManStop( p ); - return NULL; - } - // perform simulation of the first timeframes - Ssw_ManRefineByConstrSim( p ); - } - else - { - // perform one round of seq simulation and generate candidate equivalence classes - p->ppClasses = Ssw_ClassesPrepare( pAig, pPars->nFramesK, pPars->fLatchCorr, pPars->fConstCorr, pPars->fOutputCorr, pPars->nMaxLevs, pPars->fVerbose ); -// p->ppClasses = Ssw_ClassesPrepareTargets( pAig ); - if ( pPars->fLatchCorrOpt ) - p->pSml = Ssw_SmlStart( pAig, 0, 2, 1 ); - else if ( pPars->fDynamic ) - p->pSml = Ssw_SmlStart( pAig, 0, p->nFrames + p->pPars->nFramesAddSim, 1 ); - else - p->pSml = Ssw_SmlStart( pAig, 0, 1 + p->pPars->nFramesAddSim, 1 ); - Ssw_ClassesSetData( p->ppClasses, p->pSml, (unsigned(*)(void *,Aig_Obj_t *))Ssw_SmlObjHashWord, (int(*)(void *,Aig_Obj_t *))Ssw_SmlObjIsConstWord, (int(*)(void *,Aig_Obj_t *,Aig_Obj_t *))Ssw_SmlObjsAreEqualWord ); - } - // allocate storage - if ( p->pPars->fLocalSim ) - p->pVisited = ABC_CALLOC( int, Ssw_SmlNumFrames( p->pSml ) * Aig_ManObjNumMax(p->pAig) ); - // perform refinement of classes - pAigNew = Ssw_SignalCorrespondenceRefine( p ); -// Ssw_ReportOutputs( pAigNew ); - if ( pPars->fConstrs && pPars->fVerbose ) - Ssw_ReportConeReductions( p, pAig, pAigNew ); - // cleanup - Ssw_ManStop( p ); - return pAigNew; -} - -/**Function************************************************************* - - Synopsis [Performs computation of latch correspondence.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Ssw_LatchCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars ) -{ - Aig_Man_t * pRes; - Ssw_Pars_t Pars; - if ( pPars == NULL ) - Ssw_ManSetDefaultParamsLcorr( pPars = &Pars ); - pRes = Ssw_SignalCorrespondence( pAig, pPars ); -// if ( pPars->fConstrs && pPars->fVerbose ) -// Ssw_ReportConeReductions( pAig, pRes ); - return pRes; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ssw/sswDyn.c b/src/aig/ssw/sswDyn.c deleted file mode 100644 index 7bdb2652..00000000 --- a/src/aig/ssw/sswDyn.c +++ /dev/null @@ -1,489 +0,0 @@ -/**CFile**************************************************************** - - FileName [sswDyn.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Inductive prover with constraints.] - - Synopsis [Dynamic loading of constraints.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 1, 2008.] - - Revision [$Id: sswDyn.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "sswInt.h" -#include "bar.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Label PIs nodes of the frames corresponding to PIs of AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ManLabelPiNodes( Ssw_Man_t * p ) -{ - Aig_Obj_t * pObj, * pObjFrames; - int f, i; - Aig_ManConst1( p->pFrames )->fMarkA = 1; - Aig_ManConst1( p->pFrames )->fMarkB = 1; - for ( f = 0; f < p->nFrames; f++ ) - { - Saig_ManForEachPi( p->pAig, pObj, i ) - { - pObjFrames = Ssw_ObjFrame( p, pObj, f ); - assert( Aig_ObjIsPi(pObjFrames) ); - assert( pObjFrames->fMarkB == 0 ); - pObjFrames->fMarkA = 1; - pObjFrames->fMarkB = 1; - } - } -} - -/**Function************************************************************* - - Synopsis [Collects new POs in p->vNewPos.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ManCollectPis_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vNewPis ) -{ - assert( !Aig_IsComplement(pObj) ); - if ( pObj->fMarkA ) - return; - pObj->fMarkA = 1; - if ( Aig_ObjIsPi(pObj) ) - { - Vec_PtrPush( vNewPis, pObj ); - return; - } - assert( Aig_ObjIsNode(pObj) ); - Ssw_ManCollectPis_rec( Aig_ObjFanin0(pObj), vNewPis ); - Ssw_ManCollectPis_rec( Aig_ObjFanin1(pObj), vNewPis ); -} - -/**Function************************************************************* - - Synopsis [Collects new POs in p->vNewPos.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ManCollectPos_rec( Ssw_Man_t * p, Aig_Obj_t * pObj, Vec_Int_t * vNewPos ) -{ - Aig_Obj_t * pFanout; - int iFanout = -1, i; - assert( !Aig_IsComplement(pObj) ); - if ( pObj->fMarkB ) - return; - pObj->fMarkB = 1; - if ( pObj->Id > p->nSRMiterMaxId ) - return; - if ( Aig_ObjIsPo(pObj) ) - { - // skip if it is a register input PO - if ( Aig_ObjPioNum(pObj) >= Aig_ManPoNum(p->pFrames)-Aig_ManRegNum(p->pAig) ) - return; - // add the number of this constraint - Vec_IntPush( vNewPos, Aig_ObjPioNum(pObj)/2 ); - return; - } - // visit the fanouts - assert( p->pFrames->pFanData != NULL ); - Aig_ObjForEachFanout( p->pFrames, pObj, pFanout, iFanout, i ) - Ssw_ManCollectPos_rec( p, pFanout, vNewPos ); -} - -/**Function************************************************************* - - Synopsis [Loads logic cones and relevant constraints.] - - Description [Both pRepr and pObj are objects of the AIG. - The result is the current SAT solver loaded with the logic cones - for pRepr and pObj corresponding to them in the frames, - as well as all the relevant constraints.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ManLoadSolver( Ssw_Man_t * p, Aig_Obj_t * pRepr, Aig_Obj_t * pObj ) -{ - Aig_Obj_t * pObjFrames, * pReprFrames; - Aig_Obj_t * pTemp, * pObj0, * pObj1; - int i, iConstr, RetValue; - - assert( pRepr != pObj ); - // get the corresponding frames nodes - pReprFrames = Aig_Regular( Ssw_ObjFrame( p, pRepr, p->pPars->nFramesK ) ); - pObjFrames = Aig_Regular( Ssw_ObjFrame( p, pObj, p->pPars->nFramesK ) ); - assert( pReprFrames != pObjFrames ); - /* - // compute the AIG support - Vec_PtrClear( p->vNewLos ); - Ssw_ManCollectPis_rec( pRepr, p->vNewLos ); - Ssw_ManCollectPis_rec( pObj, p->vNewLos ); - // add logic cones for register outputs - Vec_PtrForEachEntry( Aig_Obj_t *, p->vNewLos, pTemp, i ) - { - pObj0 = Aig_Regular( Ssw_ObjFrame( p, pTemp, p->pPars->nFramesK ) ); - Ssw_CnfNodeAddToSolver( p->pMSat, pObj0 ); - } -*/ - // add cones for the nodes - Ssw_CnfNodeAddToSolver( p->pMSat, pReprFrames ); - Ssw_CnfNodeAddToSolver( p->pMSat, pObjFrames ); - - // compute the frames support - Vec_PtrClear( p->vNewLos ); - Ssw_ManCollectPis_rec( pReprFrames, p->vNewLos ); - Ssw_ManCollectPis_rec( pObjFrames, p->vNewLos ); - // these nodes include both nodes corresponding to PIs and LOs - // (the nodes corresponding to PIs should be labeled with fMarkB!) - - // collect the related constraint POs - Vec_IntClear( p->vNewPos ); - Vec_PtrForEachEntry( Aig_Obj_t *, p->vNewLos, pTemp, i ) - Ssw_ManCollectPos_rec( p, pTemp, p->vNewPos ); - // check if the corresponding pairs are added - Vec_IntForEachEntry( p->vNewPos, iConstr, i ) - { - pObj0 = Aig_ManPo( p->pFrames, 2*iConstr ); - pObj1 = Aig_ManPo( p->pFrames, 2*iConstr+1 ); -// if ( pObj0->fMarkB && pObj1->fMarkB ) - if ( pObj0->fMarkB || pObj1->fMarkB ) - { - pObj0->fMarkB = 1; - pObj1->fMarkB = 1; - Ssw_NodesAreConstrained( p, Aig_ObjChild0(pObj0), Aig_ObjChild0(pObj1) ); - } - } - if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead ) - { - RetValue = sat_solver_simplify(p->pMSat->pSat); - assert( RetValue != 0 ); - } -} - -/**Function************************************************************* - - Synopsis [Tranfers simulation information from FRAIG to AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ManSweepTransferDyn( Ssw_Man_t * p ) -{ - Aig_Obj_t * pObj, * pObjFraig; - unsigned * pInfo; - int i, f, nFrames; - - // transfer simulation information - Aig_ManForEachPi( p->pAig, pObj, i ) - { - pObjFraig = Ssw_ObjFrame( p, pObj, 0 ); - if ( pObjFraig == Aig_ManConst0(p->pFrames) ) - { - Ssw_SmlObjAssignConst( p->pSml, pObj, 0, 0 ); - continue; - } - assert( !Aig_IsComplement(pObjFraig) ); - assert( Aig_ObjIsPi(pObjFraig) ); - pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjPioNum(pObjFraig) ); - Ssw_SmlObjSetWord( p->pSml, pObj, pInfo[0], 0, 0 ); - } - // set random simulation info for the second frame - for ( f = 1; f < p->nFrames; f++ ) - { - Saig_ManForEachPi( p->pAig, pObj, i ) - { - pObjFraig = Ssw_ObjFrame( p, pObj, f ); - assert( !Aig_IsComplement(pObjFraig) ); - assert( Aig_ObjIsPi(pObjFraig) ); - pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjPioNum(pObjFraig) ); - Ssw_SmlObjSetWord( p->pSml, pObj, pInfo[0], 0, f ); - } - } - // create random info - nFrames = Ssw_SmlNumFrames( p->pSml ); - for ( ; f < nFrames; f++ ) - { - Saig_ManForEachPi( p->pAig, pObj, i ) - Ssw_SmlAssignRandomFrame( p->pSml, pObj, f ); - } -} - -/**Function************************************************************* - - Synopsis [Performs one round of simulation with counter-examples.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ManSweepResimulateDyn( Ssw_Man_t * p, int f ) -{ - int RetValue1, RetValue2, clk = clock(); - // transfer PI simulation information from storage -// Ssw_SmlAssignDist1Plus( p->pSml, p->pPatWords ); - Ssw_ManSweepTransferDyn( p ); - // simulate internal nodes -// Ssw_SmlSimulateOneFrame( p->pSml ); - Ssw_SmlSimulateOne( p->pSml ); - // check equivalence classes - RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 1 ); - RetValue2 = Ssw_ClassesRefine( p->ppClasses, 1 ); - // prepare simulation info for the next round - Vec_PtrCleanSimInfo( p->vSimInfo, 0, 1 ); - p->nPatterns = 0; - p->nSimRounds++; -p->timeSimSat += clock() - clk; - return RetValue1 > 0 || RetValue2 > 0; -} - -/**Function************************************************************* - - Synopsis [Performs one round of simulation with counter-examples.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ManSweepResimulateDynLocal( Ssw_Man_t * p, int f ) -{ - Aig_Obj_t * pObj, * pRepr, ** ppClass; - int i, k, nSize, RetValue1, RetValue2, clk = clock(); - p->nSimRounds++; - // transfer PI simulation information from storage -// Ssw_SmlAssignDist1Plus( p->pSml, p->pPatWords ); - Ssw_ManSweepTransferDyn( p ); - // determine const1 cands and classes to be simulated - Vec_PtrClear( p->vResimConsts ); - Vec_PtrClear( p->vResimClasses ); - Aig_ManIncrementTravId( p->pAig ); - for ( i = p->iNodeStart; i < p->iNodeLast + p->pPars->nResimDelta; i++ ) - { - if ( i >= Aig_ManObjNumMax( p->pAig ) ) - break; - pObj = Aig_ManObj( p->pAig, i ); - if ( pObj == NULL ) - continue; - if ( Ssw_ObjIsConst1Cand(p->pAig, pObj) ) - { - Vec_PtrPush( p->vResimConsts, pObj ); - continue; - } - pRepr = Aig_ObjRepr(p->pAig, pObj); - if ( pRepr == NULL ) - continue; - if ( Aig_ObjIsTravIdCurrent(p->pAig, pRepr) ) - continue; - Aig_ObjSetTravIdCurrent(p->pAig, pRepr); - Vec_PtrPush( p->vResimClasses, pRepr ); - } - // simulate internal nodes -// Ssw_SmlSimulateOneFrame( p->pSml ); -// Ssw_SmlSimulateOne( p->pSml ); - // resimulate dynamically -// Aig_ManIncrementTravId( p->pAig ); -// Aig_ObjIsTravIdCurrent( p->pAig, Aig_ManConst1(p->pAig) ); - p->nVisCounter++; - Vec_PtrForEachEntry( Aig_Obj_t *, p->vResimConsts, pObj, i ) - Ssw_SmlSimulateOneDyn_rec( p->pSml, pObj, p->nFrames-1, p->pVisited, p->nVisCounter ); - // resimulate the cone of influence of the cand classes - Vec_PtrForEachEntry( Aig_Obj_t *, p->vResimClasses, pRepr, i ) - { - ppClass = Ssw_ClassesReadClass( p->ppClasses, pRepr, &nSize ); - for ( k = 0; k < nSize; k++ ) - Ssw_SmlSimulateOneDyn_rec( p->pSml, ppClass[k], p->nFrames-1, p->pVisited, p->nVisCounter ); - } - - // check equivalence classes -// RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 1 ); -// RetValue2 = Ssw_ClassesRefine( p->ppClasses, 1 ); - // refine these nodes - RetValue1 = Ssw_ClassesRefineConst1Group( p->ppClasses, p->vResimConsts, 1 ); - RetValue2 = 0; - Vec_PtrForEachEntry( Aig_Obj_t *, p->vResimClasses, pRepr, i ) - RetValue2 += Ssw_ClassesRefineOneClass( p->ppClasses, pRepr, 1 ); - - // prepare simulation info for the next round - Vec_PtrCleanSimInfo( p->vSimInfo, 0, 1 ); - p->nPatterns = 0; - p->nSimRounds++; -p->timeSimSat += clock() - clk; - return RetValue1 > 0 || RetValue2 > 0; -} - -/**Function************************************************************* - - Synopsis [Performs fraiging for the internal nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ManSweepDyn( Ssw_Man_t * p ) -{ - Bar_Progress_t * pProgress = NULL; - Aig_Obj_t * pObj, * pObjNew; - int clk, i, f; - - // perform speculative reduction -clk = clock(); - // create timeframes - p->pFrames = Ssw_FramesWithClasses( p ); - Aig_ManFanoutStart( p->pFrames ); - p->nSRMiterMaxId = Aig_ManObjNumMax( p->pFrames ); - - // map constants and PIs of the last frame - f = p->pPars->nFramesK; - Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) ); - Saig_ManForEachPi( p->pAig, pObj, i ) - Ssw_ObjSetFrame( p, pObj, f, Aig_ObjCreatePi(p->pFrames) ); - Aig_ManSetPioNumbers( p->pFrames ); - // label nodes corresponding to primary inputs - Ssw_ManLabelPiNodes( p ); -p->timeReduce += clock() - clk; - - // prepare simulation info - assert( p->vSimInfo == NULL ); - p->vSimInfo = Vec_PtrAllocSimInfo( Aig_ManPiNum(p->pFrames), 1 ); - Vec_PtrCleanSimInfo( p->vSimInfo, 0, 1 ); - - // sweep internal nodes - p->fRefined = 0; - Ssw_ClassesClearRefined( p->ppClasses ); - if ( p->pPars->fVerbose ) - pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) ); - p->iNodeStart = 0; - Aig_ManForEachObj( p->pAig, pObj, i ) - { - if ( p->iNodeStart == 0 ) - p->iNodeStart = i; - if ( p->pPars->fVerbose ) - Bar_ProgressUpdate( pProgress, i, NULL ); - if ( Saig_ObjIsLo(p->pAig, pObj) ) - p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 0, NULL ); - else if ( Aig_ObjIsNode(pObj) ) - { - pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); - Ssw_ObjSetFrame( p, pObj, f, pObjNew ); - p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 0, NULL ); - } - // check if it is time to recycle the solver - if ( p->pMSat->pSat == NULL || - (p->pPars->nSatVarMax2 && - p->pMSat->nSatVars > p->pPars->nSatVarMax2 && - p->nRecycleCalls > p->pPars->nRecycleCalls2) ) - { - // resimulate - if ( p->nPatterns > 0 ) - { - p->iNodeLast = i; - if ( p->pPars->fLocalSim ) - Ssw_ManSweepResimulateDynLocal( p, f ); - else - Ssw_ManSweepResimulateDyn( p, f ); - p->iNodeStart = i+1; - } -// printf( "Recycling SAT solver with %d vars and %d calls.\n", -// p->pMSat->nSatVars, p->nRecycleCalls ); -// Aig_ManCleanMarkAB( p->pAig ); - Aig_ManCleanMarkAB( p->pFrames ); - // label nodes corresponding to primary inputs - Ssw_ManLabelPiNodes( p ); - // replace the solver - if ( p->pMSat ) - { - p->nVarsMax = ABC_MAX( p->nVarsMax, p->pMSat->nSatVars ); - p->nCallsMax = ABC_MAX( p->nCallsMax, p->pMSat->nSolverCalls ); - Ssw_SatStop( p->pMSat ); - p->nRecycles++; - p->nRecyclesTotal++; - p->nRecycleCalls = 0; - } - p->pMSat = Ssw_SatStart( 0 ); - assert( p->nPatterns == 0 ); - } - // resimulate - if ( p->nPatterns == 32 ) - { - p->iNodeLast = i; - if ( p->pPars->fLocalSim ) - Ssw_ManSweepResimulateDynLocal( p, f ); - else - Ssw_ManSweepResimulateDyn( p, f ); - p->iNodeStart = i+1; - } - } - // resimulate - if ( p->nPatterns > 0 ) - { - p->iNodeLast = i; - if ( p->pPars->fLocalSim ) - Ssw_ManSweepResimulateDynLocal( p, f ); - else - Ssw_ManSweepResimulateDyn( p, f ); - } - // collect stats - if ( p->pPars->fVerbose ) - Bar_ProgressStop( pProgress ); - - // cleanup -// Ssw_ClassesCheck( p->ppClasses ); - return p->fRefined; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ssw/sswFilter.c b/src/aig/ssw/sswFilter.c deleted file mode 100644 index 7298c5f8..00000000 --- a/src/aig/ssw/sswFilter.c +++ /dev/null @@ -1,493 +0,0 @@ -/**CFile**************************************************************** - - FileName [sswConstr.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Inductive prover with constraints.] - - Synopsis [One round of SAT sweeping.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 1, 2008.] - - Revision [$Id: sswConstr.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "sswInt.h" -#include "giaAig.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs fraiging for one node.] - - Description [Returns the fraiged node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ManRefineByFilterSim( Ssw_Man_t * p, int nFrames ) -{ - Aig_Obj_t * pObj, * pObjLi; - int f, i, RetValue1, RetValue2; - assert( nFrames > 0 ); - // assign register outputs - Saig_ManForEachLi( p->pAig, pObj, i ) - pObj->fMarkB = Aig_InfoHasBit( p->pPatWords, Saig_ManPiNum(p->pAig) + i ); - // simulate the timeframes - for ( f = 0; f < nFrames; f++ ) - { - // set the PI simulation information - Aig_ManConst1(p->pAig)->fMarkB = 1; - Saig_ManForEachPi( p->pAig, pObj, i ) - pObj->fMarkB = 0; - Saig_ManForEachLiLo( p->pAig, pObjLi, pObj, i ) - pObj->fMarkB = pObjLi->fMarkB; - // simulate internal nodes - Aig_ManForEachNode( p->pAig, pObj, i ) - pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ) - & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) ); - // assign the COs - Aig_ManForEachPo( p->pAig, pObj, i ) - pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ); - // transfer - if ( f == 0 ) - { // copy markB into phase - Aig_ManForEachObj( p->pAig, pObj, i ) - pObj->fPhase = pObj->fMarkB; - } - else - { // refine classes - RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 0 ); - RetValue2 = Ssw_ClassesRefine( p->ppClasses, 0 ); - } - } -} - - -/**Function************************************************************* - - Synopsis [Performs fraiging for one node.] - - Description [Returns the fraiged node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ManRollForward( Ssw_Man_t * p, int nFrames ) -{ - Aig_Obj_t * pObj, * pObjLi; - int f, i; - assert( nFrames > 0 ); - // assign register outputs - Saig_ManForEachLi( p->pAig, pObj, i ) - pObj->fMarkB = Aig_InfoHasBit( p->pPatWords, Saig_ManPiNum(p->pAig) + i ); - // simulate the timeframes - for ( f = 0; f < nFrames; f++ ) - { - // set the PI simulation information - Aig_ManConst1(p->pAig)->fMarkB = 1; - Saig_ManForEachPi( p->pAig, pObj, i ) - pObj->fMarkB = Aig_ManRandom(0) & 1; - Saig_ManForEachLiLo( p->pAig, pObjLi, pObj, i ) - pObj->fMarkB = pObjLi->fMarkB; - // simulate internal nodes - Aig_ManForEachNode( p->pAig, pObj, i ) - pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ) - & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) ); - // assign the COs - Aig_ManForEachPo( p->pAig, pObj, i ) - pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ); - } - // record the new pattern - Saig_ManForEachLi( p->pAig, pObj, i ) - if ( pObj->fMarkB ^ Aig_InfoHasBit(p->pPatWords, Saig_ManPiNum(p->pAig) + i) ) - Aig_InfoXorBit( p->pPatWords, Saig_ManPiNum(p->pAig) + i ); -} - -/**Function************************************************************* - - Synopsis [Performs fraiging for one node.] - - Description [Returns the fraiged node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ManFindStartingState( Ssw_Man_t * p, Abc_Cex_t * pCex ) -{ - Aig_Obj_t * pObj, * pObjLi; - int f, i, iBit; - // assign register outputs - Saig_ManForEachLi( p->pAig, pObj, i ) - pObj->fMarkB = 0; - // simulate the timeframes - iBit = pCex->nRegs; - for ( f = 0; f <= pCex->iFrame; f++ ) - { - // set the PI simulation information - Aig_ManConst1(p->pAig)->fMarkB = 1; - Saig_ManForEachPi( p->pAig, pObj, i ) - pObj->fMarkB = Aig_InfoHasBit( pCex->pData, iBit++ ); - Saig_ManForEachLiLo( p->pAig, pObjLi, pObj, i ) - pObj->fMarkB = pObjLi->fMarkB; - // simulate internal nodes - Aig_ManForEachNode( p->pAig, pObj, i ) - pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ) - & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) ); - // assign the COs - Aig_ManForEachPo( p->pAig, pObj, i ) - pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ); - } - assert( iBit == pCex->nBits ); - // check that the output failed as expected -- cannot check because it is not an SRM! -// pObj = Aig_ManPo( p->pAig, pCex->iPo ); -// if ( pObj->fMarkB != 1 ) -// printf( "The counter-example does not refine the output.\n" ); - // record the new pattern - Saig_ManForEachLo( p->pAig, pObj, i ) - if ( pObj->fMarkB ^ Aig_InfoHasBit(p->pPatWords, Saig_ManPiNum(p->pAig) + i) ) - Aig_InfoXorBit( p->pPatWords, Saig_ManPiNum(p->pAig) + i ); -} - -/**Function************************************************************* - - Synopsis [Performs fraiging for one node.] - - Description [Returns the fraiged node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ManSweepNodeFilter( Ssw_Man_t * p, Aig_Obj_t * pObj, int f ) -{ - Aig_Obj_t * pObjRepr, * pObjFraig, * pObjFraig2, * pObjReprFraig; - int RetValue; - // get representative of this class - pObjRepr = Aig_ObjRepr( p->pAig, pObj ); - if ( pObjRepr == NULL ) - return 0; - // get the fraiged node - pObjFraig = Ssw_ObjFrame( p, pObj, f ); - // get the fraiged representative - pObjReprFraig = Ssw_ObjFrame( p, pObjRepr, f ); - // check if constant 0 pattern distinquishes these nodes - assert( pObjFraig != NULL && pObjReprFraig != NULL ); - assert( (pObj->fPhase == pObjRepr->fPhase) == (Aig_ObjPhaseReal(pObjFraig) == Aig_ObjPhaseReal(pObjReprFraig)) ); - // if the fraiged nodes are the same, return - if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) ) - return 0; - // call equivalence checking - if ( Aig_Regular(pObjFraig) != Aig_ManConst1(p->pFrames) ) - RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) ); - else - RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjFraig), Aig_Regular(pObjReprFraig) ); - if ( RetValue == 1 ) // proved equivalent - { - pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase ); - Ssw_ObjSetFrame( p, pObj, f, pObjFraig2 ); - return 0; - } - if ( RetValue == -1 ) // timed out - { -// Ssw_ClassesRemoveNode( p->ppClasses, pObj ); - return 1; - } - // disproved equivalence - Ssw_SmlSavePatternAig( p, f ); - Ssw_ManResimulateBit( p, pObj, pObjRepr ); - assert( Aig_ObjRepr( p->pAig, pObj ) != pObjRepr ); - if ( Aig_ObjRepr( p->pAig, pObj ) == pObjRepr ) - { - printf( "Ssw_ManSweepNodeFilter(): Failed to refine representative.\n" ); - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Performs fraiging for the internal nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Ssw_ManSweepBmcFilter_rec( Ssw_Man_t * p, Aig_Obj_t * pObj, int f ) -{ - Aig_Obj_t * pObjNew, * pObjLi; - pObjNew = Ssw_ObjFrame( p, pObj, f ); - if ( pObjNew ) - return pObjNew; - assert( !Saig_ObjIsPi(p->pAig, pObj) ); - if ( Saig_ObjIsLo(p->pAig, pObj) ) - { - assert( f > 0 ); - pObjLi = Saig_ObjLoToLi( p->pAig, pObj ); - pObjNew = Ssw_ManSweepBmcFilter_rec( p, Aig_ObjFanin0(pObjLi), f-1 ); - pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObjLi) ); - } - else - { - assert( Aig_ObjIsNode(pObj) ); - Ssw_ManSweepBmcFilter_rec( p, Aig_ObjFanin0(pObj), f ); - Ssw_ManSweepBmcFilter_rec( p, Aig_ObjFanin1(pObj), f ); - pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); - } - Ssw_ObjSetFrame( p, pObj, f, pObjNew ); - assert( pObjNew != NULL ); - return pObjNew; -} - -/**Function************************************************************* - - Synopsis [Filter equivalence classes of nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ManSweepBmcFilter( Ssw_Man_t * p, int TimeLimit ) -{ - Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo; - int f, f1, i, clkTotal = clock(); - // start initialized timeframes - p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK ); - Saig_ManForEachLo( p->pAig, pObj, i ) - { - if ( Aig_InfoHasBit( p->pPatWords, Saig_ManPiNum(p->pAig) + i ) ) - { - Ssw_ObjSetFrame( p, pObj, 0, Aig_ManConst1(p->pFrames) ); -//printf( "1" ); - } - else - { - Ssw_ObjSetFrame( p, pObj, 0, Aig_ManConst0(p->pFrames) ); -//printf( "0" ); - } - } -//printf( "\n" ); - - // sweep internal nodes - for ( f = 0; f < p->pPars->nFramesK; f++ ) - { - // realloc mapping of timeframes - if ( f == p->nFrames-1 ) - { - Aig_Obj_t ** pNodeToFrames; - pNodeToFrames = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) * 2 * p->nFrames ); - for ( f1 = 0; f1 < p->nFrames; f1++ ) - { - Aig_ManForEachObj( p->pAig, pObj, i ) - pNodeToFrames[2*p->nFrames*pObj->Id + f1] = Ssw_ObjFrame( p, pObj, f1 ); - } - ABC_FREE( p->pNodeToFrames ); - p->pNodeToFrames = pNodeToFrames; - p->nFrames *= 2; - } - // map constants and PIs - Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) ); - Saig_ManForEachPi( p->pAig, pObj, i ) - { - pObjNew = Aig_ObjCreatePi(p->pFrames); - Ssw_ObjSetFrame( p, pObj, f, pObjNew ); - } - // sweep internal nodes - Aig_ManForEachNode( p->pAig, pObj, i ) - { - pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); - Ssw_ObjSetFrame( p, pObj, f, pObjNew ); - if ( Ssw_ManSweepNodeFilter( p, pObj, f ) ) - break; - } - // printout - if ( p->pPars->fVerbose ) - { - printf( "Frame %4d : ", f ); - Ssw_ClassesPrint( p->ppClasses, 0 ); - } - if ( i < Vec_PtrSize(p->pAig->vObjs) ) - { - if ( p->pPars->fVerbose ) - printf( "Exceeded the resource limits (%d conflicts). Quitting...\n", p->pPars->nBTLimit ); - break; - } - // quit if this is the last timeframe - if ( f == p->pPars->nFramesK - 1 ) - { - if ( p->pPars->fVerbose ) - printf( "Exceeded the time frame limit (%d time frames). Quitting...\n", p->pPars->nFramesK ); - break; - } - // check timeout - if ( TimeLimit && ((float)TimeLimit <= (float)(clock()-clkTotal)/(float)(CLOCKS_PER_SEC)) ) - break; - // transfer latch input to the latch outputs - Aig_ManForEachPo( p->pAig, pObj, i ) - Ssw_ObjSetFrame( p, pObj, f, Ssw_ObjChild0Fra(p, pObj, f) ); - // build logic cones for register outputs - Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) - { - pObjNew = Ssw_ObjFrame( p, pObjLi, f ); - Ssw_ObjSetFrame( p, pObjLo, f+1, pObjNew ); - Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pObjNew) );// - } - } - // verify -// Ssw_ClassesCheck( p->ppClasses ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Filter equivalence classes of nodes.] - - Description [Unrolls at most nFramesMax frames. Works with nConfMax - conflicts until the first undefined SAT call. Verbose prints the message.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SignalFilter( Aig_Man_t * pAig, int nFramesMax, int nConfMax, int nRounds, int TimeLimit, int TimeLimit2, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose ) -{ - Ssw_Pars_t Pars, * pPars = &Pars; - Ssw_Man_t * p; - int r, TimeLimitPart, clkTotal = clock(); - int nTimeToStop = TimeLimit ? TimeLimit + time(NULL) : 0; - assert( Aig_ManRegNum(pAig) > 0 ); - assert( Aig_ManConstrNum(pAig) == 0 ); - // consider the case of empty AIG - if ( Aig_ManNodeNum(pAig) == 0 ) - return; - // reset random numbers - Aig_ManRandom( 1 ); - // if parameters are not given, create them - Ssw_ManSetDefaultParams( pPars = &Pars ); - pPars->nFramesK = 3; //nFramesMax; - pPars->nBTLimit = nConfMax; - pPars->TimeLimit = TimeLimit; - pPars->fVerbose = fVerbose; - // start the induction manager - p = Ssw_ManCreate( pAig, pPars ); - pPars->nFramesK = nFramesMax; - // create trivial equivalence classes with all nodes being candidates for constant 1 - if ( pAig->pReprs == NULL ) - p->ppClasses = Ssw_ClassesPrepareSimple( pAig, fLatchOnly, 0 ); - else - p->ppClasses = Ssw_ClassesPrepareFromReprs( pAig ); - Ssw_ClassesSetData( p->ppClasses, NULL, NULL, Ssw_SmlObjIsConstBit, Ssw_SmlObjsAreEqualBit ); - assert( p->vInits == NULL ); - // compute starting state if needed - if ( pCex ) - Ssw_ManFindStartingState( p, pCex ); - // refine classes using BMC - for ( r = 0; r < nRounds; r++ ) - { - if ( p->pPars->fVerbose ) - printf( "Round %3d:\n", r ); - // start filtering equivalence classes - Ssw_ManRefineByFilterSim( p, p->pPars->nFramesK ); - if ( Ssw_ClassesCand1Num(p->ppClasses) == 0 && Ssw_ClassesClassNum(p->ppClasses) == 0 ) - { - printf( "All equivalences are refined away.\n" ); - break; - } - // printout - if ( p->pPars->fVerbose ) - { - printf( "Initial : " ); - Ssw_ClassesPrint( p->ppClasses, 0 ); - } - p->pMSat = Ssw_SatStart( 0 ); - TimeLimitPart = TimeLimit ? nTimeToStop - time(NULL) : 0; - if ( TimeLimit2 ) - { - if ( TimeLimitPart ) - TimeLimitPart = ABC_MIN( TimeLimitPart, TimeLimit2 ); - else - TimeLimitPart = TimeLimit2; - } - Ssw_ManSweepBmcFilter( p, TimeLimitPart ); - Ssw_SatStop( p->pMSat ); - p->pMSat = NULL; - Ssw_ManCleanup( p ); - // simulate pattern forward - Ssw_ManRollForward( p, p->pPars->nFramesK ); - // check timeout - if ( TimeLimit && time(NULL) > nTimeToStop ) - { - printf( "Reached timeout (%d seconds).\n", TimeLimit ); - break; - } - } - // cleanup - Aig_ManSetPhase( p->pAig ); - Aig_ManCleanMarkB( p->pAig ); - // cleanup - pPars->fVerbose = 0; - Ssw_ManStop( p ); -} - -/**Function************************************************************* - - Synopsis [Filter equivalence classes of nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SignalFilterGia( Gia_Man_t * p, int nFramesMax, int nConfMax, int nRounds, int TimeLimit, int TimeLimit2, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose ) -{ - Aig_Man_t * pAig; - pAig = Gia_ManToAigSimple( p ); - if ( p->pReprs != NULL ) - { - Gia_ManReprToAigRepr2( pAig, p ); - ABC_FREE( p->pReprs ); - ABC_FREE( p->pNexts ); - } - Ssw_SignalFilter( pAig, nFramesMax, nConfMax, nRounds, TimeLimit, TimeLimit2, pCex, fLatchOnly, fVerbose ); - Gia_ManReprFromAigRepr( pAig, p ); - Aig_ManStop( pAig ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ssw/sswInt.h b/src/aig/ssw/sswInt.h deleted file mode 100644 index 15756782..00000000 --- a/src/aig/ssw/sswInt.h +++ /dev/null @@ -1,302 +0,0 @@ -/**CFile**************************************************************** - - FileName [sswInt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Inductive prover with constraints.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 1, 2008.] - - Revision [$Id: sswInt.h,v 1.00 2008/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __SSW_INT_H__ -#define __SSW_INT_H__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "saig.h" -#include "satSolver.h" -#include "ssw.h" -#include "ioa.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Ssw_Man_t_ Ssw_Man_t; // signal correspondence manager -typedef struct Ssw_Frm_t_ Ssw_Frm_t; // unrolled frames manager -typedef struct Ssw_Sat_t_ Ssw_Sat_t; // SAT solver manager -typedef struct Ssw_Cla_t_ Ssw_Cla_t; // equivalence classe manager - -struct Ssw_Man_t_ -{ - // parameters - Ssw_Pars_t * pPars; // parameters - int nFrames; // for quick lookup - // AIGs used in the package - Aig_Man_t * pAig; // user-given AIG - Aig_Man_t * pFrames; // final AIG - Aig_Obj_t ** pNodeToFrames; // mapping of AIG nodes into FRAIG nodes - // equivalence classes - Ssw_Cla_t * ppClasses; // equivalence classes of nodes - int fRefined; // is set to 1 when refinement happens - // SAT solving - Ssw_Sat_t * pMSatBmc; // SAT manager for base case - Ssw_Sat_t * pMSat; // SAT manager for inductive case - // SAT solving (latch corr only) - Vec_Ptr_t * vSimInfo; // simulation information for the framed PIs - int nPatterns; // the number of patterns saved - int nSimRounds; // the number of simulation rounds performed - int nCallsCount; // the number of calls in this round - int nCallsDelta; // the number of calls to skip - int nCallsSat; // the number of SAT calls in this round - int nCallsUnsat; // the number of UNSAT calls in this round - int nRecycleCalls; // the number of calls since last recycling - int nRecycles; // the number of time SAT solver was recycled - int nRecyclesTotal; // the number of time SAT solver was recycled - int nVarsMax; // the maximum variables in the solver - int nCallsMax; // the maximum number of SAT calls - // uniqueness - Vec_Ptr_t * vCommon; // the set of common variables in the logic cones - int iOutputLit; // the output literal of the uniqueness constraint - Vec_Int_t * vDiffPairs; // is set to 1 if reg pair can be diff - int nUniques; // the number of uniqueness constraints used - int nUniquesAdded; // useful uniqueness constraints - int nUniquesUseful; // useful uniqueness constraints - // dynamic constraint addition - int nSRMiterMaxId; // max ID after which the last frame begins - Vec_Ptr_t * vNewLos; // new time frame LOs of to constrain - Vec_Int_t * vNewPos; // new time frame POs of to add constraints - int * pVisited; // flags to label visited nodes in each frame - int nVisCounter; // the traversal ID - // sequential simulation - Ssw_Sml_t * pSml; // the simulator - int iNodeStart; // the first node considered - int iNodeLast; // the last node considered - Vec_Ptr_t * vResimConsts; // resimulation constants - Vec_Ptr_t * vResimClasses; // resimulation classes - Vec_Int_t * vInits; // the init values of primary inputs under constraints - // counter example storage - int nPatWords; // the number of words in the counter example - unsigned * pPatWords; // the counter example - // constraints - int nConstrTotal; // the number of total constraints - int nConstrReduced; // the number of reduced constraints - int nStrangers; // the number of strange situations - // SAT calls statistics - int nSatCalls; // the number of SAT calls - int nSatProof; // the number of proofs - int nSatFailsReal; // the number of timeouts - int nSatCallsUnsat; // the number of unsat SAT calls - int nSatCallsSat; // the number of sat SAT calls - // node/register/lit statistics - int nLitsBeg; - int nLitsEnd; - int nNodesBeg; - int nNodesEnd; - int nRegsBeg; - int nRegsEnd; - // equiv statistis - int nConesTotal; - int nConesConstr; - int nEquivsTotal; - int nEquivsConstr; - int nNodesBegC; - int nNodesEndC; - int nRegsBegC; - int nRegsEndC; - // runtime stats - int timeBmc; // bounded model checking - int timeReduce; // speculative reduction - int timeMarkCones; // marking the cones not to be refined - int timeSimSat; // simulation of the counter-examples - int timeSat; // solving SAT - int timeSatSat; // sat - int timeSatUnsat; // unsat - int timeSatUndec; // undecided - int timeOther; // other runtime - int timeTotal; // total runtime -}; - -// internal SAT manager -struct Ssw_Sat_t_ -{ - Aig_Man_t * pAig; // the AIG manager - int fPolarFlip; // flips polarity - sat_solver * pSat; // recyclable SAT solver - int nSatVars; // the counter of SAT variables - Vec_Int_t * vSatVars; // mapping of each node into its SAT var - Vec_Ptr_t * vFanins; // fanins of the CNF node - Vec_Ptr_t * vUsedPis; // the PIs with SAT variables - int nSolverCalls; // the total number of SAT calls -}; - -// internal frames manager -struct Ssw_Frm_t_ -{ - Aig_Man_t * pAig; // user-given AIG - int nObjs; // offset in terms of AIG nodes - int nFrames; // the number of frames in current unrolling - Aig_Man_t * pFrames; // unrolled AIG - Vec_Ptr_t * vAig2Frm; // mapping of AIG nodes into frame nodes -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline int Ssw_ObjSatNum( Ssw_Sat_t * p, Aig_Obj_t * pObj ) { return Vec_IntGetEntry( p->vSatVars, pObj->Id ); } -static inline void Ssw_ObjSetSatNum( Ssw_Sat_t * p, Aig_Obj_t * pObj, int Num ) { Vec_IntSetEntry(p->vSatVars, pObj->Id, Num); } - -static inline int Ssw_ObjIsConst1Cand( Aig_Man_t * pAig, Aig_Obj_t * pObj ) -{ - return Aig_ObjRepr(pAig, pObj) == Aig_ManConst1(pAig); -} -static inline void Ssw_ObjSetConst1Cand( Aig_Man_t * pAig, Aig_Obj_t * pObj ) -{ - assert( !Ssw_ObjIsConst1Cand( pAig, pObj ) ); - Aig_ObjSetRepr( pAig, pObj, Aig_ManConst1(pAig) ); -} - -static inline Aig_Obj_t * Ssw_ObjFrame( Ssw_Man_t * p, Aig_Obj_t * pObj, int i ) { return p->pNodeToFrames[p->nFrames*pObj->Id + i]; } -static inline void Ssw_ObjSetFrame( Ssw_Man_t * p, Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { p->pNodeToFrames[p->nFrames*pObj->Id + i] = pNode; } - -static inline Aig_Obj_t * Ssw_ObjChild0Fra( Ssw_Man_t * p, Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Ssw_ObjFrame(p, Aig_ObjFanin0(pObj), i), Aig_ObjFaninC0(pObj)) : NULL; } -static inline Aig_Obj_t * Ssw_ObjChild1Fra( Ssw_Man_t * p, Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Ssw_ObjFrame(p, Aig_ObjFanin1(pObj), i), Aig_ObjFaninC1(pObj)) : NULL; } - -static inline Aig_Obj_t * Ssw_ObjFrame_( Ssw_Frm_t * p, Aig_Obj_t * pObj, int i ) { return (Aig_Obj_t *)Vec_PtrGetEntry( p->vAig2Frm, p->nObjs*i+pObj->Id ); } -static inline void Ssw_ObjSetFrame_( Ssw_Frm_t * p, Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { Vec_PtrSetEntry( p->vAig2Frm, p->nObjs*i+pObj->Id, pNode ); } - -static inline Aig_Obj_t * Ssw_ObjChild0Fra_( Ssw_Frm_t * p, Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Ssw_ObjFrame_(p, Aig_ObjFanin0(pObj), i), Aig_ObjFaninC0(pObj)) : NULL; } -static inline Aig_Obj_t * Ssw_ObjChild1Fra_( Ssw_Frm_t * p, Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Ssw_ObjFrame_(p, Aig_ObjFanin1(pObj), i), Aig_ObjFaninC1(pObj)) : NULL; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== sswAig.c ===================================================*/ -extern Ssw_Frm_t * Ssw_FrmStart( Aig_Man_t * pAig ); -extern void Ssw_FrmStop( Ssw_Frm_t * p ); -extern Aig_Man_t * Ssw_FramesWithClasses( Ssw_Man_t * p ); -extern Aig_Man_t * Ssw_SpeculativeReduction( Ssw_Man_t * p ); -/*=== sswBmc.c ===================================================*/ -/*=== sswClass.c =================================================*/ -extern Ssw_Cla_t * Ssw_ClassesStart( Aig_Man_t * pAig ); -extern void Ssw_ClassesSetData( Ssw_Cla_t * p, void * pManData, - unsigned (*pFuncNodeHash)(void *,Aig_Obj_t *), - int (*pFuncNodeIsConst)(void *,Aig_Obj_t *), - int (*pFuncNodesAreEqual)(void *,Aig_Obj_t *, Aig_Obj_t *) ); -extern void Ssw_ClassesStop( Ssw_Cla_t * p ); -extern Aig_Man_t * Ssw_ClassesReadAig( Ssw_Cla_t * p ); -extern Vec_Ptr_t * Ssw_ClassesGetRefined( Ssw_Cla_t * p ); -extern void Ssw_ClassesClearRefined( Ssw_Cla_t * p ); -extern int Ssw_ClassesCand1Num( Ssw_Cla_t * p ); -extern int Ssw_ClassesClassNum( Ssw_Cla_t * p ); -extern int Ssw_ClassesLitNum( Ssw_Cla_t * p ); -extern Aig_Obj_t ** Ssw_ClassesReadClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, int * pnSize ); -extern void Ssw_ClassesCollectClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, Vec_Ptr_t * vClass ); -extern void Ssw_ClassesCheck( Ssw_Cla_t * p ); -extern void Ssw_ClassesPrint( Ssw_Cla_t * p, int fVeryVerbose ); -extern void Ssw_ClassesRemoveNode( Ssw_Cla_t * p, Aig_Obj_t * pObj ); -extern Ssw_Cla_t * Ssw_ClassesPrepare( Aig_Man_t * pAig, int nFramesK, int fLatchCorr, int fConstCorr, int fOutputCorr, int nMaxLevs, int fVerbose ); -extern Ssw_Cla_t * Ssw_ClassesPrepareSimple( Aig_Man_t * pAig, int fLatchCorr, int nMaxLevs ); -extern Ssw_Cla_t * Ssw_ClassesPrepareFromReprs( Aig_Man_t * pAig ); -extern Ssw_Cla_t * Ssw_ClassesPrepareTargets( Aig_Man_t * pAig ); -extern Ssw_Cla_t * Ssw_ClassesPreparePairs( Aig_Man_t * pAig, Vec_Int_t ** pvClasses ); -extern Ssw_Cla_t * Ssw_ClassesPreparePairsSimple( Aig_Man_t * pMiter, Vec_Int_t * vPairs ); -extern int Ssw_ClassesRefine( Ssw_Cla_t * p, int fRecursive ); -extern int Ssw_ClassesRefineGroup( Ssw_Cla_t * p, Vec_Ptr_t * vReprs, int fRecursive ); -extern int Ssw_ClassesRefineOneClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, int fRecursive ); -extern int Ssw_ClassesRefineConst1Group( Ssw_Cla_t * p, Vec_Ptr_t * vRoots, int fRecursive ); -extern int Ssw_ClassesRefineConst1( Ssw_Cla_t * p, int fRecursive ); -extern int Ssw_ClassesPrepareRehash( Ssw_Cla_t * p, Vec_Ptr_t * vCands, int fConstCorr ); -/*=== sswCnf.c ===================================================*/ -extern Ssw_Sat_t * Ssw_SatStart( int fPolarFlip ); -extern void Ssw_SatStop( Ssw_Sat_t * p ); -extern void Ssw_CnfNodeAddToSolver( Ssw_Sat_t * p, Aig_Obj_t * pObj ); -extern int Ssw_CnfGetNodeValue( Ssw_Sat_t * p, Aig_Obj_t * pObjFraig ); -/*=== sswConstr.c ===================================================*/ -extern int Ssw_ManSweepBmcConstr( Ssw_Man_t * p ); -extern int Ssw_ManSweepConstr( Ssw_Man_t * p ); -extern void Ssw_ManRefineByConstrSim( Ssw_Man_t * p ); -/*=== sswCore.c ===================================================*/ -extern Aig_Man_t * Ssw_SignalCorrespondenceRefine( Ssw_Man_t * p ); -/*=== sswDyn.c ===================================================*/ -extern void Ssw_ManLoadSolver( Ssw_Man_t * p, Aig_Obj_t * pRepr, Aig_Obj_t * pObj ); -extern int Ssw_ManSweepDyn( Ssw_Man_t * p ); -/*=== sswLcorr.c ==========================================================*/ -extern int Ssw_ManSweepLatch( Ssw_Man_t * p ); -/*=== sswMan.c ===================================================*/ -extern Ssw_Man_t * Ssw_ManCreate( Aig_Man_t * pAig, Ssw_Pars_t * pPars ); -extern void Ssw_ManCleanup( Ssw_Man_t * p ); -extern void Ssw_ManStop( Ssw_Man_t * p ); -/*=== sswSat.c ===================================================*/ -extern int Ssw_NodesAreEquiv( Ssw_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ); -extern int Ssw_NodesAreConstrained( Ssw_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ); -extern int Ssw_NodeIsConstrained( Ssw_Man_t * p, Aig_Obj_t * pPoObj ); -/*=== sswSemi.c ===================================================*/ -extern int Ssw_FilterUsingSemi( Ssw_Man_t * pMan, int fCheckTargets, int nConfMax, int fVerbose ); -/*=== sswSim.c ===================================================*/ -extern unsigned Ssw_SmlObjHashWord( Ssw_Sml_t * p, Aig_Obj_t * pObj ); -extern int Ssw_SmlObjIsConstWord( Ssw_Sml_t * p, Aig_Obj_t * pObj ); -extern int Ssw_SmlObjsAreEqualWord( Ssw_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ); -extern int Ssw_SmlObjIsConstBit( void * p, Aig_Obj_t * pObj ); -extern int Ssw_SmlObjsAreEqualBit( void * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ); -extern void Ssw_SmlAssignRandomFrame( Ssw_Sml_t * p, Aig_Obj_t * pObj, int iFrame ); -extern Ssw_Sml_t * Ssw_SmlStart( Aig_Man_t * pAig, int nPref, int nFrames, int nWordsFrame ); -extern void Ssw_SmlClean( Ssw_Sml_t * p ); -extern void Ssw_SmlStop( Ssw_Sml_t * p ); -extern void Ssw_SmlObjAssignConst( Ssw_Sml_t * p, Aig_Obj_t * pObj, int fConst1, int iFrame ); -extern void Ssw_SmlObjSetWord( Ssw_Sml_t * p, Aig_Obj_t * pObj, unsigned Word, int iWord, int iFrame ); -extern void Ssw_SmlAssignDist1Plus( Ssw_Sml_t * p, unsigned * pPat ); -extern void Ssw_SmlSimulateOne( Ssw_Sml_t * p ); -extern void Ssw_SmlSimulateOneFrame( Ssw_Sml_t * p ); -extern void Ssw_SmlSimulateOneDyn_rec( Ssw_Sml_t * p, Aig_Obj_t * pObj, int f, int * pVisited, int nVisCounter ); -extern void Ssw_SmlResimulateSeq( Ssw_Sml_t * p ); -/*=== sswSimSat.c ===================================================*/ -extern void Ssw_ManResimulateBit( Ssw_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr ); -extern void Ssw_ManResimulateWord( Ssw_Man_t * p, Aig_Obj_t * pCand, Aig_Obj_t * pRepr, int f ); -/*=== sswSweep.c ===================================================*/ -extern int Ssw_ManGetSatVarValue( Ssw_Man_t * p, Aig_Obj_t * pObj, int f ); -extern void Ssw_SmlSavePatternAig( Ssw_Man_t * p, int f ); -extern int Ssw_ManSweepNode( Ssw_Man_t * p, Aig_Obj_t * pObj, int f, int fBmc, Vec_Int_t * vPairs ); -extern int Ssw_ManSweepBmc( Ssw_Man_t * p ); -extern int Ssw_ManSweep( Ssw_Man_t * p ); -/*=== sswUnique.c ===================================================*/ -extern void Ssw_UniqueRegisterPairInfo( Ssw_Man_t * p ); -extern int Ssw_ManUniqueOne( Ssw_Man_t * p, Aig_Obj_t * pRepr, Aig_Obj_t * pObj, int fVerbose ); -extern int Ssw_ManUniqueAddConstraint( Ssw_Man_t * p, Vec_Ptr_t * vCommon, int f1, int f2 ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/ssw/sswIslands.c b/src/aig/ssw/sswIslands.c deleted file mode 100644 index 0802aca5..00000000 --- a/src/aig/ssw/sswIslands.c +++ /dev/null @@ -1,598 +0,0 @@ -/**CFile**************************************************************** - - FileName [sswIslands.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Inductive prover with constraints.] - - Synopsis [Detection of islands of difference.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 1, 2008.] - - Revision [$Id: sswIslands.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "sswInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates pair of structurally equivalent nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_CreatePair( Vec_Int_t * vPairs, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) -{ - pObj0->pData = pObj1; - pObj1->pData = pObj0; - Vec_IntPush( vPairs, pObj0->Id ); - Vec_IntPush( vPairs, pObj1->Id ); -} - -/**Function************************************************************* - - Synopsis [Establishes relationship between nodes using pairing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_MatchingStart( Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairs ) -{ - Aig_Obj_t * pObj0, * pObj1; - int i; - // create matching - Aig_ManCleanData( p0 ); - Aig_ManCleanData( p1 ); - for ( i = 0; i < Vec_IntSize(vPairs); i += 2 ) - { - pObj0 = Aig_ManObj( p0, Vec_IntEntry(vPairs, i) ); - pObj1 = Aig_ManObj( p1, Vec_IntEntry(vPairs, i+1) ); - assert( pObj0->pData == NULL ); - assert( pObj1->pData == NULL ); - pObj0->pData = pObj1; - pObj1->pData = pObj0; - } - // make sure constants are matched - pObj0 = Aig_ManConst1( p0 ); - pObj1 = Aig_ManConst1( p1 ); - assert( pObj0->pData == pObj1 ); - assert( pObj1->pData == pObj0 ); - // make sure PIs are matched - Saig_ManForEachPi( p0, pObj0, i ) - { - pObj1 = Aig_ManPi( p1, i ); - assert( pObj0->pData == pObj1 ); - assert( pObj1->pData == pObj0 ); - } - // make sure the POs are not matched - Aig_ManForEachPo( p0, pObj0, i ) - { - pObj1 = Aig_ManPo( p1, i ); - assert( pObj0->pData == NULL ); - assert( pObj1->pData == NULL ); - } - - // check that LIs/LOs are matched in sync - Saig_ManForEachLo( p0, pObj0, i ) - { - if ( pObj0->pData == NULL ) - continue; - pObj1 = (Aig_Obj_t *)pObj0->pData; - if ( !Saig_ObjIsLo(p1, pObj1) ) - printf( "Mismatch between LO pairs.\n" ); - } - Saig_ManForEachLo( p1, pObj1, i ) - { - if ( pObj1->pData == NULL ) - continue; - pObj0 = (Aig_Obj_t *)pObj1->pData; - if ( !Saig_ObjIsLo(p0, pObj0) ) - printf( "Mismatch between LO pairs.\n" ); - } -} - -/**Function************************************************************* - - Synopsis [Establishes relationship between nodes using pairing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_MatchingExtendOne( Aig_Man_t * p, Vec_Ptr_t * vNodes ) -{ - Aig_Obj_t * pNext, * pObj; - int i, k, iFan; - Vec_PtrClear( vNodes ); - Aig_ManIncrementTravId( p ); - Aig_ManForEachObj( p, pObj, i ) - { - if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) ) - continue; - if ( pObj->pData != NULL ) - continue; - if ( Saig_ObjIsLo(p, pObj) ) - { - pNext = Saig_ObjLoToLi(p, pObj); - pNext = Aig_ObjFanin0(pNext); - if ( pNext->pData && !Aig_ObjIsTravIdCurrent(p, pNext) && !Aig_ObjIsConst1(pNext) ) - { - Aig_ObjSetTravIdCurrent(p, pNext); - Vec_PtrPush( vNodes, pNext ); - } - } - if ( Aig_ObjIsNode(pObj) ) - { - pNext = Aig_ObjFanin0(pObj); - if ( pNext->pData && !Aig_ObjIsTravIdCurrent(p, pNext) ) - { - Aig_ObjSetTravIdCurrent(p, pNext); - Vec_PtrPush( vNodes, pNext ); - } - pNext = Aig_ObjFanin1(pObj); - if ( pNext->pData && !Aig_ObjIsTravIdCurrent(p, pNext) ) - { - Aig_ObjSetTravIdCurrent(p, pNext); - Vec_PtrPush( vNodes, pNext ); - } - } - Aig_ObjForEachFanout( p, pObj, pNext, iFan, k ) - { - if ( Saig_ObjIsPo(p, pNext) ) - continue; - if ( Saig_ObjIsLi(p, pNext) ) - pNext = Saig_ObjLiToLo(p, pNext); - if ( pNext->pData && !Aig_ObjIsTravIdCurrent(p, pNext) ) - { - Aig_ObjSetTravIdCurrent(p, pNext); - Vec_PtrPush( vNodes, pNext ); - } - } - } -} - -/**Function************************************************************* - - Synopsis [Establishes relationship between nodes using pairing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_MatchingCountUnmached( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i, Counter = 0; - Aig_ManForEachObj( p, pObj, i ) - { - if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) ) - continue; - if ( pObj->pData != NULL ) - continue; - Counter++; - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Establishes relationship between nodes using pairing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_MatchingExtend( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose ) -{ - Vec_Ptr_t * vNodes0, * vNodes1; - Aig_Obj_t * pNext0, * pNext1; - int d, k; - Aig_ManFanoutStart(p0); - Aig_ManFanoutStart(p1); - vNodes0 = Vec_PtrAlloc( 1000 ); - vNodes1 = Vec_PtrAlloc( 1000 ); - if ( fVerbose ) - { - int nUnmached = Ssw_MatchingCountUnmached(p0); - printf( "Extending islands by %d steps:\n", nDist ); - printf( "%2d : Total = %6d. Unmatched = %6d. Ratio = %6.2f %%\n", - 0, Aig_ManPiNum(p0) + Aig_ManNodeNum(p0), - nUnmached, 100.0 * nUnmached/(Aig_ManPiNum(p0) + Aig_ManNodeNum(p0)) ); - } - for ( d = 0; d < nDist; d++ ) - { - Ssw_MatchingExtendOne( p0, vNodes0 ); - Ssw_MatchingExtendOne( p1, vNodes1 ); - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes0, pNext0, k ) - { - pNext1 = (Aig_Obj_t *)pNext0->pData; - if ( pNext1 == NULL ) - continue; - assert( pNext1->pData == pNext0 ); - if ( Saig_ObjIsPi(p0, pNext1) ) - continue; - pNext0->pData = NULL; - pNext1->pData = NULL; - } - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes1, pNext0, k ) - { - pNext1 = (Aig_Obj_t *)pNext0->pData; - if ( pNext1 == NULL ) - continue; - assert( pNext1->pData == pNext0 ); - if ( Saig_ObjIsPi(p1, pNext1) ) - continue; - pNext0->pData = NULL; - pNext1->pData = NULL; - } - if ( fVerbose ) - { - int nUnmached = Ssw_MatchingCountUnmached(p0); - printf( "%2d : Total = %6d. Unmatched = %6d. Ratio = %6.2f %%\n", - d+1, Aig_ManPiNum(p0) + Aig_ManNodeNum(p0), - nUnmached, 100.0 * nUnmached/(Aig_ManPiNum(p0) + Aig_ManNodeNum(p0)) ); - } - } - Vec_PtrFree( vNodes0 ); - Vec_PtrFree( vNodes1 ); - Aig_ManFanoutStop(p0); - Aig_ManFanoutStop(p1); -} - -/**Function************************************************************* - - Synopsis [Used differences in p0 to complete p1.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_MatchingComplete( Aig_Man_t * p0, Aig_Man_t * p1 ) -{ - Vec_Ptr_t * vNewLis; - Aig_Obj_t * pObj0, * pObj0Li, * pObj1; - int i; - // create register outputs in p0 that are absent in p1 - vNewLis = Vec_PtrAlloc( 100 ); - Saig_ManForEachLiLo( p0, pObj0Li, pObj0, i ) - { - if ( pObj0->pData != NULL ) - continue; - pObj1 = Aig_ObjCreatePi( p1 ); - pObj0->pData = pObj1; - pObj1->pData = pObj0; - Vec_PtrPush( vNewLis, pObj0Li ); - } - // add missing nodes in the topological order - Aig_ManForEachNode( p0, pObj0, i ) - { - if ( pObj0->pData != NULL ) - continue; - pObj1 = Aig_And( p1, Aig_ObjChild0Copy(pObj0), Aig_ObjChild1Copy(pObj0) ); - pObj0->pData = pObj1; - pObj1->pData = pObj0; - } - // create register outputs in p0 that are absent in p1 - Vec_PtrForEachEntry( Aig_Obj_t *, vNewLis, pObj0Li, i ) - Aig_ObjCreatePo( p1, Aig_ObjChild0Copy(pObj0Li) ); - // increment the number of registers - Aig_ManSetRegNum( p1, Aig_ManRegNum(p1) + Vec_PtrSize(vNewLis) ); - Vec_PtrFree( vNewLis ); -} - - -/**Function************************************************************* - - Synopsis [Derives matching for all pairs.] - - Description [Modifies both AIGs.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Ssw_MatchingPairs( Aig_Man_t * p0, Aig_Man_t * p1 ) -{ - Vec_Int_t * vPairsNew; - Aig_Obj_t * pObj0, * pObj1; - int i; - // check correctness - assert( Aig_ManPiNum(p0) == Aig_ManPiNum(p1) ); - assert( Aig_ManPoNum(p0) == Aig_ManPoNum(p1) ); - assert( Aig_ManRegNum(p0) == Aig_ManRegNum(p1) ); - assert( Aig_ManObjNum(p0) == Aig_ManObjNum(p1) ); - // create complete pairs - vPairsNew = Vec_IntAlloc( 2*Aig_ManObjNum(p0) ); - Aig_ManForEachObj( p0, pObj0, i ) - { - if ( Aig_ObjIsPo(pObj0) ) - continue; - pObj1 = (Aig_Obj_t *)pObj0->pData; - Vec_IntPush( vPairsNew, pObj0->Id ); - Vec_IntPush( vPairsNew, pObj1->Id ); - } - return vPairsNew; -} - - - - - -/**Function************************************************************* - - Synopsis [Transfers the result of matching to miter.] - - Description [The array of pairs should be complete.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Ssw_MatchingMiter( Aig_Man_t * pMiter, Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairsAll ) -{ - Vec_Int_t * vPairsMiter; - Aig_Obj_t * pObj0, * pObj1; - int i; - // create matching of nodes in the miter - vPairsMiter = Vec_IntAlloc( 2*Aig_ManObjNum(p0) ); - for ( i = 0; i < Vec_IntSize(vPairsAll); i += 2 ) - { - pObj0 = Aig_ManObj( p0, Vec_IntEntry(vPairsAll, i) ); - pObj1 = Aig_ManObj( p1, Vec_IntEntry(vPairsAll, i+1) ); - assert( pObj0->pData != NULL ); - assert( pObj1->pData != NULL ); - if ( pObj0->pData == pObj1->pData ) - continue; - if ( Aig_ObjIsNone((Aig_Obj_t *)pObj0->pData) || Aig_ObjIsNone((Aig_Obj_t *)pObj1->pData) ) - continue; - // get the miter nodes - pObj0 = (Aig_Obj_t *)pObj0->pData; - pObj1 = (Aig_Obj_t *)pObj1->pData; - assert( !Aig_IsComplement(pObj0) ); - assert( !Aig_IsComplement(pObj1) ); - assert( Aig_ObjType(pObj0) == Aig_ObjType(pObj1) ); - if ( Aig_ObjIsPo(pObj0) ) - continue; - assert( Aig_ObjIsNode(pObj0) || Saig_ObjIsLo(pMiter, pObj0) ); - assert( Aig_ObjIsNode(pObj1) || Saig_ObjIsLo(pMiter, pObj1) ); - assert( pObj0->Id < pObj1->Id ); - Vec_IntPush( vPairsMiter, pObj0->Id ); - Vec_IntPush( vPairsMiter, pObj1->Id ); - } - return vPairsMiter; -} - - - - - -/**Function************************************************************* - - Synopsis [Solves SEC using structural similarity.] - - Description [Modifies both p0 and p1 by adding extra logic.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Ssw_SecWithSimilaritySweep( Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairs, Ssw_Pars_t * pPars ) -{ - Ssw_Man_t * p; - Vec_Int_t * vPairsAll, * vPairsMiter; - Aig_Man_t * pMiter, * pAigNew; - // derive full matching - Ssw_MatchingStart( p0, p1, vPairs ); - if ( pPars->nIsleDist ) - Ssw_MatchingExtend( p0, p1, pPars->nIsleDist, pPars->fVerbose ); - Ssw_MatchingComplete( p0, p1 ); - Ssw_MatchingComplete( p1, p0 ); - vPairsAll = Ssw_MatchingPairs( p0, p1 ); - // create miter and transfer matching - pMiter = Saig_ManCreateMiter( p0, p1, 0 ); - vPairsMiter = Ssw_MatchingMiter( pMiter, p0, p1, vPairsAll ); - Vec_IntFree( vPairsAll ); - // start the induction manager - p = Ssw_ManCreate( pMiter, pPars ); - // create equivalence classes using these IDs - if ( p->pPars->fPartSigCorr ) - p->ppClasses = Ssw_ClassesPreparePairsSimple( pMiter, vPairsMiter ); - else - p->ppClasses = Ssw_ClassesPrepare( pMiter, pPars->nFramesK, pPars->fLatchCorr, pPars->fConstCorr, pPars->fOutputCorr, pPars->nMaxLevs, pPars->fVerbose ); - if ( p->pPars->fDumpSRInit ) - { - if ( p->pPars->fPartSigCorr ) - { - Aig_Man_t * pSRed = Ssw_SpeculativeReduction( p ); - Aig_ManDumpBlif( pSRed, "srm_part.blif", NULL, NULL ); - Aig_ManStop( pSRed ); - printf( "Speculatively reduced miter is saved in file \"%s\".\n", "srm_part.blif" ); - } - else - printf( "Dumping speculative miter is possible only for partial signal correspondence (switch \"-c\").\n" ); - } - p->pSml = Ssw_SmlStart( pMiter, 0, 1 + p->pPars->nFramesAddSim, 1 ); - Ssw_ClassesSetData( p->ppClasses, p->pSml, (unsigned(*)(void *,Aig_Obj_t *))Ssw_SmlObjHashWord, (int(*)(void *,Aig_Obj_t *))Ssw_SmlObjIsConstWord, (int(*)(void *,Aig_Obj_t *,Aig_Obj_t *))Ssw_SmlObjsAreEqualWord ); - // perform refinement of classes - pAigNew = Ssw_SignalCorrespondenceRefine( p ); - // cleanup - Ssw_ManStop( p ); - Aig_ManStop( pMiter ); - Vec_IntFree( vPairsMiter ); - return pAigNew; -} - -/**Function************************************************************* - - Synopsis [Solves SEC with structural similarity.] - - Description [The first two arguments are pointers to the AIG managers. - The third argument is the array of pairs of IDs of structurally equivalent - nodes from the first and second managers, respectively.] - - SideEffects [The managers will be updated by adding "islands of difference".] - - SeeAlso [] - -***********************************************************************/ -int Ssw_SecWithSimilarityPairs( Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairs, Ssw_Pars_t * pPars ) -{ - Ssw_Pars_t Pars; - Aig_Man_t * pAigRes; - int RetValue, clk = clock(); - // derive parameters if not given - if ( pPars == NULL ) - Ssw_ManSetDefaultParams( pPars = &Pars ); - // reduce the AIG with pairs - pAigRes = Ssw_SecWithSimilaritySweep( p0, p1, vPairs, pPars ); - // report the result of verification - RetValue = Ssw_MiterStatus( pAigRes, 1 ); - if ( RetValue == 1 ) - printf( "Verification successful. " ); - else if ( RetValue == 0 ) - printf( "Verification failed with a counter-example. " ); - else - printf( "Verification UNDECIDED. The number of remaining regs = %d (total = %d). ", - Aig_ManRegNum(pAigRes), Aig_ManRegNum(p0)+Aig_ManRegNum(p1) ); - ABC_PRT( "Time", clock() - clk ); - Aig_ManStop( pAigRes ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Dummy procedure to detect structural similarity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Saig_StrSimPerformMatching_hack( Aig_Man_t * p0, Aig_Man_t * p1 ) -{ - Vec_Int_t * vPairs; - Aig_Obj_t * pObj; - int i; - // create array of pairs - vPairs = Vec_IntAlloc( 100 ); - Aig_ManForEachObj( p0, pObj, i ) - { - if ( !Aig_ObjIsConst1(pObj) && !Aig_ObjIsPi(pObj) && !Aig_ObjIsNode(pObj) ) - continue; - Vec_IntPush( vPairs, i ); - Vec_IntPush( vPairs, i ); - } - return vPairs; -} - -/**Function************************************************************* - - Synopsis [Solves SEC with structural similarity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_SecWithSimilarity( Aig_Man_t * p0, Aig_Man_t * p1, Ssw_Pars_t * pPars ) -{ - Vec_Int_t * vPairs; - Aig_Man_t * pPart0, * pPart1; - int RetValue; - if ( pPars->fVerbose ) - printf( "Performing sequential verification using structural similarity.\n" ); - // consider the case when a miter is given - if ( p1 == NULL ) - { - if ( pPars->fVerbose ) - { - Aig_ManPrintStats( p0 ); - } - // demiter the miter - if ( !Saig_ManDemiterSimpleDiff( p0, &pPart0, &pPart1 ) ) - { - printf( "Demitering has failed.\n" ); - return -1; - } - } - else - { - pPart0 = Aig_ManDupSimple( p0 ); - pPart1 = Aig_ManDupSimple( p1 ); - } - if ( pPars->fVerbose ) - { -// Aig_ManPrintStats( pPart0 ); -// Aig_ManPrintStats( pPart1 ); - if ( p1 == NULL ) - { -// Aig_ManDumpBlif( pPart0, "part0.blif", NULL, NULL ); -// Aig_ManDumpBlif( pPart1, "part1.blif", NULL, NULL ); -// printf( "The result of demitering is written into files \"%s\" and \"%s\".\n", "part0.blif", "part1.blif" ); - } - } - assert( Aig_ManRegNum(pPart0) > 0 ); - assert( Aig_ManRegNum(pPart1) > 0 ); - assert( Saig_ManPiNum(pPart0) == Saig_ManPiNum(pPart1) ); - assert( Saig_ManPoNum(pPart0) == Saig_ManPoNum(pPart1) ); - // derive pairs -// vPairs = Saig_StrSimPerformMatching_hack( pPart0, pPart1 ); - vPairs = Saig_StrSimPerformMatching( pPart0, pPart1, 0, pPars->fVerbose, NULL ); - RetValue = Ssw_SecWithSimilarityPairs( pPart0, pPart1, vPairs, pPars ); - Aig_ManStop( pPart0 ); - Aig_ManStop( pPart1 ); - Vec_IntFree( vPairs ); - return RetValue; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ssw/sswLcorr.c b/src/aig/ssw/sswLcorr.c deleted file mode 100644 index 7cd94727..00000000 --- a/src/aig/ssw/sswLcorr.c +++ /dev/null @@ -1,336 +0,0 @@ -/**CFile**************************************************************** - - FileName [sswLcorr.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Inductive prover with constraints.] - - Synopsis [Latch correspondence.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 1, 2008.] - - Revision [$Id: sswLcorr.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "sswInt.h" -//#include "bar.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Tranfers simulation information from FRAIG to AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ManSweepTransfer( Ssw_Man_t * p ) -{ - Aig_Obj_t * pObj, * pObjFraig; - unsigned * pInfo; - int i; - // transfer simulation information - Aig_ManForEachPi( p->pAig, pObj, i ) - { - pObjFraig = Ssw_ObjFrame( p, pObj, 0 ); - if ( pObjFraig == Aig_ManConst0(p->pFrames) ) - { - Ssw_SmlObjAssignConst( p->pSml, pObj, 0, 0 ); - continue; - } - assert( !Aig_IsComplement(pObjFraig) ); - assert( Aig_ObjIsPi(pObjFraig) ); - pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjPioNum(pObjFraig) ); - Ssw_SmlObjSetWord( p->pSml, pObj, pInfo[0], 0, 0 ); - } -} - -/**Function************************************************************* - - Synopsis [Performs one round of simulation with counter-examples.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ManSweepResimulate( Ssw_Man_t * p ) -{ - int RetValue1, RetValue2, clk = clock(); - // transfer PI simulation information from storage - Ssw_ManSweepTransfer( p ); - // simulate internal nodes - Ssw_SmlSimulateOneFrame( p->pSml ); - // check equivalence classes - RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 1 ); - RetValue2 = Ssw_ClassesRefine( p->ppClasses, 1 ); - // prepare simulation info for the next round - Vec_PtrCleanSimInfo( p->vSimInfo, 0, 1 ); - p->nPatterns = 0; - p->nSimRounds++; -p->timeSimSat += clock() - clk; - return RetValue1 > 0 || RetValue2 > 0; -} - -/**Function************************************************************* - - Synopsis [Saves one counter-example into internal storage.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SmlAddPattern( Ssw_Man_t * p, Aig_Obj_t * pRepr, Aig_Obj_t * pCand ) -{ - Aig_Obj_t * pObj; - unsigned * pInfo; - int i, nVarNum, Value; - Vec_PtrForEachEntry( Aig_Obj_t *, p->pMSat->vUsedPis, pObj, i ) - { - nVarNum = Ssw_ObjSatNum( p->pMSat, pObj ); - assert( nVarNum > 0 ); - Value = sat_solver_var_value( p->pMSat->pSat, nVarNum ); - if ( Value == 0 ) - continue; - pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjPioNum(pObj) ); - Aig_InfoSetBit( pInfo, p->nPatterns ); - } -} - -/**Function************************************************************* - - Synopsis [Builds fraiged logic cone of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ManBuildCone_rec( Ssw_Man_t * p, Aig_Obj_t * pObj ) -{ - Aig_Obj_t * pObjNew; - assert( !Aig_IsComplement(pObj) ); - if ( Ssw_ObjFrame( p, pObj, 0 ) ) - return; - assert( Aig_ObjIsNode(pObj) ); - Ssw_ManBuildCone_rec( p, Aig_ObjFanin0(pObj) ); - Ssw_ManBuildCone_rec( p, Aig_ObjFanin1(pObj) ); - pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, 0), Ssw_ObjChild1Fra(p, pObj, 0) ); - Ssw_ObjSetFrame( p, pObj, 0, pObjNew ); -} - -/**Function************************************************************* - - Synopsis [Recycles the SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ManSweepLatchOne( Ssw_Man_t * p, Aig_Obj_t * pObjRepr, Aig_Obj_t * pObj ) -{ - Aig_Obj_t * pObjFraig, * pObjReprFraig, * pObjLi; - int RetValue, clk; - assert( Aig_ObjIsPi(pObj) ); - assert( Aig_ObjIsPi(pObjRepr) || Aig_ObjIsConst1(pObjRepr) ); - // check if it makes sense to skip some calls - if ( p->nCallsCount > 100 && p->nCallsUnsat < p->nCallsSat ) - { - if ( ++p->nCallsDelta < 0 ) - return; - } - p->nCallsDelta = 0; -clk = clock(); - // get the fraiged node - pObjLi = Saig_ObjLoToLi( p->pAig, pObj ); - Ssw_ManBuildCone_rec( p, Aig_ObjFanin0(pObjLi) ); - pObjFraig = Ssw_ObjChild0Fra( p, pObjLi, 0 ); - // get the fraiged representative - if ( Aig_ObjIsPi(pObjRepr) ) - { - pObjLi = Saig_ObjLoToLi( p->pAig, pObjRepr ); - Ssw_ManBuildCone_rec( p, Aig_ObjFanin0(pObjLi) ); - pObjReprFraig = Ssw_ObjChild0Fra( p, pObjLi, 0 ); - } - else - pObjReprFraig = Ssw_ObjFrame( p, pObjRepr, 0 ); -p->timeReduce += clock() - clk; - // if the fraiged nodes are the same, return - if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) ) - return; - p->nRecycleCalls++; - p->nCallsCount++; - - // check equivalence of the two nodes - if ( (pObj->fPhase == pObjRepr->fPhase) != (Aig_ObjPhaseReal(pObjFraig) == Aig_ObjPhaseReal(pObjReprFraig)) ) - { - p->nPatterns++; - p->nStrangers++; - p->fRefined = 1; - } - else - { - RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) ); - if ( RetValue == 1 ) // proved equivalence - { - p->nCallsUnsat++; - return; - } - if ( RetValue == -1 ) // timed out - { - Ssw_ClassesRemoveNode( p->ppClasses, pObj ); - p->nCallsUnsat++; - p->fRefined = 1; - return; - } - else // disproved equivalence - { - Ssw_SmlAddPattern( p, pObjRepr, pObj ); - p->nPatterns++; - p->nCallsSat++; - p->fRefined = 1; - } - } -} - -/**Function************************************************************* - - Synopsis [Performs one iteration of sweeping latches.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ManSweepLatch( Ssw_Man_t * p ) -{ -// Bar_Progress_t * pProgress = NULL; - Vec_Ptr_t * vClass; - Aig_Obj_t * pObj, * pRepr, * pTemp; - int i, k; - - // start the timeframe - p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) ); - // map constants and PIs - Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), 0, Aig_ManConst1(p->pFrames) ); - Saig_ManForEachPi( p->pAig, pObj, i ) - Ssw_ObjSetFrame( p, pObj, 0, Aig_ObjCreatePi(p->pFrames) ); - - // implement equivalence classes - Saig_ManForEachLo( p->pAig, pObj, i ) - { - pRepr = Aig_ObjRepr( p->pAig, pObj ); - if ( pRepr == NULL ) - { - pTemp = Aig_ObjCreatePi(p->pFrames); - pTemp->pData = pObj; - } - else - pTemp = Aig_NotCond( Ssw_ObjFrame(p, pRepr, 0), pRepr->fPhase ^ pObj->fPhase ); - Ssw_ObjSetFrame( p, pObj, 0, pTemp ); - } - Aig_ManSetPioNumbers( p->pFrames ); - - // prepare simulation info - assert( p->vSimInfo == NULL ); - p->vSimInfo = Vec_PtrAllocSimInfo( Aig_ManPiNum(p->pFrames), 1 ); - Vec_PtrCleanSimInfo( p->vSimInfo, 0, 1 ); - - // go through the registers -// if ( p->pPars->fVerbose ) -// pProgress = Bar_ProgressStart( stdout, Aig_ManRegNum(p->pAig) ); - vClass = Vec_PtrAlloc( 100 ); - p->fRefined = 0; - p->nCallsCount = p->nCallsSat = p->nCallsUnsat = 0; - Saig_ManForEachLo( p->pAig, pObj, i ) - { -// if ( p->pPars->fVerbose ) -// Bar_ProgressUpdate( pProgress, i, NULL ); - // consider the case of constant candidate - if ( Ssw_ObjIsConst1Cand( p->pAig, pObj ) ) - Ssw_ManSweepLatchOne( p, Aig_ManConst1(p->pAig), pObj ); - else - { - // consider the case of equivalence class - Ssw_ClassesCollectClass( p->ppClasses, pObj, vClass ); - if ( Vec_PtrSize(vClass) == 0 ) - continue; - // try to prove equivalences in this class - Vec_PtrForEachEntry( Aig_Obj_t *, vClass, pTemp, k ) - if ( Aig_ObjRepr(p->pAig, pTemp) == pObj ) - { - Ssw_ManSweepLatchOne( p, pObj, pTemp ); - if ( p->nPatterns == 32 ) - break; - } - } - // resimulate - if ( p->nPatterns == 32 ) - Ssw_ManSweepResimulate( p ); - // attempt recycling the SAT solver - if ( p->pPars->nSatVarMax && - p->pMSat->nSatVars > p->pPars->nSatVarMax && - p->nRecycleCalls > p->pPars->nRecycleCalls ) - { - p->nVarsMax = ABC_MAX( p->nVarsMax, p->pMSat->nSatVars ); - p->nCallsMax = ABC_MAX( p->nCallsMax, p->pMSat->nSolverCalls ); - Ssw_SatStop( p->pMSat ); - p->pMSat = Ssw_SatStart( 0 ); - p->nRecycles++; - p->nRecycleCalls = 0; - } - } -// ABC_PRT( "reduce", p->timeReduce ); -// Aig_TableProfile( p->pFrames ); -// printf( "And gates = %d\n", Aig_ManNodeNum(p->pFrames) ); - // resimulate - if ( p->nPatterns > 0 ) - Ssw_ManSweepResimulate( p ); - // cleanup - Vec_PtrFree( vClass ); -// if ( p->pPars->fVerbose ) -// Bar_ProgressStop( pProgress ); - - // cleanup -// Ssw_ClassesCheck( p->ppClasses ); - return p->fRefined; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ssw/sswMan.c b/src/aig/ssw/sswMan.c deleted file mode 100644 index 0f1317e1..00000000 --- a/src/aig/ssw/sswMan.c +++ /dev/null @@ -1,218 +0,0 @@ -/**CFile**************************************************************** - - FileName [sswMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Inductive prover with constraints.] - - Synopsis [Calls to the SAT solver.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 1, 2008.] - - Revision [$Id: sswMan.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "sswInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ssw_Man_t * Ssw_ManCreate( Aig_Man_t * pAig, Ssw_Pars_t * pPars ) -{ - Ssw_Man_t * p; - // prepare the sequential AIG - assert( Saig_ManRegNum(pAig) > 0 ); - Aig_ManFanoutStart( pAig ); - Aig_ManSetPioNumbers( pAig ); - // create interpolation manager - p = ABC_ALLOC( Ssw_Man_t, 1 ); - memset( p, 0, sizeof(Ssw_Man_t) ); - p->pPars = pPars; - p->pAig = pAig; - p->nFrames = pPars->nFramesK + 1; - p->pNodeToFrames = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) * p->nFrames ); - p->vCommon = Vec_PtrAlloc( 100 ); - p->iOutputLit = -1; - // allocate storage for sim pattern - p->nPatWords = Aig_BitWordNum( Saig_ManPiNum(pAig) * p->nFrames + Saig_ManRegNum(pAig) ); - p->pPatWords = ABC_CALLOC( unsigned, p->nPatWords ); - // other - p->vNewLos = Vec_PtrAlloc( 100 ); - p->vNewPos = Vec_IntAlloc( 100 ); - p->vResimConsts = Vec_PtrAlloc( 100 ); - p->vResimClasses = Vec_PtrAlloc( 100 ); -// p->pPars->fVerbose = 1; - return p; -} - -/**Function************************************************************* - - Synopsis [Prints stats of the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ManCountEquivs( Ssw_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i, nEquivs = 0; - Aig_ManForEachObj( p->pAig, pObj, i ) - nEquivs += ( Aig_ObjRepr(p->pAig, pObj) != NULL ); - return nEquivs; -} - -/**Function************************************************************* - - Synopsis [Prints stats of the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ManPrintStats( Ssw_Man_t * p ) -{ - double nMemory = 1.0*Aig_ManObjNumMax(p->pAig)*p->nFrames*(2*sizeof(int)+2*sizeof(void*))/(1<<20); - - printf( "Parameters: F = %d. AddF = %d. C-lim = %d. Constr = %d. MaxLev = %d. Mem = %0.2f Mb.\n", - p->pPars->nFramesK, p->pPars->nFramesAddSim, p->pPars->nBTLimit, Saig_ManConstrNum(p->pAig), p->pPars->nMaxLevs, nMemory ); - printf( "AIG : PI = %d. PO = %d. Latch = %d. Node = %d. Ave SAT vars = %d.\n", - Saig_ManPiNum(p->pAig), Saig_ManPoNum(p->pAig), Saig_ManRegNum(p->pAig), Aig_ManNodeNum(p->pAig), - 0/(p->pPars->nIters+1) ); - printf( "SAT calls : Proof = %d. Cex = %d. Fail = %d. Lits proved = %d.\n", - p->nSatProof, p->nSatCallsSat, p->nSatFailsReal, Ssw_ManCountEquivs(p) ); - printf( "SAT solver: Vars max = %d. Calls max = %d. Recycles = %d. Sim rounds = %d.\n", - p->nVarsMax, p->nCallsMax, p->nRecyclesTotal, p->nSimRounds ); - 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) ); - - p->timeOther = p->timeTotal-p->timeBmc-p->timeReduce-p->timeMarkCones-p->timeSimSat-p->timeSat; - ABC_PRTP( "BMC ", p->timeBmc, p->timeTotal ); - ABC_PRTP( "Spec reduce", p->timeReduce, p->timeTotal ); - ABC_PRTP( "Mark cones ", p->timeMarkCones, p->timeTotal ); - ABC_PRTP( "Sim SAT ", p->timeSimSat, p->timeTotal ); - ABC_PRTP( "SAT solving", p->timeSat, p->timeTotal ); - ABC_PRTP( " unsat ", p->timeSatUnsat, p->timeTotal ); - ABC_PRTP( " sat ", p->timeSatSat, p->timeTotal ); - ABC_PRTP( " undecided", p->timeSatUndec, p->timeTotal ); - ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); - ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); - - // report the reductions - if ( p->pAig->nConstrs ) - { - printf( "Statistics reflecting the use of constraints:\n" ); - printf( "Total cones = %6d. Constraint cones = %6d. (%6.2f %%)\n", - p->nConesTotal, p->nConesConstr, 100.0*p->nConesConstr/p->nConesTotal ); - printf( "Total equivs = %6d. Removed equivs = %6d. (%6.2f %%)\n", - p->nEquivsTotal, p->nEquivsConstr, 100.0*p->nEquivsConstr/p->nEquivsTotal ); - printf( "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n", - p->nNodesBegC, p->nNodesEndC, 100.0*(p->nNodesBegC-p->nNodesEndC)/(p->nNodesBegC?p->nNodesBegC:1), - p->nRegsBegC, p->nRegsEndC, 100.0*(p->nRegsBegC-p->nRegsEndC)/(p->nRegsBegC?p->nRegsBegC:1) ); - } -} - -/**Function************************************************************* - - Synopsis [Frees the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ManCleanup( Ssw_Man_t * p ) -{ -// Aig_ManCleanMarkAB( p->pAig ); - assert( p->pMSat == NULL ); - if ( p->pFrames ) - { - Aig_ManCleanMarkAB( p->pFrames ); - Aig_ManStop( p->pFrames ); - p->pFrames = NULL; - memset( p->pNodeToFrames, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(p->pAig) * p->nFrames ); - } - if ( p->vSimInfo ) - { - Vec_PtrFree( p->vSimInfo ); - p->vSimInfo = NULL; - } - p->nConstrTotal = 0; - p->nConstrReduced = 0; -} - -/**Function************************************************************* - - Synopsis [Frees the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ManStop( Ssw_Man_t * p ) -{ - ABC_FREE( p->pVisited ); - if ( p->pPars->fVerbose )//&& p->pPars->nStepsMax == -1 ) - Ssw_ManPrintStats( p ); - if ( p->ppClasses ) - Ssw_ClassesStop( p->ppClasses ); - if ( p->pSml ) - Ssw_SmlStop( p->pSml ); - if ( p->vDiffPairs ) - Vec_IntFree( p->vDiffPairs ); - if ( p->vInits ) - Vec_IntFree( p->vInits ); - Vec_PtrFree( p->vResimConsts ); - Vec_PtrFree( p->vResimClasses ); - Vec_PtrFree( p->vNewLos ); - Vec_IntFree( p->vNewPos ); - Vec_PtrFree( p->vCommon ); - ABC_FREE( p->pNodeToFrames ); - ABC_FREE( p->pPatWords ); - ABC_FREE( p ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ssw/sswPairs.c b/src/aig/ssw/sswPairs.c deleted file mode 100644 index 0aba942f..00000000 --- a/src/aig/ssw/sswPairs.c +++ /dev/null @@ -1,477 +0,0 @@ -/**CFile**************************************************************** - - FileName [sswPairs.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Inductive prover with constraints.] - - Synopsis [Calls to the SAT solver.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 1, 2008.] - - Revision [$Id: sswPairs.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "sswInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Reports the status of the miter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_MiterStatus( Aig_Man_t * p, int fVerbose ) -{ - Aig_Obj_t * pObj, * pChild; - int i, CountConst0 = 0, CountNonConst0 = 0, CountUndecided = 0; -// if ( p->pData ) -// return 0; - Saig_ManForEachPo( 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 is a primary input - if ( p->nRegs == 0 && Aig_ObjIsPi(Aig_Regular(pChild)) ) - { - CountNonConst0++; - continue; - } - // check if the output can be not constant 0 - if ( Aig_Regular(pChild)->fPhase != (unsigned)Aig_IsComplement(pChild) ) - { - CountNonConst0++; - continue; - } - CountUndecided++; - } - - if ( fVerbose ) - { - printf( "Miter has %d outputs. ", Saig_ManPoNum(p) ); - 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 [Transfer equivalent pairs to the miter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Ssw_TransferSignalPairs( Aig_Man_t * pMiter, Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec_Int_t * vIds1, Vec_Int_t * vIds2 ) -{ - Vec_Int_t * vIds; - Aig_Obj_t * pObj1, * pObj2; - Aig_Obj_t * pObj1m, * pObj2m; - int i; - vIds = Vec_IntAlloc( 2 * Vec_IntSize(vIds1) ); - for ( i = 0; i < Vec_IntSize(vIds1); i++ ) - { - pObj1 = Aig_ManObj( pAig1, Vec_IntEntry(vIds1, i) ); - pObj2 = Aig_ManObj( pAig2, Vec_IntEntry(vIds2, i) ); - pObj1m = Aig_Regular((Aig_Obj_t *)pObj1->pData); - pObj2m = Aig_Regular((Aig_Obj_t *)pObj2->pData); - assert( pObj1m && pObj2m ); - if ( pObj1m == pObj2m ) - continue; - if ( pObj1m->Id < pObj2m->Id ) - { - Vec_IntPush( vIds, pObj1m->Id ); - Vec_IntPush( vIds, pObj2m->Id ); - } - else - { - Vec_IntPush( vIds, pObj2m->Id ); - Vec_IntPush( vIds, pObj1m->Id ); - } - } - return vIds; -} - -/**Function************************************************************* - - Synopsis [Transform pairs into class representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t ** Ssw_TransformPairsIntoTempClasses( Vec_Int_t * vPairs, int nObjNumMax ) -{ - Vec_Int_t ** pvClasses; // vector of classes - int * pReprs; // mapping nodes into their representatives - int Entry, idObj, idRepr, idReprObj, idReprRepr, i; - // allocate data-structures - pvClasses = ABC_CALLOC( Vec_Int_t *, nObjNumMax ); - pReprs = ABC_ALLOC( int, nObjNumMax ); - for ( i = 0; i < nObjNumMax; i++ ) - pReprs[i] = -1; - // consider pairs - for ( i = 0; i < Vec_IntSize(vPairs); i += 2 ) - { - // get both objects - idRepr = Vec_IntEntry( vPairs, i ); - idObj = Vec_IntEntry( vPairs, i+1 ); - assert( idObj > 0 ); - assert( (pReprs[idRepr] == -1) || (pvClasses[pReprs[idRepr]] != NULL) ); - assert( (pReprs[idObj] == -1) || (pvClasses[pReprs[idObj] ] != NULL) ); - // get representatives of both objects - idReprRepr = pReprs[idRepr]; - idReprObj = pReprs[idObj]; - // check different situations - if ( idReprRepr == -1 && idReprObj == -1 ) - { // they do not have classes - // create a class - pvClasses[idRepr] = Vec_IntAlloc( 4 ); - Vec_IntPush( pvClasses[idRepr], idRepr ); - Vec_IntPush( pvClasses[idRepr], idObj ); - pReprs[ idRepr ] = idRepr; - pReprs[ idObj ] = idRepr; - } - else if ( idReprRepr >= 0 && idReprObj == -1 ) - { // representative has a class - // add iObj to the same class - Vec_IntPushUniqueOrder( pvClasses[idReprRepr], idObj ); - pReprs[ idObj ] = idReprRepr; - } - else if ( idReprRepr == -1 && idReprObj >= 0 ) - { // object has a class - assert( idReprObj != idRepr ); - if ( idReprObj < idRepr ) - { // add idRepr to the same class - Vec_IntPushUniqueOrder( pvClasses[idReprObj], idRepr ); - pReprs[ idRepr ] = idReprObj; - } - else // if ( idReprObj > idRepr ) - { // make idRepr new representative - Vec_IntPushFirst( pvClasses[idReprObj], idRepr ); - pvClasses[idRepr] = pvClasses[idReprObj]; - pvClasses[idReprObj] = NULL; - // set correct representatives of each node - Vec_IntForEachEntry( pvClasses[idRepr], Entry, i ) - pReprs[ Entry ] = idRepr; - } - } - else // if ( idReprRepr >= 0 && idReprObj >= 0 ) - { // both have classes - if ( idReprRepr == idReprObj ) - { // the classes are the same - // nothing to do - } - else - { // the classes are different - // find the repr of the new class - if ( idReprRepr < idReprObj ) - { - Vec_IntForEachEntry( pvClasses[idReprObj], Entry, i ) - { - Vec_IntPushUniqueOrder( pvClasses[idReprRepr], Entry ); - pReprs[ Entry ] = idReprRepr; - } - Vec_IntFree( pvClasses[idReprObj] ); - pvClasses[idReprObj] = NULL; - } - else // if ( idReprRepr > idReprObj ) - { - Vec_IntForEachEntry( pvClasses[idReprRepr], Entry, i ) - { - Vec_IntPushUniqueOrder( pvClasses[idReprObj], Entry ); - pReprs[ Entry ] = idReprObj; - } - Vec_IntFree( pvClasses[idReprRepr] ); - pvClasses[idReprRepr] = NULL; - } - } - } - } - ABC_FREE( pReprs ); - return pvClasses; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_FreeTempClasses( Vec_Int_t ** pvClasses, int nObjNumMax ) -{ - int i; - for ( i = 0; i < nObjNumMax; i++ ) - if ( pvClasses[i] ) - Vec_IntFree( pvClasses[i] ); - ABC_FREE( pvClasses ); -} - -/**Function************************************************************* - - Synopsis [Performs signal correspondence for the miter of two AIGs with node pairs defined.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Ssw_SignalCorrespondenceWithPairs( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec_Int_t * vIds1, Vec_Int_t * vIds2, Ssw_Pars_t * pPars ) -{ - Ssw_Man_t * p; - Aig_Man_t * pAigNew, * pMiter; - Ssw_Pars_t Pars; - Vec_Int_t * vPairs; - Vec_Int_t ** pvClasses; - assert( Vec_IntSize(vIds1) == Vec_IntSize(vIds2) ); - // create sequential miter - pMiter = Saig_ManCreateMiter( pAig1, pAig2, 0 ); - Aig_ManCleanup( pMiter ); - // transfer information to the miter - vPairs = Ssw_TransferSignalPairs( pMiter, pAig1, pAig2, vIds1, vIds2 ); - // create representation of the classes - pvClasses = Ssw_TransformPairsIntoTempClasses( vPairs, Aig_ManObjNumMax(pMiter) ); - Vec_IntFree( vPairs ); - // if parameters are not given, create them - if ( pPars == NULL ) - Ssw_ManSetDefaultParams( pPars = &Pars ); - // start the induction manager - p = Ssw_ManCreate( pMiter, pPars ); - // create equivalence classes using these IDs - p->ppClasses = Ssw_ClassesPreparePairs( pMiter, pvClasses ); - p->pSml = Ssw_SmlStart( pMiter, 0, p->nFrames + p->pPars->nFramesAddSim, 1 ); - Ssw_ClassesSetData( p->ppClasses, p->pSml, (unsigned(*)(void *,Aig_Obj_t *))Ssw_SmlObjHashWord, (int(*)(void *,Aig_Obj_t *))Ssw_SmlObjIsConstWord, (int(*)(void *,Aig_Obj_t *,Aig_Obj_t *))Ssw_SmlObjsAreEqualWord ); - // perform refinement of classes - pAigNew = Ssw_SignalCorrespondenceRefine( p ); - // cleanup - Ssw_FreeTempClasses( pvClasses, Aig_ManObjNumMax(pMiter) ); - Ssw_ManStop( p ); - Aig_ManStop( pMiter ); - return pAigNew; -} - -/**Function************************************************************* - - Synopsis [Runs inductive SEC for the miter of two AIGs with node pairs defined.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Ssw_SignalCorrespondeceTestPairs( Aig_Man_t * pAig ) -{ - Aig_Man_t * pAigNew, * pAigRes; - Ssw_Pars_t Pars, * pPars = &Pars; - Vec_Int_t * vIds1, * vIds2; - Aig_Obj_t * pObj, * pRepr; - int RetValue, i, clk = clock(); - Ssw_ManSetDefaultParams( pPars ); - pPars->fVerbose = 1; - pAigNew = Ssw_SignalCorrespondence( pAig, pPars ); - // record pairs of equivalent nodes - vIds1 = Vec_IntAlloc( Aig_ManObjNumMax(pAig) ); - vIds2 = Vec_IntAlloc( Aig_ManObjNumMax(pAig) ); - Aig_ManForEachObj( pAig, pObj, i ) - { - pRepr = Aig_Regular((Aig_Obj_t *)pObj->pData); - if ( pRepr == NULL ) - continue; - if ( Aig_ManObj(pAigNew, pRepr->Id) == NULL ) - continue; -/* - if ( Aig_ObjIsNode(pObj) ) - printf( "n " ); - else if ( Saig_ObjIsPi(pAig, pObj) ) - printf( "pi " ); - else if ( Saig_ObjIsLo(pAig, pObj) ) - printf( "lo " ); -*/ - Vec_IntPush( vIds1, Aig_ObjId(pObj) ); - Vec_IntPush( vIds2, Aig_ObjId(pRepr) ); - } - printf( "Recorded %d pairs (before: %d after: %d).\n", Vec_IntSize(vIds1), Aig_ManObjNumMax(pAig), Aig_ManObjNumMax(pAigNew) ); - // try the new AIGs - pAigRes = Ssw_SignalCorrespondenceWithPairs( pAig, pAigNew, vIds1, vIds2, pPars ); - Vec_IntFree( vIds1 ); - Vec_IntFree( vIds2 ); - // report the results - RetValue = Ssw_MiterStatus( pAigRes, 1 ); - if ( RetValue == 1 ) - printf( "Verification successful. " ); - else if ( RetValue == 0 ) - printf( "Verification failed with the counter-example. " ); - else - printf( "Verification UNDECIDED. Remaining registers %d (total %d). ", - Aig_ManRegNum(pAigRes), Aig_ManRegNum(pAig) + Aig_ManRegNum(pAigNew) ); - ABC_PRT( "Time", clock() - clk ); - // cleanup - Aig_ManStop( pAigNew ); - return pAigRes; -} - -/**Function************************************************************* - - Synopsis [Runs inductive SEC for the miter of two AIGs with node pairs defined.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_SecWithPairs( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec_Int_t * vIds1, Vec_Int_t * vIds2, Ssw_Pars_t * pPars ) -{ - Aig_Man_t * pAigRes; - int RetValue, clk = clock(); - assert( vIds1 != NULL && vIds2 != NULL ); - // try the new AIGs - printf( "Performing specialized verification with node pairs.\n" ); - pAigRes = Ssw_SignalCorrespondenceWithPairs( pAig1, pAig2, vIds1, vIds2, pPars ); - // report the results - RetValue = Ssw_MiterStatus( pAigRes, 1 ); - if ( RetValue == 1 ) - printf( "Verification successful. " ); - else if ( RetValue == 0 ) - printf( "Verification failed with a counter-example. " ); - else - printf( "Verification UNDECIDED. The number of remaining regs = %d (total = %d). ", - Aig_ManRegNum(pAigRes), Aig_ManRegNum(pAig1) + Aig_ManRegNum(pAig2) ); - ABC_PRT( "Time", clock() - clk ); - // cleanup - Aig_ManStop( pAigRes ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Runs inductive SEC for the miter of two AIGs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_SecGeneral( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Ssw_Pars_t * pPars ) -{ - Aig_Man_t * pAigRes, * pMiter; - int RetValue, clk = clock(); - // try the new AIGs - printf( "Performing general verification without node pairs.\n" ); - pMiter = Saig_ManCreateMiter( pAig1, pAig2, 0 ); - Aig_ManCleanup( pMiter ); - pAigRes = Ssw_SignalCorrespondence( pMiter, pPars ); - Aig_ManStop( pMiter ); - // report the results - RetValue = Ssw_MiterStatus( pAigRes, 1 ); - if ( RetValue == 1 ) - printf( "Verification successful. " ); - else if ( RetValue == 0 ) - printf( "Verification failed with a counter-example. " ); - else - printf( "Verification UNDECIDED. The number of remaining regs = %d (total = %d). ", - Aig_ManRegNum(pAigRes), Aig_ManRegNum(pAig1) + Aig_ManRegNum(pAig2) ); - ABC_PRT( "Time", clock() - clk ); - // cleanup - Aig_ManStop( pAigRes ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Runs inductive SEC for the miter of two AIGs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_SecGeneralMiter( Aig_Man_t * pMiter, Ssw_Pars_t * pPars ) -{ - Aig_Man_t * pAigRes; - int RetValue, clk = clock(); - // try the new AIGs -// printf( "Performing general verification without node pairs.\n" ); - pAigRes = Ssw_SignalCorrespondence( pMiter, pPars ); - // report the results - RetValue = Ssw_MiterStatus( pAigRes, 1 ); - if ( RetValue == 1 ) - printf( "Verification successful. " ); - else if ( RetValue == 0 ) - printf( "Verification failed with a counter-example. " ); - else - printf( "Verification UNDECIDED. The number of remaining regs = %d (total = %d). ", - Aig_ManRegNum(pAigRes), Aig_ManRegNum(pMiter) ); - ABC_PRT( "Time", clock() - clk ); - // cleanup - Aig_ManStop( pAigRes ); - return RetValue; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ssw/sswPart.c b/src/aig/ssw/sswPart.c deleted file mode 100644 index 8a0e69da..00000000 --- a/src/aig/ssw/sswPart.c +++ /dev/null @@ -1,141 +0,0 @@ -/**CFile**************************************************************** - - FileName [sswPart.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Inductive prover with constraints.] - - Synopsis [Partitioned signal correspondence.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 1, 2008.] - - Revision [$Id: sswPart.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "sswInt.h" -#include "ioa.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs partitioned sequential SAT sweeping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Ssw_SignalCorrespondencePart( Aig_Man_t * pAig, Ssw_Pars_t * pPars ) -{ - int fPrintParts = 0; - char Buffer[100]; - Aig_Man_t * pTemp, * pNew; - Vec_Ptr_t * vResult; - Vec_Int_t * vPart; - int * pMapBack; - int i, nCountPis, nCountRegs; - int nClasses, nPartSize, fVerbose; - int clk = clock(); - if ( pPars->fConstrs ) - { - printf( "Cannot use partitioned computation with constraints.\n" ); - return NULL; - } - // save parameters - nPartSize = pPars->nPartSize; pPars->nPartSize = 0; - fVerbose = pPars->fVerbose; pPars->fVerbose = 0; - // generate partitions - if ( pAig->vClockDoms ) - { - // divide large clock domains into separate partitions - vResult = Vec_PtrAlloc( 100 ); - Vec_PtrForEachEntry( Vec_Int_t *, (Vec_Ptr_t *)pAig->vClockDoms, vPart, i ) - { - if ( nPartSize && Vec_IntSize(vPart) > nPartSize ) - Aig_ManPartDivide( vResult, vPart, nPartSize, pPars->nOverSize ); - else - Vec_PtrPush( vResult, Vec_IntDup(vPart) ); - } - } - else - vResult = Aig_ManRegPartitionSimple( pAig, nPartSize, pPars->nOverSize ); -// vResult = Aig_ManPartitionSmartRegisters( pAig, nPartSize, 0 ); -// vResult = Aig_ManRegPartitionSmart( pAig, nPartSize ); - if ( fPrintParts ) - { - // print partitions - printf( "Simple partitioning. %d partitions are saved:\n", Vec_PtrSize(vResult) ); - Vec_PtrForEachEntry( Vec_Int_t *, vResult, vPart, i ) - { -// extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact ); - sprintf( Buffer, "part%03d.aig", i ); - pTemp = Aig_ManRegCreatePart( pAig, vPart, &nCountPis, &nCountRegs, NULL ); - Ioa_WriteAiger( pTemp, Buffer, 0, 0 ); - printf( "part%03d.aig : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d.\n", - i, Vec_IntSize(vPart), Aig_ManPiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Aig_ManNodeNum(pTemp) ); - Aig_ManStop( pTemp ); - } - } - - // perform SSW with partitions - Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) ); - Vec_PtrForEachEntry( Vec_Int_t *, vResult, vPart, i ) - { - pTemp = Aig_ManRegCreatePart( pAig, vPart, &nCountPis, &nCountRegs, &pMapBack ); - Aig_ManSetRegNum( pTemp, pTemp->nRegs ); - // create the projection of 1-hot registers - if ( pAig->vOnehots ) - pTemp->vOnehots = Aig_ManRegProjectOnehots( pAig, pTemp, pAig->vOnehots, fVerbose ); - // run SSW - if (nCountPis>0) { - pNew = Ssw_SignalCorrespondence( pTemp, pPars ); - nClasses = Aig_TransferMappedClasses( pAig, pTemp, pMapBack ); - if ( fVerbose ) - printf( "%3d : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d. It = %3d. Cl = %5d.\n", - i, Vec_IntSize(vPart), Aig_ManPiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Aig_ManNodeNum(pTemp), pPars->nIters, nClasses ); - Aig_ManStop( pNew ); - } - Aig_ManStop( pTemp ); - ABC_FREE( pMapBack ); - } - // remap the AIG - pNew = Aig_ManDupRepr( pAig, 0 ); - Aig_ManSeqCleanup( pNew ); -// Aig_ManPrintStats( pAig ); -// Aig_ManPrintStats( pNew ); - Vec_VecFree( (Vec_Vec_t *)vResult ); - pPars->nPartSize = nPartSize; - pPars->fVerbose = fVerbose; - if ( fVerbose ) - { - ABC_PRT( "Total time", clock() - clk ); - } - return pNew; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ssw/sswRarity.c b/src/aig/ssw/sswRarity.c deleted file mode 100644 index 5480afb5..00000000 --- a/src/aig/ssw/sswRarity.c +++ /dev/null @@ -1,1158 +0,0 @@ -/**CFile**************************************************************** - - FileName [sswRarity.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Inductive prover with constraints.] - - Synopsis [Rarity-driven refinement of equivalence classes.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 1, 2008.] - - Revision [$Id: sswRarity.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "sswInt.h" -#include "giaAig.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Ssw_RarMan_t_ Ssw_RarMan_t; -struct Ssw_RarMan_t_ -{ - // parameters - int nWords; // the number of words to simulate - int nFrames; // the number of frames to simulate - int nBinSize; // the number of flops in one group - int fVerbose; // the verbosiness flag - int nGroups; // the number of flop groups - int nWordsReg; // the number of words in the registers - // internal data - Aig_Man_t * pAig; // AIG with equivalence classes - Ssw_Cla_t * ppClasses; // equivalence classes - Vec_Int_t * vInits; // initial state - // simulation data - word * pObjData; // simulation info for each obj - word * pPatData; // pattern data for each reg - // candidates to update - Vec_Ptr_t * vUpdConst; // constant 1 candidates - Vec_Ptr_t * vUpdClass; // class representatives - // rarity data - int * pRarity; // occur counts for patterns in groups - double * pPatCosts; // pattern costs - // best patterns - Vec_Int_t * vPatBests; // best patterns - int iFailPo; // failed primary output - int iFailPat; // failed pattern -}; - - -static inline int Ssw_RarGetBinPat( Ssw_RarMan_t * p, int iBin, int iPat ) -{ - assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->nBinSize ); - assert( iPat >= 0 && iPat < (1 << p->nBinSize) ); - return p->pRarity[iBin * (1 << p->nBinSize) + iPat]; -} -static inline void Ssw_RarSetBinPat( Ssw_RarMan_t * p, int iBin, int iPat, int Value ) -{ - assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->nBinSize ); - assert( iPat >= 0 && iPat < (1 << p->nBinSize) ); - p->pRarity[iBin * (1 << p->nBinSize) + iPat] = Value; -} -static inline void Ssw_RarAddToBinPat( Ssw_RarMan_t * p, int iBin, int iPat ) -{ - assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->nBinSize ); - assert( iPat >= 0 && iPat < (1 << p->nBinSize) ); - p->pRarity[iBin * (1 << p->nBinSize) + iPat]++; -} - -static inline int Ssw_RarBitWordNum( int nBits ) { return (nBits>>6) + ((nBits&63) > 0); } - -static inline word * Ssw_RarObjSim( Ssw_RarMan_t * p, int Id ) { assert( Id < Aig_ManObjNumMax(p->pAig) ); return p->pObjData + p->nWords * Id; } -static inline word * Ssw_RarPatSim( Ssw_RarMan_t * p, int Id ) { assert( Id < 64 * p->nWords ); return p->pPatData + p->nWordsReg * Id; } - - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Prepares random number generator.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_RarManPrepareRandom( int nRandSeed ) -{ - int i; - Aig_ManRandom( 1 ); - for ( i = 0; i < nRandSeed; i++ ) - Aig_ManRandom( 0 ); -} - -/**Function************************************************************* - - Synopsis [Initializes random primary inputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_RarManAssingRandomPis( Ssw_RarMan_t * p ) -{ - word * pSim; - Aig_Obj_t * pObj; - int w, i; - Saig_ManForEachPi( p->pAig, pObj, i ) - { - pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); - for ( w = 0; w < p->nWords; w++ ) - pSim[w] = Aig_ManRandom64(0); -// pSim[0] <<= 1; -// pSim[0] = (pSim[0] << 2) | 2; - pSim[0] = (pSim[0] << 4) | ((i & 1) ? 0xA : 0xC); - } -} - -/**Function************************************************************* - - Synopsis [Derives the counter-example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Cex_t * Ssw_RarDeriveCex( Ssw_RarMan_t * p, int iFrame, int iPo, int iPatFinal, int fVerbose ) -{ - Abc_Cex_t * pCex; - Aig_Obj_t * pObj; - Vec_Int_t * vTrace; - word * pSim; - int i, r, f, iBit, iPatThis; - // compute the pattern sequence - iPatThis = iPatFinal; - vTrace = Vec_IntStartFull( iFrame / p->nFrames + 1 ); - Vec_IntWriteEntry( vTrace, iFrame / p->nFrames, iPatThis ); - for ( r = iFrame / p->nFrames - 1; r >= 0; r-- ) - { - iPatThis = Vec_IntEntry( p->vPatBests, r * p->nWords + iPatThis / 64 ); - Vec_IntWriteEntry( vTrace, r, iPatThis ); - } - // create counter-example - pCex = Abc_CexAlloc( Aig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), iFrame+1 ); - pCex->iFrame = iFrame; - pCex->iPo = iPo; - // insert the bits - iBit = Aig_ManRegNum(p->pAig); - for ( f = 0; f <= iFrame; f++ ) - { - Ssw_RarManAssingRandomPis( p ); - iPatThis = Vec_IntEntry( vTrace, f / p->nFrames ); - Saig_ManForEachPi( p->pAig, pObj, i ) - { - pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); - if ( Aig_InfoHasBit( (unsigned *)pSim, iPatThis ) ) - Aig_InfoSetBit( pCex->pData, iBit ); - iBit++; - } - } - Vec_IntFree( vTrace ); - assert( iBit == pCex->nBits ); - // verify the counter example - if ( !Saig_ManVerifyCex( p->pAig, pCex ) ) - { - printf( "Ssw_RarDeriveCex(): Counter-example is invalid.\n" ); -// Abc_CexFree( pCex ); -// pCex = NULL; - } - else - { -// printf( "Counter-example verification is successful.\n" ); - if ( fVerbose ) - printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump a witness). \n", pCex->iPo, pCex->iFrame ); - } - return pCex; -} - - -/**Function************************************************************* - - Synopsis [Transposing 32-bit matrix.] - - Description [Borrowed from "Hacker's Delight", by Henry Warren.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void transpose32( unsigned A[32] ) -{ - int j, k; - unsigned t, m = 0x0000FFFF; - for ( j = 16; j != 0; j = j >> 1, m = m ^ (m << j) ) - { - for ( k = 0; k < 32; k = (k + j + 1) & ~j ) - { - t = (A[k] ^ (A[k+j] >> j)) & m; - A[k] = A[k] ^ t; - A[k+j] = A[k+j] ^ (t << j); - } - } -} - -/**Function************************************************************* - - Synopsis [Transposing 64-bit matrix.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void transpose64( word A[64] ) -{ - int j, k; - word t, m = 0x00000000FFFFFFFF; - for ( j = 32; j != 0; j = j >> 1, m = m ^ (m << j) ) - { - for ( k = 0; k < 64; k = (k + j + 1) & ~j ) - { - t = (A[k] ^ (A[k+j] >> j)) & m; - A[k] = A[k] ^ t; - A[k+j] = A[k+j] ^ (t << j); - } - } -} - -/**Function************************************************************* - - Synopsis [Transposing 64-bit matrix.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void transpose64Simple( word A[64], word B[64] ) -{ - int i, k; - for ( i = 0; i < 64; i++ ) - B[i] = 0; - for ( i = 0; i < 64; i++ ) - for ( k = 0; k < 64; k++ ) - if ( (A[i] >> k) & 1 ) - B[k] |= ((word)1 << (63-i)); -} - -/**Function************************************************************* - - Synopsis [Testing the transposing code.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void TransposeTest() -{ - word M[64], N[64]; - int i, clk; - Aig_ManRandom64( 1 ); -// for ( i = 0; i < 64; i++ ) -// M[i] = Aig_ManRandom64( 0 ); - for ( i = 0; i < 64; i++ ) - M[i] = i? (word)0 : ~(word)0; -// for ( i = 0; i < 64; i++ ) -// Extra_PrintBinary( stdout, (unsigned *)&M[i], 64 ), printf( "\n" ); - - clk = clock(); - for ( i = 0; i < 100001; i++ ) - transpose64Simple( M, N ); - Abc_PrintTime( 1, "Time", clock() - clk ); - - clk = clock(); - for ( i = 0; i < 100001; i++ ) - transpose64( M ); - Abc_PrintTime( 1, "Time", clock() - clk ); - - for ( i = 0; i < 64; i++ ) - if ( M[i] != N[i] ) - printf( "Mismatch\n" ); -/* - printf( "\n" ); - for ( i = 0; i < 64; i++ ) - Extra_PrintBinary( stdout, (unsigned *)&M[i], 64 ), printf( "\n" ); - printf( "\n" ); - for ( i = 0; i < 64; i++ ) - Extra_PrintBinary( stdout, (unsigned *)&N[i], 64 ), printf( "\n" ); -*/ -} - -/**Function************************************************************* - - Synopsis [Transposing pObjData[ nRegs x nWords ] -> pPatData[ nWords x nRegs ].] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_RarTranspose( Ssw_RarMan_t * p ) -{ - Aig_Obj_t * pObj; - word M[64]; - int w, r, i; - for ( w = 0; w < p->nWords; w++ ) - for ( r = 0; r < p->nWordsReg; r++ ) - { - // save input - for ( i = 0; i < 64; i++ ) - { - if ( r*64 + 63-i < Aig_ManRegNum(p->pAig) ) - { - pObj = Saig_ManLi( p->pAig, r*64 + 63-i ); - M[i] = Ssw_RarObjSim( p, Aig_ObjId(pObj) )[w]; - } - else - M[i] = 0; - } - // transpose - transpose64( M ); - // save output - for ( i = 0; i < 64; i++ ) - Ssw_RarPatSim( p, w*64 + 63-i )[r] = M[i]; - } -/* - Saig_ManForEachLi( p->pAig, pObj, i ) - { - word * pBitData = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); - Extra_PrintBinary( stdout, (unsigned *)pBitData, 64*p->nWords ); printf( "\n" ); - } - printf( "\n" ); - for ( i = 0; i < p->nWords*64; i++ ) - { - word * pBitData = Ssw_RarPatSim( p, i ); - Extra_PrintBinary( stdout, (unsigned *)pBitData, Aig_ManRegNum(p->pAig) ); printf( "\n" ); - } - printf( "\n" ); -*/ -} - - - - -/**Function************************************************************* - - Synopsis [Sets random inputs and specialied flop outputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_RarManInitialize( Ssw_RarMan_t * p, Vec_Int_t * vInit ) -{ - Aig_Obj_t * pObj, * pObjLi; - word * pSim, * pSimLi; - int w, i; - // constant - pObj = Aig_ManConst1( p->pAig ); - pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); - for ( w = 0; w < p->nWords; w++ ) - pSim[w] = ~(word)0; - // primary inputs - Ssw_RarManAssingRandomPis( p ); - // flop outputs - if ( vInit ) - { - assert( Vec_IntSize(vInit) == Saig_ManRegNum(p->pAig) * p->nWords ); - Saig_ManForEachLo( p->pAig, pObj, i ) - { - pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); - for ( w = 0; w < p->nWords; w++ ) - pSim[w] = Vec_IntEntry(vInit, w * Saig_ManRegNum(p->pAig) + i) ? ~(word)0 : (word)0; - } - } - else - { - Saig_ManForEachLiLo( p->pAig, pObjLi, pObj, i ) - { - pSimLi = Ssw_RarObjSim( p, Aig_ObjId(pObjLi) ); - pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); - for ( w = 0; w < p->nWords; w++ ) - pSim[w] = pSimLi[w]; - } - } -} - -/**Function************************************************************* - - Synopsis [Returns 1 if simulation info is composed of all zeros.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_RarManObjIsConst( void * pMan, Aig_Obj_t * pObj ) -{ - Ssw_RarMan_t * p = (Ssw_RarMan_t *)pMan; - word * pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); - word Flip = pObj->fPhase ? ~0 : 0; - int w; - for ( w = 0; w < p->nWords; w++ ) - if ( pSim[w] ^ Flip ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if simulation infos are equal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_RarManObjsAreEqual( void * pMan, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) -{ - Ssw_RarMan_t * p = (Ssw_RarMan_t *)pMan; - word * pSim0 = Ssw_RarObjSim( p, pObj0->Id ); - word * pSim1 = Ssw_RarObjSim( p, pObj1->Id ); - word Flip = (pObj0->fPhase != pObj1->fPhase) ? ~0 : 0; - int w; - for ( w = 0; w < p->nWords; w++ ) - if ( pSim0[w] ^ pSim1[w] ^ Flip ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Computes hash value of the node using its simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Ssw_RarManObjHashWord( void * pMan, Aig_Obj_t * pObj ) -{ - Ssw_RarMan_t * p = (Ssw_RarMan_t *)pMan; - static int s_SPrimes[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; - uHash = 0; - pSims = (unsigned *)Ssw_RarObjSim( p, pObj->Id ); - for ( i = 0; i < 2 * p->nWords; i++ ) - uHash ^= pSims[i] * s_SPrimes[i & 0x7F]; - return uHash; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if simulation info is composed of all zeros.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_RarManObjWhichOne( Ssw_RarMan_t * p, Aig_Obj_t * pObj ) -{ - word * pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); - word Flip = pObj->fPhase ? ~0 : 0; - int w, i; - for ( w = 0; w < p->nWords; w++ ) - if ( pSim[w] ^ Flip ) - { - for ( i = 0; i < 64; i++ ) - if ( ((pSim[w] ^ Flip) >> i) & 1 ) - break; - assert( i < 64 ); - return w * 64 + i; - } - return -1; -} - -/**Function************************************************************* - - Synopsis [Check if any of the POs becomes non-constant.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_RarManCheckNonConstOutputs( Ssw_RarMan_t * p ) -{ - Aig_Obj_t * pObj; - int i; - p->iFailPo = -1; - p->iFailPat = -1; - Saig_ManForEachPo( p->pAig, pObj, i ) - { - if ( p->pAig->nConstrs && i >= Saig_ManPoNum(p->pAig) - p->pAig->nConstrs ) - return 0; - if ( !Ssw_RarManObjIsConst(p, pObj) ) - { - p->iFailPo = i; - p->iFailPat = Ssw_RarManObjWhichOne( p, pObj ); - return 1; - } - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Performs one round of simulation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_RarManSimulate( Ssw_RarMan_t * p, Vec_Int_t * vInit, int fUpdate, int fFirst ) -{ - Aig_Obj_t * pObj, * pRepr; - word * pSim, * pSim0, * pSim1; - word Flip, Flip0, Flip1; - int w, i; - // initialize - Ssw_RarManInitialize( p, vInit ); - Vec_PtrClear( p->vUpdConst ); - Vec_PtrClear( p->vUpdClass ); - Aig_ManIncrementTravId( p->pAig ); - // check comb inputs - if ( fUpdate ) - Aig_ManForEachPi( p->pAig, pObj, i ) - { - pRepr = Aig_ObjRepr(p->pAig, pObj); - if ( pRepr == NULL || Aig_ObjIsTravIdCurrent( p->pAig, pRepr ) ) - continue; - if ( Ssw_RarManObjsAreEqual( p, pObj, pRepr ) ) - continue; - // save for update - if ( pRepr == Aig_ManConst1(p->pAig) ) - Vec_PtrPush( p->vUpdConst, pObj ); - else - { - Vec_PtrPush( p->vUpdClass, pRepr ); - Aig_ObjSetTravIdCurrent( p->pAig, pRepr ); - } - } - // simulate - Aig_ManForEachNode( p->pAig, pObj, i ) - { - pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); - pSim0 = Ssw_RarObjSim( p, Aig_ObjFaninId0(pObj) ); - pSim1 = Ssw_RarObjSim( p, Aig_ObjFaninId1(pObj) ); - Flip0 = Aig_ObjFaninC0(pObj) ? ~0 : 0; - Flip1 = Aig_ObjFaninC1(pObj) ? ~0 : 0; - for ( w = 0; w < p->nWords; w++ ) - pSim[w] = (Flip0 ^ pSim0[w]) & (Flip1 ^ pSim1[w]); - if ( !fUpdate ) - continue; - // check classes - pRepr = Aig_ObjRepr(p->pAig, pObj); - if ( pRepr == NULL || Aig_ObjIsTravIdCurrent( p->pAig, pRepr ) ) - continue; - if ( Ssw_RarManObjsAreEqual( p, pObj, pRepr ) ) - continue; - // save for update - if ( pRepr == Aig_ManConst1(p->pAig) ) - Vec_PtrPush( p->vUpdConst, pObj ); - else - { - Vec_PtrPush( p->vUpdClass, pRepr ); - Aig_ObjSetTravIdCurrent( p->pAig, pRepr ); - } - } - // transfer to POs - Aig_ManForEachPo( p->pAig, pObj, i ) - { - pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); - pSim0 = Ssw_RarObjSim( p, Aig_ObjFaninId0(pObj) ); - Flip = Aig_ObjFaninC0(pObj) ? ~0 : 0; - for ( w = 0; w < p->nWords; w++ ) - pSim[w] = Flip ^ pSim0[w]; - } - // refine classes - if ( fUpdate ) - { - if ( fFirst ) - { - Vec_Ptr_t * vCands = Vec_PtrAlloc( 1000 ); - Aig_ManForEachObj( p->pAig, pObj, i ) - if ( Ssw_ObjIsConst1Cand( p->pAig, pObj ) ) - Vec_PtrPush( vCands, pObj ); - assert( Vec_PtrSize(vCands) == Ssw_ClassesCand1Num(p->ppClasses) ); - Ssw_ClassesPrepareRehash( p->ppClasses, vCands, 0 ); - Vec_PtrFree( vCands ); - } - else - { - Ssw_ClassesRefineConst1Group( p->ppClasses, p->vUpdConst, 1 ); - Ssw_ClassesRefineGroup( p->ppClasses, p->vUpdClass, 1 ); - } - } -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static Ssw_RarMan_t * Ssw_RarManStart( Aig_Man_t * pAig, int nWords, int nFrames, int nBinSize, int fVerbose ) -{ - Ssw_RarMan_t * p; -// if ( Aig_ManRegNum(pAig) < nBinSize || nBinSize <= 0 ) -// return NULL; - p = ABC_CALLOC( Ssw_RarMan_t, 1 ); - p->pAig = pAig; - p->nWords = nWords; - p->nFrames = nFrames; - p->nBinSize = nBinSize; - p->fVerbose = fVerbose; - p->nGroups = Aig_ManRegNum(pAig) / nBinSize; - p->pRarity = ABC_CALLOC( int, (1 << nBinSize) * p->nGroups ); - p->pPatCosts = ABC_CALLOC( double, p->nWords * 64 ); - p->nWordsReg = Ssw_RarBitWordNum( Aig_ManRegNum(pAig) ); - p->pObjData = ABC_ALLOC( word, Aig_ManObjNumMax(pAig) * p->nWords ); - p->pPatData = ABC_ALLOC( word, 64 * p->nWords * p->nWordsReg ); - p->vUpdConst = Vec_PtrAlloc( 100 ); - p->vUpdClass = Vec_PtrAlloc( 100 ); - p->vPatBests = Vec_IntAlloc( 100 ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Ssw_RarManStop( Ssw_RarMan_t * p ) -{ - if ( p->ppClasses ) Ssw_ClassesStop( p->ppClasses ); - Vec_IntFreeP( &p->vInits ); - Vec_IntFreeP( &p->vPatBests ); - Vec_PtrFreeP( &p->vUpdConst ); - Vec_PtrFreeP( &p->vUpdClass ); - ABC_FREE( p->pObjData ); - ABC_FREE( p->pPatData ); - ABC_FREE( p->pPatCosts ); - ABC_FREE( p->pRarity ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Select best patterns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Ssw_RarTransferPatterns( Ssw_RarMan_t * p, Vec_Int_t * vInits ) -{ -// Aig_Obj_t * pObj; - unsigned char * pData; - unsigned * pPattern; - int i, k, Value; - - // more data from regs to pats - Ssw_RarTranspose( p ); - - // update counters - for ( k = 0; k < p->nWords * 64; k++ ) - { - pData = (unsigned char *)Ssw_RarPatSim( p, k ); - for ( i = 0; i < p->nGroups; i++ ) - Ssw_RarAddToBinPat( p, i, pData[i] ); - } - - // for each pattern - for ( k = 0; k < p->nWords * 64; k++ ) - { - pData = (unsigned char *)Ssw_RarPatSim( p, k ); - // find the cost of its values - p->pPatCosts[k] = 0.0; - for ( i = 0; i < p->nGroups; i++ ) - { - Value = Ssw_RarGetBinPat( p, i, pData[i] ); - assert( Value > 0 ); - p->pPatCosts[k] += 1.0/(Value*Value); - } - // print the result -//printf( "%3d : %9.6f\n", k, p->pPatCosts[k] ); - } - - // choose as many as there are words - Vec_IntClear( vInits ); - for ( i = 0; i < p->nWords; i++ ) - { - // select the best - int iPatBest = -1; - double iCostBest = -ABC_INFINITY; - for ( k = 0; k < p->nWords * 64; k++ ) - if ( iCostBest < p->pPatCosts[k] ) - { - iCostBest = p->pPatCosts[k]; - iPatBest = k; - } - // remove from costs - assert( iPatBest >= 0 ); - p->pPatCosts[iPatBest] = -ABC_INFINITY; - // set the flops - pPattern = (unsigned *)Ssw_RarPatSim( p, iPatBest ); - for ( k = 0; k < Aig_ManRegNum(p->pAig); k++ ) - Vec_IntPush( vInits, Aig_InfoHasBit(pPattern, k) ); -//printf( "Best pattern %5d\n", iPatBest ); - Vec_IntPush( p->vPatBests, iPatBest ); - } - assert( Vec_IntSize(vInits) == Aig_ManRegNum(p->pAig) * p->nWords ); -} - - -/**Function************************************************************* - - Synopsis [Performs fraiging for one node.] - - Description [Returns the fraiged node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static Vec_Int_t * Ssw_RarFindStartingState( Aig_Man_t * pAig, Abc_Cex_t * pCex ) -{ - Vec_Int_t * vInit; - Aig_Obj_t * pObj, * pObjLi; - int f, i, iBit; - // assign register outputs - Saig_ManForEachLi( pAig, pObj, i ) - pObj->fMarkB = Aig_InfoHasBit( pCex->pData, i ); - // simulate the timeframes - iBit = pCex->nRegs; - for ( f = 0; f <= pCex->iFrame; f++ ) - { - // set the PI simulation information - Aig_ManConst1(pAig)->fMarkB = 1; - Saig_ManForEachPi( pAig, pObj, i ) - pObj->fMarkB = Aig_InfoHasBit( pCex->pData, iBit++ ); - Saig_ManForEachLiLo( pAig, pObjLi, pObj, i ) - pObj->fMarkB = pObjLi->fMarkB; - // simulate internal nodes - Aig_ManForEachNode( pAig, pObj, i ) - pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ) - & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) ); - // assign the COs - Aig_ManForEachPo( pAig, pObj, i ) - pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ); - } - assert( iBit == pCex->nBits ); - // check that the output failed as expected -- cannot check because it is not an SRM! -// pObj = Aig_ManPo( pAig, pCex->iPo ); -// if ( pObj->fMarkB != 1 ) -// printf( "The counter-example does not refine the output.\n" ); - // record the new pattern - vInit = Vec_IntAlloc( Saig_ManRegNum(pAig) ); - Saig_ManForEachLo( pAig, pObj, i ) - { -//printf( "%d", pObj->fMarkB ); - Vec_IntPush( vInit, pObj->fMarkB ); - } -//printf( "\n" ); - Aig_ManCleanMarkB( pAig ); - return vInit; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_RarCheckTrivial( Aig_Man_t * pAig, int fVerbose ) -{ - Aig_Obj_t * pObj; - int i; - Saig_ManForEachPo( pAig, pObj, i ) - { - if ( pAig->nConstrs && i >= Saig_ManPoNum(pAig) - pAig->nConstrs ) - return 0; - if ( pObj->fPhase ) - { - ABC_FREE( pAig->pSeqModel ); - pAig->pSeqModel = Abc_CexAlloc( Aig_ManRegNum(pAig), Saig_ManPiNum(pAig), 1 ); - pAig->pSeqModel->iPo = i; - if ( fVerbose ) - printf( "Output %d is trivally SAT in frame 0. \n", i ); - return 1; - } - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Perform sequential simulation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_RarSimulate( Aig_Man_t * pAig, int nFrames, int nWords, int nBinSize, int nRounds, int nRandSeed, int TimeOut, int fVerbose ) -{ - int fTryBmc = 0; - int fMiter = 1; - Ssw_RarMan_t * p; - int r, f, clk, clkTotal = clock(); - int nTimeToStop = time(NULL) + TimeOut; - int RetValue = -1; - int iFrameFail = -1; - assert( Aig_ManRegNum(pAig) > 0 ); - assert( Aig_ManConstrNum(pAig) == 0 ); - // consider the case of empty AIG - if ( Aig_ManNodeNum(pAig) == 0 ) - return -1; - // check trivially SAT miters - if ( fMiter && Ssw_RarCheckTrivial( pAig, fVerbose ) ) - return 0; - if ( fVerbose ) - printf( "Rarity simulation with %d words, %d frames, %d rounds, %d seed, and %d sec timeout.\n", - nWords, nFrames, nRounds, nRandSeed, TimeOut ); - // reset random numbers - Ssw_RarManPrepareRandom( nRandSeed ); - - // create manager - p = Ssw_RarManStart( pAig, nWords, nFrames, nBinSize, fVerbose ); - p->vInits = Vec_IntStart( Aig_ManRegNum(pAig) * nWords ); - - // perform simulation rounds - for ( r = 0; r < nRounds; r++ ) - { - clk = clock(); - if ( fTryBmc ) - { - Aig_Man_t * pNewAig = Saig_ManDupWithPhase( pAig, p->vInits ); - Saig_BmcPerform( pNewAig, 0, 100, 2000, 3, 0, 0, 1 /*fVerbose*/, 0, &iFrameFail ); -// if ( pNewAig->pSeqModel != NULL ) -// printf( "BMC has found a counter-example in frame %d.\n", iFrameFail ); - Aig_ManStop( pNewAig ); - } - // simulate - for ( f = 0; f < nFrames; f++ ) - { - Ssw_RarManSimulate( p, f ? NULL : p->vInits, 0, 0 ); - if ( fMiter && Ssw_RarManCheckNonConstOutputs(p) ) - { - if ( fVerbose ) printf( "\n" ); -// printf( "Simulation asserted a PO in frame f: %d <= f < %d.\n", r * nFrames, (r+1) * nFrames ); - Ssw_RarManPrepareRandom( nRandSeed ); - ABC_FREE( pAig->pSeqModel ); - pAig->pSeqModel = Ssw_RarDeriveCex( p, r * p->nFrames + f, p->iFailPo, p->iFailPat, fVerbose ); - RetValue = 0; - goto finish; - } - // check timeout - if ( TimeOut && time(NULL) > nTimeToStop ) - { - if ( fVerbose ) printf( "\n" ); - printf( "Reached timeout (%d seconds).\n", TimeOut ); - goto finish; - } - } - // get initialization patterns - Ssw_RarTransferPatterns( p, p->vInits ); - // printout - if ( fVerbose ) - { -// printf( "Round %3d: ", r ); -// Abc_PrintTime( 1, "Time", clock() - clk ); - printf( "." ); - } - } -finish: - if ( r == nRounds && f == nFrames ) - { - if ( fVerbose ) printf( "\n" ); - printf( "Simulation did not assert POs in the first %d frames. ", nRounds * nFrames ); - Abc_PrintTime( 1, "Time", clock() - clkTotal ); - } - // cleanup - Ssw_RarManStop( p ); - return RetValue; -} - - -/**Function************************************************************* - - Synopsis [Perform sequential simulation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_RarSimulateGia( Gia_Man_t * p, int nFrames, int nWords, int nBinSize, int nRounds, int nRandSeed, int TimeOut, int fVerbose ) -{ - Aig_Man_t * pAig; - int RetValue; - pAig = Gia_ManToAigSimple( p ); - RetValue = Ssw_RarSimulate( pAig, nFrames, nWords, nBinSize, nRounds, nRandSeed, TimeOut, fVerbose ); - // save counter-example - Abc_CexFree( p->pCexSeq ); - p->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL; - Aig_ManStop( pAig ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Filter equivalence classes of nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_RarSignalFilter( Aig_Man_t * pAig, int nFrames, int nWords, int nBinSize, int nRounds, int nRandSeed, int TimeOut, int fMiter, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose ) -{ - Ssw_RarMan_t * p; - int r, f, i, k, clkTotal = clock(); - int nTimeToStop = time(NULL) + TimeOut; - int RetValue = -1; - assert( Aig_ManRegNum(pAig) > 0 ); - assert( Aig_ManConstrNum(pAig) == 0 ); - // consider the case of empty AIG - if ( Aig_ManNodeNum(pAig) == 0 ) - return -1; - // check trivially SAT miters - if ( fMiter && Ssw_RarCheckTrivial( pAig, 1 ) ) - return 0; - if ( fVerbose ) - printf( "Rarity equiv filtering with %d words, %d frames, %d rounds, %d seed, and %d sec timeout.\n", - nWords, nFrames, nRounds, nRandSeed, TimeOut ); - // reset random numbers - Ssw_RarManPrepareRandom( nRandSeed ); - - // create manager - p = Ssw_RarManStart( pAig, nWords, nFrames, nBinSize, fVerbose ); - // compute starting state if needed - assert( p->vInits == NULL ); - if ( pCex ) - { - p->vInits = Ssw_RarFindStartingState( pAig, pCex ); - printf( "Beginning simulation from the state derived using the counter-example.\n" ); - } - else - p->vInits = Vec_IntStart( Aig_ManRegNum(pAig) ); - // duplicate the array - for ( i = 1; i < nWords; i++ ) - for ( k = 0; k < Aig_ManRegNum(pAig); k++ ) - Vec_IntPush( p->vInits, Vec_IntEntry(p->vInits, k) ); - assert( Vec_IntSize(p->vInits) == Aig_ManRegNum(pAig) * nWords ); - - // create trivial equivalence classes with all nodes being candidates for constant 1 - if ( pAig->pReprs == NULL ) - p->ppClasses = Ssw_ClassesPrepareSimple( pAig, fLatchOnly, 0 ); - else - p->ppClasses = Ssw_ClassesPrepareFromReprs( pAig ); - Ssw_ClassesSetData( p->ppClasses, p, Ssw_RarManObjHashWord, Ssw_RarManObjIsConst, Ssw_RarManObjsAreEqual ); - // print the stats - if ( fVerbose ) - { - printf( "Initial : " ); - Ssw_ClassesPrint( p->ppClasses, 0 ); - } - // refine classes using BMC - for ( r = 0; r < nRounds; r++ ) - { - // start filtering equivalence classes - if ( Ssw_ClassesCand1Num(p->ppClasses) == 0 && Ssw_ClassesClassNum(p->ppClasses) == 0 ) - { - printf( "All equivalences are refined away.\n" ); - break; - } - // simulate - for ( f = 0; f < nFrames; f++ ) - { - Ssw_RarManSimulate( p, f ? NULL : p->vInits, 1, !r && !f ); - if ( fMiter && Ssw_RarManCheckNonConstOutputs(p) ) - { - if ( !fVerbose ) - printf( "\r" ); -// printf( "Simulation asserted a PO in frame f: %d <= f < %d.\n", r * nFrames, (r+1) * nFrames ); - Ssw_RarManPrepareRandom( nRandSeed ); - Abc_CexFree( pAig->pSeqModel ); - pAig->pSeqModel = Ssw_RarDeriveCex( p, r * p->nFrames + f, p->iFailPo, p->iFailPat, 1 ); - RetValue = 0; - goto finish; - } - // check timeout - if ( TimeOut && time(NULL) > nTimeToStop ) - { - if ( fVerbose ) printf( "\n" ); - printf( "Reached timeout (%d seconds).\n", TimeOut ); - goto finish; - } - } - // get initialization patterns - Ssw_RarTransferPatterns( p, p->vInits ); - // printout - if ( fVerbose ) - { - printf( "Round %3d: ", r ); - Ssw_ClassesPrint( p->ppClasses, 0 ); - } - else - { - printf( "." ); - } - } -finish: - // report - if ( r == nRounds && f == nFrames ) - { - if ( !fVerbose ) - printf( "\r" ); - printf( "Simulation did not assert POs in the first %d frames. ", nRounds * nFrames ); - Abc_PrintTime( 1, "Time", clock() - clkTotal ); - } - // cleanup - Ssw_RarManStop( p ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Filter equivalence classes of nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_RarSignalFilterGia( Gia_Man_t * p, int nFrames, int nWords, int nBinSize, int nRounds, int nRandSeed, int TimeOut, int fMiter, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose ) -{ - Aig_Man_t * pAig; - int RetValue; - pAig = Gia_ManToAigSimple( p ); - if ( p->pReprs != NULL ) - { - Gia_ManReprToAigRepr2( pAig, p ); - ABC_FREE( p->pReprs ); - ABC_FREE( p->pNexts ); - } - RetValue = Ssw_RarSignalFilter( pAig, nFrames, nWords, nBinSize, nRounds, nRandSeed, TimeOut, fMiter, pCex, fLatchOnly, fVerbose ); - Gia_ManReprFromAigRepr( pAig, p ); - // save counter-example - Abc_CexFree( p->pCexSeq ); - p->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL; - Aig_ManStop( pAig ); - return RetValue; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ssw/sswRarity2.c b/src/aig/ssw/sswRarity2.c deleted file mode 100644 index d8cb9c16..00000000 --- a/src/aig/ssw/sswRarity2.c +++ /dev/null @@ -1,517 +0,0 @@ -/**CFile**************************************************************** - - FileName [sswRarity.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Inductive prover with constraints.] - - Synopsis [Rarity-driven refinement of equivalence classes.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 1, 2008.] - - Revision [$Id: sswRarity.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "sswInt.h" -#include "giaAig.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Ssw_RarMan_t_ Ssw_RarMan_t; -struct Ssw_RarMan_t_ -{ - // parameters - int nWords; // the number of words to simulate - int nFrames; // the number of frames to simulate - int nBinSize; // the number of flops in one group - int fVerbose; // the verbosiness flag - int nGroups; // the number of flop groups - // internal data - Aig_Man_t * pAig; // AIG with equivalence classes - Ssw_Cla_t * ppClasses; // equivalence classes - Ssw_Sml_t * pSml; // simulation manager - Vec_Ptr_t * vSimInfo; // simulation info from pSml manager - Vec_Int_t * vInits; // initial state - // rarity data - int * pRarity; // occur counts for patterns in groups - int * pGroupValues; // occur counts in each group - double * pPatCosts; // pattern costs - -}; - -static inline int Ssw_RarGetBinPat( Ssw_RarMan_t * p, int iBin, int iPat ) -{ - assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->nBinSize ); - assert( iPat >= 0 && iPat < (1 << p->nBinSize) ); - return p->pRarity[iBin * (1 << p->nBinSize) + iPat]; -} -static inline void Ssw_RarSetBinPat( Ssw_RarMan_t * p, int iBin, int iPat, int Value ) -{ - assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->nBinSize ); - assert( iPat >= 0 && iPat < (1 << p->nBinSize) ); - p->pRarity[iBin * (1 << p->nBinSize) + iPat] = Value; -} -static inline void Ssw_RarAddToBinPat( Ssw_RarMan_t * p, int iBin, int iPat ) -{ - assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->nBinSize ); - assert( iPat >= 0 && iPat < (1 << p->nBinSize) ); - p->pRarity[iBin * (1 << p->nBinSize) + iPat]++; -} - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static Ssw_RarMan_t * Ssw_RarManStart( Aig_Man_t * pAig, int nWords, int nFrames, int nBinSize, int fVerbose ) -{ - Ssw_RarMan_t * p; - if ( Aig_ManRegNum(pAig) < nBinSize || nBinSize <= 0 ) - return NULL; - p = ABC_CALLOC( Ssw_RarMan_t, 1 ); - p->pAig = pAig; - p->nWords = nWords; - p->nFrames = nFrames; - p->nBinSize = nBinSize; - p->fVerbose = fVerbose; - p->nGroups = Aig_ManRegNum(pAig) / nBinSize; - p->pRarity = ABC_CALLOC( int, (1 << nBinSize) * p->nGroups ); - p->pGroupValues = ABC_CALLOC( int, p->nGroups ); - p->pPatCosts = ABC_CALLOC( double, p->nWords * 32 ); - p->pSml = Ssw_SmlStart( pAig, 0, nFrames, nWords ); - p->vSimInfo = Ssw_SmlSimDataPointers( p->pSml ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Ssw_RarManStop( Ssw_RarMan_t * p ) -{ - if ( p->pSml ) Ssw_SmlStop( p->pSml ); - if ( p->ppClasses ) Ssw_ClassesStop( p->ppClasses ); - Vec_PtrFreeP( &p->vSimInfo ); - Vec_IntFreeP( &p->vInits ); - ABC_FREE( p->pGroupValues ); - ABC_FREE( p->pPatCosts ); - ABC_FREE( p->pRarity ); - ABC_FREE( p ); -} - - -/**Function************************************************************* - - Synopsis [Updates rarity counters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Ssw_RarUpdateCounters( Ssw_RarMan_t * p ) -{ - Aig_Obj_t * pObj; - unsigned * pData; - int i, k; -/* - Saig_ManForEachLi( p->pAig, pObj, i ) - { - pData = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjId(pObj) ) + p->nWords * (p->nFrames - 1); - Extra_PrintBinary( stdout, pData, 32 ); printf( "\n" ); - } -*/ - for ( k = 0; k < p->nWords * 32; k++ ) - { - for ( i = 0; i < p->nGroups; i++ ) - p->pGroupValues[i] = 0; - Saig_ManForEachLi( p->pAig, pObj, i ) - { - pData = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjId(pObj) ) + p->nWords * (p->nFrames - 1); - if ( Aig_InfoHasBit(pData, k) && i / p->nBinSize < p->nGroups ) - p->pGroupValues[i / p->nBinSize] |= (1 << (i % p->nBinSize)); - } - for ( i = 0; i < p->nGroups; i++ ) - Ssw_RarAddToBinPat( p, i, p->pGroupValues[i] ); - } -/* - for ( i = 0; i < p->nGroups; i++ ) - { - for ( k = 0; k < (1 << p->nBinSize); k++ ) - printf( "%d ", Ssw_RarGetBinPat(p, i, k) ); - printf( "\n" ); - } -*/ -} - -/**Function************************************************************* - - Synopsis [Select best patterns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Ssw_RarTransferPatterns( Ssw_RarMan_t * p, Vec_Int_t * vInits ) -{ - Aig_Obj_t * pObj; - unsigned * pData; - int i, k, Value; - - // for each pattern - for ( k = 0; k < p->nWords * 32; k++ ) - { - for ( i = 0; i < p->nGroups; i++ ) - p->pGroupValues[i] = 0; - // compute its group values - Saig_ManForEachLi( p->pAig, pObj, i ) - { - pData = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjId(pObj) ) + p->nWords * (p->nFrames - 1); - if ( Aig_InfoHasBit(pData, k) && i / p->nBinSize < p->nGroups ) - p->pGroupValues[i / p->nBinSize] |= (1 << (i % p->nBinSize)); - } - // find the cost of its values - p->pPatCosts[k] = 0.0; - for ( i = 0; i < p->nGroups; i++ ) - { - Value = Ssw_RarGetBinPat( p, i, p->pGroupValues[i] ); - assert( Value > 0 ); - p->pPatCosts[k] += 1.0/(Value*Value); - } - // print the result -// printf( "%3d : %9.6f\n", k, p->pPatCosts[k] ); - } - - // choose as many as there are words - Vec_IntClear( vInits ); - for ( i = 0; i < p->nWords; i++ ) - { - // select the best - int iPatBest = -1; - double iCostBest = -ABC_INFINITY; - for ( k = 0; k < p->nWords * 32; k++ ) - if ( iCostBest < p->pPatCosts[k] ) - { - iCostBest = p->pPatCosts[k]; - iPatBest = k; - } - // remove from costs - assert( iPatBest >= 0 ); - p->pPatCosts[iPatBest] = -ABC_INFINITY; - // set the flops - Saig_ManForEachLi( p->pAig, pObj, k ) - { - pData = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjId(pObj) ) + p->nWords * (p->nFrames - 1); - Vec_IntPush( vInits, Aig_InfoHasBit(pData, iPatBest) ); - } -//printf( "Best pattern %5d\n", iPatBest ); - } - assert( Vec_IntSize(vInits) == Aig_ManRegNum(p->pAig) * p->nWords ); -} - - -/**Function************************************************************* - - Synopsis [Performs fraiging for one node.] - - Description [Returns the fraiged node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static Vec_Int_t * Ssw_RarFindStartingState( Aig_Man_t * pAig, Abc_Cex_t * pCex ) -{ - Vec_Int_t * vInit; - Aig_Obj_t * pObj, * pObjLi; - int f, i, iBit; - // assign register outputs - Saig_ManForEachLi( pAig, pObj, i ) - pObj->fMarkB = Aig_InfoHasBit( pCex->pData, i ); - // simulate the timeframes - iBit = pCex->nRegs; - for ( f = 0; f <= pCex->iFrame; f++ ) - { - // set the PI simulation information - Aig_ManConst1(pAig)->fMarkB = 1; - Saig_ManForEachPi( pAig, pObj, i ) - pObj->fMarkB = Aig_InfoHasBit( pCex->pData, iBit++ ); - Saig_ManForEachLiLo( pAig, pObjLi, pObj, i ) - pObj->fMarkB = pObjLi->fMarkB; - // simulate internal nodes - Aig_ManForEachNode( pAig, pObj, i ) - pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ) - & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) ); - // assign the COs - Aig_ManForEachPo( pAig, pObj, i ) - pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ); - } - assert( iBit == pCex->nBits ); - // check that the output failed as expected -- cannot check because it is not an SRM! -// pObj = Aig_ManPo( pAig, pCex->iPo ); -// if ( pObj->fMarkB != 1 ) -// printf( "The counter-example does not refine the output.\n" ); - // record the new pattern - vInit = Vec_IntAlloc( Saig_ManRegNum(pAig) ); - Saig_ManForEachLo( pAig, pObj, i ) - Vec_IntPush( vInit, pObj->fMarkB ); - return vInit; -} - - -/**Function************************************************************* - - Synopsis [Perform sequential simulation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_RarSimulate2( Aig_Man_t * pAig, int nFrames, int nWords, int nBinSize, int nRounds, int TimeOut, int fVerbose ) -{ - int fMiter = 1; - Ssw_RarMan_t * p; - int r, clk, clkTotal = clock(); - int nTimeToStop = time(NULL) + TimeOut; - int RetValue = -1; - assert( Aig_ManRegNum(pAig) > 0 ); - assert( Aig_ManConstrNum(pAig) == 0 ); - // consider the case of empty AIG - if ( Aig_ManNodeNum(pAig) == 0 ) - return -1; - if ( fVerbose ) - printf( "Simulating %d words through %d frames with %d binsize, %d rounds, and %d sec timeout.\n", - nWords, nFrames, nBinSize, nRounds, TimeOut ); - // reset random numbers - Aig_ManRandom( 1 ); - - // create manager - p = Ssw_RarManStart( pAig, nWords, nFrames, nBinSize, fVerbose ); - p->vInits = Vec_IntStart( Aig_ManRegNum(pAig) * nWords ); - Ssw_SmlInitializeSpecial( p->pSml, p->vInits ); - - // perform simulation rounds - for ( r = 0; r < nRounds; r++ ) - { - clk = clock(); - // simulate - Ssw_SmlSimulateOne( p->pSml ); - if ( fMiter && Ssw_SmlCheckNonConstOutputs(p->pSml) ) - { - if ( fVerbose ) printf( "\n" ); - printf( "Simulation asserted a PO in frame f: %d <= f < %d.\n", r * nFrames, (r+1) * nFrames ); - RetValue = 0; - break; - } - // get initialization patterns - Ssw_RarUpdateCounters( p ); - Ssw_RarTransferPatterns( p, p->vInits ); - Ssw_SmlInitializeSpecial( p->pSml, p->vInits ); - // printout - if ( fVerbose ) - { -// printf( "Round %3d: ", r ); -// Abc_PrintTime( 1, "Time", clock() - clk ); - printf( "." ); - } - // check timeout - if ( TimeOut && time(NULL) > nTimeToStop ) - { - if ( fVerbose ) printf( "\n" ); - printf( "Reached timeout (%d seconds).\n", TimeOut ); - break; - } - } - if ( r == nRounds ) - { - if ( fVerbose ) printf( "\n" ); - printf( "Simulation did not assert POs in the first %d frames. ", nRounds * nFrames ); - Abc_PrintTime( 1, "Time", clock() - clkTotal ); - } - // cleanup - Ssw_RarManStop( p ); - return RetValue; -} - - -/**Function************************************************************* - - Synopsis [Filter equivalence classes of nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_RarSignalFilter2( Aig_Man_t * pAig, int nFrames, int nWords, int nBinSize, int nRounds, int TimeOut, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose ) -{ - int fMiter = 0; - Ssw_RarMan_t * p; - int r, i, k, clkTotal = clock(); - int nTimeToStop = time(NULL) + TimeOut; - int RetValue = -1; - assert( Aig_ManRegNum(pAig) > 0 ); - assert( Aig_ManConstrNum(pAig) == 0 ); - // consider the case of empty AIG - if ( Aig_ManNodeNum(pAig) == 0 ) - return -1; - if ( fVerbose ) - printf( "Filtering equivs with %d words through %d frames with %d binsize, %d rounds, and %d sec timeout.\n", - nWords, nFrames, nBinSize, nRounds, TimeOut ); - // reset random numbers - Aig_ManRandom( 1 ); - - // create manager - p = Ssw_RarManStart( pAig, nWords, nFrames, nBinSize, fVerbose ); - // compute starting state if needed - assert( p->vInits == NULL ); - if ( pCex ) - p->vInits = Ssw_RarFindStartingState( pAig, pCex ); - else - p->vInits = Vec_IntStart( Aig_ManRegNum(pAig) ); - // duplicate the array - for ( i = 1; i < nWords; i++ ) - for ( k = 0; k < Aig_ManRegNum(pAig); k++ ) - Vec_IntPush( p->vInits, Vec_IntEntry(p->vInits, k) ); - assert( Vec_IntSize(p->vInits) == Aig_ManRegNum(pAig) * nWords ); - // initialize simulation manager - Ssw_SmlInitializeSpecial( p->pSml, p->vInits ); - - // create trivial equivalence classes with all nodes being candidates for constant 1 - if ( pAig->pReprs == NULL ) - p->ppClasses = Ssw_ClassesPrepareSimple( pAig, fLatchOnly, 0 ); - else - p->ppClasses = Ssw_ClassesPrepareFromReprs( pAig ); - Ssw_ClassesSetData( p->ppClasses, p->pSml, NULL, Ssw_SmlObjIsConstWord, Ssw_SmlObjsAreEqualWord ); - // print the stats - if ( fVerbose ) - { - printf( "Initial : " ); - Ssw_ClassesPrint( p->ppClasses, 0 ); - } - // refine classes using BMC - for ( r = 0; r < nRounds; r++ ) - { - // start filtering equivalence classes - if ( Ssw_ClassesCand1Num(p->ppClasses) == 0 && Ssw_ClassesClassNum(p->ppClasses) == 0 ) - { - printf( "All equivalences are refined away.\n" ); - break; - } - // simulate - Ssw_SmlSimulateOne( p->pSml ); - if ( fMiter && Ssw_SmlCheckNonConstOutputs(p->pSml) ) - { - if ( fVerbose ) printf( "\n" ); - printf( "Simulation asserted a PO in frame f: %d <= f < %d.\n", r * nFrames, (r+1) * nFrames ); - RetValue = 0; - break; - } - // check equivalence classes - Ssw_ClassesRefineConst1( p->ppClasses, 1 ); - Ssw_ClassesRefine( p->ppClasses, 1 ); - // printout - if ( fVerbose ) - { - printf( "Round %3d: ", r ); - Ssw_ClassesPrint( p->ppClasses, 0 ); - } - // get initialization patterns - Ssw_RarUpdateCounters( p ); - Ssw_RarTransferPatterns( p, p->vInits ); - Ssw_SmlInitializeSpecial( p->pSml, p->vInits ); - // check timeout - if ( TimeOut && time(NULL) > nTimeToStop ) - { - if ( fVerbose ) printf( "\n" ); - printf( "Reached timeout (%d seconds).\n", TimeOut ); - break; - } - } - if ( r == nRounds ) - { - printf( "Simulation did not assert POs in the first %d frames. ", nRounds * nFrames ); - Abc_PrintTime( 1, "Time", clock() - clkTotal ); - } - // cleanup - Ssw_RarManStop( p ); - return -1; -} - -/**Function************************************************************* - - Synopsis [Filter equivalence classes of nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_RarSignalFilterGia2( Gia_Man_t * p, int nFrames, int nWords, int nBinSize, int nRounds, int TimeOut, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose ) -{ - Aig_Man_t * pAig; - int RetValue; - pAig = Gia_ManToAigSimple( p ); - if ( p->pReprs != NULL ) - { - Gia_ManReprToAigRepr2( pAig, p ); - ABC_FREE( p->pReprs ); - ABC_FREE( p->pNexts ); - } - RetValue = Ssw_RarSignalFilter2( pAig, nFrames, nWords, nBinSize, nRounds, TimeOut, pCex, fLatchOnly, fVerbose ); - Gia_ManReprFromAigRepr( pAig, p ); - Aig_ManStop( pAig ); - return RetValue; -} - - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ssw/sswSat.c b/src/aig/ssw/sswSat.c deleted file mode 100644 index 7d371cac..00000000 --- a/src/aig/ssw/sswSat.c +++ /dev/null @@ -1,306 +0,0 @@ -/**CFile**************************************************************** - - FileName [sswSat.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Inductive prover with constraints.] - - Synopsis [Calls to the SAT solver.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 1, 2008.] - - Revision [$Id: sswSat.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "sswInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Runs equivalence test for the two nodes.] - - Description [Both nodes should be regular and different from each other.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_NodesAreEquiv( Ssw_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ) -{ - int nBTLimit = p->pPars->nBTLimit; - int pLits[3], nLits, RetValue, RetValue1, clk;//, status; - p->nSatCalls++; - p->pMSat->nSolverCalls++; - - // sanity checks - assert( !Aig_IsComplement(pOld) ); - assert( !Aig_IsComplement(pNew) ); - assert( pOld != pNew ); - assert( p->pMSat != NULL ); - - // if the nodes do not have SAT variables, allocate them - Ssw_CnfNodeAddToSolver( p->pMSat, pOld ); - Ssw_CnfNodeAddToSolver( p->pMSat, pNew ); - - // solve under assumptions - // A = 1; B = 0 OR A = 1; B = 1 - nLits = 2; - pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pOld), 0 ); - pLits[1] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), pOld->fPhase == pNew->fPhase ); - if ( p->iOutputLit > -1 ) - pLits[nLits++] = p->iOutputLit; - if ( p->pPars->fPolarFlip ) - { - if ( pOld->fPhase ) pLits[0] = lit_neg( pLits[0] ); - if ( pNew->fPhase ) pLits[1] = lit_neg( pLits[1] ); - } -//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 ); - - if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead ) - { - RetValue = sat_solver_simplify(p->pMSat->pSat); - assert( RetValue != 0 ); - } - -clk = clock(); - RetValue1 = sat_solver_solve( p->pMSat->pSat, pLits, pLits + nLits, - (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); -p->timeSat += clock() - clk; - if ( RetValue1 == l_False ) - { -p->timeSatUnsat += clock() - clk; - if ( nLits == 2 ) - { - pLits[0] = lit_neg( pLits[0] ); - pLits[1] = lit_neg( pLits[1] ); - RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 2 ); - assert( RetValue ); -/* - if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead ) - { - RetValue = sat_solver_simplify(p->pMSat->pSat); - assert( RetValue != 0 ); - } -*/ - } - p->nSatCallsUnsat++; - } - else if ( RetValue1 == l_True ) - { -p->timeSatSat += clock() - clk; - p->nSatCallsSat++; - return 0; - } - else // if ( RetValue1 == l_Undef ) - { -p->timeSatUndec += clock() - clk; - p->nSatFailsReal++; - return -1; - } - - // if the old node was constant 0, we already know the answer - if ( pOld == Aig_ManConst1(p->pFrames) ) - { - p->nSatProof++; - return 1; - } - - // solve under assumptions - // A = 0; B = 1 OR A = 0; B = 0 - nLits = 2; - pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pOld), 1 ); - pLits[1] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), pOld->fPhase ^ pNew->fPhase ); - if ( p->iOutputLit > -1 ) - pLits[nLits++] = p->iOutputLit; - if ( p->pPars->fPolarFlip ) - { - if ( pOld->fPhase ) pLits[0] = lit_neg( pLits[0] ); - if ( pNew->fPhase ) pLits[1] = lit_neg( pLits[1] ); - } - - if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead ) - { - RetValue = sat_solver_simplify(p->pMSat->pSat); - assert( RetValue != 0 ); - } - -clk = clock(); - RetValue1 = sat_solver_solve( p->pMSat->pSat, pLits, pLits + nLits, - (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); -p->timeSat += clock() - clk; - if ( RetValue1 == l_False ) - { -p->timeSatUnsat += clock() - clk; - if ( nLits == 2 ) - { - pLits[0] = lit_neg( pLits[0] ); - pLits[1] = lit_neg( pLits[1] ); - RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 2 ); - assert( RetValue ); -/* - if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead ) - { - RetValue = sat_solver_simplify(p->pMSat->pSat); - assert( RetValue != 0 ); - } -*/ - } - p->nSatCallsUnsat++; - } - else if ( RetValue1 == l_True ) - { -p->timeSatSat += clock() - clk; - p->nSatCallsSat++; - return 0; - } - else // if ( RetValue1 == l_Undef ) - { -p->timeSatUndec += clock() - clk; - p->nSatFailsReal++; - return -1; - } - // return SAT proof - p->nSatProof++; - return 1; -} - -/**Function************************************************************* - - Synopsis [Constrains two nodes to be equivalent in the SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_NodesAreConstrained( Ssw_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ) -{ - int pLits[2], RetValue, fComplNew; - Aig_Obj_t * pTemp; - - // sanity checks - assert( Aig_Regular(pOld) != Aig_Regular(pNew) ); - assert( p->pPars->fConstrs || Aig_ObjPhaseReal(pOld) == Aig_ObjPhaseReal(pNew) ); - - // move constant to the old node - if ( Aig_Regular(pNew) == Aig_ManConst1(p->pFrames) ) - { - assert( Aig_Regular(pOld) != Aig_ManConst1(p->pFrames) ); - pTemp = pOld; - pOld = pNew; - pNew = pTemp; - } - - // move complement to the new node - if ( Aig_IsComplement(pOld) ) - { - pOld = Aig_Regular(pOld); - pNew = Aig_Not(pNew); - } - assert( p->pMSat != NULL ); - - // if the nodes do not have SAT variables, allocate them - Ssw_CnfNodeAddToSolver( p->pMSat, pOld ); - Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pNew) ); - - // transform the new node - fComplNew = Aig_IsComplement( pNew ); - pNew = Aig_Regular( pNew ); - - // consider the constant 1 case - if ( pOld == Aig_ManConst1(p->pFrames) ) - { - // add constraint A = 1 ----> A - pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), fComplNew ); - if ( p->pPars->fPolarFlip ) - { - if ( pNew->fPhase ) pLits[0] = lit_neg( pLits[0] ); - } - RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 1 ); - assert( RetValue ); - } - else - { - // add constraint A = B ----> (A v !B)(!A v B) - - // (A v !B) - pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pOld), 0 ); - pLits[1] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), !fComplNew ); - if ( p->pPars->fPolarFlip ) - { - if ( pOld->fPhase ) pLits[0] = lit_neg( pLits[0] ); - if ( pNew->fPhase ) pLits[1] = lit_neg( pLits[1] ); - } - pLits[0] = lit_neg( pLits[0] ); - pLits[1] = lit_neg( pLits[1] ); - RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 2 ); - assert( RetValue ); - - // (!A v B) - pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pOld), 1 ); - pLits[1] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), fComplNew); - if ( p->pPars->fPolarFlip ) - { - if ( pOld->fPhase ) pLits[0] = lit_neg( pLits[0] ); - if ( pNew->fPhase ) pLits[1] = lit_neg( pLits[1] ); - } - pLits[0] = lit_neg( pLits[0] ); - pLits[1] = lit_neg( pLits[1] ); - RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 2 ); - assert( RetValue ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Constrains one node in the SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_NodeIsConstrained( Ssw_Man_t * p, Aig_Obj_t * pPoObj ) -{ - int RetValue, Lit; - Ssw_CnfNodeAddToSolver( p->pMSat, Aig_ObjFanin0(pPoObj) ); - // add constraint A = 1 ----> A - Lit = toLitCond( Ssw_ObjSatNum(p->pMSat,Aig_ObjFanin0(pPoObj)), !Aig_ObjFaninC0(pPoObj) ); - if ( p->pPars->fPolarFlip ) - { - if ( Aig_ObjFanin0(pPoObj)->fPhase ) Lit = lit_neg( Lit ); - } - RetValue = sat_solver_addclause( p->pMSat->pSat, &Lit, &Lit + 1 ); - assert( RetValue ); - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ssw/sswSemi.c b/src/aig/ssw/sswSemi.c deleted file mode 100644 index 2a28a29b..00000000 --- a/src/aig/ssw/sswSemi.c +++ /dev/null @@ -1,322 +0,0 @@ -/**CFile**************************************************************** - - FileName [sswSemi.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Inductive prover with constraints.] - - Synopsis [Semiformal for equivalence clases.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 1, 2008.] - - Revision [$Id: sswSemi.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "sswInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Ssw_Sem_t_ Ssw_Sem_t; // BMC manager - -struct Ssw_Sem_t_ -{ - // parameters - int nConfMaxStart; // the starting conflict limit - int nConfMax; // the intermediate conflict limit - int nFramesSweep; // the number of frames to sweep - int fVerbose; // prints output statistics - // equivalences considered - Ssw_Man_t * pMan; // SAT sweeping manager - Vec_Ptr_t * vTargets; // the nodes that are watched - // storage for patterns - int nPatternsAlloc; // the max number of interesting states - int nPatterns; // the number of patterns - Vec_Ptr_t * vPatterns; // storage for the interesting states - Vec_Int_t * vHistory; // what state and how many steps -}; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ssw_Sem_t * Ssw_SemManStart( Ssw_Man_t * pMan, int nConfMax, int fVerbose ) -{ - Ssw_Sem_t * p; - Aig_Obj_t * pObj; - int i; - // create interpolation manager - p = ABC_ALLOC( Ssw_Sem_t, 1 ); - memset( p, 0, sizeof(Ssw_Sem_t) ); - p->nConfMaxStart = nConfMax; - p->nConfMax = nConfMax; - p->nFramesSweep = ABC_MAX( (1<<21)/Aig_ManNodeNum(pMan->pAig), pMan->nFrames ); - p->fVerbose = fVerbose; - // equivalences considered - p->pMan = pMan; - p->vTargets = Vec_PtrAlloc( Saig_ManPoNum(p->pMan->pAig) ); - Saig_ManForEachPo( p->pMan->pAig, pObj, i ) - Vec_PtrPush( p->vTargets, Aig_ObjFanin0(pObj) ); - // storage for patterns - p->nPatternsAlloc = 512; - p->nPatterns = 1; - p->vPatterns = Vec_PtrAllocSimInfo( Aig_ManRegNum(p->pMan->pAig), Aig_BitWordNum(p->nPatternsAlloc) ); - Vec_PtrCleanSimInfo( p->vPatterns, 0, Aig_BitWordNum(p->nPatternsAlloc) ); - p->vHistory = Vec_IntAlloc( 100 ); - Vec_IntPush( p->vHistory, 0 ); - // update arrays of the manager - assert( 0 ); -/* - ABC_FREE( p->pMan->pNodeToFrames ); - Vec_IntFree( p->pMan->vSatVars ); - p->pMan->pNodeToFrames = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pMan->pAig) * p->nFramesSweep ); - p->pMan->vSatVars = Vec_IntStart( Aig_ManObjNumMax(p->pMan->pAig) * (p->nFramesSweep+1) ); -*/ - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SemManStop( Ssw_Sem_t * p ) -{ - Vec_PtrFree( p->vTargets ); - Vec_PtrFree( p->vPatterns ); - Vec_IntFree( p->vHistory ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_SemCheckTargets( Ssw_Sem_t * p ) -{ - Aig_Obj_t * pObj; - int i; - Vec_PtrForEachEntry( Aig_Obj_t *, p->vTargets, pObj, i ) - if ( !Ssw_ObjIsConst1Cand(p->pMan->pAig, pObj) ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ManFilterBmcSavePattern( Ssw_Sem_t * p ) -{ - unsigned * pInfo; - Aig_Obj_t * pObj; - int i; - if ( p->nPatterns >= p->nPatternsAlloc ) - return; - Saig_ManForEachLo( p->pMan->pAig, pObj, i ) - { - pInfo = (unsigned *)Vec_PtrEntry( p->vPatterns, i ); - if ( Aig_InfoHasBit( p->pMan->pPatWords, Saig_ManPiNum(p->pMan->pAig) + i ) ) - Aig_InfoSetBit( pInfo, p->nPatterns ); - } - p->nPatterns++; -} - -/**Function************************************************************* - - Synopsis [Performs fraiging for the internal nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ManFilterBmc( Ssw_Sem_t * pBmc, int iPat, int fCheckTargets ) -{ - Ssw_Man_t * p = pBmc->pMan; - Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo; - unsigned * pInfo; - int i, f, clk, RetValue, fFirst = 0; -clk = clock(); - - // start initialized timeframes - p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * 3 ); - Saig_ManForEachLo( p->pAig, pObj, i ) - { - pInfo = (unsigned *)Vec_PtrEntry( pBmc->vPatterns, i ); - pObjNew = Aig_NotCond( Aig_ManConst1(p->pFrames), !Aig_InfoHasBit(pInfo, iPat) ); - Ssw_ObjSetFrame( p, pObj, 0, pObjNew ); - } - - // sweep internal nodes - RetValue = pBmc->nFramesSweep; - for ( f = 0; f < pBmc->nFramesSweep; f++ ) - { - // map constants and PIs - Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) ); - Saig_ManForEachPi( p->pAig, pObj, i ) - Ssw_ObjSetFrame( p, pObj, f, Aig_ObjCreatePi(p->pFrames) ); - // sweep internal nodes - Aig_ManForEachNode( p->pAig, pObj, i ) - { - pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); - Ssw_ObjSetFrame( p, pObj, f, pObjNew ); - if ( Ssw_ManSweepNode( p, pObj, f, 1, NULL ) ) - { - Ssw_ManFilterBmcSavePattern( pBmc ); - if ( fFirst == 0 ) - { - fFirst = 1; - pBmc->nConfMax *= 10; - } - } - if ( f > 0 && p->pMSat->pSat->stats.conflicts >= pBmc->nConfMax ) - { - RetValue = -1; - break; - } - } - // quit if this is the last timeframe - if ( p->pMSat->pSat->stats.conflicts >= pBmc->nConfMax ) - { - RetValue += f + 1; - break; - } - if ( fCheckTargets && Ssw_SemCheckTargets( pBmc ) ) - break; - // transfer latch input to the latch outputs - // build logic cones for register outputs - Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) - { - pObjNew = Ssw_ObjChild0Fra(p, pObjLi,f); - Ssw_ObjSetFrame( p, pObjLo, f+1, pObjNew ); - Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pObjNew) ); - } -//printf( "Frame %2d : Conflicts = %6d. \n", f, p->pSat->stats.conflicts ); - } - if ( fFirst ) - pBmc->nConfMax /= 10; - - // cleanup - Ssw_ClassesCheck( p->ppClasses ); -p->timeBmc += clock() - clk; - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if one of the targets has failed.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_FilterUsingSemi( Ssw_Man_t * pMan, int fCheckTargets, int nConfMax, int fVerbose ) -{ - Ssw_Sem_t * p; - int RetValue, Frames, Iter, clk = clock(); - p = Ssw_SemManStart( pMan, nConfMax, fVerbose ); - if ( fCheckTargets && Ssw_SemCheckTargets( p ) ) - { - assert( 0 ); - Ssw_SemManStop( p ); - return 1; - } - if ( fVerbose ) - { - printf( "AIG : C = %6d. Cl = %6d. Nodes = %6d. ConfMax = %6d. FramesMax = %6d.\n", - Ssw_ClassesCand1Num(p->pMan->ppClasses), Ssw_ClassesClassNum(p->pMan->ppClasses), - Aig_ManNodeNum(p->pMan->pAig), p->nConfMax, p->nFramesSweep ); - } - RetValue = 0; - for ( Iter = 0; Iter < p->nPatterns; Iter++ ) - { -clk = clock(); - pMan->pMSat = Ssw_SatStart( 0 ); - Frames = Ssw_ManFilterBmc( p, Iter, fCheckTargets ); - if ( fVerbose ) - { - printf( "%3d : C = %6d. Cl = %6d. NR = %6d. F = %3d. C = %5d. P = %3d. %s ", - Iter, Ssw_ClassesCand1Num(p->pMan->ppClasses), Ssw_ClassesClassNum(p->pMan->ppClasses), - Aig_ManNodeNum(p->pMan->pFrames), Frames, (int)p->pMan->pMSat->pSat->stats.conflicts, p->nPatterns, - p->pMan->nSatFailsReal? "f" : " " ); - ABC_PRT( "T", clock() - clk ); - } - Ssw_ManCleanup( p->pMan ); - if ( fCheckTargets && Ssw_SemCheckTargets( p ) ) - { - printf( "Target is hit!!!\n" ); - RetValue = 1; - } - if ( p->nPatterns >= p->nPatternsAlloc ) - break; - } - Ssw_SemManStop( p ); - - pMan->nStrangers = 0; - pMan->nSatCalls = 0; - pMan->nSatProof = 0; - pMan->nSatFailsReal = 0; - pMan->nSatCallsUnsat = 0; - pMan->nSatCallsSat = 0; - pMan->timeSimSat = 0; - pMan->timeSat = 0; - pMan->timeSatSat = 0; - pMan->timeSatUnsat = 0; - pMan->timeSatUndec = 0; - return RetValue; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ssw/sswSim.c b/src/aig/ssw/sswSim.c deleted file mode 100644 index daee24ec..00000000 --- a/src/aig/ssw/sswSim.c +++ /dev/null @@ -1,1405 +0,0 @@ -/**CFile**************************************************************** - - FileName [sswSim.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Inductive prover with constraints.] - - Synopsis [Sequential simulator used by the inductive prover.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 1, 2008.] - - Revision [$Id: sswSim.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "sswInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// simulation manager -struct Ssw_Sml_t_ -{ - Aig_Man_t * pAig; // the original AIG manager - int nPref; // the number of timeframes in the prefix - int nFrames; // the number of timeframes - int nWordsFrame; // the number of words in each timeframe - 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 -}; - -static inline unsigned * Ssw_ObjSim( Ssw_Sml_t * p, int Id ) { return p->pData + p->nWordsTotal * Id; } -static inline unsigned Ssw_ObjRandomSim() { return Aig_ManRandom(0); } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes hash value of the node using its simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Ssw_SmlObjHashWord( Ssw_Sml_t * p, Aig_Obj_t * pObj ) -{ - static int s_SPrimes[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->nWordsTotal <= 128 ); - uHash = 0; - pSims = Ssw_ObjSim(p, pObj->Id); - for ( i = p->nWordsPref; i < p->nWordsTotal; i++ ) - uHash ^= pSims[i] * s_SPrimes[i & 0x7F]; - return uHash; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if simulation info is composed of all zeros.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_SmlObjIsConstWord( Ssw_Sml_t * p, Aig_Obj_t * pObj ) -{ - unsigned * pSims; - int i; - pSims = Ssw_ObjSim(p, pObj->Id); - for ( i = p->nWordsPref; i < p->nWordsTotal; i++ ) - if ( pSims[i] ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if simulation infos are equal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_SmlObjsAreEqualWord( Ssw_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) -{ - unsigned * pSims0, * pSims1; - int i; - pSims0 = Ssw_ObjSim(p, pObj0->Id); - pSims1 = Ssw_ObjSim(p, pObj1->Id); - for ( i = p->nWordsPref; i < p->nWordsTotal; i++ ) - if ( pSims0[i] != pSims1[i] ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the node appears to be constant 1 candidate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_SmlObjIsConstBit( void * p, Aig_Obj_t * pObj ) -{ - return pObj->fPhase == pObj->fMarkB; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the nodes appear equal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_SmlObjsAreEqualBit( void * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) -{ - return (pObj0->fPhase == pObj1->fPhase) == (pObj0->fMarkB == pObj1->fMarkB); -} - - -/**Function************************************************************* - - Synopsis [Counts the number of 1s in the XOR of simulation data.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_SmlNodeNotEquWeight( Ssw_Sml_t * p, int Left, int Right ) -{ - unsigned * pSimL, * pSimR; - int k, Counter = 0; - pSimL = Ssw_ObjSim( p, Left ); - pSimR = Ssw_ObjSim( p, Right ); - for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) - Counter += Aig_WordCountOnes( pSimL[k] ^ pSimR[k] ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Checks implication.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_SmlCheckXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo, Aig_Obj_t * pCand ) -{ - unsigned * pSimLi, * pSimLo, * pSimCand; - int k; - assert( pObjLo->fPhase == 0 ); - // pObjLi->fPhase may be 1, but the LI simulation data is not complemented! - pSimCand = Ssw_ObjSim( p, Aig_Regular(pCand)->Id ); - pSimLi = Ssw_ObjSim( p, pObjLi->Id ); - pSimLo = Ssw_ObjSim( p, pObjLo->Id ); - if ( Aig_Regular(pCand)->fPhase ^ Aig_IsComplement(pCand) ) - { - for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) - if ( ~pSimCand[k] & (pSimLi[k] ^ pSimLo[k]) ) - return 0; - } - else - { - for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) - if ( pSimCand[k] & (pSimLi[k] ^ pSimLo[k]) ) - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Counts the number of 1s in the implication.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_SmlCountXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo, Aig_Obj_t * pCand ) -{ - unsigned * pSimLi, * pSimLo, * pSimCand; - int k, Counter = 0; - assert( pObjLo->fPhase == 0 ); - // pObjLi->fPhase may be 1, but the LI simulation data is not complemented! - pSimCand = Ssw_ObjSim( p, Aig_Regular(pCand)->Id ); - pSimLi = Ssw_ObjSim( p, pObjLi->Id ); - pSimLo = Ssw_ObjSim( p, pObjLo->Id ); - if ( Aig_Regular(pCand)->fPhase ^ Aig_IsComplement(pCand) ) - { - for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) - Counter += Aig_WordCountOnes(~pSimCand[k] & ~(pSimLi[k] ^ pSimLo[k])); - } - else - { - for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) - Counter += Aig_WordCountOnes(pSimCand[k] & ~(pSimLi[k] ^ pSimLo[k])); - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts the number of 1s in the implication.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_SmlCountEqual( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo ) -{ - unsigned * pSimLi, * pSimLo; - int k, Counter = 0; - assert( pObjLo->fPhase == 0 ); - // pObjLi->fPhase may be 1, but the LI simulation data is not complemented! - pSimLi = Ssw_ObjSim( p, pObjLi->Id ); - pSimLo = Ssw_ObjSim( p, pObjLo->Id ); - for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) - Counter += Aig_WordCountOnes( ~(pSimLi[k] ^ pSimLo[k]) ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if simulation info is composed of all zeros.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_SmlNodeIsZero( Ssw_Sml_t * p, Aig_Obj_t * pObj ) -{ - unsigned * pSims; - int i; - pSims = Ssw_ObjSim(p, pObj->Id); - for ( i = p->nWordsPref; i < p->nWordsTotal; i++ ) - if ( pSims[i] ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if simulation info is composed of all zeros.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_SmlNodeIsZeroFrame( Ssw_Sml_t * p, Aig_Obj_t * pObj, int f ) -{ - unsigned * pSims = Ssw_ObjSim(p, pObj->Id); - return pSims[f] == 0; -} - -/**Function************************************************************* - - Synopsis [Counts the number of one's in the patten the object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_SmlNodeCountOnesReal( Ssw_Sml_t * p, Aig_Obj_t * pObj ) -{ - unsigned * pSims; - int i, Counter = 0; - pSims = Ssw_ObjSim(p, Aig_Regular(pObj)->Id); - if ( Aig_Regular(pObj)->fPhase ^ Aig_IsComplement(pObj) ) - { - for ( i = 0; i < p->nWordsTotal; i++ ) - Counter += Aig_WordCountOnes( ~pSims[i] ); - } - else - { - for ( i = 0; i < p->nWordsTotal; i++ ) - Counter += Aig_WordCountOnes( pSims[i] ); - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts the number of one's in the patten the object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_SmlNodeCountOnesRealVec( Ssw_Sml_t * p, Vec_Ptr_t * vObjs ) -{ - Aig_Obj_t * pObj; - unsigned * pSims, uWord; - int i, k, Counter = 0; - if ( Vec_PtrSize(vObjs) == 0 ) - return 0; - for ( i = 0; i < p->nWordsTotal; i++ ) - { - uWord = 0; - Vec_PtrForEachEntry( Aig_Obj_t *, vObjs, pObj, k ) - { - pSims = Ssw_ObjSim(p, Aig_Regular(pObj)->Id); - if ( Aig_Regular(pObj)->fPhase ^ Aig_IsComplement(pObj) ) - uWord |= ~pSims[i]; - else - uWord |= pSims[i]; - } - Counter += Aig_WordCountOnes( uWord ); - } - return Counter; -} - - - -/**Function************************************************************* - - Synopsis [Generated const 0 pattern.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SmlSavePattern0( Ssw_Man_t * p, int fInit ) -{ - memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); -} - -/**Function************************************************************* - - Synopsis [[Generated const 1 pattern.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SmlSavePattern1( Ssw_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 = Saig_ManPiNum(p->pAig); - k = 0; - Saig_ManForEachLo( p->pAig, pObj, i ) - Aig_InfoXorBit( p->pPatWords, nTruePis * p->nFrames + k++ ); -} - - -/**Function************************************************************* - - Synopsis [Creates the counter-example from the successful pattern.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int * Ssw_SmlCheckOutputSavePattern( Ssw_Sml_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 = Ssw_ObjSim(p, pFanin->Id); - for ( i = 0; i < p->nWordsTotal; i++ ) - if ( pSims[i] ) - break; - assert( i < p->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 = ABC_ALLOC( int, Aig_ManPiNum(p->pAig)+1 ); - Aig_ManForEachPi( p->pAig, pObjPi, i ) - { - pModel[i] = Aig_InfoHasBit(Ssw_ObjSim(p, pObjPi->Id), BestPat); -// printf( "%d", pModel[i] ); - } - pModel[Aig_ManPiNum(p->pAig)] = pObjPo->Id; -// printf( "\n" ); - return pModel; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the one of the output is already non-constant 0.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int * Ssw_SmlCheckOutput( Ssw_Sml_t * p ) -{ - Aig_Obj_t * pObj; - int i; - // make sure the reference simulation pattern does not detect the bug - pObj = Aig_ManPo( p->pAig, 0 ); - assert( Aig_ObjFanin0(pObj)->fPhase == (unsigned)Aig_ObjFaninC0(pObj) ); - Aig_ManForEachPo( p->pAig, pObj, i ) - { - if ( !Ssw_SmlObjIsConstWord( p, Aig_ObjFanin0(pObj) ) ) - { - // create the counter-example from this pattern - return Ssw_SmlCheckOutputSavePattern( p, pObj ); - } - } - return NULL; -} - - - -/**Function************************************************************* - - Synopsis [Assigns random patterns to the PI node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SmlAssignRandom( Ssw_Sml_t * p, Aig_Obj_t * pObj ) -{ - unsigned * pSims; - int i, f; - assert( Aig_ObjIsPi(pObj) ); - pSims = Ssw_ObjSim( p, pObj->Id ); - for ( i = 0; i < p->nWordsTotal; i++ ) - pSims[i] = Ssw_ObjRandomSim(); - // set the first bit 0 in each frame - assert( p->nWordsFrame * p->nFrames == p->nWordsTotal ); - for ( f = 0; f < p->nFrames; f++ ) - pSims[p->nWordsFrame*f] <<= 1; -} - -/**Function************************************************************* - - Synopsis [Assigns random patterns to the PI node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SmlAssignRandomFrame( Ssw_Sml_t * p, Aig_Obj_t * pObj, int iFrame ) -{ - unsigned * pSims; - int i; - assert( iFrame < p->nFrames ); - assert( Aig_ObjIsPi(pObj) ); - pSims = Ssw_ObjSim( p, pObj->Id ) + p->nWordsFrame * iFrame; - for ( i = 0; i < p->nWordsFrame; i++ ) - pSims[i] = Ssw_ObjRandomSim(); -} - -/**Function************************************************************* - - Synopsis [Assigns constant patterns to the PI node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SmlObjAssignConst( Ssw_Sml_t * p, Aig_Obj_t * pObj, int fConst1, int iFrame ) -{ - unsigned * pSims; - int i; - assert( iFrame < p->nFrames ); - assert( Aig_ObjIsPi(pObj) ); - pSims = Ssw_ObjSim( p, pObj->Id ) + p->nWordsFrame * iFrame; - for ( i = 0; i < p->nWordsFrame; i++ ) - pSims[i] = fConst1? ~(unsigned)0 : 0; -} - -/**Function************************************************************* - - Synopsis [Assigns constant patterns to the PI node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SmlObjAssignConstWord( Ssw_Sml_t * p, Aig_Obj_t * pObj, int fConst1, int iFrame, int iWord ) -{ - unsigned * pSims; - assert( iFrame < p->nFrames ); - assert( iWord < p->nWordsFrame ); - assert( Aig_ObjIsPi(pObj) ); - pSims = Ssw_ObjSim( p, pObj->Id ) + p->nWordsFrame * iFrame; - pSims[iWord] = fConst1? ~(unsigned)0 : 0; -} - -/**Function************************************************************* - - Synopsis [Assigns constant patterns to the PI node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SmlObjSetWord( Ssw_Sml_t * p, Aig_Obj_t * pObj, unsigned Word, int iWord, int iFrame ) -{ - unsigned * pSims; - assert( iFrame < p->nFrames ); - assert( Aig_ObjIsPi(pObj) ); - pSims = Ssw_ObjSim( p, pObj->Id ) + p->nWordsFrame * iFrame; - pSims[iWord] = Word; -} - -/**Function************************************************************* - - Synopsis [Assings distance-1 simulation info for the PIs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SmlAssignDist1( Ssw_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 ) - Ssw_SmlObjAssignConst( p, pObj, Aig_InfoHasBit(pPat, i), 0 ); - // flip one bit - Limit = ABC_MIN( Aig_ManPiNum(p->pAig), p->nWordsTotal * 32 - 1 ); - for ( i = 0; i < Limit; i++ ) - Aig_InfoXorBit( Ssw_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++ ) - Saig_ManForEachPi( p->pAig, pObj, i ) - Ssw_SmlObjAssignConst( p, pObj, Aig_InfoHasBit(pPat, nTruePis * f + i), f ); - // copy the latch info - k = 0; - Saig_ManForEachLo( p->pAig, pObj, i ) - Ssw_SmlObjAssignConst( p, pObj, Aig_InfoHasBit(pPat, nTruePis * p->nFrames + k++), 0 ); -// assert( p->pFrames == NULL || nTruePis * p->nFrames + k == Aig_ManPiNum(p->pFrames) ); - - // flip one bit of the last frame - if ( fUseDist1 ) //&& p->nFrames == 2 ) - { - Limit = ABC_MIN( nTruePis, p->nWordsFrame * 32 - 1 ); - for ( i = 0; i < Limit; i++ ) - Aig_InfoXorBit( Ssw_ObjSim( p, Aig_ManPi(p->pAig, i)->Id ) + p->nWordsFrame*(p->nFrames-1), i+1 ); - } - } -} - -/**Function************************************************************* - - Synopsis [Assings distance-1 simulation info for the PIs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SmlAssignDist1Plus( Ssw_Sml_t * p, unsigned * pPat ) -{ - Aig_Obj_t * pObj; - int f, i, Limit; - assert( p->nFrames > 0 ); - - // copy the pattern into the primary inputs - Aig_ManForEachPi( p->pAig, pObj, i ) - Ssw_SmlObjAssignConst( p, pObj, Aig_InfoHasBit(pPat, i), 0 ); - - // set distance one PIs for the first frame - Limit = ABC_MIN( Saig_ManPiNum(p->pAig), p->nWordsFrame * 32 - 1 ); - for ( i = 0; i < Limit; i++ ) - Aig_InfoXorBit( Ssw_ObjSim( p, Aig_ManPi(p->pAig, i)->Id ), i+1 ); - - // create random info for the remaining timeframes - for ( f = 1; f < p->nFrames; f++ ) - Saig_ManForEachPi( p->pAig, pObj, i ) - Ssw_SmlAssignRandomFrame( p, pObj, f ); -} - -/**Function************************************************************* - - Synopsis [Simulates one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SmlNodeSimulate( Ssw_Sml_t * p, Aig_Obj_t * pObj, int iFrame ) -{ - unsigned * pSims, * pSims0, * pSims1; - int fCompl, fCompl0, fCompl1, i; - assert( iFrame < p->nFrames ); - assert( !Aig_IsComplement(pObj) ); - assert( Aig_ObjIsNode(pObj) ); - assert( iFrame == 0 || p->nWordsFrame < p->nWordsTotal ); - // get hold of the simulation information - pSims = Ssw_ObjSim(p, pObj->Id) + p->nWordsFrame * iFrame; - pSims0 = Ssw_ObjSim(p, Aig_ObjFanin0(pObj)->Id) + p->nWordsFrame * iFrame; - pSims1 = Ssw_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 [] - -***********************************************************************/ -int Ssw_SmlNodesCompareInFrame( Ssw_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1, int iFrame0, int iFrame1 ) -{ - unsigned * pSims0, * pSims1; - int i; - assert( iFrame0 < p->nFrames ); - assert( iFrame1 < p->nFrames ); - assert( !Aig_IsComplement(pObj0) ); - assert( !Aig_IsComplement(pObj1) ); - assert( iFrame0 == 0 || p->nWordsFrame < p->nWordsTotal ); - assert( iFrame1 == 0 || p->nWordsFrame < p->nWordsTotal ); - // get hold of the simulation information - pSims0 = Ssw_ObjSim(p, pObj0->Id) + p->nWordsFrame * iFrame0; - pSims1 = Ssw_ObjSim(p, pObj1->Id) + p->nWordsFrame * iFrame1; - // compare - for ( i = 0; i < p->nWordsFrame; i++ ) - if ( pSims0[i] != pSims1[i] ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Simulates one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SmlNodeCopyFanin( Ssw_Sml_t * p, Aig_Obj_t * pObj, int iFrame ) -{ - unsigned * pSims, * pSims0; - int fCompl, fCompl0, i; - assert( iFrame < p->nFrames ); - assert( !Aig_IsComplement(pObj) ); - assert( Aig_ObjIsPo(pObj) ); - assert( iFrame == 0 || p->nWordsFrame < p->nWordsTotal ); - // get hold of the simulation information - pSims = Ssw_ObjSim(p, pObj->Id) + p->nWordsFrame * iFrame; - pSims0 = Ssw_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 Ssw_SmlNodeTransferNext( Ssw_Sml_t * p, Aig_Obj_t * pOut, Aig_Obj_t * pIn, int iFrame ) -{ - unsigned * pSims0, * pSims1; - int i; - assert( iFrame < p->nFrames ); - 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 = Ssw_ObjSim(p, pOut->Id) + p->nWordsFrame * iFrame; - pSims1 = Ssw_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 [Simulates one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SmlNodeTransferFirst( Ssw_Sml_t * p, Aig_Obj_t * pOut, Aig_Obj_t * pIn ) -{ - unsigned * pSims0, * pSims1; - int i; - assert( !Aig_IsComplement(pOut) ); - assert( !Aig_IsComplement(pIn) ); - assert( Aig_ObjIsPo(pOut) ); - assert( Aig_ObjIsPi(pIn) ); - assert( p->nWordsFrame < p->nWordsTotal ); - // get hold of the simulation information - pSims0 = Ssw_ObjSim(p, pOut->Id) + p->nWordsFrame * (p->nFrames-1); - pSims1 = Ssw_ObjSim(p, pIn->Id); - // copy information as it is - for ( i = 0; i < p->nWordsFrame; i++ ) - pSims1[i] = pSims0[i]; -} - - -/**Function************************************************************* - - Synopsis [Assings random simulation info for the PIs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SmlInitialize( Ssw_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 - Saig_ManForEachPi( p->pAig, pObj, i ) - Ssw_SmlAssignRandom( p, pObj ); - // assign the initial state for the latches - Saig_ManForEachLo( p->pAig, pObj, i ) - Ssw_SmlObjAssignConst( p, pObj, 0, 0 ); - } - else - { - Aig_ManForEachPi( p->pAig, pObj, i ) - Ssw_SmlAssignRandom( p, pObj ); - } -} - -/**Function************************************************************* - - Synopsis [Assings random simulation info for the PIs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SmlInitializeSpecial( Ssw_Sml_t * p, Vec_Int_t * vInit ) -{ - Aig_Obj_t * pObj; - int Entry, i, nRegs; - nRegs = Aig_ManRegNum(p->pAig); - assert( nRegs > 0 ); - assert( nRegs <= Aig_ManPiNum(p->pAig) ); - assert( Vec_IntSize(vInit) == nRegs * p->nWordsFrame ); - // assign random info for primary inputs - Saig_ManForEachPi( p->pAig, pObj, i ) - Ssw_SmlAssignRandom( p, pObj ); - // assign the initial state for the latches - Vec_IntForEachEntry( vInit, Entry, i ) - Ssw_SmlObjAssignConstWord( p, Saig_ManLo(p->pAig, i % nRegs), Entry, 0, i / nRegs ); -} - -/**Function************************************************************* - - Synopsis [Assings random simulation info for the PIs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SmlReinitialize( Ssw_Sml_t * p ) -{ - Aig_Obj_t * pObj, * pObjLi, * pObjLo; - int i; - assert( Aig_ManRegNum(p->pAig) > 0 ); - assert( Aig_ManRegNum(p->pAig) < Aig_ManPiNum(p->pAig) ); - // assign random info for primary inputs - Saig_ManForEachPi( p->pAig, pObj, i ) - Ssw_SmlAssignRandom( p, pObj ); - // copy simulation info into the inputs - Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) - Ssw_SmlNodeTransferFirst( p, pObjLi, pObjLo ); -} - -/**Function************************************************************* - - Synopsis [Check if any of the POs becomes non-constant.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_SmlCheckNonConstOutputs( Ssw_Sml_t * p ) -{ - Aig_Obj_t * pObj; - int i; - Saig_ManForEachPo( p->pAig, pObj, i ) - { - if ( p->pAig->nConstrs && i >= Saig_ManPoNum(p->pAig) - p->pAig->nConstrs ) - return 0; - if ( !Ssw_SmlNodeIsZero(p, pObj) ) - return 1; - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Simulates AIG manager.] - - Description [Assumes that the PI simulation info is attached.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SmlSimulateOne( Ssw_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 ) - Ssw_SmlNodeSimulate( p, pObj, f ); - // copy simulation info into outputs - Saig_ManForEachPo( p->pAig, pObj, i ) - Ssw_SmlNodeCopyFanin( p, pObj, f ); - // copy simulation info into outputs - Saig_ManForEachLi( p->pAig, pObj, i ) - Ssw_SmlNodeCopyFanin( p, pObj, f ); - // quit if this is the last timeframe - if ( f == p->nFrames - 1 ) - break; - // copy simulation info into the inputs - Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) - Ssw_SmlNodeTransferNext( p, pObjLi, pObjLo, f ); - } -p->timeSim += clock() - clk; -p->nSimRounds++; -} - -/**Function************************************************************* - - Synopsis [Converts simulation information to be not normallized.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SmlUnnormalize( Ssw_Sml_t * p ) -{ - Aig_Obj_t * pObj; - unsigned * pSims; - int i, k; - // convert constant 1 - pSims = Ssw_ObjSim( p, 0 ); - for ( i = 0; i < p->nWordsFrame; i++ ) - pSims[i] = ~pSims[i]; - // convert internal nodes - Aig_ManForEachNode( p->pAig, pObj, k ) - { - if ( pObj->fPhase == 0 ) - continue; - pSims = Ssw_ObjSim( p, pObj->Id ); - for ( i = 0; i < p->nWordsFrame; i++ ) - pSims[i] = ~pSims[i]; - } - // PIs/POs are always stored in their natural state -} - -/**Function************************************************************* - - Synopsis [Simulates AIG manager.] - - Description [Assumes that the PI simulation info is attached.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SmlSimulateOneDyn_rec( Ssw_Sml_t * p, Aig_Obj_t * pObj, int f, int * pVisited, int nVisCounter ) -{ -// if ( Aig_ObjIsTravIdCurrent(p->pAig, pObj) ) -// return; -// Aig_ObjSetTravIdCurrent(p->pAig, pObj); - if ( pVisited[p->nFrames*pObj->Id+f] == nVisCounter ) - return; - pVisited[p->nFrames*pObj->Id+f] = nVisCounter; - if ( Saig_ObjIsPi( p->pAig, pObj ) || Aig_ObjIsConst1(pObj) ) - return; - if ( Saig_ObjIsLo( p->pAig, pObj ) ) - { - if ( f == 0 ) - return; - Ssw_SmlSimulateOneDyn_rec( p, Saig_ObjLoToLi(p->pAig, pObj), f-1, pVisited, nVisCounter ); - Ssw_SmlNodeTransferNext( p, Saig_ObjLoToLi(p->pAig, pObj), pObj, f-1 ); - return; - } - if ( Saig_ObjIsLi( p->pAig, pObj ) ) - { - Ssw_SmlSimulateOneDyn_rec( p, Aig_ObjFanin0(pObj), f, pVisited, nVisCounter ); - Ssw_SmlNodeCopyFanin( p, pObj, f ); - return; - } - assert( Aig_ObjIsNode(pObj) ); - Ssw_SmlSimulateOneDyn_rec( p, Aig_ObjFanin0(pObj), f, pVisited, nVisCounter ); - Ssw_SmlSimulateOneDyn_rec( p, Aig_ObjFanin1(pObj), f, pVisited, nVisCounter ); - Ssw_SmlNodeSimulate( p, pObj, f ); -} - -/**Function************************************************************* - - Synopsis [Simulates AIG manager.] - - Description [Assumes that the PI simulation info is attached.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SmlSimulateOneFrame( Ssw_Sml_t * p ) -{ - Aig_Obj_t * pObj, * pObjLi, * pObjLo; - int i, clk; -clk = clock(); - // simulate the nodes - Aig_ManForEachNode( p->pAig, pObj, i ) - Ssw_SmlNodeSimulate( p, pObj, 0 ); - // copy simulation info into outputs - Saig_ManForEachLi( p->pAig, pObj, i ) - Ssw_SmlNodeCopyFanin( p, pObj, 0 ); - // copy simulation info into the inputs - Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) - Ssw_SmlNodeTransferNext( p, pObjLi, pObjLo, 0 ); -p->timeSim += clock() - clk; -p->nSimRounds++; -} - - -/**Function************************************************************* - - Synopsis [Allocates simulation manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ssw_Sml_t * Ssw_SmlStart( Aig_Man_t * pAig, int nPref, int nFrames, int nWordsFrame ) -{ - Ssw_Sml_t * p; - p = (Ssw_Sml_t *)ABC_ALLOC( char, sizeof(Ssw_Sml_t) + sizeof(unsigned) * Aig_ManObjNumMax(pAig) * (nPref + nFrames) * nWordsFrame ); - memset( p, 0, sizeof(Ssw_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 [Allocates simulation manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SmlClean( Ssw_Sml_t * p ) -{ - memset( p->pData, 0, sizeof(unsigned) * Aig_ManObjNumMax(p->pAig) * p->nWordsTotal ); -} - -/**Function************************************************************* - - Synopsis [Get simulation data.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Ssw_SmlSimDataPointers( Ssw_Sml_t * p ) -{ - Vec_Ptr_t * vSimInfo; - Aig_Obj_t * pObj; - int i; - vSimInfo = Vec_PtrStart( Aig_ManObjNumMax(p->pAig) ); - Aig_ManForEachObj( p->pAig, pObj, i ) - Vec_PtrWriteEntry( vSimInfo, i, Ssw_ObjSim(p, i) ); - return vSimInfo; -} - -/**Function************************************************************* - - Synopsis [Deallocates simulation manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SmlStop( Ssw_Sml_t * p ) -{ - ABC_FREE( p ); -} - - -/**Function************************************************************* - - Synopsis [Performs simulation of the uninitialized circuit.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ssw_Sml_t * Ssw_SmlSimulateComb( Aig_Man_t * pAig, int nWords ) -{ - Ssw_Sml_t * p; - p = Ssw_SmlStart( pAig, 0, 1, nWords ); - Ssw_SmlInitialize( p, 0 ); - Ssw_SmlSimulateOne( p ); - return p; -} - -/**Function************************************************************* - - Synopsis [Performs simulation of the initialized circuit.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ssw_Sml_t * Ssw_SmlSimulateSeq( Aig_Man_t * pAig, int nPref, int nFrames, int nWords ) -{ - Ssw_Sml_t * p; - p = Ssw_SmlStart( pAig, nPref, nFrames, nWords ); - Ssw_SmlInitialize( p, 1 ); - Ssw_SmlSimulateOne( p ); - p->fNonConstOut = Ssw_SmlCheckNonConstOutputs( p ); - return p; -} - -/**Function************************************************************* - - Synopsis [Performs next round of sequential simulation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SmlResimulateSeq( Ssw_Sml_t * p ) -{ - Ssw_SmlReinitialize( p ); - Ssw_SmlSimulateOne( p ); - p->fNonConstOut = Ssw_SmlCheckNonConstOutputs( p ); -} - - -/**Function************************************************************* - - Synopsis [Returns the number of frames simulated in the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_SmlNumFrames( Ssw_Sml_t * p ) -{ - return p->nFrames; -} - -/**Function************************************************************* - - Synopsis [Returns the total number of simulation words.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_SmlNumWordsTotal( Ssw_Sml_t * p ) -{ - return p->nWordsTotal; -} - -/**Function************************************************************* - - Synopsis [Returns the pointer to the simulation info of the node.] - - Description [The simulation info is normalized unless procedure - Ssw_SmlUnnormalize() is called in advance.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Ssw_SmlSimInfo( Ssw_Sml_t * p, Aig_Obj_t * pObj ) -{ - assert( !Aig_IsComplement(pObj) ); - return Ssw_ObjSim( p, pObj->Id ); -} - -/**Function************************************************************* - - Synopsis [Creates sequential counter-example from the simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Cex_t * Ssw_SmlGetCounterExample( Ssw_Sml_t * p ) -{ - Abc_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; - Saig_ManForEachPo( p->pAig, pObj, iPo ) - { - if ( Ssw_SmlNodeIsZero(p, pObj) ) - continue; - pSims = Ssw_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 = Abc_CexAlloc( Aig_ManRegNum(p->pAig), Aig_ManPiNum(p->pAig) - Aig_ManRegNum(p->pAig), iFrame + 1 ); - pCex->iPo = iPo; - pCex->iFrame = iFrame; - - // copy the bit data - Saig_ManForEachLo( p->pAig, pObj, k ) - { - pSims = Ssw_ObjSim( p, pObj->Id ); - if ( Aig_InfoHasBit( pSims, iBit ) ) - Aig_InfoSetBit( pCex->pData, k ); - } - for ( i = 0; i <= iFrame; i++ ) - { - Saig_ManForEachPi( p->pAig, pObj, k ) - { - pSims = Ssw_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 ( !Saig_ManVerifyCex( p->pAig, pCex ) ) - { - printf( "Ssw_SmlGetCounterExample(): Counter-example is invalid.\n" ); - Abc_CexFree( pCex ); - pCex = NULL; - } - return pCex; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ssw/sswSimSat.c b/src/aig/ssw/sswSimSat.c deleted file mode 100644 index 6b18a3a6..00000000 --- a/src/aig/ssw/sswSimSat.c +++ /dev/null @@ -1,123 +0,0 @@ -/**CFile**************************************************************** - - FileName [sswSimSat.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Inductive prover with constraints.] - - Synopsis [Performs resimulation using counter-examples.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 1, 2008.] - - Revision [$Id: sswSimSat.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "sswInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Handle the counter-example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ManResimulateBit( Ssw_Man_t * p, Aig_Obj_t * pCand, Aig_Obj_t * pRepr ) -{ - Aig_Obj_t * pObj; - int i, RetValue1, RetValue2, clk = clock(); - // set the PI simulation information - Aig_ManConst1(p->pAig)->fMarkB = 1; - Aig_ManForEachPi( p->pAig, pObj, i ) - pObj->fMarkB = Aig_InfoHasBit( p->pPatWords, i ); - // simulate internal nodes - Aig_ManForEachNode( p->pAig, pObj, i ) - pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ) - & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) ); - // if repr is given, perform refinement - if ( pRepr ) - { - // check equivalence classes - RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 0 ); - RetValue2 = Ssw_ClassesRefine( p->ppClasses, 0 ); - // make sure refinement happened - if ( Aig_ObjIsConst1(pRepr) ) - { - assert( RetValue1 ); - if ( RetValue1 == 0 ) - printf( "\nSsw_ManResimulateBit() Error: RetValue1 does not hold.\n" ); - } - else - { - assert( RetValue2 ); - if ( RetValue2 == 0 ) - printf( "\nSsw_ManResimulateBit() Error: RetValue2 does not hold.\n" ); - } - } -p->timeSimSat += clock() - clk; -} - -/**Function************************************************************* - - Synopsis [Handle the counter-example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ManResimulateWord( Ssw_Man_t * p, Aig_Obj_t * pCand, Aig_Obj_t * pRepr, int f ) -{ - int RetValue1, RetValue2, clk = clock(); - // set the PI simulation information - Ssw_SmlAssignDist1Plus( p->pSml, p->pPatWords ); - // simulate internal nodes - Ssw_SmlSimulateOne( p->pSml ); - // check equivalence classes - RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 1 ); - RetValue2 = Ssw_ClassesRefine( p->ppClasses, 1 ); - // make sure refinement happened - if ( Aig_ObjIsConst1(pRepr) ) - { - assert( RetValue1 ); - if ( RetValue1 == 0 ) - printf( "\nSsw_ManResimulateWord() Error: RetValue1 does not hold.\n" ); - } - else - { - assert( RetValue2 ); - if ( RetValue2 == 0 ) - printf( "\nSsw_ManResimulateWord() Error: RetValue2 does not hold.\n" ); - } -p->timeSimSat += clock() - clk; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ssw/sswSweep.c b/src/aig/ssw/sswSweep.c deleted file mode 100644 index edae0846..00000000 --- a/src/aig/ssw/sswSweep.c +++ /dev/null @@ -1,435 +0,0 @@ -/**CFile**************************************************************** - - FileName [sswSweep.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Inductive prover with constraints.] - - Synopsis [One round of SAT sweeping.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 1, 2008.] - - Revision [$Id: sswSweep.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "sswInt.h" -#include "bar.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Retrives value of the PI in the original AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ManGetSatVarValue( Ssw_Man_t * p, Aig_Obj_t * pObj, int f ) -{ - int fUseNoBoundary = 0; - Aig_Obj_t * pObjFraig; - int Value; -// assert( Aig_ObjIsPi(pObj) ); - pObjFraig = Ssw_ObjFrame( p, pObj, f ); - if ( fUseNoBoundary ) - { - Value = Ssw_CnfGetNodeValue( p->pMSat, Aig_Regular(pObjFraig) ); - Value ^= Aig_IsComplement(pObjFraig); - } - else - { - int nVarNum = Ssw_ObjSatNum( p->pMSat, Aig_Regular(pObjFraig) ); - Value = (!nVarNum)? 0 : (Aig_IsComplement(pObjFraig) ^ sat_solver_var_value( p->pMSat->pSat, nVarNum )); - } - -// Value = (Aig_IsComplement(pObjFraig) ^ ((!nVarNum)? 0 : sat_solver_var_value( p->pSat, nVarNum ))); -// Value = (!nVarNum)? Aig_ManRandom(0) & 1 : (Aig_IsComplement(pObjFraig) ^ sat_solver_var_value( p->pSat, nVarNum )); - if ( p->pPars->fPolarFlip ) - { - if ( Aig_Regular(pObjFraig)->fPhase ) Value ^= 1; - } - return Value; -} - -/**Function************************************************************* - - Synopsis [Performs fraiging for the internal nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_CheckConstraints( Ssw_Man_t * p ) -{ - Aig_Obj_t * pObj, * pObj2; - int nConstrPairs, i; - int Counter = 0; - nConstrPairs = Aig_ManPoNum(p->pFrames)-Aig_ManRegNum(p->pAig); - assert( (nConstrPairs & 1) == 0 ); - for ( i = 0; i < nConstrPairs; i += 2 ) - { - pObj = Aig_ManPo( p->pFrames, i ); - pObj2 = Aig_ManPo( p->pFrames, i+1 ); - if ( Ssw_NodesAreEquiv( p, Aig_ObjFanin0(pObj), Aig_ObjFanin0(pObj2) ) != 1 ) - { - Ssw_NodesAreConstrained( p, Aig_ObjChild0(pObj), Aig_ObjChild0(pObj2) ); - Counter++; - } - } - printf( "Total constraints = %d. Added constraints = %d.\n", nConstrPairs/2, Counter ); -} - -/**Function************************************************************* - - Synopsis [Copy pattern from the solver into the internal storage.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SmlSavePatternAigPhase( Ssw_Man_t * p, int f ) -{ - Aig_Obj_t * pObj; - int i; - memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); - Aig_ManForEachPi( p->pAig, pObj, i ) - if ( Aig_ObjPhaseReal( Ssw_ObjFrame(p, pObj, f) ) ) - Aig_InfoSetBit( p->pPatWords, i ); -} - -/**Function************************************************************* - - Synopsis [Copy pattern from the solver into the internal storage.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SmlSavePatternAig( Ssw_Man_t * p, int f ) -{ - Aig_Obj_t * pObj; - int i; - memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); - Aig_ManForEachPi( p->pAig, pObj, i ) - if ( Ssw_ManGetSatVarValue( p, pObj, f ) ) - Aig_InfoSetBit( p->pPatWords, i ); -} - -/**Function************************************************************* - - Synopsis [Saves one counter-example into internal storage.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_SmlAddPatternDyn( Ssw_Man_t * p ) -{ - Aig_Obj_t * pObj; - unsigned * pInfo; - int i, nVarNum; - // iterate through the PIs of the frames - Vec_PtrForEachEntry( Aig_Obj_t *, p->pMSat->vUsedPis, pObj, i ) - { - assert( Aig_ObjIsPi(pObj) ); - nVarNum = Ssw_ObjSatNum( p->pMSat, pObj ); - assert( nVarNum > 0 ); - if ( sat_solver_var_value( p->pMSat->pSat, nVarNum ) ) - { - pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjPioNum(pObj) ); - Aig_InfoSetBit( pInfo, p->nPatterns ); - } - } -} - -/**Function************************************************************* - - Synopsis [Performs fraiging for one node.] - - Description [Returns the fraiged node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ManSweepNode( Ssw_Man_t * p, Aig_Obj_t * pObj, int f, int fBmc, Vec_Int_t * vPairs ) -{ - Aig_Obj_t * pObjRepr, * pObjFraig, * pObjFraig2, * pObjReprFraig; - int RetValue, clk; - // get representative of this class - pObjRepr = Aig_ObjRepr( p->pAig, pObj ); - if ( pObjRepr == NULL ) - return 0; - // get the fraiged node - pObjFraig = Ssw_ObjFrame( p, pObj, f ); - // get the fraiged representative - pObjReprFraig = Ssw_ObjFrame( p, pObjRepr, f ); - // check if constant 0 pattern distinquishes these nodes - assert( pObjFraig != NULL && pObjReprFraig != NULL ); - assert( (pObj->fPhase == pObjRepr->fPhase) == (Aig_ObjPhaseReal(pObjFraig) == Aig_ObjPhaseReal(pObjReprFraig)) ); - // if the fraiged nodes are the same, return - if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) ) - return 0; - // add constraints on demand - if ( !fBmc && p->pPars->fDynamic ) - { -clk = clock(); - Ssw_ManLoadSolver( p, pObjRepr, pObj ); - p->nRecycleCalls++; -p->timeMarkCones += clock() - clk; - } - // call equivalence checking - if ( Aig_Regular(pObjFraig) != Aig_ManConst1(p->pFrames) ) - RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) ); - else - RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjFraig), Aig_Regular(pObjReprFraig) ); - if ( RetValue == 1 ) // proved equivalent - { - pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase ); - Ssw_ObjSetFrame( p, pObj, f, pObjFraig2 ); - return 0; - } - if ( vPairs ) - { - Vec_IntPush( vPairs, pObjRepr->Id ); - Vec_IntPush( vPairs, pObj->Id ); - } - if ( RetValue == -1 ) // timed out - { - Ssw_ClassesRemoveNode( p->ppClasses, pObj ); - return 1; - } - // disproved the equivalence - if ( !fBmc && p->pPars->fDynamic ) - { - Ssw_SmlAddPatternDyn( p ); - p->nPatterns++; - return 1; - } - else - Ssw_SmlSavePatternAig( p, f ); - if ( !p->pPars->fConstrs ) - Ssw_ManResimulateWord( p, pObj, pObjRepr, f ); - else - Ssw_ManResimulateBit( p, pObj, pObjRepr ); - assert( Aig_ObjRepr( p->pAig, pObj ) != pObjRepr ); - if ( Aig_ObjRepr( p->pAig, pObj ) == pObjRepr ) - { - printf( "Ssw_ManSweepNode(): Failed to refine representative.\n" ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Performs fraiging for the internal nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ManSweepBmc( Ssw_Man_t * p ) -{ - Bar_Progress_t * pProgress = NULL; - Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo; - int i, f, clk; -clk = clock(); - - // start initialized timeframes - p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK ); - Saig_ManForEachLo( p->pAig, pObj, i ) - Ssw_ObjSetFrame( p, pObj, 0, Aig_ManConst0(p->pFrames) ); - - // sweep internal nodes - p->fRefined = 0; - if ( p->pPars->fVerbose ) - pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK ); - for ( f = 0; f < p->pPars->nFramesK; f++ ) - { - // map constants and PIs - Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) ); - Saig_ManForEachPi( p->pAig, pObj, i ) - Ssw_ObjSetFrame( p, pObj, f, Aig_ObjCreatePi(p->pFrames) ); - // sweep internal nodes - Aig_ManForEachNode( p->pAig, pObj, i ) - { - if ( p->pPars->fVerbose ) - Bar_ProgressUpdate( pProgress, Aig_ManObjNumMax(p->pAig) * f + i, NULL ); - pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); - Ssw_ObjSetFrame( p, pObj, f, pObjNew ); - p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 1, NULL ); - } - // quit if this is the last timeframe - if ( f == p->pPars->nFramesK - 1 ) - break; - // transfer latch input to the latch outputs - Aig_ManForEachPo( p->pAig, pObj, i ) - Ssw_ObjSetFrame( p, pObj, f, Ssw_ObjChild0Fra(p, pObj, f) ); - // build logic cones for register outputs - Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) - { - pObjNew = Ssw_ObjFrame( p, pObjLi, f ); - Ssw_ObjSetFrame( p, pObjLo, f+1, pObjNew ); - Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pObjNew) );// - } - } - if ( p->pPars->fVerbose ) - Bar_ProgressStop( pProgress ); - - // cleanup -// Ssw_ClassesCheck( p->ppClasses ); -p->timeBmc += clock() - clk; - return p->fRefined; -} - - -/**Function************************************************************* - - Synopsis [Generates AIG with the following nodes put into seq miters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_ManDumpEquivMiter( Aig_Man_t * p, Vec_Int_t * vPairs, int Num ) -{ - FILE * pFile; - char pBuffer[16]; - Aig_Man_t * pNew; - sprintf( pBuffer, "equiv%03d.aig", Num ); - pFile = fopen( pBuffer, "w" ); - if ( pFile == NULL ) - { - printf( "Cannot open file %s for writing.\n", pBuffer ); - return; - } - fclose( pFile ); - pNew = Saig_ManCreateEquivMiter( p, vPairs ); - Ioa_WriteAiger( pNew, pBuffer, 0, 0 ); - Aig_ManStop( pNew ); - printf( "AIG with %4d disproved equivs is dumped into file \"%s\".\n", Vec_IntSize(vPairs)/2, pBuffer ); -} - - -/**Function************************************************************* - - Synopsis [Performs fraiging for the internal nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ManSweep( Ssw_Man_t * p ) -{ - static int Counter; - Bar_Progress_t * pProgress = NULL; - Aig_Obj_t * pObj, * pObj2, * pObjNew; - int nConstrPairs, clk, i, f; - Vec_Int_t * vDisproved; - - // perform speculative reduction -clk = clock(); - // create timeframes - p->pFrames = Ssw_FramesWithClasses( p ); - // add constants - nConstrPairs = Aig_ManPoNum(p->pFrames)-Aig_ManRegNum(p->pAig); - assert( (nConstrPairs & 1) == 0 ); - for ( i = 0; i < nConstrPairs; i += 2 ) - { - pObj = Aig_ManPo( p->pFrames, i ); - pObj2 = Aig_ManPo( p->pFrames, i+1 ); - Ssw_NodesAreConstrained( p, Aig_ObjChild0(pObj), Aig_ObjChild0(pObj2) ); - } - // build logic cones for register inputs - for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ ) - { - pObj = Aig_ManPo( p->pFrames, nConstrPairs + i ); - Ssw_CnfNodeAddToSolver( p->pMSat, Aig_ObjFanin0(pObj) );// - } - sat_solver_simplify( p->pMSat->pSat ); - - // map constants and PIs of the last frame - f = p->pPars->nFramesK; - Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) ); - Saig_ManForEachPi( p->pAig, pObj, i ) - Ssw_ObjSetFrame( p, pObj, f, Aig_ObjCreatePi(p->pFrames) ); -p->timeReduce += clock() - clk; - - // sweep internal nodes - p->fRefined = 0; - Ssw_ClassesClearRefined( p->ppClasses ); - if ( p->pPars->fVerbose ) - pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) ); - vDisproved = p->pPars->fEquivDump? Vec_IntAlloc(1000) : NULL; - Aig_ManForEachObj( p->pAig, pObj, i ) - { - if ( p->pPars->fVerbose ) - Bar_ProgressUpdate( pProgress, i, NULL ); - if ( Saig_ObjIsLo(p->pAig, pObj) ) - p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 0, vDisproved ); - else if ( Aig_ObjIsNode(pObj) ) - { - pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); - Ssw_ObjSetFrame( p, pObj, f, pObjNew ); - p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 0, vDisproved ); - } - } - if ( p->pPars->fVerbose ) - Bar_ProgressStop( pProgress ); - - // cleanup -// Ssw_ClassesCheck( p->ppClasses ); - if ( p->pPars->fEquivDump ) - Ssw_ManDumpEquivMiter( p->pAig, vDisproved, Counter++ ); - Vec_IntFreeP( &vDisproved ); - return p->fRefined; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/ssw/sswUnique.c b/src/aig/ssw/sswUnique.c deleted file mode 100644 index b5f6a853..00000000 --- a/src/aig/ssw/sswUnique.c +++ /dev/null @@ -1,197 +0,0 @@ -/**CFile**************************************************************** - - FileName [sswSat.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Inductive prover with constraints.] - - Synopsis [On-demand uniqueness constraints.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 1, 2008.] - - Revision [$Id: sswSat.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "sswInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs computation of signal correspondence with constraints.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ssw_UniqueRegisterPairInfo( Ssw_Man_t * p ) -{ - Aig_Obj_t * pObjLo, * pObj0, * pObj1; - int i, RetValue, Counter; - if ( p->vDiffPairs == NULL ) - p->vDiffPairs = Vec_IntAlloc( Saig_ManRegNum(p->pAig) ); - Vec_IntClear( p->vDiffPairs ); - Saig_ManForEachLo( p->pAig, pObjLo, i ) - { - pObj0 = Ssw_ObjFrame( p, pObjLo, 0 ); - pObj1 = Ssw_ObjFrame( p, pObjLo, 1 ); - if ( pObj0 == pObj1 ) - Vec_IntPush( p->vDiffPairs, 0 ); - else if ( pObj0 == Aig_Not(pObj1) ) - Vec_IntPush( p->vDiffPairs, 1 ); -// else -// Vec_IntPush( p->vDiffPairs, 1 ); - else if ( Aig_ObjPhaseReal(pObj0) != Aig_ObjPhaseReal(pObj1) ) - Vec_IntPush( p->vDiffPairs, 1 ); - else - { - RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObj0), Aig_Regular(pObj1) ); - Vec_IntPush( p->vDiffPairs, RetValue!=1 ); - } - } - assert( Vec_IntSize(p->vDiffPairs) == Saig_ManRegNum(p->pAig) ); - // count the number of ones - Counter = 0; - Vec_IntForEachEntry( p->vDiffPairs, RetValue, i ) - Counter += RetValue; -// printf( "The number of different register pairs = %d.\n", Counter ); -} - - -/**Function************************************************************* - - Synopsis [Returns 1 if uniqueness constraints can be added.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ManUniqueOne( Ssw_Man_t * p, Aig_Obj_t * pRepr, Aig_Obj_t * pObj, int fVerbose ) -{ - Aig_Obj_t * ppObjs[2], * pTemp; - int i, k, Value0, Value1, RetValue, fFeasible; - - assert( p->pPars->nFramesK > 1 ); - assert( p->vDiffPairs && Vec_IntSize(p->vDiffPairs) == Saig_ManRegNum(p->pAig) ); - - // compute the first support in terms of LOs - ppObjs[0] = pRepr; - ppObjs[1] = pObj; - Aig_SupportNodes( p->pAig, ppObjs, 2, p->vCommon ); - // keep only LOs - RetValue = Vec_PtrSize( p->vCommon ); - fFeasible = 0; - k = 0; - Vec_PtrForEachEntry( Aig_Obj_t *, p->vCommon, pTemp, i ) - { - assert( Aig_ObjIsPi(pTemp) ); - if ( !Saig_ObjIsLo(p->pAig, pTemp) ) - continue; - assert( Aig_ObjPioNum(pTemp) > 0 ); - Vec_PtrWriteEntry( p->vCommon, k++, pTemp ); - if ( Vec_IntEntry(p->vDiffPairs, Aig_ObjPioNum(pTemp) - Saig_ManPiNum(p->pAig)) ) - fFeasible = 1; - } - Vec_PtrShrink( p->vCommon, k ); - - if ( fVerbose ) - printf( "Node = %5d : Supp = %3d. Regs = %3d. Feasible = %s. ", - Aig_ObjId(pObj), RetValue, Vec_PtrSize(p->vCommon), - fFeasible? "yes": "no " ); - - // check the current values - RetValue = 1; - Vec_PtrForEachEntry( Aig_Obj_t *, p->vCommon, pTemp, i ) - { - Value0 = Ssw_ManGetSatVarValue( p, pTemp, 0 ); - Value1 = Ssw_ManGetSatVarValue( p, pTemp, 1 ); - if ( Value0 != Value1 ) - RetValue = 0; - if ( fVerbose ) - printf( "%d", Value0 ^ Value1 ); - } - if ( fVerbose ) - printf( "\n" ); - - return RetValue && fFeasible; -} - -/**Function************************************************************* - - Synopsis [Returns the output of the uniqueness constraint.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_ManUniqueAddConstraint( Ssw_Man_t * p, Vec_Ptr_t * vCommon, int f1, int f2 ) -{ - Aig_Obj_t * pObj, * pObj1New, * pObj2New, * pMiter, * pTotal; - int i, pLits[2]; -// int RetValue; - assert( Vec_PtrSize(vCommon) > 0 ); - // generate the constraint - pTotal = Aig_ManConst0(p->pFrames); - Vec_PtrForEachEntry( Aig_Obj_t *, vCommon, pObj, i ) - { - assert( Saig_ObjIsLo(p->pAig, pObj) ); - pObj1New = Ssw_ObjFrame( p, pObj, f1 ); - pObj2New = Ssw_ObjFrame( p, pObj, f2 ); - pMiter = Aig_Exor( p->pFrames, pObj1New, pObj2New ); - pTotal = Aig_Or( p->pFrames, pTotal, pMiter ); - } - if ( Aig_ObjIsConst1(Aig_Regular(pTotal)) ) - { -// printf( "Skipped\n" ); - return 0; - } - // create CNF - Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pTotal) ); - // add output constraint - pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,Aig_Regular(pTotal)), Aig_IsComplement(pTotal) ); -/* - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 1 ); - assert( RetValue ); - // simplify the solver - if ( p->pSat->qtail != p->pSat->qhead ) - { - RetValue = sat_solver_simplify(p->pSat); - assert( RetValue != 0 ); - } -*/ - assert( p->iOutputLit == -1 ); - p->iOutputLit = pLits[0]; - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - 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 6b7e310c..00000000 --- a/src/aig/tim/tim.c +++ /dev/null @@ -1,996 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 fUseTravId; // enables the use of traversal ID - int nCis; // the number of PIs - int nCos; // the number of POs - Tim_Obj_t * pCis; // timing info for the PIs - Tim_Obj_t * pCos; // 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_ManCi( Tim_Man_t * p, int i ) { assert( i < p->nCis ); return p->pCis + i; } -static inline Tim_Obj_t * Tim_ManCo( Tim_Man_t * p, int i ) { assert( i < p->nCos ); return p->pCos + i; } -static inline Tim_Box_t * Tim_ManBox( Tim_Man_t * p, int i ) { return (Tim_Box_t *)Vec_PtrEntry(p->vBoxes, i); } - -static inline Tim_Box_t * Tim_ManCiBox( Tim_Man_t * p, int i ) { return Tim_ManCi(p,i)->iObj2Box < 0 ? NULL : (Tim_Box_t *)Vec_PtrEntry( p->vBoxes, Tim_ManCi(p,i)->iObj2Box ); } -static inline Tim_Box_t * Tim_ManCoBox( Tim_Man_t * p, int i ) { return Tim_ManCo(p,i)->iObj2Box < 0 ? NULL : (Tim_Box_t *)Vec_PtrEntry( p->vBoxes, Tim_ManCo(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->pCos + 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->pCis + 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_ManForEachCi( p, pObj, i ) \ - for ( i = 0; (i < (p)->nCis) && ((pObj) = (p)->pCis + i); i++ ) \ - if ( pObj->iObj2Box >= 0 ) {} else -#define Tim_ManForEachCo( p, pObj, i ) \ - for ( i = 0; (i < (p)->nCos) && ((pObj) = (p)->pCos + i); i++ ) \ - if ( pObj->iObj2Box >= 0 ) {} else -#define Tim_ManForEachBox( p, pBox, i ) \ - Vec_PtrForEachEntry( Tim_Box_t *, p->vBoxes, pBox, i ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the timing manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Tim_Man_t * Tim_ManStart( int nCis, int nCos ) -{ - Tim_Man_t * p; - int i; - p = ABC_ALLOC( Tim_Man_t, 1 ); - memset( p, 0, sizeof(Tim_Man_t) ); - p->pMemObj = Mem_FlexStart(); - p->vBoxes = Vec_PtrAlloc( 100 ); - p->nCis = nCis; - p->nCos = nCos; - p->pCis = ABC_ALLOC( Tim_Obj_t, nCis ); - memset( p->pCis, 0, sizeof(Tim_Obj_t) * nCis ); - p->pCos = ABC_ALLOC( Tim_Obj_t, nCos ); - memset( p->pCos, 0, sizeof(Tim_Obj_t) * nCos ); - for ( i = 0; i < nCis; i++ ) - { - p->pCis[i].Id = i; - p->pCis[i].iObj2Box = p->pCis[i].iObj2Num = -1; - p->pCis[i].timeReq = TIM_ETERNITY; - p->pCis[i].timeArr = 0.0; - p->pCis[i].TravId = 0; - } - for ( i = 0; i < nCos; i++ ) - { - p->pCos[i].Id = i; - p->pCos[i].iObj2Box = p->pCos[i].iObj2Num = -1; - p->pCos[i].timeReq = TIM_ETERNITY; - p->pCos[i].timeArr = 0.0; - p->pCos[i].TravId = 0; - } - p->fUseTravId = 1; - return p; -} - -/**Function************************************************************* - - Synopsis [Duplicates the timing manager.] - - Description [Derives discrete-delay-model timing manager. - Useful for AIG optimization with approximate timing information.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Tim_Man_t * Tim_ManDup( Tim_Man_t * p, int fDiscrete ) -{ - Tim_Man_t * pNew; - Tim_Box_t * pBox; - float * pDelayTableNew; - int i, k; - pNew = Tim_ManStart( p->nCis, p->nCos ); - memcpy( pNew->pCis, p->pCis, sizeof(Tim_Obj_t) * p->nCis ); - memcpy( pNew->pCos, p->pCos, sizeof(Tim_Obj_t) * p->nCos ); - for ( k = 0; k < p->nCis; k++ ) - pNew->pCis[k].TravId = 0; - for ( k = 0; k < p->nCos; k++ ) - pNew->pCos[k].TravId = 0; - if ( fDiscrete ) - { - for ( k = 0; k < p->nCis; k++ ) - pNew->pCis[k].timeArr = 0.0; // modify here - // modify the required times - } - pNew->vDelayTables = Vec_PtrAlloc( 100 ); - Tim_ManForEachBox( p, pBox, i ) - { -//printf( "%d %d\n", pBox->nInputs, pBox->nOutputs ); - pDelayTableNew = ABC_ALLOC( float, pBox->nInputs * pBox->nOutputs ); - Vec_PtrPush( pNew->vDelayTables, pDelayTableNew ); - if ( fDiscrete ) - { - for ( k = 0; k < pBox->nInputs * pBox->nOutputs; k++ ) - pDelayTableNew[k] = 1.0; // modify here - -///// begin part of improved CIN/COUT propagation - for ( k = 0; k < pBox->nInputs; k++ ) // fill in the first row - pDelayTableNew[k] = 0.5; - for ( k = 0; k < pBox->nOutputs; k++ ) // fill in the first column - pDelayTableNew[k*pBox->nInputs] = 0.5; - pDelayTableNew[0] = 0.0; // fill in the first entry -///// end part of improved CIN/COUT propagation - - /// change -// pDelayTableNew[0] = 0.0; - /// change - } - else - memcpy( pDelayTableNew, pBox->pDelayTable, sizeof(float) * pBox->nInputs * pBox->nOutputs ); - Tim_ManCreateBoxFirst( pNew, pBox->Inouts[0], pBox->nInputs, - pBox->Inouts[pBox->nInputs], pBox->nOutputs, pDelayTableNew ); - } - return pNew; -} - -/**Function************************************************************* - - Synopsis [Duplicates the timing manager.] - - Description [Derives unit-delay-model timing manager. - Useful for levelizing the network.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Tim_Man_t * Tim_ManDupUnit( Tim_Man_t * p ) -{ - Tim_Man_t * pNew; - Tim_Box_t * pBox; - float * pDelayTableNew; - int i, k; - pNew = Tim_ManStart( p->nCis, p->nCos ); - memcpy( pNew->pCis, p->pCis, sizeof(Tim_Obj_t) * p->nCis ); - memcpy( pNew->pCos, p->pCos, sizeof(Tim_Obj_t) * p->nCos ); - for ( k = 0; k < p->nCis; k++ ) - { - pNew->pCis[k].TravId = 0; - pNew->pCis[k].timeArr = 0.0; - } - for ( k = 0; k < p->nCos; k++ ) - pNew->pCos[k].TravId = 0; - pNew->vDelayTables = Vec_PtrAlloc( 100 ); - Tim_ManForEachBox( p, pBox, i ) - { - pDelayTableNew = ABC_ALLOC( float, pBox->nInputs * pBox->nOutputs ); - Vec_PtrPush( pNew->vDelayTables, pDelayTableNew ); - for ( k = 0; k < pBox->nInputs * pBox->nOutputs; k++ ) - pDelayTableNew[k] = 1.0; - Tim_ManCreateBoxFirst( pNew, pBox->Inouts[0], pBox->nInputs, - pBox->Inouts[pBox->nInputs], pBox->nOutputs, pDelayTableNew ); - } - return pNew; -} - -/**Function************************************************************* - - Synopsis [Duplicates the timing manager.] - - Description [Derives the approximate timing manager with realistic delays - but without white-boxes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Tim_Man_t * Tim_ManDupApprox( Tim_Man_t * p ) -{ - Tim_Man_t * pNew; - int k; - pNew = Tim_ManStart( p->nCis, p->nCos ); - for ( k = 0; k < p->nCis; k++ ) - if ( p->pCis[k].iObj2Box == -1 ) - pNew->pCis[k].timeArr = p->pCis[k].timeArr; - else - pNew->pCis[k].timeArr = p->pCis[k].timeReq; - for ( k = 0; k < p->nCos; k++ ) - pNew->pCos[k].timeReq = p->pCos[k].timeReq; - return pNew; -} - -/**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( float *, p->vDelayTables, pTable, i ) - ABC_FREE( pTable ); - Vec_PtrFree( p->vDelayTables ); - } - Vec_PtrFree( p->vBoxes ); - Mem_FlexStop( p->pMemObj, 0 ); - ABC_FREE( p->pCis ); - ABC_FREE( p->pCos ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Stops the timing manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Tim_ManStopP( Tim_Man_t ** p ) -{ - if ( *p == NULL ) - return; - Tim_ManStop( *p ); - *p = NULL; -} - -/**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_ManForEachCi( p, pObj, i ) - printf( "pi%5d : arr = %5.3f req = %5.3f\n", i, pObj->timeArr, pObj->timeReq ); - Tim_ManForEachCo( 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 [Disables the use of the traversal ID.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Tim_ManTravIdDisable( Tim_Man_t * p ) -{ - p->fUseTravId = 0; -} - -/**Function************************************************************* - - Synopsis [Enables the use of the traversal ID.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Tim_ManTravIdEnable( Tim_Man_t * p ) -{ - p->fUseTravId = 1; -} - -/**Function************************************************************* - - Synopsis [Label box inputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Tim_ManSetCurrentTravIdBoxInputs( Tim_Man_t * p, int iBox ) -{ - Tim_Box_t * pBox; - Tim_Obj_t * pObj; - int i; - pBox = Tim_ManBox( p, iBox ); - Tim_ManBoxForEachInput( p, pBox, pObj, i ) - pObj->TravId = p->nTravIds; -} - -/**Function************************************************************* - - Synopsis [Label box outputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Tim_ManSetCurrentTravIdBoxOutputs( Tim_Man_t * p, int iBox ) -{ - Tim_Box_t * pBox; - Tim_Obj_t * pObj; - int i; - pBox = Tim_ManBox( p, iBox ); - Tim_ManBoxForEachOutput( p, pBox, pObj, i ) - pObj->TravId = p->nTravIds; -} - -/**Function************************************************************* - - Synopsis [Label box inputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Tim_ManSetPreviousTravIdBoxInputs( Tim_Man_t * p, int iBox ) -{ - Tim_Box_t * pBox; - Tim_Obj_t * pObj; - int i; - pBox = Tim_ManBox( p, iBox ); - Tim_ManBoxForEachInput( p, pBox, pObj, i ) - pObj->TravId = p->nTravIds - 1; -} - -/**Function************************************************************* - - Synopsis [Label box outputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Tim_ManSetPreviousTravIdBoxOutputs( Tim_Man_t * p, int iBox ) -{ - Tim_Box_t * pBox; - Tim_Obj_t * pObj; - int i; - pBox = Tim_ManBox( p, iBox ); - Tim_ManBoxForEachOutput( p, pBox, pObj, i ) - pObj->TravId = p->nTravIds - 1; -} - -/**Function************************************************************* - - Synopsis [Updates required time of the PO.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Tim_ManIsCiTravIdCurrent( Tim_Man_t * p, int iCi ) -{ - assert( iCi < p->nCis ); - assert( p->fUseTravId ); - return p->pCis[iCi].TravId == p->nTravIds; -} - -/**Function************************************************************* - - Synopsis [Updates required time of the PO.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Tim_ManIsCoTravIdCurrent( Tim_Man_t * p, int iCo ) -{ - assert( iCo < p->nCos ); - assert( p->fUseTravId ); - return p->pCos[iCo].TravId == p->nTravIds; -} - -/**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->nCos ); - pBox->Inouts[i] = pIns[i]; - p->pCos[pIns[i]].iObj2Box = pBox->iBox; - p->pCos[pIns[i]].iObj2Num = i; - } - for ( i = 0; i < nOuts; i++ ) - { - assert( pOuts[i] < p->nCis ); - pBox->Inouts[nIns+i] = pOuts[i]; - p->pCis[pOuts[i]].iObj2Box = pBox->iBox; - p->pCis[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->nCos ); - pBox->Inouts[i] = firstIn+i; - p->pCos[firstIn+i].iObj2Box = pBox->iBox; - p->pCos[firstIn+i].iObj2Num = i; - } - for ( i = 0; i < nOuts; i++ ) - { - assert( firstOut+i < p->nCis ); - pBox->Inouts[nIns+i] = firstOut+i; - p->pCis[firstOut+i].iObj2Box = pBox->iBox; - p->pCis[firstOut+i].iObj2Num = i; - } -// if ( pBox->iBox < 50 ) -// printf( "%4d %4d %4d %4d \n", firstIn, nIns, firstOut, nOuts ); -} - - - -/**Function************************************************************* - - Synopsis [Increments the trav ID of the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Tim_ManIncrementTravId( Tim_Man_t * p ) -{ - int i; - if ( p->nTravIds >= (1<<30)-1 ) - { - p->nTravIds = 0; - for ( i = 0; i < p->nCis; i++ ) - p->pCis[i].TravId = 0; - for ( i = 0; i < p->nCos; i++ ) - p->pCos[i].TravId = 0; - } - assert( p->nTravIds < (1<<30)-1 ); - p->nTravIds++; -} - -/**Function************************************************************* - - Synopsis [Initializes arrival time of the PI.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Tim_ManInitCiArrival( Tim_Man_t * p, int iCi, float Delay ) -{ - assert( iCi < p->nCis ); - p->pCis[iCi].timeArr = Delay; -} - -/**Function************************************************************* - - Synopsis [Initializes required time of the PO.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Tim_ManInitCoRequired( Tim_Man_t * p, int iCo, float Delay ) -{ - assert( iCo < p->nCos ); - p->pCos[iCo].timeReq = Delay; -} - -/**Function************************************************************* - - Synopsis [Updates required time of the PO.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Tim_ManSetCoArrival( Tim_Man_t * p, int iCo, float Delay ) -{ - assert( iCo < p->nCos ); - assert( !p->fUseTravId || p->pCos[iCo].TravId != p->nTravIds ); - p->pCos[iCo].timeArr = Delay; - p->pCos[iCo].TravId = p->nTravIds; -} - -/**Function************************************************************* - - Synopsis [Updates arrival time of the PI.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Tim_ManSetCiRequired( Tim_Man_t * p, int iCi, float Delay ) -{ - assert( iCi < p->nCis ); - assert( !p->fUseTravId || p->pCis[iCi].TravId != p->nTravIds ); - p->pCis[iCi].timeReq = Delay; - p->pCis[iCi].TravId = p->nTravIds; -} - -/**Function************************************************************* - - Synopsis [Updates required time of the PO.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Tim_ManSetCoRequired( Tim_Man_t * p, int iCo, float Delay ) -{ - assert( iCo < p->nCos ); - assert( !p->fUseTravId || p->pCos[iCo].TravId != p->nTravIds ); - p->pCos[iCo].timeReq = Delay; - p->pCos[iCo].TravId = p->nTravIds; -} - -/**Function************************************************************* - - Synopsis [Sets the correct required times for all POs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Tim_ManSetCiArrivalAll( Tim_Man_t * p, float Delay ) -{ - Tim_Obj_t * pObj; - int i; - Tim_ManForEachCi( p, pObj, i ) - Tim_ManInitCiArrival( p, i, Delay ); -} - -/**Function************************************************************* - - Synopsis [Sets the correct required times for all POs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Tim_ManSetCoRequiredAll( Tim_Man_t * p, float Delay ) -{ - Tim_Obj_t * pObj; - int i; - Tim_ManForEachCo( p, pObj, i ) - { - Tim_ManSetCoRequired( p, i, Delay ); -//printf( "%d ", i ); - } -} - - -/**Function************************************************************* - - Synopsis [Returns PI arrival time.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Tim_ManGetCiArrival( Tim_Man_t * p, int iCi ) -{ - Tim_Box_t * pBox; - Tim_Obj_t * pObjThis, * pObj, * pObjRes; - float * pDelays, DelayBest; - int i, k; - // consider the already processed PI - pObjThis = Tim_ManCi( p, iCi ); - if ( p->fUseTravId && pObjThis->TravId == p->nTravIds ) - return pObjThis->timeArr; - pObjThis->TravId = p->nTravIds; - // consider the main PI - pBox = Tim_ManCiBox( p, iCi ); - if ( pBox == NULL ) - return pObjThis->timeArr; - // update box timing - pBox->TravId = p->nTravIds; - // get the arrival times of the inputs of the box (POs) - if ( p->fUseTravId ) - Tim_ManBoxForEachInput( p, pBox, pObj, i ) - if ( pObj->TravId != p->nTravIds ) - printf( "Tim_ManGetCiArrival(): Input 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 = -TIM_ETERNITY; - Tim_ManBoxForEachInput( p, pBox, pObj, k ) - DelayBest = ABC_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_ManGetCoRequired( Tim_Man_t * p, int iCo ) -{ - Tim_Box_t * pBox; - Tim_Obj_t * pObjThis, * pObj, * pObjRes; - float * pDelays, DelayBest; - int i, k; - // consider the already processed PO - pObjThis = Tim_ManCo( p, iCo ); - if ( p->fUseTravId && pObjThis->TravId == p->nTravIds ) - return pObjThis->timeReq; - pObjThis->TravId = p->nTravIds; - // consider the main PO - pBox = Tim_ManCoBox( p, iCo ); - if ( pBox == NULL ) - return pObjThis->timeReq; - // update box timing - pBox->TravId = p->nTravIds; - // get the required times of the outputs of the box (PIs) - if ( p->fUseTravId ) - Tim_ManBoxForEachOutput( p, pBox, pObj, i ) - if ( pObj->TravId != p->nTravIds ) - printf( "Tim_ManGetCoRequired(): Output required times of the box are not up to date!\n" ); - // compute the required times for each input of the box (POs) - Tim_ManBoxForEachInput( p, pBox, pObjRes, i ) - { - DelayBest = TIM_ETERNITY; - Tim_ManBoxForEachOutput( p, pBox, pObj, k ) - { - pDelays = pBox->pDelayTable + k * pBox->nInputs; - DelayBest = ABC_MIN( DelayBest, pObj->timeReq - pDelays[i] ); - } - pObjRes->timeReq = DelayBest; - pObjRes->TravId = p->nTravIds; - } - return pObjThis->timeReq; -} - -/**Function************************************************************* - - Synopsis [Returns the box number for the given input.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Tim_ManBoxForCi( Tim_Man_t * p, int iCi ) -{ - if ( iCi >= p->nCis ) - return -1; - return p->pCis[iCi].iObj2Box; -} - -/**Function************************************************************* - - Synopsis [Returns the box number for the given output.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Tim_ManBoxForCo( Tim_Man_t * p, int iCo ) -{ - if ( iCo >= p->nCos ) - return -1; - return p->pCos[iCo].iObj2Box; -} - -/**Function************************************************************* - - Synopsis [Returns the first input of the box.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Tim_ManBoxInputFirst( Tim_Man_t * p, int iBox ) -{ - Tim_Box_t * pBox = (Tim_Box_t *)Vec_PtrEntry( p->vBoxes, iBox ); - return pBox->Inouts[0]; -} - -/**Function************************************************************* - - Synopsis [Returns the first input of the box.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Tim_ManBoxOutputFirst( Tim_Man_t * p, int iBox ) -{ - Tim_Box_t * pBox = (Tim_Box_t *)Vec_PtrEntry( p->vBoxes, iBox ); - return pBox->Inouts[pBox->nInputs]; -} - -/**Function************************************************************* - - Synopsis [Returns the first input of the box.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Tim_ManBoxInputNum( Tim_Man_t * p, int iBox ) -{ - Tim_Box_t * pBox = (Tim_Box_t *)Vec_PtrEntry( p->vBoxes, iBox ); - return pBox->nInputs; -} - -/**Function************************************************************* - - Synopsis [Returns the first input of the box.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Tim_ManBoxOutputNum( Tim_Man_t * p, int iBox ) -{ - Tim_Box_t * pBox = (Tim_Box_t *)Vec_PtrEntry( p->vBoxes, iBox ); - return pBox->nOutputs; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Tim_ManChangeForAdders( Tim_Man_t * p ) -{ - Tim_Box_t * pBox; - int i; - Tim_ManForEachBox( p, pBox, i ) - pBox->pDelayTable[0] = 0.0; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/tim/tim.h b/src/aig/tim/tim.h deleted file mode 100644 index 2d52b7b1..00000000 --- a/src/aig/tim/tim.h +++ /dev/null @@ -1,110 +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__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Tim_Man_t_ Tim_Man_t; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#define TIM_ETERNITY 10000 - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// SEQUENTIAL ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== time.c ===========================================================*/ -extern Tim_Man_t * Tim_ManStart( int nCis, int nCos ); -extern Tim_Man_t * Tim_ManDup( Tim_Man_t * p, int fDiscrete ); -extern Tim_Man_t * Tim_ManDupUnit( Tim_Man_t * p ); -extern Tim_Man_t * Tim_ManDupApprox( Tim_Man_t * p ); -extern void Tim_ManStop( Tim_Man_t * p ); -extern void Tim_ManStopP( Tim_Man_t ** p ); -extern void Tim_ManPrint( Tim_Man_t * p ); -extern void Tim_ManTravIdDisable( Tim_Man_t * p ); -extern void Tim_ManTravIdEnable( Tim_Man_t * p ); -extern void Tim_ManSetCurrentTravIdBoxInputs( Tim_Man_t * p, int iBox ); -extern void Tim_ManSetCurrentTravIdBoxOutputs( Tim_Man_t * p, int iBox ); -extern void Tim_ManSetPreviousTravIdBoxInputs( Tim_Man_t * p, int iBox ); -extern void Tim_ManSetPreviousTravIdBoxOutputs( Tim_Man_t * p, int iBox ); -extern int Tim_ManIsCiTravIdCurrent( Tim_Man_t * p, int iCi ); -extern int Tim_ManIsCoTravIdCurrent( Tim_Man_t * p, int iCo ); -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_ManInitCiArrival( Tim_Man_t * p, int iCi, float Delay ); -extern void Tim_ManInitCoRequired( Tim_Man_t * p, int iCo, float Delay ); -extern void Tim_ManSetCoArrival( Tim_Man_t * p, int iCo, float Delay ); -extern void Tim_ManSetCiRequired( Tim_Man_t * p, int iCi, float Delay ); -extern void Tim_ManSetCoRequired( Tim_Man_t * p, int iCo, float Delay ); -extern void Tim_ManSetCiArrivalAll( Tim_Man_t * p, float Delay ); -extern void Tim_ManSetCoRequiredAll( Tim_Man_t * p, float Delay ); -extern float Tim_ManGetCiArrival( Tim_Man_t * p, int iCi ); -extern float Tim_ManGetCoRequired( Tim_Man_t * p, int iCo ); -extern int Tim_ManBoxForCi( Tim_Man_t * p, int iCo ); -extern int Tim_ManBoxForCo( Tim_Man_t * p, int iCi ); -extern int Tim_ManBoxInputFirst( Tim_Man_t * p, int iBox ); -extern int Tim_ManBoxOutputFirst( Tim_Man_t * p, int iBox ); -extern int Tim_ManBoxInputNum( Tim_Man_t * p, int iBox ); -extern int Tim_ManBoxOutputNum( Tim_Man_t * p, int iBox ); -extern void Tim_ManChangeForAdders( Tim_Man_t * p ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h index 587d50d8..a0b65e63 100644 --- a/src/base/abc/abc.h +++ b/src/base/abc/abc.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __ABC_H__ -#define __ABC_H__ +#ifndef ABC__base__abc__abc_h +#define ABC__base__abc__abc_h //////////////////////////////////////////////////////////////////////// @@ -32,13 +32,14 @@ #include #include -#include "vec.h" -#include "hop.h" -#include "st.h" -#include "stmm.h" -#include "nm.h" -#include "mem.h" -#include "utilCex.h" +#include "src/misc/vec/vec.h" +#include "src/aig/hop/hop.h" +#include "src/misc/st/st.h" +#include "src/misc/st/stmm.h" +#include "src/misc/nm/nm.h" +#include "src/misc/mem/mem.h" +#include "src/misc/util/utilCex.h" +#include "src/misc/extra/extra.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// @@ -239,15 +240,6 @@ struct Abc_Lib_t_ //////////////////////////////////////////////////////////////////////// // 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_Float2Int( float Val ) { union { int x; float y; } v; v.y = Val; return v.x; } -static inline float Abc_Int2Float( int Num ) { union { int x; float y; } v; v.x = Num; return v.y; } -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 ); } diff --git a/src/base/abc/abcAig.c b/src/base/abc/abcAig.c index c6611a1a..d594846b 100644 --- a/src/base/abc/abcAig.c +++ b/src/base/abc/abcAig.c @@ -19,7 +19,6 @@ ***********************************************************************/ #include "abc.h" -#include "extra.h" ABC_NAMESPACE_IMPL_START @@ -133,7 +132,7 @@ Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtkAig ) pMan = ABC_ALLOC( Abc_Aig_t, 1 ); memset( pMan, 0, sizeof(Abc_Aig_t) ); // allocate the table - pMan->nBins = Cudd_Prime( 10000 ); + pMan->nBins = Abc_PrimeCudd( 10000 ); pMan->pBins = ABC_ALLOC( Abc_Obj_t *, pMan->nBins ); memset( pMan->pBins, 0, sizeof(Abc_Obj_t *) * pMan->nBins ); pMan->vNodes = Vec_PtrAlloc( 100 ); @@ -250,7 +249,7 @@ int Abc_AigCheck( Abc_Aig_t * pMan ) printf( "Abc_AigCheck: The AIG has non-standard nodes.\n" ); return 0; } - if ( pObj->Level != 1 + ABC_MAX( Abc_ObjFanin0(pObj)->Level, Abc_ObjFanin1(pObj)->Level ) ) + if ( pObj->Level != 1 + (unsigned)Abc_MaxInt( Abc_ObjFanin0(pObj)->Level, Abc_ObjFanin1(pObj)->Level ) ) printf( "Abc_AigCheck: Node \"%s\" has level that does not agree with the fanin levels.\n", Abc_ObjName(pObj) ); pAnd = Abc_AigAndLookup( pMan, Abc_ObjChild0(pObj), Abc_ObjChild1(pObj) ); if ( pAnd != pObj ) @@ -330,7 +329,7 @@ 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->Level = 1 + Abc_MaxInt( 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 @@ -374,7 +373,7 @@ Abc_Obj_t * Abc_AigAndCreateFrom( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * 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->Level = 1 + Abc_MaxInt( Abc_ObjRegular(p0)->Level, Abc_ObjRegular(p1)->Level ); pAnd->fExor = Abc_NodeIsExorType(pAnd); // add the node to the corresponding linked list in the table Key = Abc_HashKey2( p0, p1, pMan->nBins ); @@ -595,7 +594,7 @@ void Abc_AigResize( Abc_Aig_t * pMan ) clk = clock(); // get the new table size - nBinsNew = Cudd_Prime( 3 * pMan->nBins ); + nBinsNew = Abc_PrimeCudd( 3 * pMan->nBins ); // allocate a new array pBinsNew = ABC_ALLOC( Abc_Obj_t *, nBinsNew ); memset( pBinsNew, 0, sizeof(Abc_Obj_t *) * nBinsNew ); @@ -1076,7 +1075,7 @@ void Abc_AigUpdateLevel_int( Abc_Aig_t * pMan ) if ( Abc_ObjIsCo(pFanout) ) continue; // get the new level of this fanout - LevelNew = 1 + ABC_MAX( Abc_ObjFanin0(pFanout)->Level, Abc_ObjFanin1(pFanout)->Level ); + LevelNew = 1 + Abc_MaxInt( Abc_ObjFanin0(pFanout)->Level, Abc_ObjFanin1(pFanout)->Level ); assert( LevelNew > i ); if ( (int)pFanout->Level == LevelNew ) // no change continue; diff --git a/src/base/abc/abcBlifMv.c b/src/base/abc/abcBlifMv.c index cffdc8da..47a4c15e 100644 --- a/src/base/abc/abcBlifMv.c +++ b/src/base/abc/abcBlifMv.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "abc.h" -#include "extra.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START @@ -401,7 +401,7 @@ Abc_Ntk_t * Abc_NtkStrashBlifMv( Abc_Ntk_t * pNtk ) if ( nValuesMax < nValues ) nValuesMax = nValues; } - nBits = Extra_Base2Log( nValuesMax ); + nBits = Abc_Base2Log( nValuesMax ); pBits = ABC_ALLOC( Abc_Obj_t *, nBits ); // clean the node copy fields @@ -474,7 +474,7 @@ Abc_Ntk_t * Abc_NtkStrashBlifMv( Abc_Ntk_t * pNtk ) nValues = Abc_ObjMvVarNum(pNet); pValues = ABC_ALLOC( Abc_Obj_t *, nValues ); // create PIs for the encoding bits - nBits = Extra_Base2Log( nValues ); + nBits = Abc_Base2Log( nValues ); for ( k = 0; k < nBits; k++ ) { pBits[k] = Abc_NtkCreatePi( pNtkNew ); @@ -506,7 +506,7 @@ Abc_Ntk_t * Abc_NtkStrashBlifMv( Abc_Ntk_t * pNtk ) nValues = Abc_ObjMvVarNum(pNet); pValues = ABC_ALLOC( Abc_Obj_t *, nValues ); // create PIs for the encoding bits - nBits = Extra_Base2Log( nValues ); + nBits = Abc_Base2Log( nValues ); for ( k = 0; k < nBits; k++ ) { pBits[k] = Abc_NtkCreateBo( pNtkNew ); @@ -602,7 +602,7 @@ Abc_Ntk_t * Abc_NtkStrashBlifMv( Abc_Ntk_t * pNtk ) // Abc_NodeSetTravIdCurrent( pNet ); nValues = Abc_ObjMvVarNum(pNet); pValues = (Abc_Obj_t **)pNet->pCopy; - nBits = Extra_Base2Log( nValues ); + nBits = Abc_Base2Log( nValues ); for ( k = 0; k < nBits; k++ ) { pBit = Abc_ObjNot( Abc_AigConst1(pNtkNew) ); @@ -628,7 +628,7 @@ Abc_Ntk_t * Abc_NtkStrashBlifMv( Abc_Ntk_t * pNtk ) // Abc_NodeSetTravIdCurrent( pNet ); nValues = Abc_ObjMvVarNum(pNet); pValues = (Abc_Obj_t **)pNet->pCopy; - nBits = Extra_Base2Log( nValues ); + nBits = Abc_Base2Log( nValues ); for ( k = 0; k < nBits; k++ ) { pBit = Abc_ObjNot( Abc_AigConst1(pNtkNew) ); @@ -805,7 +805,7 @@ Abc_Ntk_t * Abc_NtkSkeletonBlifMv( Abc_Ntk_t * pNtk ) { pNet = Abc_ObjFanout0(pObj); nValues = Abc_ObjMvVarNum(pNet); - nBits = Extra_Base2Log( nValues ); + nBits = Abc_Base2Log( nValues ); for ( k = 0; k < nBits; k++ ) { pNodeNew = Abc_NtkCreateNode( pNtkNew ); @@ -856,7 +856,7 @@ Abc_Ntk_t * Abc_NtkSkeletonBlifMv( Abc_Ntk_t * pNtk ) continue; Abc_NodeSetTravIdCurrent( pNet ); nValues = Abc_ObjMvVarNum(pNet); - nBits = Extra_Base2Log( nValues ); + nBits = Abc_Base2Log( nValues ); pNodeNew = Abc_NtkCreateNode( pNtkNew ); pNodeNew->pData = Abc_SopDecoderLog( (Mem_Flex_t *)pNtkNew->pManFunc, nValues ); for ( k = 0; k < nBits; k++ ) diff --git a/src/base/abc/abcCheck.c b/src/base/abc/abcCheck.c index aa264314..a80c4372 100644 --- a/src/base/abc/abcCheck.c +++ b/src/base/abc/abcCheck.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "abc.h" -#include "main.h" -//#include "seq.h" +#include "src/base/main/main.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abc/abcDfs.c b/src/base/abc/abcDfs.c index cc001ab6..6d67785b 100644 --- a/src/base/abc/abcDfs.c +++ b/src/base/abc/abcDfs.c @@ -1312,14 +1312,14 @@ int Abc_NodeSetChoiceLevel_rec( Abc_Obj_t * pNode, int fMaximum ) // 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 ); + Level = 1 + Abc_MaxInt( Level1, Level2 ); if ( pNode->pData ) { LevelE = Abc_NodeSetChoiceLevel_rec( (Abc_Obj_t *)pNode->pData, fMaximum ); if ( fMaximum ) - Level = ABC_MAX( Level, LevelE ); + Level = Abc_MaxInt( Level, LevelE ); else - Level = ABC_MIN( Level, LevelE ); + Level = Abc_MinInt( Level, LevelE ); // set the level of all equivalent nodes to be the same minimum for ( pTemp = (Abc_Obj_t *)pNode->pData; pTemp; pTemp = (Abc_Obj_t *)pTemp->pData ) pTemp->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)Level; @@ -1363,7 +1363,7 @@ int Abc_AigSetChoiceLevels( Abc_Ntk_t * pNtk ) Abc_NtkForEachCo( pNtk, pObj, i ) { LevelCur = Abc_NodeSetChoiceLevel_rec( Abc_ObjFanin0(pObj), 1 ); - LevelMax = ABC_MAX( LevelMax, LevelCur ); + LevelMax = Abc_MaxInt( LevelMax, LevelCur ); } return LevelMax; } diff --git a/src/base/abc/abcFunc.c b/src/base/abc/abcFunc.c index 7ff7db17..86604f39 100644 --- a/src/base/abc/abcFunc.c +++ b/src/base/abc/abcFunc.c @@ -19,8 +19,9 @@ ***********************************************************************/ #include "abc.h" -#include "main.h" -#include "mio.h" +#include "src/base/main/main.h" +#include "src/map/mio/mio.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abc/abcHie.c b/src/base/abc/abcHie.c index a3ec3c5f..73b08fcc 100644 --- a/src/base/abc/abcHie.c +++ b/src/base/abc/abcHie.c @@ -19,7 +19,6 @@ ***********************************************************************/ #include "abc.h" -#include "extra.h" ABC_NAMESPACE_IMPL_START @@ -194,8 +193,8 @@ Abc_Ntk_t * Abc_NtkFlattenLogicHierarchy2( Abc_Ntk_t * 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); + pNtkNew->pName = Abc_UtilStrsav(pNtk->pName); + pNtkNew->pSpec = Abc_UtilStrsav(pNtk->pSpec); // clean the node copy fields Abc_NtkCleanCopy( pNtk ); diff --git a/src/base/abc/abcHieCec.c b/src/base/abc/abcHieCec.c index ace7583b..ab29c3ca 100644 --- a/src/base/abc/abcHieCec.c +++ b/src/base/abc/abcHieCec.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "abc.h" -#include "ioAbc.h" -#include "gia.h" +#include "src/base/io/ioAbc.h" +#include "src/aig/gia/gia.h" ABC_NAMESPACE_IMPL_START @@ -154,16 +154,16 @@ int Abc_NtkDeriveFlatGiaSop( Gia_Man_t * pGia, int * gFanins, char * pSop ) if ( Value == '1' ) gAnd = Gia_ManHashAnd( pGia, gAnd, gFanins[i] ); else if ( Value == '0' ) - gAnd = Gia_ManHashAnd( pGia, gAnd, Gia_LitNot(gFanins[i]) ); + gAnd = Gia_ManHashAnd( pGia, gAnd, Abc_LitNot(gFanins[i]) ); } // add to the sum of cubes - gSum = Gia_ManHashAnd( pGia, Gia_LitNot(gSum), Gia_LitNot(gAnd) ); - gSum = Gia_LitNot( gSum ); + gSum = Gia_ManHashAnd( pGia, Abc_LitNot(gSum), Abc_LitNot(gAnd) ); + gSum = Abc_LitNot( gSum ); } } // decide whether to complement the result if ( Abc_SopIsComplement(pSop) ) - gSum = Gia_LitNot(gSum); + gSum = Abc_LitNot(gSum); return gSum; } @@ -199,7 +199,7 @@ void Abc_NtkDeriveFlatGia_rec( Gia_Man_t * pGia, Abc_Ntk_t * pNtk ) assert( pSop[2] == '1' ); assert( pSop[0] == '0' || pSop[0] == '1' ); assert( Abc_ObjFanin0(pObj)->iTemp >= 0 ); - Abc_ObjFanout0(pObj)->iTemp = Gia_LitNotCond( Abc_ObjFanin0(pObj)->iTemp, pSop[0]=='0' ); + Abc_ObjFanout0(pObj)->iTemp = Abc_LitNotCond( Abc_ObjFanin0(pObj)->iTemp, pSop[0]=='0' ); continue; } if ( nLength == 5 ) // and2 @@ -210,8 +210,8 @@ void Abc_NtkDeriveFlatGia_rec( Gia_Man_t * pGia, Abc_Ntk_t * pNtk ) assert( Abc_ObjFanin0(pObj)->iTemp >= 0 ); assert( Abc_ObjFanin1(pObj)->iTemp >= 0 ); Abc_ObjFanout0(pObj)->iTemp = Gia_ManHashAnd( pGia, - Gia_LitNotCond( Abc_ObjFanin0(pObj)->iTemp, pSop[0]=='0' ), - Gia_LitNotCond( Abc_ObjFanin1(pObj)->iTemp, pSop[1]=='0' ) + Abc_LitNotCond( Abc_ObjFanin0(pObj)->iTemp, pSop[0]=='0' ), + Abc_LitNotCond( Abc_ObjFanin1(pObj)->iTemp, pSop[1]=='0' ) ); continue; } @@ -267,7 +267,7 @@ Gia_Man_t * Abc_NtkDeriveFlatGia( Abc_Ntk_t * pNtk ) Abc_NtkFillTemp( pNtk ); // start the network pGia = Gia_ManStart( (1<<16) ); - pGia->pName = Gia_UtilStrsav( Abc_NtkName(pNtk) ); + pGia->pName = Abc_UtilStrsav( Abc_NtkName(pNtk) ); Gia_ManHashAlloc( pGia ); // create PIs Abc_NtkForEachPi( pNtk, pTerm, i ) @@ -343,7 +343,7 @@ Gia_Man_t * Abc_NtkDeriveFlatGia2Derive( Abc_Ntk_t * pNtk, Vec_Ptr_t * vOrder ) // start the network pGia = Gia_ManStart( (1<<15) ); - pGia->pName = Gia_UtilStrsav( Abc_NtkName(pNtk) ); + pGia->pName = Abc_UtilStrsav( Abc_NtkName(pNtk) ); Gia_ManHashAlloc( pGia ); // create PIs Abc_NtkForEachPi( pNtk, pTerm, i ) @@ -458,7 +458,7 @@ Gia_Man_t * Abc_NtkDeriveFlatGia2( Abc_Ntk_t * pNtk, Vec_Ptr_t * vModels ) Vec_PtrFree( vOrder ); } - pGia = pModel->pData; pModel->pData = NULL; + pGia = (Gia_Man_t *)pModel->pData; pModel->pData = NULL; Vec_PtrForEachEntry( Abc_Ntk_t *, vModels, pModel, i ) Gia_ManStopP( (Gia_Man_t **)&pModel->pData ); diff --git a/src/base/abc/abcHieNew.c b/src/base/abc/abcHieNew.c index 509b8b96..fa544a93 100644 --- a/src/base/abc/abcHieNew.c +++ b/src/base/abc/abcHieNew.c @@ -24,8 +24,9 @@ #include #include -#include "vec.h" -#include "utilNam.h" +#include "src/misc/vec/vec.h" +#include "src/misc/util/utilNam.h" +#include "src/misc/extra/extra.h" ABC_NAMESPACE_IMPL_START @@ -958,7 +959,6 @@ static inline void Au_NtkParseCBlifNum( Vec_Int_t * vFanins, char * pToken, Vec_ ***********************************************************************/ Au_Ntk_t * Au_NtkParseCBlif( char * pFileName ) { - extern char * Extra_FileRead( FILE * pFile ); FILE * pFile; Au_Man_t * pMan; Au_Ntk_t * pRoot; @@ -1109,7 +1109,7 @@ Au_Ntk_t * Au_NtkParseCBlif( char * pFileName ) #include "abc.h" -#include "gia.h" +#include "src/aig/gia/gia.h" extern Vec_Ptr_t * Abc_NtkDfsBoxes( Abc_Ntk_t * pNtk ); extern int Abc_NtkDeriveFlatGiaSop( Gia_Man_t * pGia, int * gFanins, char * pSop ); @@ -1161,15 +1161,15 @@ void Au_NtkDeriveFlatGia_rec( Gia_Man_t * pGia, Au_Ntk_t * p ) { int Lit0, Lit1, Lit2; assert( pObj->Func >= 1 && pObj->Func <= 3 ); - Lit0 = Gia_LitNotCond( Au_ObjCopy(Au_ObjFanin0(pObj)), Au_ObjFaninC0(pObj) ); - Lit1 = Gia_LitNotCond( Au_ObjCopy(Au_ObjFanin1(pObj)), Au_ObjFaninC1(pObj) ); + Lit0 = Abc_LitNotCond( Au_ObjCopy(Au_ObjFanin0(pObj)), Au_ObjFaninC0(pObj) ); + Lit1 = Abc_LitNotCond( Au_ObjCopy(Au_ObjFanin1(pObj)), Au_ObjFaninC1(pObj) ); if ( pObj->Func == 1 ) Lit = Gia_ManHashAnd( pGia, Lit0, Lit1 ); else if ( pObj->Func == 2 ) Lit = Gia_ManHashXor( pGia, Lit0, Lit1 ); else if ( pObj->Func == 3 ) { - Lit2 = Gia_LitNotCond( Au_ObjCopy(Au_ObjFanin2(pObj)), Au_ObjFaninC2(pObj) ); + Lit2 = Abc_LitNotCond( Au_ObjCopy(Au_ObjFanin2(pObj)), Au_ObjFaninC2(pObj) ); Lit = Gia_ManHashMux( pGia, Lit0, Lit1, Lit2 ); } else assert( 0 ); @@ -1199,7 +1199,7 @@ void Au_NtkDeriveFlatGia_rec( Gia_Man_t * pGia, Au_Ntk_t * p ) } Au_NtkForEachPo( p, pTerm, i ) { - Lit = Gia_LitNotCond( Au_ObjCopy(Au_ObjFanin0(pTerm)), Au_ObjFaninC0(pTerm) ); + Lit = Abc_LitNotCond( Au_ObjCopy(Au_ObjFanin0(pTerm)), Au_ObjFaninC0(pTerm) ); Au_ObjSetCopy( pTerm, Lit ); } Au_NtkForEachPo( p, pTerm, i ) @@ -1227,7 +1227,7 @@ Gia_Man_t * Au_NtkDeriveFlatGia( Au_Ntk_t * p ) Au_NtkCleanCopy( p ); // start the network pGia = Gia_ManStart( (1<<16) ); - pGia->pName = Gia_UtilStrsav( Au_NtkName(p) ); + pGia->pName = Abc_UtilStrsav( Au_NtkName(p) ); Gia_ManHashAlloc( pGia ); Gia_ManFlipVerbose( pGia ); // create PIs diff --git a/src/base/abc/abcInt.h b/src/base/abc/abcInt.h index 326ff5a2..0bcddcfb 100644 --- a/src/base/abc/abcInt.h +++ b/src/base/abc/abcInt.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __ABC_INT_H__ -#define __ABC_INT_H__ +#ifndef ABC__base__abc__abcInt_h +#define ABC__base__abc__abcInt_h ABC_NAMESPACE_HEADER_START diff --git a/src/base/abc/abcLatch.c b/src/base/abc/abcLatch.c index b5fa1f64..865fb8b9 100644 --- a/src/base/abc/abcLatch.c +++ b/src/base/abc/abcLatch.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "abc.h" -#include "extra.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START @@ -150,7 +150,7 @@ void Abc_NtkLatchPipe( Abc_Ntk_t * pNtk, int nLatches ) if ( nLatches < 1 ) return; nTotal = nLatches * Abc_NtkPiNum(pNtk); - nDigits = Extra_Base10Log( nTotal ); + nDigits = Abc_Base10Log( nTotal ); vNodes = Vec_PtrAlloc( 100 ); Abc_NtkForEachPi( pNtk, pObj, i ) { @@ -486,7 +486,7 @@ Abc_Ntk_t * Abc_NtkConvertOnehot( Abc_Ntk_t * pNtk ) ABC_NAMESPACE_IMPL_END -#include "giaAig.h" +#include "src/aig/gia/giaAig.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abc/abcLib.c b/src/base/abc/abcLib.c index a9bb5691..b80ebd97 100644 --- a/src/base/abc/abcLib.c +++ b/src/base/abc/abcLib.c @@ -19,7 +19,6 @@ ***********************************************************************/ #include "abc.h" -#include "extra.h" ABC_NAMESPACE_IMPL_START @@ -48,7 +47,7 @@ Abc_Lib_t * Abc_LibCreate( char * pName ) Abc_Lib_t * p; p = ABC_ALLOC( Abc_Lib_t, 1 ); memset( p, 0, sizeof(Abc_Lib_t) ); - p->pName = Extra_UtilStrsav( pName ); + p->pName = Abc_UtilStrsav( pName ); p->tModules = st_init_table( strcmp, st_strhash ); p->vTops = Vec_PtrAlloc( 100 ); p->vModules = Vec_PtrAlloc( 100 ); diff --git a/src/base/abc/abcMinBase.c b/src/base/abc/abcMinBase.c index a8dc9249..2efe404f 100644 --- a/src/base/abc/abcMinBase.c +++ b/src/base/abc/abcMinBase.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "abc.h" -#include "extra.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abc/abcNames.c b/src/base/abc/abcNames.c index 74e4e493..ab33c91a 100644 --- a/src/base/abc/abcNames.c +++ b/src/base/abc/abcNames.c @@ -19,7 +19,6 @@ ***********************************************************************/ #include "abc.h" -#include "extra.h" ABC_NAMESPACE_IMPL_START @@ -204,7 +203,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, Abc_UtilStrsav(Abc_ObjName(pFanin)) ); return vNodes; } @@ -380,7 +379,7 @@ void Abc_NtkAddDummyPiNames( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int nDigits, i; - nDigits = Extra_Base10Log( Abc_NtkPiNum(pNtk) ); + nDigits = Abc_Base10Log( Abc_NtkPiNum(pNtk) ); Abc_NtkForEachPi( pNtk, pObj, i ) Abc_ObjAssignName( pObj, Abc_ObjNameDummy("pi", i, nDigits), NULL ); } @@ -400,7 +399,7 @@ void Abc_NtkAddDummyPoNames( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int nDigits, i; - nDigits = Extra_Base10Log( Abc_NtkPoNum(pNtk) ); + nDigits = Abc_Base10Log( Abc_NtkPoNum(pNtk) ); Abc_NtkForEachPo( pNtk, pObj, i ) Abc_ObjAssignName( pObj, Abc_ObjNameDummy("po", i, nDigits), NULL ); } @@ -432,7 +431,7 @@ void Abc_NtkAddDummyBoxNames( Abc_Ntk_t * pNtk ) CountCur++; else break; - CountMax = ABC_MAX( CountMax, CountCur ); + CountMax = Abc_MaxInt( CountMax, CountCur ); } Abc_NtkForEachPo( pNtk, pObj, i ) { @@ -443,7 +442,7 @@ void Abc_NtkAddDummyBoxNames( Abc_Ntk_t * pNtk ) CountCur++; else break; - CountMax = ABC_MAX( CountMax, CountCur ); + CountMax = Abc_MaxInt( CountMax, CountCur ); } //printf( "CountMax = %d\n", CountMax ); assert( CountMax < 100-2 ); @@ -455,7 +454,7 @@ void Abc_NtkAddDummyBoxNames( Abc_Ntk_t * pNtk ) PrefLo[i+1] = 0; // create latch names assert( !Abc_NtkIsNetlist(pNtk) ); - nDigits = Extra_Base10Log( Abc_NtkLatchNum(pNtk) ); + nDigits = Abc_Base10Log( Abc_NtkLatchNum(pNtk) ); Abc_NtkForEachLatch( pNtk, pObj, i ) { Abc_ObjAssignName( pObj, Abc_ObjNameDummy("l", i, nDigits), NULL ); @@ -463,14 +462,14 @@ void Abc_NtkAddDummyBoxNames( Abc_Ntk_t * pNtk ) Abc_ObjAssignName( Abc_ObjFanout0(pObj), Abc_ObjNameDummy(PrefLo, i, nDigits), NULL ); } /* - nDigits = Extra_Base10Log( Abc_NtkBlackboxNum(pNtk) ); + nDigits = Abc_Base10Log( Abc_NtkBlackboxNum(pNtk) ); Abc_NtkForEachBlackbox( pNtk, pObj, i ) { pName = Abc_ObjAssignName( pObj, Abc_ObjNameDummy("B", i, nDigits), NULL ); - nDigitsF = Extra_Base10Log( Abc_ObjFaninNum(pObj) ); + nDigitsF = Abc_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) ); + nDigitsF = Abc_Base10Log( Abc_ObjFanoutNum(pObj) ); Abc_ObjForEachFanout( pObj, pTerm, k ) Abc_ObjAssignName( Abc_ObjFanin0(pObj), pName, Abc_ObjNameDummy("o", k, nDigitsF) ); } diff --git a/src/base/abc/abcNetlist.c b/src/base/abc/abcNetlist.c index f2e02bc0..f8ff8f0c 100644 --- a/src/base/abc/abcNetlist.c +++ b/src/base/abc/abcNetlist.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "abc.h" -#include "main.h" +#include "src/base/main/main.h" //#include "seq.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abc/abcNtk.c b/src/base/abc/abcNtk.c index 6a20bf91..1f76de81 100644 --- a/src/base/abc/abcNtk.c +++ b/src/base/abc/abcNtk.c @@ -20,9 +20,10 @@ #include "abc.h" #include "abcInt.h" -#include "main.h" -#include "mio.h" -#include "gia.h" +#include "src/base/main/main.h" +#include "src/map/mio/mio.h" +#include "src/aig/gia/gia.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abc/abcObj.c b/src/base/abc/abcObj.c index 36fd6397..7741d963 100644 --- a/src/base/abc/abcObj.c +++ b/src/base/abc/abcObj.c @@ -20,8 +20,9 @@ #include "abc.h" #include "abcInt.h" -#include "main.h" -#include "mio.h" +#include "src/base/main/main.h" +#include "src/map/mio/mio.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abc/abcShow.c b/src/base/abc/abcShow.c index 4295726e..4b8fae49 100644 --- a/src/base/abc/abcShow.c +++ b/src/base/abc/abcShow.c @@ -26,8 +26,9 @@ #include "abc.h" -#include "main.h" -#include "ioAbc.h" +#include "src/base/main/main.h" +#include "src/base/io/ioAbc.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abc/abcSop.c b/src/base/abc/abcSop.c index 297b0737..f8421b93 100644 --- a/src/base/abc/abcSop.c +++ b/src/base/abc/abcSop.c @@ -19,7 +19,6 @@ ***********************************************************************/ #include "abc.h" -#include "extra.h" ABC_NAMESPACE_IMPL_START @@ -885,7 +884,7 @@ char * Abc_SopFromTruthBin( char * pTruth ) // get the number of variables nTruthSize = strlen(pTruth); - nVars = Extra_Base2Log( nTruthSize ); + nVars = Abc_Base2Log( nTruthSize ); if ( nTruthSize != (1 << (nVars)) ) { printf( "String %s does not look like a truth table of a %d-variable function.\n", pTruth, nVars ); @@ -954,7 +953,7 @@ char * Abc_SopFromTruthHex( char * pTruth ) // get the number of variables nTruthSize = strlen(pTruth); - nVars = (nTruthSize < 2) ? 2 : Extra_Base2Log(nTruthSize) + 2; + nVars = (nTruthSize < 2) ? 2 : Abc_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 ); @@ -1051,7 +1050,7 @@ char * Abc_SopEncoderLog( Mem_Flex_t * pMan, int iBit, int nValues ) { char * pResult; Vec_Str_t * vSop; - int v, Counter, fFirst = 1, nBits = Extra_Base2Log(nValues); + int v, Counter, fFirst = 1, nBits = Abc_Base2Log(nValues); assert( iBit < nBits ); // count the number of literals Counter = 0; @@ -1131,7 +1130,7 @@ char * Abc_SopDecoderLog( Mem_Flex_t * pMan, int nValues ) { char * pResult; Vec_Str_t * vSop; - int i, b, nBits = Extra_Base2Log(nValues); + int i, b, nBits = Abc_Base2Log(nValues); assert( nValues > 1 && nValues <= (1< @@ -112,7 +105,7 @@ static int Abc_CommandMfs ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandTrace ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSpeedup ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPowerdown ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandMerge ( Abc_Frame_t * pAbc, int argc, char ** argv ); +//static int Abc_CommandMerge ( 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 ); @@ -287,44 +280,6 @@ static int Abc_CommandCexMin ( Abc_Frame_t * pAbc, int argc, cha 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_CommandAbc8Read ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc8ReadLogic ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc8Write ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc8WriteLogic ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc8ReadLut ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc8PrintLut ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc8Check ( Abc_Frame_t * pAbc, int argc, char ** argv ); - -static int Abc_CommandAbc8Ps ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc8Pfan ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc8If ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc8DChoice ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc8Dch ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc8Dc2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc8Bidec ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc8Strash ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc8Mfs ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc8Lutpack ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc8Lutmin ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc8Balance ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc8Speedup ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc8Merge ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc8Insert ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc8ClpLut ( Abc_Frame_t * pAbc, int argc, char ** argv ); - -static int Abc_CommandAbc8Fraig ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc8Scl ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc8Lcorr ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc8Ssw ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc8Scorr ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc8Sweep ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc8Zero ( Abc_Frame_t * pAbc, int argc, char ** argv ); - -static int Abc_CommandAbc8Cec ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAbc8DSec ( Abc_Frame_t * pAbc, int argc, char ** argv ); - - static int Abc_CommandAbc9Get ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Put ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Read ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -466,24 +421,6 @@ void Abc_FrameReplaceCexVec( Abc_Frame_t * pAbc, Vec_Ptr_t ** pvCexVec ) ***********************************************************************/ void Abc_FrameClearDesign() { - Abc_Frame_t * pAbc; - - pAbc = Abc_FrameGetGlobalFrame(); - if ( pAbc->pAbc8Ntl ) - { - Ntl_ManFree( pAbc->pAbc8Ntl ); - pAbc->pAbc8Ntl = NULL; - } - if ( pAbc->pAbc8Aig ) - { - Aig_ManStop( pAbc->pAbc8Aig ); - pAbc->pAbc8Aig = NULL; - } - if ( pAbc->pAbc8Nwk ) - { - Nwk_ManFree( pAbc->pAbc8Nwk ); - pAbc->pAbc8Nwk = NULL; - } } /**Function************************************************************* @@ -536,18 +473,6 @@ void Abc_CommandUpdate9( Abc_Frame_t * pAbc, Gia_Man_t * pNew ) ***********************************************************************/ void Abc_Init( Abc_Frame_t * pAbc ) { -/* - char * pBuff = ABC_ALLOC( char, (1<<29) ); - int i, clk = clock(); - for ( i = 0; i < (1<<29); i++ ) - pBuff[i] = i % 53; - if ( pBuff == NULL ) - printf( "Not allocated. " ); - else - printf( "Allocated %d bytes. ", (1<<29) ); - Abc_PrintTime( 1, "Time", clock() - clk ); -*/ - 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 ); @@ -591,7 +516,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Synthesis", "trace", Abc_CommandTrace, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "speedup", Abc_CommandSpeedup, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "powerdown", Abc_CommandPowerdown, 1 ); - Cmd_CommandAdd( pAbc, "Synthesis", "merge", Abc_CommandMerge, 1 ); +// Cmd_CommandAdd( pAbc, "Synthesis", "merge", Abc_CommandMerge, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "rewrite", Abc_CommandRewrite, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "refactor", Abc_CommandRefactor, 1 ); @@ -762,42 +687,6 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Verification", "reconcile", Abc_CommandReconcile, 1 ); Cmd_CommandAdd( pAbc, "Verification", "cexmin", Abc_CommandCexMin, 0 ); - - Cmd_CommandAdd( pAbc, "ABC8", "*r", Abc_CommandAbc8Read, 0 ); - Cmd_CommandAdd( pAbc, "ABC8", "*rlogic", Abc_CommandAbc8ReadLogic, 0 ); - Cmd_CommandAdd( pAbc, "ABC8", "*w", Abc_CommandAbc8Write, 0 ); - Cmd_CommandAdd( pAbc, "ABC8", "*wlogic", Abc_CommandAbc8WriteLogic, 0 ); - Cmd_CommandAdd( pAbc, "ABC8", "*rlut", Abc_CommandAbc8ReadLut, 0 ); - Cmd_CommandAdd( pAbc, "ABC8", "*plut", Abc_CommandAbc8PrintLut, 0 ); - Cmd_CommandAdd( pAbc, "ABC8", "*check", Abc_CommandAbc8Check, 0 ); - - Cmd_CommandAdd( pAbc, "ABC8", "*ps", Abc_CommandAbc8Ps, 0 ); - Cmd_CommandAdd( pAbc, "ABC8", "*pfan", Abc_CommandAbc8Pfan, 0 ); - Cmd_CommandAdd( pAbc, "ABC8", "*if", Abc_CommandAbc8If, 0 ); - Cmd_CommandAdd( pAbc, "ABC8", "*dchoice", Abc_CommandAbc8DChoice, 0 ); - Cmd_CommandAdd( pAbc, "ABC8", "*dch", Abc_CommandAbc8Dch, 0 ); - Cmd_CommandAdd( pAbc, "ABC8", "*dc2", Abc_CommandAbc8Dc2, 0 ); - Cmd_CommandAdd( pAbc, "ABC8", "*bidec", Abc_CommandAbc8Bidec, 0 ); - Cmd_CommandAdd( pAbc, "ABC8", "*st", Abc_CommandAbc8Strash, 0 ); - Cmd_CommandAdd( pAbc, "ABC8", "*mfs", Abc_CommandAbc8Mfs, 0 ); - Cmd_CommandAdd( pAbc, "ABC8", "*lp", Abc_CommandAbc8Lutpack, 0 ); - Cmd_CommandAdd( pAbc, "ABC8", "*b", Abc_CommandAbc8Balance, 0 ); - Cmd_CommandAdd( pAbc, "ABC8", "*speedup", Abc_CommandAbc8Speedup, 0 ); - Cmd_CommandAdd( pAbc, "ABC8", "*merge", Abc_CommandAbc8Merge, 0 ); - Cmd_CommandAdd( pAbc, "ABC8", "*insert", Abc_CommandAbc8Insert, 0 ); - Cmd_CommandAdd( pAbc, "ABC8", "*clplut", Abc_CommandAbc8ClpLut, 0 ); - - Cmd_CommandAdd( pAbc, "ABC8", "*fraig", Abc_CommandAbc8Fraig, 0 ); - Cmd_CommandAdd( pAbc, "ABC8", "*scl", Abc_CommandAbc8Scl, 0 ); - Cmd_CommandAdd( pAbc, "ABC8", "*lcorr", Abc_CommandAbc8Lcorr, 0 ); - Cmd_CommandAdd( pAbc, "ABC8", "*ssw", Abc_CommandAbc8Ssw, 0 ); - Cmd_CommandAdd( pAbc, "ABC8", "*scorr", Abc_CommandAbc8Scorr, 0 ); - Cmd_CommandAdd( pAbc, "ABC8", "*sw", Abc_CommandAbc8Sweep, 0 ); - Cmd_CommandAdd( pAbc, "ABC8", "*zero", Abc_CommandAbc8Zero, 0 ); - - Cmd_CommandAdd( pAbc, "ABC8", "*cec", Abc_CommandAbc8Cec, 0 ); - Cmd_CommandAdd( pAbc, "ABC8", "*dsec", Abc_CommandAbc8DSec, 0 ); - Cmd_CommandAdd( pAbc, "ABC9", "&get", Abc_CommandAbc9Get, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&put", Abc_CommandAbc9Put, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&r", Abc_CommandAbc9Read, 0 ); @@ -956,11 +845,6 @@ void Abc_End( Abc_Frame_t * pAbc ) // extern void Au_TabManPrint(); // Au_TabManPrint(); } - { - extern void If_LutLibFree( If_Lib_t * pLutLib ); - if ( Abc_FrameGetGlobalFrame()->pAbc8Lib ) - If_LutLibFree( (If_Lib_t *)Abc_FrameGetGlobalFrame()->pAbc8Lib ); - } // Dar_LibDumpPriorities(); { @@ -4570,6 +4454,7 @@ usage: return 1; } +#if 0 /**Function************************************************************* Synopsis [] @@ -4702,7 +4587,7 @@ usage: Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } - +#endif /**Function************************************************************* Synopsis [] @@ -21305,7 +21190,6 @@ usage: } - /**Function************************************************************* Synopsis [] @@ -21317,28 +21201,21 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandAbc8Read( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandAbcTestNew( Abc_Frame_t * pAbc, int argc, char ** argv ) { - FILE * pFile; - char * pFileName; + extern int Abc_NtkTestProcedure( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 ); + + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; - int fMapped; - int fTest; + + pNtk = Abc_FrameReadNtk(pAbc); // set defaults - fMapped = 0; - fTest = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "mth" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { - case 'm': - fMapped ^= 1; - break; - case 't': - fTest ^= 1; - break; case 'h': goto usage; default: @@ -21346,59 +21223,30 @@ int Abc_CommandAbc8Read( Abc_Frame_t * pAbc, int argc, char ** argv ) } } - // get the input file name - pFileName = argv[globalUtilOptind]; - if ( (pFile = fopen( pFileName, "r" )) == NULL ) + if ( pNtk == NULL ) { - Abc_Print( -1, "Cannot open input file \"%s\". ", pFileName ); - if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".blif", NULL, NULL, NULL, NULL )) ) - Abc_Print( 1, "Did you mean \"%s\"?", pFileName ); - Abc_Print( 1, "\n" ); + Abc_Print( -1, "Empty network.\n" ); return 1; } - fclose( pFile ); - if ( fTest ) - { - Ntl_Man_t * pTemp = Ntl_ManReadBlif( pFileName, 1 ); - if ( pTemp ) - { -// Ntl_ManWriteBlif( pTemp, "test_boxes.blif" ); - Ntl_ManPrintStats( pTemp ); - Ntl_ManFree( pTemp ); - } - return 0; - } - Abc_FrameClearDesign(); - pAbc->pAbc8Ntl = Ntl_ManReadBlif( pFileName, 1 ); - if ( pAbc->pAbc8Ntl == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Read(): Reading BLIF has failed.\n" ); - return 1; - } - pAbc->pAbc8Aig = Ntl_ManExtract( pAbc->pAbc8Ntl ); - if ( pAbc->pAbc8Aig == NULL ) + if ( !Abc_NtkIsStrash( pNtk) ) { - Abc_Print( -1, "Abc_CommandAbc8Read(): AIG extraction has failed.\n" ); + Abc_Print( -1, "The current network is not an AIG. Cannot continue.\n" ); return 1; } - if ( fMapped ) - { - pAbc->pAbc8Nwk = Ntl_ManExtractNwk( pAbc->pAbc8Ntl, pAbc->pAbc8Aig, NULL ); - if ( pAbc->pAbc8Nwk == NULL ) - Abc_Print( -1, "Abc_CommandAbc8Read(): Warning! Mapped network is not extracted.\n" ); - } + +// Abc_NtkTestProcedure( pNtk, NULL ); + return 0; usage: - Abc_Print( -2, "usage: *r [-mth]\n" ); - Abc_Print( -2, "\t reads the design with whiteboxes\n" ); - Abc_Print( -2, "\t-m : toggle extracting mapped network [default = %s]\n", fMapped? "yes": "no" ); - Abc_Print( -2, "\t-t : toggle reading in the test mode [default = %s]\n", fTest? "yes": "no" ); + Abc_Print( -2, "usage: testnew [-h]\n" ); + Abc_Print( -2, "\t new testing procedure\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } + /**Function************************************************************* Synopsis [] @@ -21410,62 +21258,60 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandAbc8ReadLogic( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandAbc9Read( Abc_Frame_t * pAbc, int argc, char ** argv ) { + Gia_Man_t * pAig; FILE * pFile; - char * pFileName; - Nwk_Man_t * pNtkNew; - int c; - - // set defaults + char ** pArgvNew; + char * FileName, * pTemp; + int nArgcNew; + int c, fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) { switch ( c ) { - case 'h': - goto usage; + case 'v': + fVerbose ^= 1; + break; default: goto usage; } } - - // get the input file name - pFileName = argv[globalUtilOptind]; - if ( (pFile = fopen( pFileName, "r" )) == NULL ) + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew != 1 ) { - Abc_Print( -1, "Cannot open input file \"%s\". ", pFileName ); - if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".blif", NULL, NULL, NULL, NULL )) ) - Abc_Print( 1, "Did you mean \"%s\"?", pFileName ); - Abc_Print( 1, "\n" ); + Abc_Print( -1, "There is no file name.\n" ); return 1; } - fclose( pFile ); - if ( pAbc->pAbc8Ntl == NULL || pAbc->pAbc8Aig == NULL ) + // get the input file name + FileName = pArgvNew[0]; + // fix the wrong symbol + for ( pTemp = FileName; *pTemp; pTemp++ ) + if ( *pTemp == '>' ) + *pTemp = '\\'; + if ( (pFile = fopen( FileName, "r" )) == NULL ) { - Abc_Print( -1, "Abc_CommandAbc8ReadLogic(): There is no design or its AIG.\n" ); + Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); + if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", ".blif", ".pla", ".eqn", ".bench" )) ) + Abc_Print( 1, "Did you mean \"%s\"?", FileName ); + Abc_Print( 1, "\n" ); return 1; } + fclose( pFile ); - // read the new logic - pNtkNew = Ntl_ManReadNwk( pFileName, pAbc->pAbc8Aig, Ntl_ManReadTimeMan(pAbc->pAbc8Ntl) ); - if ( pNtkNew == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8ReadLogic(): Procedure has failed.\n" ); - return 1; - } - if ( pAbc->pAbc8Nwk != NULL ) - Nwk_ManFree( pAbc->pAbc8Nwk ); - pAbc->pAbc8Nwk = pNtkNew; + pAig = Gia_ReadAiger( FileName, 0 ); + Abc_CommandUpdate9( pAbc, pAig ); return 0; usage: - Abc_Print( -2, "usage: *rlogic [-h]\n" ); - Abc_Print( -2, "\t reads the logic part of the design without whiteboxes\n" ); - Abc_Print( -2, "\t and sets the new logic as the current mapped network\n" ); - Abc_Print( -2, "\t (the logic part should be comb and with the same PIs/POs)\n" ); - Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "usage: &r [-vh] \n" ); + Abc_Print( -2, "\t reads the current AIG from the AIGER file\n" ); + Abc_Print( -2, "\t-v : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : the file name\n"); return 1; } @@ -21480,112 +21326,61 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandAbc8Write( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandAbc9ReadBlif( Abc_Frame_t * pAbc, int argc, char ** argv ) { - char * pFileName; - Aig_Man_t * pTemp; - Ntl_Man_t * pTemp2; - int fAig; - int fBlif; - int fCollapsed; - int c; - - // set defaults - fAig = 0; - fBlif = 1; - fCollapsed = 0; + extern Gia_Man_t * Abc_NtkHieCecTest( char * pFileName, int fVerbose ); + Gia_Man_t * pAig; + FILE * pFile; + char ** pArgvNew; + char * FileName, * pTemp; + int nArgcNew; + int c, fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "abch" ) ) != EOF ) - { + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { switch ( c ) { - case 'a': - fAig ^= 1; - break; - case 'b': - fBlif ^= 1; - break; - case 'c': - fCollapsed ^= 1; + case 'v': + fVerbose ^= 1; break; - case 'h': - goto usage; default: goto usage; } } - if ( pAbc->pAbc8Ntl == NULL ) + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew != 1 ) { - Abc_Print( -1, "Abc_CommandAbc8Write(): There is no design to write.\n" ); + Abc_Print( -1, "There is no file name.\n" ); return 1; - } - // create the design to write - pFileName = argv[globalUtilOptind]; - if ( fAig ) - { - if ( fCollapsed ) - { - pTemp = Ntl_ManCollapseSeq( pAbc->pAbc8Ntl, 0, 0 ); - if ( fBlif ) - Saig_ManDumpBlif( pTemp, pFileName ); - else - Ioa_WriteAiger( pTemp, pFileName, 0, 0 ); - Aig_ManStop( pTemp ); - } - else - { - if ( pAbc->pAbc8Aig != NULL ) - { - if ( fBlif ) - { - pTemp2 = Ntl_ManInsertAig( pAbc->pAbc8Ntl, pAbc->pAbc8Aig ); - if ( pTemp2 == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Write(): Inserting AIG has failed.\n" ); - return 1; - } - Ntl_ManWriteBlif( pTemp2, pFileName ); - Ntl_ManFree( pTemp2 ); - } - else - Ioa_WriteAiger( pAbc->pAbc8Aig, pFileName, 0, 0 ); - } - else - { - Abc_Print( -1, "There is no AIG to write.\n" ); - return 1; - } - } } - else + + // get the input file name + FileName = pArgvNew[0]; + // fix the wrong symbol + for ( pTemp = FileName; *pTemp; pTemp++ ) + if ( *pTemp == '>' ) + *pTemp = '\\'; + if ( (pFile = fopen( FileName, "r" )) == NULL ) { - if ( pAbc->pAbc8Nwk != NULL ) - { - pTemp2 = Ntl_ManInsertNtk( pAbc->pAbc8Ntl, pAbc->pAbc8Nwk ); - if ( pTemp2 == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Write(): Inserting mapped network has failed.\n" ); - return 1; - } - Ntl_ManWriteBlif( pTemp2, pFileName ); - Ntl_ManFree( pTemp2 ); - } - else - { - Abc_Print( -1, "Writing the unmapped netlist.\n" ); - pTemp2 = pAbc->pAbc8Ntl; - Ntl_ManWriteBlif( pTemp2, pFileName ); - } + Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); + if ( (FileName = Extra_FileGetSimilarName( FileName, ".blif", NULL, NULL, NULL, NULL )) ) + Abc_Print( 1, "Did you mean \"%s\"?", FileName ); + Abc_Print( 1, "\n" ); + return 1; } + fclose( pFile ); + + pAig = Abc_NtkHieCecTest( FileName, fVerbose ); + Abc_CommandUpdate9( pAbc, pAig ); return 0; usage: - Abc_Print( -2, "usage: *w [-abch]\n" ); - Abc_Print( -2, "\t write the design with whiteboxes\n" ); - Abc_Print( -2, "\t-a : toggle writing design or internal AIG [default = %s]\n", fAig? "AIG": "design" ); - Abc_Print( -2, "\t-b : toggle writing AIG as BLIF or AIGER [default = %s]\n", fBlif? "BLIF": "AIGER" ); - Abc_Print( -2, "\t-c : toggle writing collapsed sequential AIG [default = %s]\n", fCollapsed? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "usage: &read_blif [-vh] \n" ); + Abc_Print( -2, "\t reads the current AIG from a hierarchical BLIF file\n" ); + Abc_Print( -2, "\t-v : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : the file name\n"); return 1; } @@ -21600,3042 +21395,63 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandAbc8WriteLogic( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandAbc9ReadCBlif( Abc_Frame_t * pAbc, int argc, char ** argv ) { - Vec_Ptr_t * vCiNames = NULL, * vCoNames = NULL; - char * pFileName; - int fAig; - int c; - - // set defaults - fAig = 0; + extern Gia_Man_t * Abc_NtkHieCecTest2( char * pFileName, char * pModelName, int fVerbose ); + Gia_Man_t * pAig; + FILE * pFile; + char ** pArgvNew; + char * FileName, * pTemp; + char * pModelName = NULL; + int nArgcNew; + int c, fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ah" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Mvh" ) ) != EOF ) { switch ( c ) { - case 'a': - fAig ^= 1; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by a file name.\n" ); + goto usage; + } + pModelName = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'v': + fVerbose ^= 1; break; - case 'h': - goto usage; default: goto usage; } } - if ( pAbc->pAbc8Ntl == NULL ) + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew != 1 ) { - Abc_Print( -1, "Abc_CommandAbc8Write(): There is no design to write.\n" ); + Abc_Print( -1, "There is no file name.\n" ); return 1; } - // create the design to write - pFileName = argv[globalUtilOptind]; -// vCiNames = Ntl_ManCollectCiNames( pAbc->pAbc8Ntl ); -// vCoNames = Ntl_ManCollectCoNames( pAbc->pAbc8Ntl ); - // the problem is duplicated CO names... - if ( fAig ) - { - if ( pAbc->pAbc8Aig != NULL ) - Aig_ManDumpBlif( pAbc->pAbc8Aig, pFileName, vCiNames, vCoNames ); - else - { - Abc_Print( -1, "There is no AIG to write.\n" ); - return 1; - } - } - else + + // get the input file name + FileName = pArgvNew[0]; + // fix the wrong symbol + for ( pTemp = FileName; *pTemp; pTemp++ ) + if ( *pTemp == '>' ) + *pTemp = '\\'; + if ( (pFile = fopen( FileName, "r" )) == NULL ) { - if ( pAbc->pAbc8Nwk != NULL ) - Nwk_ManDumpBlif( pAbc->pAbc8Nwk, pFileName, vCiNames, vCoNames ); - else - { - Abc_Print( -1, "There is no mapped network to write.\n" ); - return 1; - } + Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); + if ( (FileName = Extra_FileGetSimilarName( FileName, ".cblif", NULL, NULL, NULL, NULL )) ) + Abc_Print( 1, "Did you mean \"%s\"?", FileName ); + Abc_Print( 1, "\n" ); + return 1; } - if ( vCiNames ) Vec_PtrFree( vCiNames ); - if ( vCoNames ) Vec_PtrFree( vCoNames ); - return 0; - -usage: - Abc_Print( -2, "usage: *wlogic [-ah]\n" ); - Abc_Print( -2, "\t write the logic part of the design without whiteboxes\n" ); - Abc_Print( -2, "\t-a : toggle writing mapped network or AIG [default = %s]\n", fAig? "AIG": "network" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [Command procedure to read LUT libraries.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc8ReadLut( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - FILE * pFile; - char * FileName; - If_Lib_t * pLib; - int c; - extern If_Lib_t * If_LutLibRead( char * FileName ); - extern void If_LutLibFree( If_Lib_t * pLutLib ); - - // set the defaults - Extra_UtilGetoptReset(); - while ( (c = Extra_UtilGetopt(argc, argv, "h")) != EOF ) - { - switch (c) - { - case 'h': - goto usage; - break; - default: - goto usage; - } - } - - - if ( argc != globalUtilOptind + 1 ) - { - goto usage; - } - - // get the input file name - FileName = argv[globalUtilOptind]; - if ( (pFile = fopen( FileName, "r" )) == NULL ) - { - Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); - if ( (FileName = Extra_FileGetSimilarName( FileName, ".lut", NULL, NULL, NULL, NULL )) ) - Abc_Print( 1, "Did you mean \"%s\"?", FileName ); - Abc_Print( 1, "\n" ); - return 1; - } - fclose( pFile ); - - // set the new network - pLib = If_LutLibRead( FileName ); - if ( pLib == NULL ) - { - Abc_Print( -1, "Reading LUT library has failed.\n" ); - goto usage; - } - // replace the current library - if ( pAbc->pAbc8Lib != NULL ) - If_LutLibFree( pAbc->pAbc8Lib ); - pAbc->pAbc8Lib = pLib; - return 0; - -usage: - Abc_Print( -2, "\nusage: *rlut [-h]\n"); - Abc_Print( -2, "\t read the LUT library from the file\n" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - Abc_Print( -2, "\t \n"); - Abc_Print( -2, "\t File format for a LUT library:\n"); - Abc_Print( -2, "\t (the default library is shown)\n"); - Abc_Print( -2, "\t \n"); - Abc_Print( -2, "\t # The area/delay of k-variable LUTs:\n"); - Abc_Print( -2, "\t # k area delay\n"); - Abc_Print( -2, "\t 1 1 1\n"); - Abc_Print( -2, "\t 2 2 2\n"); - Abc_Print( -2, "\t 3 4 3\n"); - Abc_Print( -2, "\t 4 8 4\n"); - Abc_Print( -2, "\t 5 16 5\n"); - Abc_Print( -2, "\t 6 32 6\n"); - return 1; /* error exit */ -} - -/**Function************************************************************* - - Synopsis [Command procedure to read LUT libraries.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc8PrintLut( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - int c; - extern void If_LutLibPrint( If_Lib_t * pLutLib ); - - // set the defaults - Extra_UtilGetoptReset(); - while ( (c = Extra_UtilGetopt(argc, argv, "h")) != EOF ) - { - switch (c) - { - case 'h': - goto usage; - break; - default: - goto usage; - } - } - - if ( argc != globalUtilOptind ) - { - goto usage; - } - - // set the new network - if ( pAbc->pAbc8Lib == NULL ) - Abc_Print( -1, "Abc_CommandAbc8PrintLut(): LUT library is not specified.\n" ); - else - If_LutLibPrint( (If_Lib_t *)pAbc->pAbc8Lib ); - return 0; - -usage: - Abc_Print( -2, "\nusage: *plut [-h]\n"); - Abc_Print( -2, "\t print the current LUT library\n" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - return 1; /* error exit */ -} - -/**Function************************************************************* - - Synopsis [Command procedure to read LUT libraries.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc8Check( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - int c; - - // set the defaults - Extra_UtilGetoptReset(); - while ( (c = Extra_UtilGetopt(argc, argv, "h")) != EOF ) - { - switch (c) - { - case 'h': - goto usage; - break; - default: - goto usage; - } - } - - if ( argc != globalUtilOptind ) - { - goto usage; - } - - // set the new network - if ( pAbc->pAbc8Nwk == NULL ) - Abc_Print( -1, "Abc_CommandAbc8Check(): There is no mapped network.\n" ); - else - Nwk_ManCheck( pAbc->pAbc8Nwk ); - return 0; - -usage: - Abc_Print( -2, "\nusage: *check [-h]\n"); - Abc_Print( -2, "\t checks if the current mapped network has duplicated fanins\n" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - return 1; /* error exit */ -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc8Ps( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - int c; - int fSaveBest; - int fDumpResult; - int fPower; - int fShort; - extern If_Lib_t * If_SetSimpleLutLib( int nLutSize ); - - // set defaults - fSaveBest = 0; - fDumpResult = 0; - fPower = 0; - fShort = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "bdpsh" ) ) != EOF ) - { - switch ( c ) - { - case 'b': - fSaveBest ^= 1; - break; - case 'd': - fDumpResult ^= 1; - break; - case 'p': - fPower ^= 1; - break; - case 's': - fShort ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pAbc->pAbc8Ntl == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Ps(): There is no design to show.\n" ); - return 1; - } - - if ( fShort ) - { - Nwk_ManPrintStatsShort( pAbc->pAbc8Ntl, pAbc->pAbc8Aig, pAbc->pAbc8Nwk ); - return 0; - } - // get the input file name - if ( pAbc->pAbc8Ntl ) - { - Abc_Print( -1, "NETLIST: " ); - Ntl_ManPrintStats( pAbc->pAbc8Ntl ); - } - if ( pAbc->pAbc8Aig ) - { - Abc_Print( -1, "AIG: " ); - Aig_ManPrintStats( pAbc->pAbc8Aig ); - } - if ( pAbc->pAbc8Nwk ) - { - if ( pAbc->pAbc8Lib == NULL ) - { - Abc_Print( -1, "LUT library is not given. Using default LUT library.\n" ); - pAbc->pAbc8Lib = If_SetSimpleLutLib( 6 ); - } - Abc_Print( -1, "MAPPED: " ); - Nwk_ManPrintStats( pAbc->pAbc8Nwk, pAbc->pAbc8Lib, fSaveBest, fDumpResult, fPower, pAbc->pAbc8Ntl ); - } - return 0; - -usage: - Abc_Print( -2, "usage: *ps [-bdpsh]\n" ); - Abc_Print( -2, "\t prints design statistics\n" ); - Abc_Print( -2, "\t-b : toggles saving the best logic network in \"best.blif\" [default = %s]\n", fSaveBest? "yes": "no" ); - Abc_Print( -2, "\t-d : toggles dumping network into file \"_dump.blif\" [default = %s]\n", fDumpResult? "yes": "no" ); - Abc_Print( -2, "\t-p : toggles printing power dissipation due to switching [default = %s]\n", fPower? "yes": "no" ); - Abc_Print( -2, "\t-s : toggles short printing mode [default = %s]\n", fShort? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc8Pfan( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - int c; - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pAbc->pAbc8Nwk == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Pfan(): There is no mapped network for print fanin/fanout.\n" ); - return 1; - } - Nwk_ManPrintFanioNew( pAbc->pAbc8Nwk ); - return 0; - -usage: - Abc_Print( -2, "usage: *pfan [-h]\n" ); - Abc_Print( -2, "\t prints fanin/fanout stats of the mapped network\n" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc8If( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - char Buffer[200]; - char LutSize[200]; - If_Par_t Pars, * pPars = &Pars; - Nwk_Man_t * pNtkNew; - int c; - - if ( pAbc->pAbc8Lib == NULL ) - { -// Abc_Print( -1, "LUT library is not given. Using default LUT library.\n" ); - pAbc->pAbc8Lib = If_SetSimpleLutLib( 6 ); - } - - // set defaults - Nwk_ManSetIfParsDefault( pPars ); - pPars->pLutLib = pAbc->pAbc8Lib; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KCFADEqaflepmrsdbvh" ) ) != EOF ) - { - switch ( c ) - { - case 'K': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "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 ) - { - Abc_Print( -1, "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 ) - { - Abc_Print( -1, "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 ) - { - Abc_Print( -1, "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 ) - { - Abc_Print( -1, "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 'E': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-E\" should be followed by a floating point number.\n" ); - goto usage; - } - pPars->Epsilon = (float)atof(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->Epsilon < 0.0 || pPars->Epsilon > 1.0 ) - goto usage; - break; - case 'q': - 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 'p': - pPars->fPower ^= 1; - break; - case 'm': - pPars->fCutMin ^= 1; - break; - case 's': - pPars->fSeqMap ^= 1; - break; - case 'd': - pPars->fBidec ^= 1; - break; - case 'b': - pPars->fUseBat ^= 1; - break; - case 'v': - pPars->fVerbose ^= 1; - break; - case 'h': - default: - goto usage; - } - } - if ( pAbc->pAbc8Aig == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8If(): There is no AIG to map.\n" ); - return 1; - } - - if ( pPars->nLutSize < 3 || pPars->nLutSize > IF_MAX_LUTSIZE ) - { - Abc_Print( -1, "Incorrect LUT size (%d).\n", pPars->nLutSize ); - return 1; - } - - if ( pPars->nCutsMax < 1 || pPars->nCutsMax >= (1<<12) ) - { - Abc_Print( -1, "Incorrect number of cuts.\n" ); - return 1; - } - - // enable truth table computation if choices are selected - if ( (c = Aig_ManChoiceNum( pAbc->pAbc8Aig )) ) - { -// Abc_Print( 0, "Performing LUT mapping with %d choices.\n", c ); - pPars->fExpRed = 0; - } - - if ( pPars->fUseBat ) - { - if ( pPars->nLutSize < 4 || pPars->nLutSize > 6 ) - { - Abc_Print( -1, "This feature only works for {4,5,6}-LUTs.\n" ); - return 1; - } - pPars->fCutMin = 1; - } - - // enable truth table computation if cut minimization is selected - if ( pPars->fCutMin ) - { - pPars->fTruth = 1; - pPars->fExpRed = 0; - } - - // complain if truth tables are requested but the cut size is too large - if ( pPars->fTruth && pPars->nLutSize > IF_MAX_FUNC_LUTSIZE ) - { - Abc_Print( -1, "Truth tables cannot be computed for LUT larger than %d inputs.\n", IF_MAX_FUNC_LUTSIZE ); - return 1; - } - - pNtkNew = Nwk_MappingIf( pAbc->pAbc8Aig, Ntl_ManReadTimeMan(pAbc->pAbc8Ntl), pPars ); - if ( pNtkNew == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8If(): Mapping of the AIG has failed.\n" ); - return 1; - } - if ( pAbc->pAbc8Nwk != NULL ) - Nwk_ManFree( pAbc->pAbc8Nwk ); - pAbc->pAbc8Nwk = pNtkNew; - 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 ); - Abc_Print( -2, "usage: *if [-KCFA num] [-DE float] [-qarlepmdbvh]\n" ); - Abc_Print( -2, "\t performs FPGA technology mapping of the network\n" ); - Abc_Print( -2, "\t-K num : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize ); - Abc_Print( -2, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax ); - Abc_Print( -2, "\t-F num : the number of area flow recovery iterations (num >= 0) [default = %d]\n", pPars->nFlowIters ); - Abc_Print( -2, "\t-A num : the number of exact area recovery iterations (num >= 0) [default = %d]\n", pPars->nAreaIters ); - Abc_Print( -2, "\t-D float : sets the delay constraint for the mapping [default = %s]\n", Buffer ); - Abc_Print( -2, "\t-E float : sets epsilon used for tie-breaking [default = %f]\n", pPars->Epsilon ); - Abc_Print( -2, "\t-q : toggles preprocessing using several starting points [default = %s]\n", pPars->fPreprocess? "yes": "no" ); - Abc_Print( -2, "\t-a : toggles area-oriented mapping [default = %s]\n", pPars->fArea? "yes": "no" ); -// Abc_Print( -2, "\t-f : toggles one fancy feature [default = %s]\n", pPars->fFancy? "yes": "no" ); - Abc_Print( -2, "\t-r : enables expansion/reduction of the best cuts [default = %s]\n", pPars->fExpRed? "yes": "no" ); - Abc_Print( -2, "\t-l : optimizes latch paths for delay, other paths for area [default = %s]\n", pPars->fLatchPaths? "yes": "no" ); - Abc_Print( -2, "\t-e : uses edge-based cut selection heuristics [default = %s]\n", pPars->fEdge? "yes": "no" ); - Abc_Print( -2, "\t-p : uses power-aware cut selection heuristics [default = %s]\n", pPars->fPower? "yes": "no" ); - Abc_Print( -2, "\t-m : enables cut minimization by removing vacuous variables [default = %s]\n", pPars->fCutMin? "yes": "no" ); -// Abc_Print( -2, "\t-s : toggles sequential mapping [default = %s]\n", pPars->fSeqMap? "yes": "no" ); - Abc_Print( -2, "\t-d : toggles deriving local AIGs using bi-decomposition [default = %s]\n", pPars->fBidec? "yes": "no" ); - Abc_Print( -2, "\t-b : toggles the use of one special feature [default = %s]\n", pPars->fUseBat? "yes": "no" ); - Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : prints the command usage\n"); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc8DChoice( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Aig_Man_t * pAigNew; - int fBalance, fVerbose, fUpdateLevel, fConstruct, c; - int nConfMax, nLevelMax; - extern Aig_Man_t * Ntl_ManPerformChoicing( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fConstruct, int nConfMax, int nLevelMax, int fVerbose ); - - // set defaults - fBalance = 1; - fUpdateLevel = 1; - fConstruct = 0; - nConfMax = 1000; - nLevelMax = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "CLblcvh" ) ) != EOF ) - { - switch ( c ) - { - case 'C': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "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 'L': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); - goto usage; - } - nLevelMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nLevelMax < 0 ) - goto usage; - break; - case 'b': - fBalance ^= 1; - break; - case 'l': - fUpdateLevel ^= 1; - break; - case 'c': - fConstruct ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pAbc->pAbc8Aig == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8DChoice(): There is no AIG to synthesize.\n" ); - return 1; - } - - // get the input file name - pAigNew = Ntl_ManPerformChoicing( pAbc->pAbc8Aig, fBalance, fUpdateLevel, fConstruct, nConfMax, nLevelMax, fVerbose ); - if ( pAigNew == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8DChoice(): Tranformation has failed.\n" ); - return 1; - } - Aig_ManStop( pAbc->pAbc8Aig ); - pAbc->pAbc8Aig = pAigNew; - return 0; - -usage: - Abc_Print( -2, "usage: *dchoice [-C num] [-L num] [-blcvh]\n" ); - Abc_Print( -2, "\t performs AIG-based synthesis and derives choices\n" ); - Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", nConfMax ); - Abc_Print( -2, "\t-L num : the max level of nodes to consider (0 = not used) [default = %d]\n", nLevelMax ); - Abc_Print( -2, "\t-b : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" ); - Abc_Print( -2, "\t-l : toggle updating level [default = %s]\n", fUpdateLevel? "yes": "no" ); - Abc_Print( -2, "\t-c : toggle constructive computation of choices [default = %s]\n", fConstruct? "yes": "no" ); - Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc8Dch( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Dch_Pars_t Pars, * pPars = &Pars; - Aig_Man_t * pAigNew; - int c; - extern Aig_Man_t * Ntl_ManPerformChoicingNew( Aig_Man_t * pAig, Dch_Pars_t * pPars ); - - // set defaults - Dch_ManSetDefaultParams( pPars ); - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "WCSsptfvh" ) ) != EOF ) - { - switch ( c ) - { - case 'W': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nWords = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nWords < 0 ) - goto usage; - break; - case 'C': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nBTLimit = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nBTLimit < 0 ) - goto usage; - break; - case 'S': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nSatVarMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nSatVarMax < 0 ) - goto usage; - break; - case 's': - pPars->fSynthesis ^= 1; - break; - case 'p': - pPars->fPower ^= 1; - break; - case 't': - pPars->fSimulateTfo ^= 1; - break; - case 'f': - pPars->fLightSynth ^= 1; - break; - case 'v': - pPars->fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pAbc->pAbc8Aig == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Dch(): There is no AIG to synthesize.\n" ); - return 1; - } - - // get the input file name - pAigNew = Ntl_ManPerformChoicingNew( pAbc->pAbc8Aig, pPars ); - if ( pAigNew == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Dch(): Tranformation has failed.\n" ); - return 1; - } -// Aig_ManStop( pAbc->pAbc8Aig ); - pAbc->pAbc8Aig = pAigNew; - return 0; - -usage: - Abc_Print( -2, "usage: *dch [-WCS num] [-sptfvh]\n" ); - Abc_Print( -2, "\t computes structural choices using a new approach\n" ); - Abc_Print( -2, "\t-W num : the max number of simulation words [default = %d]\n", pPars->nWords ); - Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); - Abc_Print( -2, "\t-S num : the max number of SAT variables [default = %d]\n", pPars->nSatVarMax ); - Abc_Print( -2, "\t-s : toggle synthesizing three snapshots [default = %s]\n", pPars->fSynthesis? "yes": "no" ); - Abc_Print( -2, "\t-p : toggle power-aware rewriting [default = %s]\n", pPars->fPower? "yes": "no" ); - Abc_Print( -2, "\t-t : toggle simulation of the TFO classes [default = %s]\n", pPars->fSimulateTfo? "yes": "no" ); - Abc_Print( -2, "\t-f : toggle using lighter logic synthesis [default = %s]\n", pPars->fLightSynth? "yes": "no" ); - Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc8Dc2( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Aig_Man_t * pAigNew; - int c; - int fBalance; - int fUpdateLevel; - int fVerbose; - int fPower; - - extern Aig_Man_t * Dar_ManCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fFanout, int fPower, int fVerbose ); - - // set defaults - fBalance = 1; - fUpdateLevel = 1; - fPower = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "blpvh" ) ) != EOF ) - { - switch ( c ) - { - case 'b': - fBalance ^= 1; - break; - case 'l': - fUpdateLevel ^= 1; - break; - case 'p': - fPower ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pAbc->pAbc8Aig == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Dc2(): There is no AIG to synthesize.\n" ); - return 1; - } - - // get the input file name - pAigNew = Dar_ManCompress2( pAbc->pAbc8Aig, fBalance, fUpdateLevel, 1, fPower, fVerbose ); - if ( pAigNew == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Dc2(): Tranformation has failed.\n" ); - return 1; - } - Aig_ManStop( pAbc->pAbc8Aig ); - pAbc->pAbc8Aig = pAigNew; - return 0; - -usage: - Abc_Print( -2, "usage: *dc2 [-blpvh]\n" ); - Abc_Print( -2, "\t performs AIG-based synthesis without deriving choices\n" ); - Abc_Print( -2, "\t-b : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" ); - Abc_Print( -2, "\t-l : toggle updating level [default = %s]\n", fUpdateLevel? "yes": "no" ); - Abc_Print( -2, "\t-p : toggle power-aware rewriting [default = %s]\n", fPower? "yes": "no" ); - Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc8Bidec( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - int c; - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pAbc->pAbc8Nwk == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Bidec(): There is no mapped network to strash.\n" ); - return 1; - } - Nwk_ManBidecResyn( pAbc->pAbc8Nwk, 0 ); - return 0; - -usage: - Abc_Print( -2, "usage: *bidec [-h]\n" ); - Abc_Print( -2, "\t performs bi-decomposition of local functions\n" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc8Strash( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Aig_Man_t * pAigNew; - int c; - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pAbc->pAbc8Nwk == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Strash(): There is no mapped network to strash.\n" ); - return 1; - } - - pAigNew = Nwk_ManStrash( pAbc->pAbc8Nwk ); - if ( pAigNew == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Strash(): Tranformation has failed.\n" ); - return 1; - } - Aig_ManStop( pAbc->pAbc8Aig ); - pAbc->pAbc8Aig = pAigNew; - return 0; - -usage: - Abc_Print( -2, "usage: *st [-h]\n" ); - Abc_Print( -2, "\t performs structural hashing of mapped network\n" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc8Mfs( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Mfx_Par_t Pars, * pPars = &Pars; - int c; -// extern int Mfx_Perform( void * pNtk, Mfx_Par_t * pPars, If_Lib_t * pLutLib ); - - // set defaults - Mfx_ParsDefault( pPars ); - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "WFDMLCraespvwh" ) ) != EOF ) - { - switch ( c ) - { - case 'W': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nWinTfoLevs = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nWinTfoLevs < 0 ) - goto usage; - break; - case 'F': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nFanoutsMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nFanoutsMax < 1 ) - goto usage; - break; - case 'D': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nDepthMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nDepthMax < 0 ) - goto usage; - break; - case 'M': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nWinSizeMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nWinSizeMax < 0 ) - goto usage; - break; - case 'L': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "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 'C': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nBTLimit = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nBTLimit < 0 ) - goto usage; - break; - case 'r': - pPars->fResub ^= 1; - break; - case 'a': - pPars->fArea ^= 1; - break; - case 'e': - pPars->fMoreEffort ^= 1; - break; - case 's': - pPars->fSwapEdge ^= 1; - break; - case 'p': - pPars->fPower ^= 1; - break; - case 'v': - pPars->fVerbose ^= 1; - break; - case 'w': - pPars->fVeryVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pAbc->pAbc8Nwk == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Mfs(): There is no mapped network.\n" ); - return 1; - } - if ( pAbc->pAbc8Lib == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Mfs(): There is no LUT library.\n" ); - return 1; - } - if ( If_LutLibDelaysAreDifferent(pAbc->pAbc8Lib) ) - { - Abc_Print( -1, "Abc_CommandAbc8Mfs(): Cannot perform don't-care simplication with variable-pin-delay LUT model.\n" ); - Abc_Print( -1, "The delay model should be fixed-pin-delay, for example, the delay of all pins of all LUTs is 0.4.\n" ); - return 1; - } - - - // modify the current network - if ( !Mfx_Perform( pAbc->pAbc8Nwk, pPars, pAbc->pAbc8Lib ) ) - { - Abc_Print( -1, "Abc_CommandAbc8Mfs(): Command has failed.\n" ); - return 1; - } - return 0; - -usage: - Abc_Print( -2, "usage: *mfs [-WFDMLC num] [-raespvh]\n" ); - Abc_Print( -2, "\t performs don't-care-based optimization of logic networks\n" ); - Abc_Print( -2, "\t-W : the number of levels in the TFO cone (0 <= num) [default = %d]\n", pPars->nWinTfoLevs ); - Abc_Print( -2, "\t-F : the max number of fanouts to skip (1 <= num) [default = %d]\n", pPars->nFanoutsMax ); - Abc_Print( -2, "\t-D : the max depth nodes to try (0 = no limit) [default = %d]\n", pPars->nDepthMax ); - Abc_Print( -2, "\t-M : the max node count of windows to consider (0 = no limit) [default = %d]\n", pPars->nWinSizeMax ); - Abc_Print( -2, "\t-L : the max increase in node level after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel ); - Abc_Print( -2, "\t-C : the max number of conflicts in one SAT run (0 = no limit) [default = %d]\n", pPars->nBTLimit ); - Abc_Print( -2, "\t-r : toggle resubstitution and dc-minimization [default = %s]\n", pPars->fResub? "resub": "dc-min" ); - Abc_Print( -2, "\t-a : toggle minimizing area or area+edges [default = %s]\n", pPars->fArea? "area": "area+edges" ); - Abc_Print( -2, "\t-e : toggle high-effort resubstitution [default = %s]\n", pPars->fMoreEffort? "yes": "no" ); - Abc_Print( -2, "\t-s : toggle evaluation of edge swapping [default = %s]\n", pPars->fSwapEdge? "yes": "no" ); - Abc_Print( -2, "\t-p : toggle power-aware optimization [default = %s]\n", pPars->fPower? "yes": "no" ); - Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", pPars->fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-w : toggle printing detailed stats for each node [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc8Lutpack( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - int c; - - Abc_Print( -1, "This command is temporarily disabled.\n" ); - return 0; - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pAbc->pAbc8Nwk == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Lutpack(): There is no mapped network to strash.\n" ); - return 1; - } - - - return 0; -usage: -/* - Abc_Print( -2, "usage: *lp [-h]\n" ); - Abc_Print( -2, "usage: lutpack [-N ] [-Q ] [-S ] [-L ] [-szfovwh]\n" ); - Abc_Print( -2, "\t performs \"rewriting\" for LUT network;\n" ); - Abc_Print( -2, "\t determines LUT size as the max fanin count of a node;\n" ); - Abc_Print( -2, "\t if the network is not LUT-mapped, packs it into 6-LUTs\n" ); - Abc_Print( -2, "\t (there is another command for resynthesis after LUT mapping, \"imfs\")\n" ); - Abc_Print( -2, "\t-N : the max number of LUTs in the structure (2 <= num) [default = %d]\n", pPars->nLutsMax ); - Abc_Print( -2, "\t-Q : the max number of LUTs not in MFFC (0 <= num) [default = %d]\n", pPars->nLutsOver ); - Abc_Print( -2, "\t-S : the max number of LUT inputs shared (0 <= num <= 3) [default = %d]\n", pPars->nVarsShared ); - Abc_Print( -2, "\t-L : max level increase after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel ); - Abc_Print( -2, "\t-s : toggle iteration till saturation [default = %s]\n", pPars->fSatur? "yes": "no" ); - Abc_Print( -2, "\t-z : toggle zero-cost replacements [default = %s]\n", pPars->fZeroCost? "yes": "no" ); - Abc_Print( -2, "\t-f : toggle using only first node and first cut [default = %s]\n", pPars->fFirst? "yes": "no" ); - Abc_Print( -2, "\t-o : toggle using old implementation [default = %s]\n", pPars->fOldAlgo? "yes": "no" ); - Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-w : toggle detailed printout of decomposed functions [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); -*/ - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc8Balance( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Aig_Man_t * pAigNew; - int c; - int fExor; - int fUpdateLevel; - int fVerbose; - extern Aig_Man_t * Dar_ManBalanceXor( Aig_Man_t * pAig, int fExor, int fUpdateLevel, int fVerbose ); - - // set defaults - fExor = 0; - fUpdateLevel = 1; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "xlh" ) ) != EOF ) - { - switch ( c ) - { - case 'x': - fExor ^= 1; - break; - case 'l': - fUpdateLevel ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pAbc->pAbc8Aig == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Balance(): There is no AIG to synthesize.\n" ); - return 1; - } - - // get the input file name - pAigNew = Dar_ManBalanceXor( pAbc->pAbc8Aig, fExor, fUpdateLevel, fVerbose ); - if ( pAigNew == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Balance(): Tranformation has failed.\n" ); - return 1; - } - Aig_ManStop( pAbc->pAbc8Aig ); - pAbc->pAbc8Aig = pAigNew; - return 0; - -usage: - Abc_Print( -2, "usage: *b [-xlvh]\n" ); - Abc_Print( -2, "\t performs balancing of the AIG\n" ); - Abc_Print( -2, "\t-x : toggle using XOR-balancing [default = %s]\n", fExor? "yes": "no" ); - Abc_Print( -2, "\t-l : toggle updating level [default = %s]\n", fUpdateLevel? "yes": "no" ); - Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc8Speedup( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Aig_Man_t * pAigNew; - int c; - int fUseLutLib = 0; - int Percentage = 100; - int Degree = 5; - int fVerbose = 0; - int fVeryVerbose = 0; - - // set defaults - fUseLutLib = 0; - Percentage = 5; - Degree = 2; - fVerbose = 0; - fVeryVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "PNlvwh" ) ) != EOF ) - { - switch ( c ) - { - case 'P': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); - goto usage; - } - Percentage = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( Percentage < 1 || Percentage > 100 ) - goto usage; - break; - case 'N': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); - goto usage; - } - Degree = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( Degree < 1 || Degree > 5 ) - goto usage; - break; - case 'l': - fUseLutLib ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'w': - fVeryVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pAbc->pAbc8Nwk == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Speedup(): There is no mapped network to strash.\n" ); - return 1; - } - - pAigNew = Nwk_ManSpeedup( pAbc->pAbc8Nwk, fUseLutLib, Percentage, Degree, fVerbose, fVeryVerbose ); - if ( pAigNew == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Speedup(): Tranformation has failed.\n" ); - return 1; - } - Aig_ManStop( pAbc->pAbc8Aig ); - pAbc->pAbc8Aig = pAigNew; - return 0; - -usage: - Abc_Print( -2, "usage: *speedup [-P num] [-N num] [-lvwh]\n" ); - Abc_Print( -2, "\t transforms LUT-mapped network into an AIG with choices;\n" ); - Abc_Print( -2, "\t the choices are added to speedup the next round of mapping\n" ); - Abc_Print( -2, "\t-P : delay delta defining critical path for library model [default = %d%%]\n", Percentage ); - Abc_Print( -2, "\t-N : the max critical path degree for resynthesis (0 < num < 6) [default = %d]\n", Degree ); - Abc_Print( -2, "\t-l : toggle using unit- or LUT-library-delay model [default = %s]\n", fUseLutLib? "lib" : "unit" ); - Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-w : toggle printing detailed stats for each node [default = %s]\n", fVeryVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc8Merge( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Nwk_LMPars_t Pars, * pPars = &Pars; - Vec_Int_t * vResult; - int c; - - // set defaults - memset( pPars, 0, sizeof(Nwk_LMPars_t) ); - pPars->nMaxLutSize = 5; // the max LUT size for merging (N=5) - pPars->nMaxSuppSize = 5; // the max total support size after merging (S=5) - pPars->nMaxDistance = 3; // the max number of nodes separating LUTs - pPars->nMaxLevelDiff = 2; // the max difference in levels - pPars->nMaxFanout = 100; // the max number of fanouts to traverse - pPars->fUseDiffSupp = 0; // enables the use of nodes with different support - pPars->fUseTfiTfo = 0; // enables the use of TFO/TFO nodes as candidates - pPars->fVeryVerbose = 0; // enables additional verbose output - pPars->fVerbose = 1; // enables verbose output - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "NSDLFscvwh" ) ) != EOF ) - { - switch ( c ) - { - case 'N': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nMaxLutSize = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nMaxLutSize < 2 ) - goto usage; - break; - case 'S': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nMaxSuppSize = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nMaxSuppSize < 2 ) - goto usage; - break; - case 'D': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nMaxDistance = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nMaxDistance < 2 ) - goto usage; - break; - case 'L': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nMaxLevelDiff = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nMaxLevelDiff < 2 ) - goto usage; - break; - case 'F': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nMaxFanout = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nMaxFanout < 2 ) - goto usage; - break; - case 's': - pPars->fUseDiffSupp ^= 1; - break; - case 'c': - pPars->fUseTfiTfo ^= 1; - break; - case 'w': - pPars->fVeryVerbose ^= 1; - break; - case 'v': - pPars->fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pAbc->pAbc8Nwk == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Speedup(): There is no mapped network to merge LUTs.\n" ); - return 1; - } - - vResult = Nwk_ManLutMerge( pAbc->pAbc8Nwk, pPars ); - Vec_IntFree( vResult ); - return 0; - -usage: - Abc_Print( -2, "usage: *merge [-NSDLF num] [-scwvh]\n" ); - Abc_Print( -2, "\t creates pairs of topologically-related LUTs\n" ); - Abc_Print( -2, "\t-N : the max LUT size for merging (1 < num) [default = %d]\n", pPars->nMaxLutSize ); - Abc_Print( -2, "\t-S : the max total support size after merging (1 < num) [default = %d]\n", pPars->nMaxSuppSize ); - Abc_Print( -2, "\t-D : the max distance in terms of LUTs (0 < num) [default = %d]\n", pPars->nMaxDistance ); - Abc_Print( -2, "\t-L : the max difference in levels (0 <= num) [default = %d]\n", pPars->nMaxLevelDiff ); - Abc_Print( -2, "\t-F : the max number of fanouts to stop traversal (0 < num) [default = %d]\n", pPars->nMaxFanout ); - Abc_Print( -2, "\t-s : toggle the use of nodes without support overlap [default = %s]\n", pPars->fUseDiffSupp? "yes" : "no" ); - Abc_Print( -2, "\t-c : toggle the use of TFI/TFO nodes as candidates [default = %s]\n", pPars->fUseTfiTfo? "yes" : "no" ); - Abc_Print( -2, "\t-w : toggle printing detailed stats for each node [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); - Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", pPars->fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc8Insert( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Ntl_Man_t * pNtlNew; - int c; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pAbc->pAbc8Ntl == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Insert(): There is no design.\n" ); - return 1; - } - if ( pAbc->pAbc8Nwk == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Insert(): There is no network to insert.\n" ); - return 1; - } - pNtlNew = Ntl_ManInsertNtk( pAbc->pAbc8Ntl, pAbc->pAbc8Nwk ); - Abc_FrameClearDesign(); - pAbc->pAbc8Ntl = pNtlNew; - return 0; - -usage: - Abc_Print( -2, "usage: *insert [-h]\n" ); - Abc_Print( -2, "\t inserts the mapped network into the netlist\n" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc8ClpLut( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Ntl_Man_t * pNtlNew; - int c; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pAbc->pAbc8Ntl == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Insert(): There is no design.\n" ); - return 1; - } - pNtlNew = Ntl_ManDupCollapseLuts( pAbc->pAbc8Ntl ); - Abc_FrameClearDesign(); - pAbc->pAbc8Ntl = pNtlNew; - pAbc->pAbc8Aig = Ntl_ManExtract( pAbc->pAbc8Ntl ); - return 0; - -usage: - Abc_Print( -2, "usage: *clplut [-h]\n" ); - Abc_Print( -2, "\t collapses comb white boxes whose model name begins with \"LUT\"\n" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - return 1; -} -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc8Fraig( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Ntl_Man_t * pNtlNew, * pNtlOld; - int c, fVerbose; - int nPartSize; - int nConfLimit; - int nLevelMax; - int fUseCSat; - - // set defaults - nPartSize = 0; - nConfLimit = 100; - nLevelMax = 0; - fUseCSat = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "PCLcvh" ) ) != EOF ) - { - switch ( c ) - { - case 'P': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "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': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "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': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); - goto usage; - } - nLevelMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nLevelMax < 0 ) - goto usage; - break; - case 'c': - fUseCSat ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pAbc->pAbc8Ntl == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Fraig(): There is no design to SAT sweep.\n" ); - return 1; - } - - // get the input file name - pNtlOld = pAbc->pAbc8Ntl; pAbc->pAbc8Ntl = NULL; - pNtlNew = Ntl_ManFraig( pNtlOld, nPartSize, nConfLimit, nLevelMax, fUseCSat, fVerbose ); - if ( pNtlNew == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Fraig(): Tranformation has failed.\n" ); - return 1; - } - - Abc_FrameClearDesign(); - pAbc->pAbc8Ntl = pNtlNew; - if ( pAbc->pAbc8Ntl == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Fraig(): Reading BLIF has failed.\n" ); - return 1; - } - pAbc->pAbc8Aig = Ntl_ManExtract( pAbc->pAbc8Ntl ); - if ( pAbc->pAbc8Aig == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Fraig(): AIG extraction has failed.\n" ); - return 1; - } - return 0; - -usage: - Abc_Print( -2, "usage: *fraig [-P num] [-C num] [-L num] [-vh]\n" ); - Abc_Print( -2, "\t applies SAT sweeping to netlist with white-boxes\n" ); - Abc_Print( -2, "\t-P num : partition size (0 = partitioning is not used) [default = %d]\n", nPartSize ); - Abc_Print( -2, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); - Abc_Print( -2, "\t-L num : limit on node level to fraig (0 = fraig all nodes) [default = %d]\n", nLevelMax ); -// Abc_Print( -2, "\t-c : toggle using new AIG package and SAT solver [default = %s]\n", fUseCSat? "yes": "no" ); - Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc8Scl( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Ntl_Man_t * pNtlNew, * pNtlOld; - int c; - int fLatchConst; - int fLatchEqual; - int fVerbose; - - // set defaults - fLatchConst = 1; - fLatchEqual = 1; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "cevh" ) ) != EOF ) - { - switch ( c ) - { - case 'c': - fLatchConst ^= 1; - break; - case 'e': - fLatchEqual ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pAbc->pAbc8Ntl == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Scl(): There is no design to SAT sweep.\n" ); - return 1; - } - - if ( Ntl_ManIsComb(pAbc->pAbc8Ntl) ) - { - Abc_Print( -1, "Abc_CommandAbc8Scl(): The network is combinational.\n" ); - return 0; - } - - // get the input file name - pNtlOld = pAbc->pAbc8Ntl; pAbc->pAbc8Ntl = NULL; - pNtlNew = Ntl_ManScl( pNtlOld, fLatchConst, fLatchEqual, fVerbose ); - if ( pNtlNew == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Scl(): Tranformation has failed.\n" ); - return 1; - } - - Abc_FrameClearDesign(); - pAbc->pAbc8Ntl = pNtlNew; - if ( pAbc->pAbc8Ntl == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Scl(): Reading BLIF has failed.\n" ); - return 1; - } - pAbc->pAbc8Aig = Ntl_ManExtract( pAbc->pAbc8Ntl ); - if ( pAbc->pAbc8Aig == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Scl(): AIG extraction has failed.\n" ); - return 1; - } - return 0; - -usage: - Abc_Print( -2, "usage: *scl [-cevh]\n" ); - Abc_Print( -2, "\t performs sequential cleanup of the netlist\n" ); - Abc_Print( -2, "\t by removing nodes and latches that do not feed into POs\n" ); - Abc_Print( -2, "\t-c : sweep stuck-at latches detected by ternary simulation [default = %s]\n", fLatchConst? "yes": "no" ); - Abc_Print( -2, "\t-e : merge equal latches (same data inputs and init states) [default = %s]\n", fLatchEqual? "yes": "no" ); - Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc8Lcorr( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Ntl_Man_t * pNtlNew, * pNtlOld; - int c; - int fScorrGia; - int fUseCSat; - int nFramesP; - int nConfMax; - int fVerbose; - - // set defaults - fScorrGia = 0; - fUseCSat = 0; - nFramesP = 0; - nConfMax = 10000; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "PCncvh" ) ) != EOF ) - { - switch ( c ) - { - case 'P': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "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 ) - { - Abc_Print( -1, "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 'n': - fScorrGia ^= 1; - break; - case 'c': - fUseCSat ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pAbc->pAbc8Ntl == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Lcorr(): There is no design to SAT sweep.\n" ); - return 1; - } - - if ( Ntl_ManIsComb(pAbc->pAbc8Ntl) ) - { - Abc_Print( -1, "Abc_CommandAbc8Lcorr(): The network is combinational.\n" ); - return 0; - } - - // get the input file name - pNtlOld = pAbc->pAbc8Ntl; pAbc->pAbc8Ntl = NULL; - pNtlNew = Ntl_ManLcorr( pNtlOld, nConfMax, fScorrGia, fUseCSat, fVerbose ); - if ( pNtlNew == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Lcorr(): Tranformation has failed.\n" ); - return 1; - } - - Abc_FrameClearDesign(); - pAbc->pAbc8Ntl = pNtlNew; - if ( pAbc->pAbc8Ntl == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Lcorr(): Reading BLIF has failed.\n" ); - return 1; - } - pAbc->pAbc8Aig = Ntl_ManExtract( pAbc->pAbc8Ntl ); - if ( pAbc->pAbc8Aig == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Lcorr(): AIG extraction has failed.\n" ); - return 1; - } - return 0; - -usage: - Abc_Print( -2, "usage: *lcorr [-C num] [-ncvh]\n" ); - Abc_Print( -2, "\t computes latch correspondence for the netlist\n" ); -// Abc_Print( -2, "\t-P num : number of time frames to use as the prefix [default = %d]\n", nFramesP ); - Abc_Print( -2, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfMax ); - Abc_Print( -2, "\t-n : toggle using new AIG package [default = %s]\n", fScorrGia? "yes": "no" ); - Abc_Print( -2, "\t-c : toggle using new AIG package and SAT solver [default = %s]\n", fUseCSat? "yes": "no" ); - Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc8Ssw( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Ntl_Man_t * pNtlNew, * pNtlOld; - Fra_Ssw_t Pars, * pPars = &Pars; - int c; - - // set defaults - pPars->nPartSize = 0; - pPars->nOverSize = 0; - pPars->nFramesP = 0; - pPars->nFramesK = 1; - pPars->nMaxImps = 5000; - pPars->nMaxLevs = 0; - pPars->nMinDomSize = 100; - pPars->fUseImps = 0; - pPars->fRewrite = 0; - pPars->fFraiging = 0; - pPars->fLatchCorr = 0; - pPars->fWriteImps = 0; - pPars->fUse1Hot = 0; - pPars->fVerbose = 0; - pPars->TimeLimit = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "PQNFILDirfletvh" ) ) != EOF ) - { - switch ( c ) - { - case 'P': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nPartSize = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nPartSize < 2 ) - goto usage; - break; - case 'Q': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-Q\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nOverSize = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nOverSize < 0 ) - goto usage; - break; - case 'N': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nFramesP = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nFramesP < 0 ) - goto usage; - break; - case 'F': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nFramesK = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nFramesK <= 0 ) - goto usage; - break; - case 'I': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nMaxImps = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nMaxImps <= 0 ) - goto usage; - break; - case 'L': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nMaxLevs = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nMaxLevs <= 0 ) - goto usage; - break; - case 'D': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nMinDomSize = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nMinDomSize <= 0 ) - goto usage; - break; - case 'i': - pPars->fUseImps ^= 1; - break; - case 'r': - pPars->fRewrite ^= 1; - break; - case 'f': - pPars->fFraiging ^= 1; - break; - case 'l': - pPars->fLatchCorr ^= 1; - break; - case 'e': - pPars->fWriteImps ^= 1; - break; - case 't': - pPars->fUse1Hot ^= 1; - break; - case 'v': - pPars->fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pAbc->pAbc8Ntl == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Ssw(): There is no design to SAT sweep.\n" ); - return 1; - } - - if ( Ntl_ManIsComb(pAbc->pAbc8Ntl) ) - { - Abc_Print( -1, "The network is combinational.\n" ); - return 0; - } - - if ( pPars->nFramesK > 1 && pPars->fUse1Hot ) - { - Abc_Print( -1, "Currrently can only use one-hotness for simple induction (K=1).\n" ); - return 0; - } - - if ( pPars->nFramesP && pPars->fUse1Hot ) - { - Abc_Print( -1, "Currrently can only use one-hotness without prefix.\n" ); - return 0; - } - - // get the input file name - pNtlOld = pAbc->pAbc8Ntl; pAbc->pAbc8Ntl = NULL; - pNtlNew = Ntl_ManSsw( pNtlOld, pPars ); - if ( pNtlNew == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Ssw(): Tranformation has failed.\n" ); - return 1; - } - - Abc_FrameClearDesign(); - pAbc->pAbc8Ntl = pNtlNew; - if ( pAbc->pAbc8Ntl == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Ssw(): Reading BLIF has failed.\n" ); - return 1; - } - pAbc->pAbc8Aig = Ntl_ManExtract( pAbc->pAbc8Ntl ); - if ( pAbc->pAbc8Aig == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Ssw(): AIG extraction has failed.\n" ); - return 1; - } - return 0; - -usage: - Abc_Print( -2, "usage: *ssw [-PQNFLD num] [-lrfetvh]\n" ); - Abc_Print( -2, "\t performs sequential sweep using K-step induction on the netlist \n" ); - Abc_Print( -2, "\t-P num : max partition size (0 = no partitioning) [default = %d]\n", pPars->nPartSize ); - Abc_Print( -2, "\t-Q num : partition overlap (0 = no overlap) [default = %d]\n", pPars->nOverSize ); - Abc_Print( -2, "\t-N num : number of time frames to use as the prefix [default = %d]\n", pPars->nFramesP ); - Abc_Print( -2, "\t-F num : number of time frames for induction (1=simple) [default = %d]\n", pPars->nFramesK ); - Abc_Print( -2, "\t-L num : max number of levels to consider (0=all) [default = %d]\n", pPars->nMaxLevs ); - Abc_Print( -2, "\t-D num : min size of a clock domain used for synthesis [default = %d]\n", pPars->nMinDomSize ); -// Abc_Print( -2, "\t-I num : max number of implications to consider [default = %d]\n", pPars->nMaxImps ); -// Abc_Print( -2, "\t-i : toggle using implications [default = %s]\n", pPars->fUseImps? "yes": "no" ); - Abc_Print( -2, "\t-l : toggle latch correspondence only [default = %s]\n", pPars->fLatchCorr? "yes": "no" ); - Abc_Print( -2, "\t-r : toggle AIG rewriting [default = %s]\n", pPars->fRewrite? "yes": "no" ); - Abc_Print( -2, "\t-f : toggle fraiging (combinational SAT sweeping) [default = %s]\n", pPars->fFraiging? "yes": "no" ); - Abc_Print( -2, "\t-e : toggle writing implications as assertions [default = %s]\n", pPars->fWriteImps? "yes": "no" ); - Abc_Print( -2, "\t-t : toggle using one-hotness conditions [default = %s]\n", pPars->fUse1Hot? "yes": "no" ); - Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc8Scorr( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Ntl_Man_t * pNtlNew, * pNtlOld; - Ssw_Pars_t Pars, * pPars = &Pars; - int c; - - // set defaults - Ssw_ManSetDefaultParams( pPars ); - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "PQFCLSDVMpldsncvh" ) ) != EOF ) - { - switch ( c ) - { - case 'P': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nPartSize = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nPartSize < 2 ) - goto usage; - break; - case 'Q': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-Q\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nOverSize = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nOverSize < 0 ) - goto usage; - break; - case 'F': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nFramesK = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nFramesK <= 0 ) - goto usage; - break; - case 'C': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nBTLimit = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nBTLimit <= 0 ) - goto usage; - break; - case 'L': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nMaxLevs = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nMaxLevs <= 0 ) - goto usage; - break; - case 'S': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nFramesAddSim = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nFramesAddSim < 0 ) - goto usage; - break; - case 'D': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nMinDomSize = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nMinDomSize < 0 ) - goto usage; - break; - case 'V': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-V\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nSatVarMax2 = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nSatVarMax2 < 0 ) - goto usage; - break; - case 'M': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nRecycleCalls2 = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nRecycleCalls2 < 0 ) - goto usage; - break; - case 'p': - pPars->fPolarFlip ^= 1; - break; - case 'l': - pPars->fLatchCorr ^= 1; - break; - case 'd': - pPars->fDynamic ^= 1; - break; - case 's': - pPars->fLocalSim ^= 1; - break; - case 'n': - pPars->fScorrGia ^= 1; - break; - case 'c': - pPars->fUseCSat ^= 1; - break; - case 'v': - pPars->fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pAbc->pAbc8Ntl == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Ssw(): There is no design to SAT sweep.\n" ); - return 1; - } - - if ( Ntl_ManIsComb(pAbc->pAbc8Ntl) ) - { - Abc_Print( -1, "The network is combinational.\n" ); - return 0; - } - - if ( pPars->fDynamic && (pPars->nPartSize || pPars->nOverSize) ) - { - pPars->nPartSize = 0; - pPars->nOverSize = 0; - Abc_Print( -1, "With dynamic partitioning (-d) enabled, static one (-P -Q ) is ignored.\n" ); - } - - // get the input file name - pNtlOld = pAbc->pAbc8Ntl; pAbc->pAbc8Ntl = NULL; - pNtlNew = Ntl_ManScorr( pNtlOld, pPars ); - if ( pNtlNew == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Scorr(): Tranformation has failed.\n" ); - return 1; - } - - Abc_FrameClearDesign(); - pAbc->pAbc8Ntl = pNtlNew; - if ( pAbc->pAbc8Ntl == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Scorr(): Reading BLIF has failed.\n" ); - return 1; - } - pAbc->pAbc8Aig = Ntl_ManExtract( pAbc->pAbc8Ntl ); - if ( pAbc->pAbc8Aig == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Scorr(): AIG extraction has failed.\n" ); - return 1; - } - return 0; - -usage: - Abc_Print( -2, "usage: *scorr [-PQFCLSDVM num] [-pldsncvh]\n" ); - Abc_Print( -2, "\t performs sequential sweep using K-step induction\n" ); - Abc_Print( -2, "\t-P num : max partition size (0 = no partitioning) [default = %d]\n", pPars->nPartSize ); - Abc_Print( -2, "\t-Q num : partition overlap (0 = no overlap) [default = %d]\n", pPars->nOverSize ); - Abc_Print( -2, "\t-F num : number of time frames for induction (1=simple) [default = %d]\n", pPars->nFramesK ); - Abc_Print( -2, "\t-C num : max number of conflicts at a node (0=inifinite) [default = %d]\n", pPars->nBTLimit ); - Abc_Print( -2, "\t-L num : max number of levels to consider (0=all) [default = %d]\n", pPars->nMaxLevs ); - Abc_Print( -2, "\t-S num : additional simulation frames for c-examples (0=none) [default = %d]\n", pPars->nFramesAddSim ); - Abc_Print( -2, "\t-D num : min size of a clock domain used for synthesis [default = %d]\n", pPars->nMinDomSize ); - Abc_Print( -2, "\t-V num : min var num needed to recycle the SAT solver [default = %d]\n", pPars->nSatVarMax2 ); - Abc_Print( -2, "\t-M num : min call num needed to recycle the SAT solver [default = %d]\n", pPars->nRecycleCalls2 ); - Abc_Print( -2, "\t-p : toggle alighning polarity of SAT variables [default = %s]\n", pPars->fPolarFlip? "yes": "no" ); - Abc_Print( -2, "\t-l : toggle latch correspondence only [default = %s]\n", pPars->fLatchCorr? "yes": "no" ); - Abc_Print( -2, "\t-d : toggle dynamic addition of constraints [default = %s]\n", pPars->fDynamic? "yes": "no" ); - Abc_Print( -2, "\t-s : toggle local simulation in the cone of influence [default = %s]\n", pPars->fLocalSim? "yes": "no" ); - Abc_Print( -2, "\t-n : toggle using new AIG package [default = %s]\n", pPars->fScorrGia? "yes": "no" ); - Abc_Print( -2, "\t-c : toggle using new AIG package and SAT solver [default = %s]\n", pPars->fUseCSat? "yes": "no" ); - Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc8Sweep( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Ntl_Man_t * pNtlTemp; - int Counter; - int fMapped; - int fVerbose; - int c; - - // set defaults - fMapped = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "mvh" ) ) != EOF ) - { - switch ( c ) - { - case 'm': - fMapped ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pAbc->pAbc8Ntl == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Sweep(): There is no design to sweep.\n" ); - return 1; - } - - // if mapped, insert the network - if ( fMapped ) - { - if ( pAbc->pAbc8Nwk == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Sweep(): There is no mapped network to sweep.\n" ); - return 1; - } - pNtlTemp = Ntl_ManInsertNtk( pAbc->pAbc8Ntl, pAbc->pAbc8Nwk ); - if ( pNtlTemp == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Sweep(): Inserting mapped network has failed.\n" ); - return 1; - } - Abc_FrameClearDesign(); - pAbc->pAbc8Ntl = pNtlTemp; - } - - // sweep the current design - Counter = Ntl_ManSweep( pAbc->pAbc8Ntl, fVerbose ); - if ( Counter == 0 && fVerbose ) - Abc_Print( -1, "The netlist is unchanged by sweep.\n" ); - - // if mapped, create new AIG and new mapped network - if ( fMapped ) - { - pAbc->pAbc8Aig = Ntl_ManExtract( pAbc->pAbc8Ntl ); - if ( pAbc->pAbc8Aig == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Sweep(): AIG extraction has failed.\n" ); - return 1; - } - pAbc->pAbc8Nwk = Ntl_ManExtractNwk( pAbc->pAbc8Ntl, pAbc->pAbc8Aig, NULL ); - if ( pAbc->pAbc8Nwk == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Sweep(): Failed to extract the mapped network.\n" ); - return 1; - } - } - else // remove old AIG/mapped and create new AIG - { - pNtlTemp = pAbc->pAbc8Ntl; pAbc->pAbc8Ntl = NULL; - Abc_FrameClearDesign(); - pAbc->pAbc8Ntl = pNtlTemp; - // extract new AIG - pAbc->pAbc8Aig = Ntl_ManExtract( pAbc->pAbc8Ntl ); - if ( pAbc->pAbc8Aig == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Sweep(): AIG extraction has failed.\n" ); - return 1; - } - } - return 0; - -usage: - Abc_Print( -2, "usage: *sw [-mvh]\n" ); - Abc_Print( -2, "\t performs structural sweep of the netlist\n" ); - Abc_Print( -2, "\t removes dangling nodes, registers, and white-boxes\n" ); - Abc_Print( -2, "\t-m : inserts mapped network into netlist and sweeps it [default = %s]\n", fMapped? "yes": "no" ); - Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc8Zero( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Ntl_Man_t * pNtlNew; - int fVerbose; - int c; - - // 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 ( pAbc->pAbc8Ntl == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Zero(): There is no design to convert.\n" ); - return 1; - } - - // transform the registers - pNtlNew = pAbc->pAbc8Ntl; - pAbc->pAbc8Ntl = NULL; - Ntl_ManTransformInitValues( pNtlNew ); - - // replace the design - Abc_FrameClearDesign(); - pAbc->pAbc8Ntl = pNtlNew; - return 0; - -usage: - Abc_Print( -2, "usage: *zero [-h]\n" ); - Abc_Print( -2, "\t converts registers to have constant-0 initial value\n" ); - Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc8Cec( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Aig_Man_t * pAig1, * pAig2; - Ntl_Man_t * pTemp1, * pTemp2; - char ** pArgvNew; - int nArgcNew; - int c; - int fVerbose; - int nConfLimit; - int fSmart; - int nPartSize; - extern int Fra_FraigCecTop( Aig_Man_t * pMan1, Aig_Man_t * pMan2, int nConfLimit, int nPartSize, int fSmart, int fVerbose ); - - // set defaults - nConfLimit = 100000; - nPartSize = 100; - fSmart = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "CPsvh" ) ) != EOF ) - { - switch ( c ) - { - case 'C': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "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 'P': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "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 's': - fSmart ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - default: - goto usage; - } - } - - pArgvNew = argv + globalUtilOptind; - nArgcNew = argc - globalUtilOptind; - if ( nArgcNew != 0 && nArgcNew != 2 ) - { - Abc_Print( -1, "Currently can only compare current mapped network against the spec, or designs derived from two files.\n" ); - return 0; - } - if ( nArgcNew == 2 ) - { - Ntl_ManPrepareCec( pArgvNew[0], pArgvNew[1], &pAig1, &pAig2 ); - if ( !pAig1 || !pAig2 ) - return 1; - Fra_FraigCecTop( pAig1, pAig2, nConfLimit, nPartSize, fSmart, fVerbose ); - Aig_ManStop( pAig1 ); - Aig_ManStop( pAig2 ); - return 0; - } - - if ( pAbc->pAbc8Ntl == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Cec(): There is no design to verify.\n" ); - return 1; - } - if ( pAbc->pAbc8Nwk == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc8Cec(): There is no mapped network to verify.\n" ); - return 1; - } -// Abc_Print( -1, "Currently *cec works only for two designs given on command line.\n" ); - - // insert the mapped network - pTemp1 = Ntl_ManDup( pAbc->pAbc8Ntl ); - pTemp2 = Ntl_ManInsertNtk( pAbc->pAbc8Ntl, pAbc->pAbc8Nwk ); - if ( pTemp2 == NULL ) - { - Ntl_ManFree( pTemp1 ); - Abc_Print( -1, "Abc_CommandAbc8Cec(): Inserting the design has failed.\n" ); - return 1; - } - Ntl_ManPrepareCecMans( pTemp1, pTemp2, &pAig1, &pAig2 ); - Ntl_ManFree( pTemp1 ); - Ntl_ManFree( pTemp2 ); - if ( !pAig1 || !pAig2 ) - return 1; - Fra_FraigCecTop( pAig1, pAig2, nConfLimit, nPartSize, fSmart, fVerbose ); - Aig_ManStop( pAig1 ); - Aig_ManStop( pAig2 ); - return 0; - -usage: - Abc_Print( -2, "usage: *cec [-C num] [-P num] [-svh] \n" ); - Abc_Print( -2, "\t performs combinational equivalence checking\n" ); - Abc_Print( -2, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); - Abc_Print( -2, "\t-P num : the partition size for partitioned CEC [default = %d]\n", nPartSize ); - Abc_Print( -2, "\t-s : toggle smart and natural output partitioning [default = %s]\n", fSmart? "smart": "natural" ); - Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - Abc_Print( -2, "\tfile1 : (optional) the file with the first network\n"); - Abc_Print( -2, "\tfile2 : (optional) the file with the second network\n"); - Abc_Print( -2, "\t if no files are given, uses the current network and its spec\n"); - Abc_Print( -2, "\t if two files are given, compares designs derived from files\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc8DSec( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Fra_Sec_t SecPar, * pSecPar = &SecPar; - Aig_Man_t * pAig; - char ** pArgvNew; - int nArgcNew; - int c; - - extern void Fra_SecSetDefaultParams( Fra_Sec_t * pSecPar ); - extern int Fra_FraigSec( Aig_Man_t * p, Fra_Sec_t * pSecPar, Aig_Man_t ** ppResult ); - - // set defaults - Fra_SecSetDefaultParams( pSecPar ); - pSecPar->nFramesMax = 4; - pSecPar->fPhaseAbstract = 0; - pSecPar->fRetimeFirst = 0; - pSecPar->fRetimeRegs = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Farmfwvh" ) ) != EOF ) - { - switch ( c ) - { - case 'F': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); - goto usage; - } - pSecPar->nFramesMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pSecPar->nFramesMax < 0 ) - goto usage; - break; - case 'a': - pSecPar->fPhaseAbstract ^= 1; - break; - case 'r': - pSecPar->fRetimeFirst ^= 1; - break; - case 'm': - pSecPar->fRetimeRegs ^= 1; - break; - case 'f': - pSecPar->fFraiging ^= 1; - break; - case 'w': - pSecPar->fVeryVerbose ^= 1; - break; - case 'v': - pSecPar->fVerbose ^= 1; - break; - default: - goto usage; - } - } - - pArgvNew = argv + globalUtilOptind; - nArgcNew = argc - globalUtilOptind; - if ( nArgcNew != 2 ) - { - Abc_Print( -1, "Only works for two designs written from files specified on the command line.\n" ); - return 1; - } - - pAig = Ntl_ManPrepareSec( pArgvNew[0], pArgvNew[1] ); - if ( pAig == NULL ) - return 0; - Fra_FraigSec( pAig, pSecPar, NULL ); - Aig_ManStop( pAig ); - return 0; - -usage: - Abc_Print( -2, "usage: *dsec [-F num] [-armfwvh] \n" ); - Abc_Print( -2, "\t performs sequential equivalence checking for two designs\n" ); - Abc_Print( -2, "\t-F num : the limit on the depth of induction [default = %d]\n", pSecPar->nFramesMax ); - Abc_Print( -2, "\t-a : toggles the use of phase abstraction [default = %s]\n", pSecPar->fPhaseAbstract? "yes": "no" ); - Abc_Print( -2, "\t-r : toggles forward retiming at the beginning [default = %s]\n", pSecPar->fRetimeFirst? "yes": "no" ); - Abc_Print( -2, "\t-m : toggles min-register retiming [default = %s]\n", pSecPar->fRetimeRegs? "yes": "no" ); - Abc_Print( -2, "\t-f : toggles the internal use of fraiging [default = %s]\n", pSecPar->fFraiging? "yes": "no" ); - Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", pSecPar->fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-w : toggles additional verbose output [default = %s]\n", pSecPar->fVeryVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - Abc_Print( -2, "\tfile1 : the file with the first design\n"); - Abc_Print( -2, "\tfile2 : the file with the second design\n"); -// Abc_Print( -2, "\t if no files are given, uses the current network and its spec\n"); -// Abc_Print( -2, "\t if one file is given, uses the current network and the file\n"); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbcTestNew( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - extern int Abc_NtkTestProcedure( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 ); - - Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); - int c; - - pNtk = Abc_FrameReadNtk(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 ) - { - Abc_Print( -1, "Empty network.\n" ); - return 1; - } - - if ( !Abc_NtkIsStrash( pNtk) ) - { - Abc_Print( -1, "The current network is not an AIG. Cannot continue.\n" ); - return 1; - } - -// Abc_NtkTestProcedure( pNtk, NULL ); - - return 0; - -usage: - Abc_Print( -2, "usage: testnew [-h]\n" ); - Abc_Print( -2, "\t new testing procedure\n" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc9Read( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Gia_Man_t * pAig; - FILE * pFile; - char ** pArgvNew; - char * FileName, * pTemp; - int nArgcNew; - int c, fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) - { - switch ( c ) - { - case 'v': - fVerbose ^= 1; - break; - default: - goto usage; - } - } - pArgvNew = argv + globalUtilOptind; - nArgcNew = argc - globalUtilOptind; - if ( nArgcNew != 1 ) - { - Abc_Print( -1, "There is no file name.\n" ); - return 1; - } - - // get the input file name - FileName = pArgvNew[0]; - // fix the wrong symbol - for ( pTemp = FileName; *pTemp; pTemp++ ) - if ( *pTemp == '>' ) - *pTemp = '\\'; - if ( (pFile = fopen( FileName, "r" )) == NULL ) - { - Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); - if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", ".blif", ".pla", ".eqn", ".bench" )) ) - Abc_Print( 1, "Did you mean \"%s\"?", FileName ); - Abc_Print( 1, "\n" ); - return 1; - } - fclose( pFile ); - - pAig = Gia_ReadAiger( FileName, 0 ); - Abc_CommandUpdate9( pAbc, pAig ); - return 0; - -usage: - Abc_Print( -2, "usage: &r [-vh] \n" ); - Abc_Print( -2, "\t reads the current AIG from the AIGER file\n" ); - Abc_Print( -2, "\t-v : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - Abc_Print( -2, "\t : the file name\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc9ReadBlif( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - extern Gia_Man_t * Abc_NtkHieCecTest( char * pFileName, int fVerbose ); - Gia_Man_t * pAig; - FILE * pFile; - char ** pArgvNew; - char * FileName, * pTemp; - int nArgcNew; - int c, fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) - { - switch ( c ) - { - case 'v': - fVerbose ^= 1; - break; - default: - goto usage; - } - } - pArgvNew = argv + globalUtilOptind; - nArgcNew = argc - globalUtilOptind; - if ( nArgcNew != 1 ) - { - Abc_Print( -1, "There is no file name.\n" ); - return 1; - } - - // get the input file name - FileName = pArgvNew[0]; - // fix the wrong symbol - for ( pTemp = FileName; *pTemp; pTemp++ ) - if ( *pTemp == '>' ) - *pTemp = '\\'; - if ( (pFile = fopen( FileName, "r" )) == NULL ) - { - Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); - if ( (FileName = Extra_FileGetSimilarName( FileName, ".blif", NULL, NULL, NULL, NULL )) ) - Abc_Print( 1, "Did you mean \"%s\"?", FileName ); - Abc_Print( 1, "\n" ); - return 1; - } - fclose( pFile ); - - pAig = Abc_NtkHieCecTest( FileName, fVerbose ); - Abc_CommandUpdate9( pAbc, pAig ); - return 0; - -usage: - Abc_Print( -2, "usage: &read_blif [-vh] \n" ); - Abc_Print( -2, "\t reads the current AIG from a hierarchical BLIF file\n" ); - Abc_Print( -2, "\t-v : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - Abc_Print( -2, "\t : the file name\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc9ReadCBlif( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - extern Gia_Man_t * Abc_NtkHieCecTest2( char * pFileName, char * pModelName, int fVerbose ); - Gia_Man_t * pAig; - FILE * pFile; - char ** pArgvNew; - char * FileName, * pTemp; - char * pModelName = NULL; - int nArgcNew; - int c, fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Mvh" ) ) != EOF ) - { - switch ( c ) - { - case 'M': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-M\" should be followed by a file name.\n" ); - goto usage; - } - pModelName = argv[globalUtilOptind]; - globalUtilOptind++; - break; - case 'v': - fVerbose ^= 1; - break; - default: - goto usage; - } - } - pArgvNew = argv + globalUtilOptind; - nArgcNew = argc - globalUtilOptind; - if ( nArgcNew != 1 ) - { - Abc_Print( -1, "There is no file name.\n" ); - return 1; - } - - // get the input file name - FileName = pArgvNew[0]; - // fix the wrong symbol - for ( pTemp = FileName; *pTemp; pTemp++ ) - if ( *pTemp == '>' ) - *pTemp = '\\'; - if ( (pFile = fopen( FileName, "r" )) == NULL ) - { - Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); - if ( (FileName = Extra_FileGetSimilarName( FileName, ".cblif", NULL, NULL, NULL, NULL )) ) - Abc_Print( 1, "Did you mean \"%s\"?", FileName ); - Abc_Print( 1, "\n" ); - return 1; - } - fclose( pFile ); - - pAig = Abc_NtkHieCecTest2( FileName, pModelName, fVerbose ); - Abc_CommandUpdate9( pAbc, pAig ); + fclose( pFile ); + + pAig = Abc_NtkHieCecTest2( FileName, pModelName, fVerbose ); + Abc_CommandUpdate9( pAbc, pAig ); return 0; usage: @@ -24791,7 +21607,7 @@ int Abc_CommandAbc9Put( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_NtkForEachCi( pNtk, pObj, i ) { if (i < Vec_PtrSize(pAbc->pGia->vNamesIn)) { Nm_ManDeleteIdName(pNtk->pManName, pObj->Id); - Abc_ObjAssignName( pObj, Vec_PtrEntry(pAbc->pGia->vNamesIn, i), NULL ); + Abc_ObjAssignName( pObj, (char *)Vec_PtrEntry(pAbc->pGia->vNamesIn, i), NULL ); } } } @@ -28188,14 +25004,14 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) int c; extern void Gia_ManSetIfParsDefault( If_Par_t * pPars ); extern int Gia_MappingIf( Gia_Man_t * p, If_Par_t * pPars ); - if ( pAbc->pAbc8Lib == NULL ) - { - Abc_Print( -1, "LUT library is not given. Using default LUT library.\n" ); - pAbc->pAbc8Lib = If_SetSimpleLutLib( 6 ); - } // set defaults Gia_ManSetIfParsDefault( pPars ); - pPars->pLutLib = pAbc->pAbc8Lib; +// if ( pAbc->pAbc8Lib == NULL ) +// { +// Abc_Print( -1, "LUT library is not given. Using default LUT library.\n" ); +// pAbc->pAbc8Lib = If_SetSimpleLutLib( 6 ); +// } +// pPars->pLutLib = pAbc->pAbc8Lib; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "KCFADEqaflepmrsdbvh" ) ) != EOF ) { diff --git a/src/base/abci/abcAbc8.c b/src/base/abci/abcAbc8.c deleted file mode 100644 index 3bfaaa98..00000000 --- a/src/base/abci/abcAbc8.c +++ /dev/null @@ -1,280 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcAbc8.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: abcAbc8.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "nwk.h" -#include "mfx.h" - -#include "main.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Converts old ABC network into new ABC network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Nwk_Man_t * Abc_NtkToNtkNew( Abc_Ntk_t * pNtk ) -{ - Vec_Ptr_t * vNodes; - Nwk_Man_t * pNtkNew; - Nwk_Obj_t * pObjNew; - Abc_Obj_t * pObj, * pFanin; - int i, k; - if ( !Abc_NtkIsLogic(pNtk) ) - { - fprintf( stdout, "This is not a logic network.\n" ); - return 0; - } - // convert into the AIG - if ( !Abc_NtkToAig(pNtk) ) - { - fprintf( stdout, "Converting to AIGs has failed.\n" ); - return 0; - } - assert( Abc_NtkHasAig(pNtk) ); - // construct the network - pNtkNew = Nwk_ManAlloc(); - pNtkNew->pName = Extra_UtilStrsav( pNtk->pName ); - pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec ); - Abc_NtkForEachCi( pNtk, pObj, i ) - pObj->pCopy = (Abc_Obj_t *)Nwk_ManCreateCi( pNtkNew, Abc_ObjFanoutNum(pObj) ); - vNodes = Abc_NtkDfs( pNtk, 1 ); - Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) - { - pObjNew = Nwk_ManCreateNode( pNtkNew, Abc_ObjFaninNum(pObj), Abc_ObjFanoutNum(pObj) ); - Abc_ObjForEachFanin( pObj, pFanin, k ) - Nwk_ObjAddFanin( pObjNew, (Nwk_Obj_t *)pFanin->pCopy ); - pObjNew->pFunc = Hop_Transfer( (Hop_Man_t *)pNtk->pManFunc, pNtkNew->pManHop, (Hop_Obj_t *)pObj->pData, Abc_ObjFaninNum(pObj) ); - pObj->pCopy = (Abc_Obj_t *)pObjNew; - } - Vec_PtrFree( vNodes ); - Abc_NtkForEachCo( pNtk, pObj, i ) - { - pObjNew = Nwk_ManCreateCo( pNtkNew ); - Nwk_ObjAddFanin( pObjNew, (Nwk_Obj_t *)Abc_ObjFanin0(pObj)->pCopy ); - } -// if ( !Nwk_ManCheck( pNtkNew ) ) -// fprintf( stdout, "Abc_NtkToNtkNew(): Network check has failed.\n" ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Converts new ABC network into old ABC network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkFromNtkNew( Abc_Ntk_t * pNtkOld, Nwk_Man_t * pNtk ) -{ - Vec_Ptr_t * vNodes; - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObjNew, * pFaninNew; - Nwk_Obj_t * pObj, * pFanin; - int i, k; - // construct the network - pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_AIG, 1 ); - pNtkNew->pName = Extra_UtilStrsav( pNtk->pName ); - pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec ); - Nwk_ManForEachCi( pNtk, pObj, i ) - { - pObjNew = Abc_NtkCreatePi( pNtkNew ); - pObj->pCopy = (Nwk_Obj_t *)pObjNew; - Abc_ObjAssignName( pObjNew, Abc_ObjName( Abc_NtkCi(pNtkOld, i) ), NULL ); - } - vNodes = Nwk_ManDfs( pNtk ); - Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i ) - { - if ( !Nwk_ObjIsNode(pObj) ) - continue; - pObjNew = Abc_NtkCreateNode( pNtkNew ); - Nwk_ObjForEachFanin( pObj, pFanin, k ) - Abc_ObjAddFanin( pObjNew, (Abc_Obj_t *)pFanin->pCopy ); - pObjNew->pData = Hop_Transfer( pNtk->pManHop, (Hop_Man_t *)pNtkNew->pManFunc, pObj->pFunc, Nwk_ObjFaninNum(pObj) ); - pObj->pCopy = (Nwk_Obj_t *)pObjNew; - } - Vec_PtrFree( vNodes ); - Nwk_ManForEachCo( pNtk, pObj, i ) - { - pObjNew = Abc_NtkCreatePo( pNtkNew ); - if ( pObj->fInvert ) - pFaninNew = Abc_NtkCreateNodeInv( pNtkNew, (Abc_Obj_t *)Nwk_ObjFanin0(pObj)->pCopy ); - else - pFaninNew = (Abc_Obj_t *)Nwk_ObjFanin0(pObj)->pCopy; - Abc_ObjAddFanin( pObjNew, pFaninNew ); - Abc_ObjAssignName( pObjNew, Abc_ObjName( Abc_NtkCo(pNtkOld, i) ), NULL ); - } - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkFromNtkNew(): Network check has failed.\n" ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkNtkTest2( Abc_Ntk_t * pNtk ) -{ - extern void Abc_NtkSupportSum( Abc_Ntk_t * pNtk ); - Abc_Ntk_t * pNtkNew; - Nwk_Man_t * pMan; - int clk; - -clk = clock(); - Abc_NtkSupportSum( pNtk ); -ABC_PRT( "Time", clock() - clk ); - - pMan = Abc_NtkToNtkNew( pNtk ); -clk = clock(); - Nwk_ManSupportSum( pMan ); -ABC_PRT( "Time", clock() - clk ); - - pNtkNew = Abc_NtkFromNtkNew( pNtk, pMan ); - Nwk_ManFree( pMan ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkNtkTest3( Abc_Ntk_t * pNtk ) -{ - extern void Abc_NtkSupportSum( Abc_Ntk_t * pNtk ); - extern void * Abc_FrameReadLibLut(); - - Abc_Ntk_t * pNtkNew; - Nwk_Man_t * pMan; - int clk; - -clk = clock(); - printf( "%6.2f\n", Abc_NtkDelayTraceLut( pNtk, 1 ) ); -ABC_PRT( "Time", clock() - clk ); - - pMan = Abc_NtkToNtkNew( pNtk ); - pMan->pLutLib = (If_Lib_t *)Abc_FrameReadLibLut(); -clk = clock(); - printf( "%6.2f\n", Nwk_ManDelayTraceLut( pMan ) ); -ABC_PRT( "Time", clock() - clk ); - - pNtkNew = Abc_NtkFromNtkNew( pNtk, pMan ); - Nwk_ManFree( pMan ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkNtkTest4( Abc_Ntk_t * pNtk, If_Lib_t * pLutLib ) -{ - - Mfx_Par_t Pars, * pPars = &Pars; - Abc_Ntk_t * pNtkNew; - Nwk_Man_t * pMan; - pMan = Abc_NtkToNtkNew( pNtk ); - - Mfx_ParsDefault( pPars ); - Mfx_Perform( pMan, pPars, pLutLib ); - - pNtkNew = Abc_NtkFromNtkNew( pNtk, pMan ); - Nwk_ManFree( pMan ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkNtkTest( Abc_Ntk_t * pNtk, If_Lib_t * pLutLib ) -{ - Vec_Ptr_t * vNodes; - extern Vec_Ptr_t * Nwk_ManRetimeCutForward( Nwk_Man_t * pMan, int nLatches, int fVerbose ); - extern Vec_Ptr_t * Nwk_ManRetimeCutBackward( Nwk_Man_t * pMan, int nLatches, int fVerbose ); - - Abc_Ntk_t * pNtkNew; - Nwk_Man_t * pMan; - pMan = Abc_NtkToNtkNew( pNtk ); - - vNodes = Nwk_ManRetimeCutBackward( pMan, Abc_NtkLatchNum(pNtk), 1 ); -// vNodes = Nwk_ManRetimeCutForward( pMan, Abc_NtkLatchNum(pNtk), 1 ); - Vec_PtrFree( vNodes ); - - pNtkNew = Abc_NtkFromNtkNew( pNtk, pMan ); - Nwk_ManFree( pMan ); - return pNtkNew; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/base/abci/abcAttach.c b/src/base/abci/abcAttach.c index d1712f4d..6408b54f 100644 --- a/src/base/abci/abcAttach.c +++ b/src/base/abci/abcAttach.c @@ -18,9 +18,9 @@ ***********************************************************************/ -#include "abc.h" -#include "main.h" -#include "mio.h" +#include "src/base/abc/abc.h" +#include "src/base/main/main.h" +#include "src/map/mio/mio.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcAuto.c b/src/base/abci/abcAuto.c index 02d5fd17..e1e479e3 100644 --- a/src/base/abci/abcAuto.c +++ b/src/base/abci/abcAuto.c @@ -18,8 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcBalance.c b/src/base/abci/abcBalance.c index a4fa0451..c46fd4b7 100644 --- a/src/base/abci/abcBalance.c +++ b/src/base/abci/abcBalance.c @@ -18,8 +18,7 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcBidec.c b/src/base/abci/abcBidec.c index bae29e07..fc093420 100644 --- a/src/base/abci/abcBidec.c +++ b/src/base/abci/abcBidec.c @@ -18,9 +18,9 @@ ***********************************************************************/ -#include "abc.h" -#include "bdc.h" -#include "kit.h" +#include "src/base/abc/abc.h" +#include "src/bool/bdc/bdc.h" +#include "src/bool/kit/kit.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcBm.c b/src/base/abci/abcBm.c index 25fba5fd..3a8567fe 100644 --- a/src/base/abci/abcBm.c +++ b/src/base/abci/abcBm.c @@ -27,10 +27,10 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" -#include "sim.h" -#include "satSolver.h" +#include "src/base/abc/abc.h" +#include "src/opt/sim/sim.h" +#include "src/sat/bsat/satSolver.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcBmc.c b/src/base/abci/abcBmc.c index 21f2d484..6ea4435c 100644 --- a/src/base/abci/abcBmc.c +++ b/src/base/abci/abcBmc.c @@ -18,8 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "ivy.h" +#include "src/base/abc/abc.h" +#include "src/aig/ivy/ivy.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcCas.c b/src/base/abci/abcCas.c index 68c91343..7e80c919 100644 --- a/src/base/abci/abcCas.c +++ b/src/base/abci/abcCas.c @@ -18,8 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcCascade.c b/src/base/abci/abcCascade.c index 533321c5..a477077d 100644 --- a/src/base/abci/abcCascade.c +++ b/src/base/abci/abcCascade.c @@ -18,8 +18,9 @@ ***********************************************************************/ -#include "abc.h" -#include "reo.h" +#include "src/base/abc/abc.h" +#include "src/bdd/reo/reo.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START @@ -263,7 +264,7 @@ int Abc_ResCofCount( DdManager * dd, DdNode * bFunc, unsigned uMask, int * pChec Vec_PtrFree( vCofs ); if ( pCheck ) { - *pCheck = Abc_ResCheckNonStrict( Pattern, nVars, Extra_Base2Log(Result) ); + *pCheck = Abc_ResCheckNonStrict( Pattern, nVars, Abc_Base2Log(Result) ); /* if ( *pCheck == 1 && nVars == 4 && Result == 8 ) { @@ -290,7 +291,7 @@ int Abc_ResCofCount( DdManager * dd, DdNode * bFunc, unsigned uMask, int * pChec int Abc_ResCost( DdManager * dd, DdNode * bFunc, unsigned uMask, int * pnCofs, int * pCheck ) { int nCofs = Abc_ResCofCount( dd, bFunc, uMask, pCheck ); - int n2Log = Extra_Base2Log( nCofs ); + int n2Log = Abc_Base2Log( nCofs ); if ( pnCofs ) *pnCofs = nCofs; return 10000 * n2Log + (nCofs - (1 << (n2Log-1))) * (nCofs - (1 << (n2Log-1))); } @@ -360,7 +361,7 @@ void Abc_ResPrint( DdManager * dd, DdNode * bFunc, int nInputs, unsigned uParts[ CostAll += Cost; for ( k = 0; k < nInputs; k++ ) printf( "%c", (uParts[i] & (1 << k))? 'a' + k : '-' ); - printf( " %2d %d-%d %6d ", nCofs, Extra_Base2Log(nCofs), fCheck, Cost ); + printf( " %2d %d-%d %6d ", nCofs, Abc_Base2Log(nCofs), fCheck, Cost ); } printf( "%4d\n", CostAll ); } @@ -390,7 +391,7 @@ void Abc_ResPrintAllCofs( DdManager * dd, DdNode * bFunc, int nInputs, int nCofM for ( k = 0; k < nInputs; k++ ) printf( "%c", (i & (1 << k))? 'a' + k : '-' ); printf( " n=%2d c=%2d l=%d-%d %6d\n", - Extra_WordCountOnes(i), nCofs, Extra_Base2Log(nCofs), fCheck, Cost ); + Extra_WordCountOnes(i), nCofs, Abc_Base2Log(nCofs), fCheck, Cost ); } } diff --git a/src/base/abci/abcCollapse.c b/src/base/abci/abcCollapse.c index 07996b9a..69525e2f 100644 --- a/src/base/abci/abcCollapse.c +++ b/src/base/abci/abcCollapse.c @@ -18,8 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcCut.c b/src/base/abci/abcCut.c index a08ce490..6116649e 100644 --- a/src/base/abci/abcCut.c +++ b/src/base/abci/abcCut.c @@ -18,9 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "cut.h" -#include "extra.h" +#include "src/base/abc/abc.h" +#include "src/opt/cut/cut.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcDar.c b/src/base/abci/abcDar.c index 4a74ad7e..b032b4e4 100644 --- a/src/base/abci/abcDar.c +++ b/src/base/abci/abcDar.c @@ -18,22 +18,22 @@ ***********************************************************************/ -#include "abc.h" -#include "main.h" -#include "giaAig.h" -#include "dar.h" -#include "cnf.h" -#include "fra.h" -#include "fraig.h" -#include "int.h" -#include "dch.h" -#include "ssw.h" -#include "cgt.h" -#include "bbr.h" -#include "gia.h" -#include "cec.h" -#include "csw.h" -#include "pdr.h" +#include "src/base/abc/abc.h" +#include "src/base/main/main.h" +#include "src/aig/gia/giaAig.h" +#include "src/opt/dar/dar.h" +#include "src/sat/cnf/cnf.h" +#include "src/proof/fra/fra.h" +#include "src/proof/fraig/fraig.h" +#include "src/proof/int/int.h" +#include "src/proof/dch/dch.h" +#include "src/proof/ssw/ssw.h" +#include "src/opt/cgt/cgt.h" +#include "src/proof/bbr/bbr.h" +#include "src/aig/gia/gia.h" +#include "src/proof/cec/cec.h" +#include "src/opt/csw/csw.h" +#include "src/proof/pdr/pdr.h" ABC_NAMESPACE_IMPL_START @@ -358,7 +358,7 @@ Abc_Ntk_t * Abc_NtkFromDarSeqSweep( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ) } */ assert( Abc_NtkBoxNum(pNtkOld) == Abc_NtkLatchNum(pNtkOld) ); - nDigits = Extra_Base10Log( Abc_NtkLatchNum(pNtkNew) ); + nDigits = Abc_Base10Log( Abc_NtkLatchNum(pNtkNew) ); Abc_NtkForEachLatch( pNtkNew, pObjNew, i ) { pLatch = Abc_NtkBox( pNtkOld, Vec_IntEntry( pMan->vFlopNums, i ) ); @@ -1669,7 +1669,7 @@ Abc_Ntk_t * Abc_NtkDarLcorrNew( Abc_Ntk_t * pNtk, int nVarsMax, int nConfMax, in /* #include -#include "utilMem.h" +#include "src/misc/util/utilMem.h" static void sigfunc( int signo ) { if (signo == SIGINT) { @@ -2160,10 +2160,10 @@ int Abc_NtkDarDemiterDual( Abc_Ntk_t * pNtk, int fVerbose ) } // create new AIG ABC_FREE( pPart0->pName ); - pPart0->pName = Aig_UtilStrsav( "part0" ); + pPart0->pName = Abc_UtilStrsav( "part0" ); // create new AIGs ABC_FREE( pPart1->pName ); - pPart1->pName = Aig_UtilStrsav( "part1" ); + pPart1->pName = Abc_UtilStrsav( "part1" ); // create file names pFileNameGeneric = Extra_FileNameGeneric( pNtk->pSpec ); sprintf( pFileName0, "%s%s", pFileNameGeneric, "_part0.aig" ); @@ -3831,8 +3831,8 @@ int Abc_NtkDarReach( Abc_Ntk_t * pNtk, Saig_ParBbr_t * pPars ) ABC_NAMESPACE_IMPL_END -#include "amap.h" -#include "mio.h" +#include "src/map/amap/amap.h" +#include "src/map/mio/mio.h" ABC_NAMESPACE_IMPL_START @@ -4095,7 +4095,7 @@ void Abc_NtkDarConstrProfile( Abc_Ntk_t * pNtk, int fVerbose ) printf( "Primary output : ", i ); else printf( "Constraint %3d : ", i-(Saig_ManPoNum(pMan) - Saig_ManConstrNum(pMan)) ); - printf( "ProbOne = %f ", Aig_Int2Float(Entry) ); + printf( "ProbOne = %f ", Abc_Int2Float(Entry) ); printf( "AllZeroValue = %d ", Aig_ObjPhase(pObj) ); printf( "\n" ); } diff --git a/src/base/abci/abcDebug.c b/src/base/abci/abcDebug.c index 43ceb63a..baf87944 100644 --- a/src/base/abci/abcDebug.c +++ b/src/base/abci/abcDebug.c @@ -18,8 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "ioAbc.h" +#include "src/base/abc/abc.h" +#include "src/base/io/ioAbc.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcDress.c b/src/base/abci/abcDress.c index c9c956e4..745dcac0 100644 --- a/src/base/abci/abcDress.c +++ b/src/base/abci/abcDress.c @@ -18,8 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "ioAbc.h" +#include "src/base/abc/abc.h" +#include "src/base/io/ioAbc.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcDress2.c b/src/base/abci/abcDress2.c index 039a4fed..fbaf833a 100644 --- a/src/base/abci/abcDress2.c +++ b/src/base/abci/abcDress2.c @@ -18,9 +18,9 @@ ***********************************************************************/ -#include "abc.h" -#include "aig.h" -#include "dch.h" +#include "src/base/abc/abc.h" +#include "src/aig/aig/aig.h" +#include "src/proof/dch/dch.h" ABC_NAMESPACE_IMPL_START @@ -392,8 +392,8 @@ void Abc_NtkDressPrintStats( Vec_Ptr_t * vRes, int nNodes0, int nNodes1, int Tim NegAll[1] += Neg[1]; // total negative polarity in network 1 // assuming that the name can be transferred to only one node - PairsAll += ABC_MIN(Neg[0] + Pos[0], Neg[1] + Pos[1]); - PairsOne += ABC_MIN(Neg[0], Neg[1]) + ABC_MIN(Pos[0], Pos[1]); + PairsAll += Abc_MinInt(Neg[0] + Pos[0], Neg[1] + Pos[1]); + PairsOne += Abc_MinInt(Neg[0], Neg[1]) + Abc_MinInt(Pos[0], Pos[1]); } printf( "Total number of equiv classes = %7d.\n", Vec_PtrSize(vRes) ); printf( "Participating nodes from both networks = %7d.\n", NegAll[0]+PosAll[0]+NegAll[1]+PosAll[1] ); diff --git a/src/base/abci/abcDsd.c b/src/base/abci/abcDsd.c index 250cac14..c4086ce7 100644 --- a/src/base/abci/abcDsd.c +++ b/src/base/abci/abcDsd.c @@ -18,9 +18,9 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" -#include "dsd.h" +#include "src/base/abc/abc.h" +#include "src/misc/extra/extraBdd.h" +#include "src/bdd/dsd/dsd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcEspresso.c b/src/base/abci/abcEspresso.c index c8c1d8e1..2e78ad3f 100644 --- a/src/base/abci/abcEspresso.c +++ b/src/base/abci/abcEspresso.c @@ -18,8 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "espresso.h" +#include "base/abc/abc.h" +#include "misc/espresso/espresso.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcExtract.c b/src/base/abci/abcExtract.c index 8eca34a6..e6b4193b 100644 --- a/src/base/abci/abcExtract.c +++ b/src/base/abci/abcExtract.c @@ -18,7 +18,7 @@ ***********************************************************************/ -#include "abc.h" +#include "src/base/abc/abc.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcFlop.c b/src/base/abci/abcFlop.c index a735f279..6ed411f7 100644 --- a/src/base/abci/abcFlop.c +++ b/src/base/abci/abcFlop.c @@ -18,7 +18,7 @@ ***********************************************************************/ -#include "abc.h" +#include "base/abc/abc.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcFpga.c b/src/base/abci/abcFpga.c index 0c45c7d2..4d6b2978 100644 --- a/src/base/abci/abcFpga.c +++ b/src/base/abci/abcFpga.c @@ -18,8 +18,9 @@ ***********************************************************************/ -#include "abc.h" -#include "fpgaInt.h" +#include "src/base/abc/abc.h" +#include "src/map/fpga/fpgaInt.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcFpgaFast.c b/src/base/abci/abcFpgaFast.c index 46572fa8..1c5693fd 100644 --- a/src/base/abci/abcFpgaFast.c +++ b/src/base/abci/abcFpgaFast.c @@ -18,8 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "ivy.h" +#include "src/base/abc/abc.h" +#include "src/aig/ivy/ivy.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcFraig.c b/src/base/abci/abcFraig.c index 1beab4f4..e1c12b3f 100644 --- a/src/base/abci/abcFraig.c +++ b/src/base/abci/abcFraig.c @@ -18,9 +18,9 @@ ***********************************************************************/ -#include "abc.h" -#include "fraig.h" -#include "main.h" +#include "src/base/abc/abc.h" +#include "src/proof/fraig/fraig.h" +#include "src/base/main/main.h" ABC_NAMESPACE_IMPL_START @@ -722,7 +722,7 @@ Abc_Ntk_t * Abc_NtkFraigRestore() // 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 ); + nWordsMin = Abc_MinInt( nWords1, nWords2 ); // set parameters for fraiging Fraig_ParamsSetDefault( &Params ); diff --git a/src/base/abci/abcFxu.c b/src/base/abci/abcFxu.c index dbbcb1b1..2470a1d1 100644 --- a/src/base/abci/abcFxu.c +++ b/src/base/abci/abcFxu.c @@ -18,8 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "fxu.h" +#include "src/base/abc/abc.h" +#include "src/opt/fxu/fxu.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcGen.c b/src/base/abci/abcGen.c index 3299a968..55191021 100644 --- a/src/base/abci/abcGen.c +++ b/src/base/abci/abcGen.c @@ -18,8 +18,7 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" ABC_NAMESPACE_IMPL_START @@ -122,7 +121,7 @@ void Abc_GenSorter( char * pFileName, int nVars ) fprintf( pFile, "\n" ); Counter = 0; - nDigits = Extra_Base10Log( (nVars-2)*nVars ); + nDigits = Abc_Base10Log( (nVars-2)*nVars ); if ( nVars == 2 ) fprintf( pFile, ".subckt Comp a=x00 b=x01 x=y00 y=y01\n" ); else @@ -427,7 +426,7 @@ void Abc_GenFpga( char * pFileName, int nLutSize, int nLuts, int nVars ) int fGenerateFunc = 1; FILE * pFile; int nVarsLut = (1 << nLutSize); // the number of LUT variables - int nVarsLog = Extra_Base2Log( nVars + nLuts - 1 ); // the number of encoding vars + int nVarsLog = Abc_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 @@ -548,12 +547,12 @@ void Abc_GenOneHot( char * pFileName, int nVars ) fprintf( pFile, "# One-hotness condition for %d vars generated by ABC on %s\n", nVars, Extra_TimeStamp() ); fprintf( pFile, ".model 1hot_%dvars\n", nVars ); fprintf( pFile, ".inputs" ); - nDigitsIn = Extra_Base10Log( nVars ); + nDigitsIn = Abc_Base10Log( nVars ); for ( i = 0; i < nVars; i++ ) fprintf( pFile, " i%0*d", nDigitsIn, i ); fprintf( pFile, "\n" ); fprintf( pFile, ".outputs" ); - nDigitsOut = Extra_Base10Log( nVars * (nVars - 1) / 2 ); + nDigitsOut = Abc_Base10Log( nVars * (nVars - 1) / 2 ); for ( i = 0; i < nVars * (nVars - 1) / 2; i++ ) fprintf( pFile, " o%0*d", nDigitsOut, i ); fprintf( pFile, "\n" ); @@ -598,12 +597,12 @@ void Abc_GenOneHotIntervals( char * pFileName, int nPis, int nRegs, Vec_Ptr_t * fprintf( pFile, "}\n" ); fprintf( pFile, ".model 1hot_%dvars_%dregs\n", nPis, nRegs ); fprintf( pFile, ".inputs" ); - nDigitsIn = Extra_Base10Log( nPis+nRegs ); + nDigitsIn = Abc_Base10Log( nPis+nRegs ); for ( i = 0; i < nPis+nRegs; i++ ) fprintf( pFile, " i%0*d", nDigitsIn, i ); fprintf( pFile, "\n" ); fprintf( pFile, ".outputs" ); - nDigitsOut = Extra_Base10Log( Counter ); + nDigitsOut = Abc_Base10Log( Counter ); for ( i = 0; i < Counter; i++ ) fprintf( pFile, " o%0*d", nDigitsOut, i ); fprintf( pFile, "\n" ); @@ -626,7 +625,7 @@ void Abc_GenOneHotIntervals( char * pFileName, int nPis, int nRegs, Vec_Ptr_t * ABC_NAMESPACE_IMPL_END -#include "aig.h" +#include "src/aig/aig/aig.h" ABC_NAMESPACE_IMPL_START @@ -646,7 +645,7 @@ void Abc_GenRandom( char * pFileName, int nPis ) { FILE * pFile; unsigned * pTruth; - int i, b, w, nWords = Aig_TruthWordNum( nPis ); + int i, b, w, nWords = Abc_TruthWordNum( nPis ); int nDigitsIn; Aig_ManRandom( 1 ); pTruth = ABC_ALLOC( unsigned, nWords ); @@ -656,18 +655,18 @@ void Abc_GenRandom( char * pFileName, int nPis ) fprintf( pFile, "# Random function with %d inputs generated by ABC on %s\n", nPis, Extra_TimeStamp() ); fprintf( pFile, ".model rand%d\n", nPis ); fprintf( pFile, ".inputs" ); - nDigitsIn = Extra_Base10Log( nPis ); + nDigitsIn = Abc_Base10Log( nPis ); for ( i = 0; i < nPis; i++ ) fprintf( pFile, " i%0*d", nDigitsIn, i ); fprintf( pFile, "\n" ); fprintf( pFile, ".outputs f\n" ); fprintf( pFile, ".names" ); - nDigitsIn = Extra_Base10Log( nPis ); + nDigitsIn = Abc_Base10Log( nPis ); for ( i = 0; i < nPis; i++ ) fprintf( pFile, " i%0*d", nDigitsIn, i ); fprintf( pFile, " f\n" ); for ( i = 0; i < (1<= 0; b-- ) fprintf( pFile, "%d", (i>>b)&1 ); diff --git a/src/base/abci/abcHaig.c b/src/base/abci/abcHaig.c index b102e04f..073defd0 100644 --- a/src/base/abci/abcHaig.c +++ b/src/base/abci/abcHaig.c @@ -18,7 +18,7 @@ ***********************************************************************/ -#include "abc.h" +#include "src/base/abc/abc.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcIf.c b/src/base/abci/abcIf.c index 674a4550..ded34d3c 100644 --- a/src/base/abci/abcIf.c +++ b/src/base/abci/abcIf.c @@ -18,11 +18,11 @@ ***********************************************************************/ -#include "abc.h" -#include "main.h" -#include "if.h" -#include "kit.h" -#include "aig.h" +#include "src/base/abc/abc.h" +#include "src/base/main/main.h" +#include "src/map/if/if.h" +#include "src/bool/kit/kit.h" +#include "src/aig/aig/aig.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcIfMux.c b/src/base/abci/abcIfMux.c index bf9d6cff..545adafb 100644 --- a/src/base/abci/abcIfMux.c +++ b/src/base/abci/abcIfMux.c @@ -18,8 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "if.h" +#include "src/base/abc/abc.h" +#include "src/map/if/if.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcIvy.c b/src/base/abci/abcIvy.c index 28ff0ee6..c2637a08 100644 --- a/src/base/abci/abcIvy.c +++ b/src/base/abci/abcIvy.c @@ -18,13 +18,14 @@ ***********************************************************************/ -#include "abc.h" -#include "dec.h" -#include "fra.h" -#include "ivy.h" -#include "fraig.h" -#include "mio.h" -#include "aig.h" +#include "src/base/abc/abc.h" +#include "src/bool/dec/dec.h" +#include "src/proof/fra/fra.h" +#include "src/aig/ivy/ivy.h" +#include "src/proof/fraig/fraig.h" +#include "src/map/mio/mio.h" +#include "src/aig/aig/aig.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcLog.c b/src/base/abci/abcLog.c index ecccb36b..aa926a41 100644 --- a/src/base/abci/abcLog.c +++ b/src/base/abci/abcLog.c @@ -18,8 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "gia.h" +#include "src/base/abc/abc.h" +#include "src/aig/gia/gia.h" ABC_NAMESPACE_IMPL_START @@ -102,7 +102,7 @@ void Abc_NtkWriteLogFile( char * pFileName, Abc_Cex_t * pCex, int Status, int nF else { for ( i = 0; i < pCex->nRegs; i++ ) - fprintf( pFile, "%d", Gia_InfoHasBit(pCex->pData,i) ); + fprintf( pFile, "%d", Abc_InfoHasBit(pCex->pData,i) ); } fprintf( pFile, "\n" ); // write @@ -112,7 +112,7 @@ void Abc_NtkWriteLogFile( char * pFileName, Abc_Cex_t * pCex, int Status, int nF { assert( pCex->nBits - pCex->nRegs == pCex->nPis * (pCex->iFrame + 1) ); for ( i = pCex->nRegs; i < pCex->nBits; i++ ) - fprintf( pFile, "%d", Gia_InfoHasBit(pCex->pData,i) ); + fprintf( pFile, "%d", Abc_InfoHasBit(pCex->pData,i) ); } fprintf( pFile, "\n" ); fclose( pFile ); @@ -211,7 +211,7 @@ int Abc_NtkReadLogFile( char * pFileName, Abc_Cex_t ** ppCex, int * pnFrames ) assert( Vec_IntSize(vNums) == pCex->nBits ); for ( c = 0; c < pCex->nBits; c++ ) if ( Vec_IntEntry(vNums, c) ) - Gia_InfoSetBit( pCex->pData, c ); + Abc_InfoSetBit( pCex->pData, c ); Vec_IntFree( vNums ); if ( ppCex ) *ppCex = pCex; diff --git a/src/base/abci/abcLut.c b/src/base/abci/abcLut.c index 98991e25..1653918f 100644 --- a/src/base/abci/abcLut.c +++ b/src/base/abci/abcLut.c @@ -18,9 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" -#include "cut.h" +#include "src/base/abc/abc.h" +#include "src/opt/cut/cut.h" ABC_NAMESPACE_IMPL_START @@ -175,7 +174,7 @@ int Abc_NtkSuperChoiceLut( Abc_Ntk_t * pNtk, int nLutSize, int nCutSizeMax, int if ( Abc_ObjFaninNum(pFanin) == 1 ) pFanin = Abc_ObjFanin0( pFanin ); // get the new level - LevelMax = ABC_MAX( LevelMax, (int)pFanin->Level ); + LevelMax = Abc_MaxInt( LevelMax, (int)pFanin->Level ); } if ( fVerbose ) @@ -516,7 +515,7 @@ int Abc_NodeGetLevel( Abc_Obj_t * pObj ) int i, Level; Level = 0; Abc_ObjForEachFanin( pObj, pFanin, i ) - Level = ABC_MAX( Level, (int)pFanin->Level ); + Level = Abc_MaxInt( Level, (int)pFanin->Level ); return Level + 1; } @@ -723,7 +722,7 @@ int Abc_NodeDecomposeStep( Abc_ManScl_t * p ) return 0; } // the number of cofactors is acceptable - nVarsNew = Extra_Base2Log( nClasses ); + nVarsNew = Abc_Base2Log( nClasses ); assert( nVarsNew < p->nLutSize ); // create the remainder truth table // for each class of cofactors, multiply cofactor truth table by its code diff --git a/src/base/abci/abcLutmin.c b/src/base/abci/abcLutmin.c index 6d62f330..d740777c 100644 --- a/src/base/abci/abcLutmin.c +++ b/src/base/abci/abcLutmin.c @@ -18,8 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START @@ -418,8 +418,8 @@ Abc_Obj_t * Abc_NtkBddCurtis( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Ptr_t DdManager * ddNew = (DdManager *)pNtkNew->pManFunc; DdNode * bCof, * bUniq, * bMint, * bTemp, * bFunc, * bBits[10], ** pbCodeVars; Abc_Obj_t * pNodeNew = NULL, * pNodeBS[10]; - int nLutSize = Extra_Base2Log( Vec_PtrSize(vCofs) ); - int nBits = Extra_Base2Log( Vec_PtrSize(vUniq) ); + int nLutSize = Abc_Base2Log( Vec_PtrSize(vCofs) ); + int nBits = Abc_Base2Log( Vec_PtrSize(vUniq) ); int b, c, u, i; assert( nBits + 2 <= nLutSize ); assert( nLutSize < Abc_ObjFaninNum(pNode) ); diff --git a/src/base/abci/abcMap.c b/src/base/abci/abcMap.c index 578727cc..eeeaf15f 100644 --- a/src/base/abci/abcMap.c +++ b/src/base/abci/abcMap.c @@ -18,10 +18,10 @@ ***********************************************************************/ -#include "abc.h" -#include "main.h" -#include "mio.h" -#include "mapper.h" +#include "src/base/abc/abc.h" +#include "src/base/main/main.h" +#include "src/map/mio/mio.h" +#include "src/map/mapper/mapper.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcMeasure.c b/src/base/abci/abcMeasure.c index 5352084f..a366b830 100644 --- a/src/base/abci/abcMeasure.c +++ b/src/base/abci/abcMeasure.c @@ -18,8 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "kit.h" +#include "src/base/abc/abc.h" +#include "src/bool/kit/kit.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcMerge.c b/src/base/abci/abcMerge.c index d7abece8..917a97da 100644 --- a/src/base/abci/abcMerge.c +++ b/src/base/abci/abcMerge.c @@ -18,9 +18,9 @@ ***********************************************************************/ -#include "abc.h" -#include "aig.h" -#include "nwkMerge.h" +#include "src/base/abc/abc.h" +#include "src/aig/aig/aig.h" +#include "src/opt/nwk/nwkMerge.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcMffc.c b/src/base/abci/abcMffc.c index b4510bd0..b88452e8 100644 --- a/src/base/abci/abcMffc.c +++ b/src/base/abci/abcMffc.c @@ -18,7 +18,7 @@ ***********************************************************************/ -#include "abc.h" +#include "src/base/abc/abc.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcMini.c b/src/base/abci/abcMini.c index 429c40c6..0af87d36 100644 --- a/src/base/abci/abcMini.c +++ b/src/base/abci/abcMini.c @@ -18,7 +18,7 @@ ***********************************************************************/ -#include "abc.h" +#include "src/base/abc/abc.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcMiter.c b/src/base/abci/abcMiter.c index 9cda4608..66734c04 100644 --- a/src/base/abci/abcMiter.c +++ b/src/base/abci/abcMiter.c @@ -18,8 +18,7 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcMulti.c b/src/base/abci/abcMulti.c index 299e22d5..c8247b28 100644 --- a/src/base/abci/abcMulti.c +++ b/src/base/abci/abcMulti.c @@ -18,8 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcMv.c b/src/base/abci/abcMv.c index 98d27a19..5f612b62 100644 --- a/src/base/abci/abcMv.c +++ b/src/base/abci/abcMv.c @@ -18,8 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcNpnSave.c b/src/base/abci/abcNpnSave.c index 568a3e28..b57d2ef3 100644 --- a/src/base/abci/abcNpnSave.c +++ b/src/base/abci/abcNpnSave.c @@ -18,9 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "aig.h" -#include "extra.h" +#include "src/base/abc/abc.h" +#include "src/aig/aig/aig.h" ABC_NAMESPACE_IMPL_START @@ -81,7 +80,7 @@ static Npn_Man_t * pNpnMan = NULL; void Npn_TruthPermute_rec( char * pStr, int mid, int end ) { static int count = 0; - char * pTemp = Aig_UtilStrsav(pStr); + char * pTemp = Abc_UtilStrsav(pStr); char e; int i; if ( mid == end ) @@ -329,7 +328,7 @@ static inline word Npn_TruthCanon( word t, int nVars, int * pPhase ) } else { - if ( ABC_MIN(pSigs[2*v],pSigs[2*v+1]) >= ABC_MIN(pSigs[2*(v+1)],pSigs[2*(v+1)+1]) ) + if ( Abc_MinInt(pSigs[2*v],pSigs[2*v+1]) >= Abc_MinInt(pSigs[2*(v+1)],pSigs[2*(v+1)+1]) ) continue; } fChange = 1; @@ -400,7 +399,7 @@ clk = clock(); pBinsOld = p->pBins; nBinsOld = p->nBins; // get the new Bins - p->nBins = Aig_PrimeCudd( 3 * nBinsOld ); + p->nBins = Abc_PrimeCudd( 3 * nBinsOld ); p->pBins = ABC_CALLOC( int, p->nBins ); // rehash the entries from the old table Counter = 1; @@ -594,7 +593,7 @@ Npn_Man_t * Npn_ManStart( char * pFileName ) p->nBufferSize = 1000000; p->nBufferSize = 100; p->pBuffer = ABC_ALLOC( Npn_Obj_t, p->nBufferSize ); - p->nBins = Aig_PrimeCudd( p->nBufferSize / 2 ); + p->nBins = Abc_PrimeCudd( p->nBufferSize / 2 ); p->pBins = ABC_CALLOC( int, p->nBins ); p->nEntries = 1; } @@ -609,7 +608,7 @@ Npn_Man_t * Npn_ManStart( char * pFileName ) fclose( pFile ); p->nBufferSize = 4 * ( Extra_FileSize(pFileName) / 20 ); p->pBuffer = ABC_ALLOC( Npn_Obj_t, p->nBufferSize ); - p->nBins = Aig_PrimeCudd( p->nBufferSize / 2 ); + p->nBins = Abc_PrimeCudd( p->nBufferSize / 2 ); p->pBins = ABC_CALLOC( int, p->nBins ); p->nEntries = 1; Npn_ManRead( p, pFileName ); diff --git a/src/base/abci/abcNtbdd.c b/src/base/abci/abcNtbdd.c index e3df605e..a1fab695 100644 --- a/src/base/abci/abcNtbdd.c +++ b/src/base/abci/abcNtbdd.c @@ -18,8 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcOdc.c b/src/base/abci/abcOdc.c index 50694832..e0f6d6de 100644 --- a/src/base/abci/abcOdc.c +++ b/src/base/abci/abcOdc.c @@ -18,8 +18,7 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcOrder.c b/src/base/abci/abcOrder.c index c306d01d..a3f66a63 100644 --- a/src/base/abci/abcOrder.c +++ b/src/base/abci/abcOrder.c @@ -18,7 +18,7 @@ ***********************************************************************/ -#include "abc.h" +#include "src/base/abc/abc.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcPart.c b/src/base/abci/abcPart.c index 5df5af62..7ae435d8 100644 --- a/src/base/abci/abcPart.c +++ b/src/base/abci/abcPart.c @@ -18,9 +18,9 @@ ***********************************************************************/ -#include "abc.h" -#include "main.h" -#include "cmd.h" +#include "src/base/abc/abc.h" +#include "src/base/main/main.h" +#include "src/base/cmd/cmd.h" ABC_NAMESPACE_IMPL_START @@ -594,7 +594,7 @@ int Abc_NtkPartitionSmartFindPart( Vec_Ptr_t * vPartSuppsAll, Vec_Ptr_t * vParts if ( Vec_IntSize(vPartSupp) < 100 ) Repulse = 1; else - Repulse = 1+Extra_Base2Log(Vec_IntSize(vPartSupp)-100); + Repulse = 1+Abc_Base2Log(Vec_IntSize(vPartSupp)-100); Value = Attract/Repulse; if ( ValueBest < Value ) { diff --git a/src/base/abci/abcPlace.c b/src/base/abci/abcPlace.c index 06c23e65..7faa5d77 100644 --- a/src/base/abci/abcPlace.c +++ b/src/base/abci/abcPlace.c @@ -18,10 +18,10 @@ ***********************************************************************/ -#include "abc.h" +#include "base/abc/abc.h" // placement includes -#include "place_base.h" +#include "phys/place/place_base.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcPrint.c b/src/base/abci/abcPrint.c index 9e2f48d3..af34029e 100644 --- a/src/base/abci/abcPrint.c +++ b/src/base/abci/abcPrint.c @@ -19,12 +19,13 @@ ***********************************************************************/ #include -#include "abc.h" -#include "dec.h" -#include "main.h" -#include "mio.h" -#include "aig.h" -#include "if.h" +#include "src/base/abc/abc.h" +#include "src/bool/dec/dec.h" +#include "src/base/main/main.h" +#include "src/map/mio/mio.h" +#include "src/aig/aig/aig.h" +#include "src/map/if/if.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START @@ -523,7 +524,7 @@ void Abc_NtkPrintFanio( FILE * pFile, Abc_Ntk_t * pNtk ) if ( nFanins > vFanins->nSize || nFanouts > vFanouts->nSize ) { nOldSize = vFanins->nSize; - nNewSize = ABC_MAX(nFanins, nFanouts) + 10; + nNewSize = Abc_MaxInt(nFanins, nFanouts) + 10; Vec_IntGrow( vFanins, nNewSize ); Vec_IntGrow( vFanouts, nNewSize ); for ( k = nOldSize; k < nNewSize; k++ ) @@ -592,12 +593,12 @@ void Abc_NtkPrintFanioNew( FILE * pFile, Abc_Ntk_t * pNtk, int fMffc ) nFanouts = Abc_ObjFanoutNum(pNode); nFaninsAll += nFanins; nFanoutsAll += nFanouts; - nFaninsMax = ABC_MAX( nFaninsMax, nFanins ); - nFanoutsMax = ABC_MAX( nFanoutsMax, nFanouts ); + nFaninsMax = Abc_MaxInt( nFaninsMax, nFanins ); + nFanoutsMax = Abc_MaxInt( nFanoutsMax, nFanouts ); } // allocate storage for fanin/fanout numbers - nSizeMax = ABC_MAX( 10 * (Extra_Base10Log(nFaninsMax) + 1), 10 * (Extra_Base10Log(nFanoutsMax) + 1) ); + nSizeMax = Abc_MaxInt( 10 * (Abc_Base10Log(nFaninsMax) + 1), 10 * (Abc_Base10Log(nFanoutsMax) + 1) ); vFanins = Vec_IntStart( nSizeMax ); vFanouts = Vec_IntStart( nSizeMax ); diff --git a/src/base/abci/abcProve.c b/src/base/abci/abcProve.c index 154c5e1c..3a6c42a4 100644 --- a/src/base/abci/abcProve.c +++ b/src/base/abci/abcProve.c @@ -18,10 +18,11 @@ ***********************************************************************/ -#include "abc.h" -#include "fraig.h" -#include "math.h" -#include "extra.h" +#include + +#include "src/base/abc/abc.h" +#include "src/proof/fraig/fraig.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START @@ -254,7 +255,7 @@ Abc_Ntk_t * Abc_NtkMiterFraig( Abc_Ntk_t * pNtk, int nBTLimit, ABC_INT64_T nInsp // 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 ); + nWordsMin = Abc_MinInt( nWords1, nWords2 ); // set the FRAIGing parameters Fraig_ParamsSetDefault( pParams ); diff --git a/src/base/abci/abcQbf.c b/src/base/abci/abcQbf.c index e6395ef3..98cb3eb6 100644 --- a/src/base/abci/abcQbf.c +++ b/src/base/abci/abcQbf.c @@ -18,7 +18,7 @@ ***********************************************************************/ -#include "abc.h" +#include "src/base/abc/abc.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcQuant.c b/src/base/abci/abcQuant.c index 262797d2..7185cf8d 100644 --- a/src/base/abci/abcQuant.c +++ b/src/base/abci/abcQuant.c @@ -18,8 +18,7 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcReach.c b/src/base/abci/abcReach.c index f7bc5186..e1ffa309 100644 --- a/src/base/abci/abcReach.c +++ b/src/base/abci/abcReach.c @@ -18,8 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcRec.c b/src/base/abci/abcRec.c index abb4be4b..e51b15bd 100644 --- a/src/base/abci/abcRec.c +++ b/src/base/abci/abcRec.c @@ -18,9 +18,9 @@ ***********************************************************************/ -#include "abc.h" -#include "if.h" -#include "kit.h" +#include "src/base/abc/abc.h" +#include "src/map/if/if.h" +#include "src/bool/kit/kit.h" ABC_NAMESPACE_IMPL_START @@ -246,7 +246,7 @@ void Rec_ObjSet(Abc_ManRec_t* p, Rec_Obj_t* pRecObj, Abc_Obj_t* pObj, char* newD Abc_NodeSetTravIdCurrent(pObj); Delay0 = If_CutDelayRecComput_rec(Abc_ObjFanin0(pObj), vCosts); Delay1 = If_CutDelayRecComput_rec(Abc_ObjFanin1(pObj), vCosts); - Delay = ABC_MAX(Delay0, Delay1) + 1; + Delay = Abc_MaxInt(Delay0, Delay1) + 1; Vec_StrWriteEntry(vCosts,pObj->Id,Delay); return Delay; }*/ @@ -299,7 +299,7 @@ char If_CutDepthRecComput_rec(Abc_Obj_t* pObj, int iLeaf) return -IF_BIG_CHAR; Depth0 = If_CutDepthRecComput_rec(Abc_ObjFanin0(pObj), iLeaf); Depth1 = If_CutDepthRecComput_rec(Abc_ObjFanin1(pObj), iLeaf); - Depth = ABC_MAX(Depth0, Depth1); + Depth = Abc_MaxInt(Depth0, Depth1); Depth = (Depth == -IF_BIG_CHAR) ? -IF_BIG_CHAR : Depth + 1; assert(Depth <= 127); return Depth; @@ -1064,7 +1064,7 @@ void Abc_NtkRecLibMerge(Abc_Ntk_t* pNtk) 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)) ) ); + Abc_ObjSetMax( pObj, Abc_MaxInt( Abc_ObjGetMax(Abc_ObjFanin0(pObj)), Abc_ObjGetMax(Abc_ObjFanin1(pObj)) ) ); // insert the PO nodes into the table Abc_NtkForEachPo( pNtk, pObj, i ) @@ -1105,7 +1105,7 @@ void Abc_NtkRecRezieHash(Abc_ManRec_t* p) int nBinsNew, Counter, i; int clk = clock(); // get the new table size - nBinsNew = Cudd_Prime( 3 * p->nBins ); + nBinsNew = Abc_PrimeCudd( 3 * p->nBins ); printf("Hash table resize from %d to %d.\n", p->nBins, nBinsNew); // allocate a new array pBinsNew = ABC_ALLOC( Rec_Obj_t *, nBinsNew ); @@ -1242,7 +1242,7 @@ p->timeTruth += clock() - clk; 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)) ) ); + Abc_ObjSetMax( pObj, Abc_MaxInt( Abc_ObjGetMax(Abc_ObjFanin0(pObj)), Abc_ObjGetMax(Abc_ObjFanin1(pObj)) ) ); // insert the PO nodes into the table timeInsert = clock(); @@ -1308,7 +1308,7 @@ void Abc_NtkRecDumpTruthTables( Abc_ManRec_t * p ) for ( i = 0; i < p->nBins; i++ ) for ( pObj = p->pBins[i]; pObj; pObj = pObj->pCopy ) { - pTruth = Vec_PtrEntry(p->vTtNodes, pObj->Id); + pTruth = (unsigned *)Vec_PtrEntry(p->vTtNodes, pObj->Id); if ( (int)Kit_TruthSupport(pTruth, nVars) != (1<nBins; i++ ) for ( entry = p->pBins[i]; entry; entry = entry->pCopy ) { int tmp = 0; - pTruth = Vec_PtrEntry(p->vTtNodes, entry->Id); + pTruth = (unsigned *)Vec_PtrEntry(p->vTtNodes, entry->Id); /*if ( (int)Kit_TruthSupport(pTruth, nVars) != (1<Level; Level2 = Dec_GraphNode( pGraph, eNode2.Node )->Level; - Dec_GraphNode( pGraph, eNode3.Node )->Level = 1 + ABC_MAX(Level1, Level2); + Dec_GraphNode( pGraph, eNode3.Node )->Level = 1 + Abc_MaxInt(Level1, Level2); // get the new node if possible if ( pNode3 ) { @@ -708,7 +708,7 @@ Dec_Edge_t Abc_NodeEvaluateDsd_rec( Dec_Graph_t * pGraph, Abc_ManRst_t * pManRst // 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); + Dec_GraphNode( pGraph, eNode3.Node )->Level = 2 + Abc_MaxInt(Level1, Level2); // get the new node if possible if ( pNode3 ) { @@ -824,7 +824,7 @@ Dec_Edge_t Abc_NodeEvaluateDsd_rec( Dec_Graph_t * pGraph, Abc_ManRst_t * pManRst 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 ); + Dec_GraphNode( pGraph, eResult.Node )->Level = 2 + Abc_MaxInt( Abc_MaxInt(Level1, Level2), Level3 ); // get the new node if possible if ( pNode4 ) { diff --git a/src/base/abci/abcResub.c b/src/base/abci/abcResub.c index aab4d1ce..b03c36aa 100644 --- a/src/base/abci/abcResub.c +++ b/src/base/abci/abcResub.c @@ -18,9 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "dec.h" -#include "extra.h" +#include "src/base/abc/abc.h" +#include "src/bool/dec/dec.h" ABC_NAMESPACE_IMPL_START @@ -1151,7 +1150,7 @@ Dec_Graph_t * Abc_ManResubDivs12( Abc_ManRes_t * p, int Required ) break; if ( w == p->nWords ) { - LevelMax = ABC_MAX( pObj0->Level, ABC_MAX(pObj1->Level, pObj2->Level) ); + LevelMax = Abc_MaxInt( pObj0->Level, Abc_MaxInt(pObj1->Level, pObj2->Level) ); assert( LevelMax <= Required - 1 ); pObjMax = NULL; @@ -1192,7 +1191,7 @@ Dec_Graph_t * Abc_ManResubDivs12( Abc_ManRes_t * p, int Required ) break; if ( w == p->nWords ) { - LevelMax = ABC_MAX( pObj0->Level, ABC_MAX(pObj1->Level, pObj2->Level) ); + LevelMax = Abc_MaxInt( pObj0->Level, Abc_MaxInt(pObj1->Level, pObj2->Level) ); assert( LevelMax <= Required - 1 ); pObjMax = NULL; diff --git a/src/base/abci/abcRewrite.c b/src/base/abci/abcRewrite.c index 54e19f50..5e2745b9 100644 --- a/src/base/abci/abcRewrite.c +++ b/src/base/abci/abcRewrite.c @@ -18,10 +18,9 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" -#include "rwr.h" -#include "dec.h" +#include "src/base/abc/abc.h" +#include "src/opt/rwr/rwr.h" +#include "src/bool/dec/dec.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcRr.c b/src/base/abci/abcRr.c index 3e60ebf9..61c8d085 100644 --- a/src/base/abci/abcRr.c +++ b/src/base/abci/abcRr.c @@ -18,10 +18,9 @@ ***********************************************************************/ -#include "abc.h" -#include "fraig.h" -#include "extra.h" -#include "sim.h" +#include "src/base/abc/abc.h" +#include "src/proof/fraig/fraig.h" +#include "src/opt/sim/sim.h" ABC_NAMESPACE_IMPL_START @@ -434,7 +433,7 @@ int Abc_NtkRRWindow( Abc_RRMan_t * p ) 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 ); + LevelMin = Abc_MaxInt( 0, ((int)p->pFanin->Level) - p->nFaninLevels ); LevelMax = (int)pEdgeFanout->Level + p->nFanoutLevels; // start the TFI leaves with the fanin diff --git a/src/base/abci/abcSat.c b/src/base/abci/abcSat.c index b0c5024a..29f13bda 100644 --- a/src/base/abci/abcSat.c +++ b/src/base/abci/abcSat.c @@ -18,10 +18,11 @@ ***********************************************************************/ -#include "abc.h" -#include "main.h" -#include "cmd.h" -#include "satSolver.h" +#include "src/base/abc/abc.h" +#include "src/base/main/main.h" +#include "src/base/cmd/cmd.h" +#include "src/sat/bsat/satSolver.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START @@ -590,7 +591,7 @@ int Abc_NtkMiterSatCreateInt( sat_solver * pSat, Abc_Ntk_t * pNtk ) continue; pPrefVars[nVars++] = (int)pNode->pCopy; } - nVars = ABC_MIN( nVars, 10 ); + nVars = Abc_MinInt( nVars, 10 ); ASat_SolverSetPrefVars( pSat, pPrefVars, nVars ); } */ diff --git a/src/base/abci/abcScorr.c b/src/base/abci/abcScorr.c index 9687003b..e7683edf 100644 --- a/src/base/abci/abcScorr.c +++ b/src/base/abci/abcScorr.c @@ -18,13 +18,13 @@ ***********************************************************************/ -#include "abc.h" -#include "ioAbc.h" -#include "saig.h" -#include "ssw.h" -#include "gia.h" -#include "cec.h" -#include "giaAig.h" +#include "src/base/abc/abc.h" +#include "src/base/io/ioAbc.h" +#include "src/aig/saig/saig.h" +#include "src/proof/ssw/ssw.h" +#include "src/aig/gia/gia.h" +#include "src/proof/cec/cec.h" +#include "src/aig/gia/giaAig.h" ABC_NAMESPACE_IMPL_START @@ -80,7 +80,7 @@ Vec_Int_t * Abc_NtkMapGiaIntoNameId( Abc_Ntk_t * pNetlist, Aig_Man_t * pAig, Gia if ( pGia == NULL ) Vec_IntWriteEntry( vId2Name, Aig_ObjId(pObjAig), Abc_ObjId(pNet) ); else - Vec_IntWriteEntry( vId2Name, Gia_Lit2Var(pObjAig->iData), Abc_ObjId(pNet) ); + Vec_IntWriteEntry( vId2Name, Abc_Lit2Var(pObjAig->iData), Abc_ObjId(pNet) ); } } // overwrite CO names @@ -95,7 +95,7 @@ Vec_Int_t * Abc_NtkMapGiaIntoNameId( Abc_Ntk_t * pNetlist, Aig_Man_t * pAig, Gia if ( pGia == NULL ) Vec_IntWriteEntry( vId2Name, Aig_ObjId(pObjAig), Abc_ObjId(pNet) ); else - Vec_IntWriteEntry( vId2Name, Gia_Lit2Var(pObjAig->iData), Abc_ObjId(pNet) ); + Vec_IntWriteEntry( vId2Name, Abc_Lit2Var(pObjAig->iData), Abc_ObjId(pNet) ); } } // overwrite CI names @@ -110,7 +110,7 @@ Vec_Int_t * Abc_NtkMapGiaIntoNameId( Abc_Ntk_t * pNetlist, Aig_Man_t * pAig, Gia if ( pGia == NULL ) Vec_IntWriteEntry( vId2Name, Aig_ObjId(pObjAig), Abc_ObjId(pNet) ); else - Vec_IntWriteEntry( vId2Name, Gia_Lit2Var(pObjAig->iData), Abc_ObjId(pNet) ); + Vec_IntWriteEntry( vId2Name, Abc_Lit2Var(pObjAig->iData), Abc_ObjId(pNet) ); } } return vId2Name; diff --git a/src/base/abci/abcSense.c b/src/base/abci/abcSense.c index 8a477c4e..3bcbc205 100644 --- a/src/base/abci/abcSense.c +++ b/src/base/abci/abcSense.c @@ -18,9 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "fraig.h" -#include "extra.h" +#include "src/base/abc/abc.h" +#include "src/proof/fraig/fraig.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcSpeedup.c b/src/base/abci/abcSpeedup.c index 35a901ad..2c3ebca0 100644 --- a/src/base/abci/abcSpeedup.c +++ b/src/base/abci/abcSpeedup.c @@ -18,10 +18,10 @@ ***********************************************************************/ -#include "abc.h" -#include "main.h" -#include "if.h" -#include "aig.h" +#include "src/base/abc/abc.h" +#include "src/base/main/main.h" +#include "src/map/if/if.h" +#include "src/aig/aig/aig.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcStrash.c b/src/base/abci/abcStrash.c index e08def57..996c9db0 100644 --- a/src/base/abci/abcStrash.c +++ b/src/base/abci/abcStrash.c @@ -18,9 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" -#include "dec.h" +#include "src/base/abc/abc.h" +#include "src/bool/dec/dec.h" ABC_NAMESPACE_IMPL_START @@ -468,7 +467,7 @@ Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels ) assert( Abc_NtkIsStrash(pNtk) ); assert( Abc_NtkCoNum(pNtk) == 1 ); // get the cutoff level - LevelCut = ABC_MAX( 0, Abc_AigLevel(pNtk) - nLevels ); + LevelCut = Abc_MaxInt( 0, Abc_AigLevel(pNtk) - nLevels ); // start the network pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); diff --git a/src/base/abci/abcSweep.c b/src/base/abci/abcSweep.c index 43c99d90..a898f26c 100644 --- a/src/base/abci/abcSweep.c +++ b/src/base/abci/abcSweep.c @@ -18,13 +18,13 @@ ***********************************************************************/ -#include "abc.h" -#include "main.h" -#include "fraig.h" +#include "src/base/abc/abc.h" +#include "src/base/main/main.h" +#include "src/proof/fraig/fraig.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START - //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abci/abcSymm.c b/src/base/abci/abcSymm.c index 41abc4db..2a36be14 100644 --- a/src/base/abci/abcSymm.c +++ b/src/base/abci/abcSymm.c @@ -18,9 +18,9 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" -#include "sim.h" +#include "src/base/abc/abc.h" +#include "src/opt/sim/sim.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcTiming.c b/src/base/abci/abcTiming.c index 79768645..d8334e9d 100644 --- a/src/base/abci/abcTiming.c +++ b/src/base/abci/abcTiming.c @@ -18,9 +18,9 @@ ***********************************************************************/ -#include "abc.h" -#include "main.h" -#include "mio.h" +#include "src/base/abc/abc.h" +#include "src/base/main/main.h" +#include "src/map/mio/mio.h" ABC_NAMESPACE_IMPL_START @@ -139,7 +139,7 @@ void Abc_NtkTimeSetDefaultArrival( Abc_Ntk_t * pNtk, float Rise, float Fall ) pNtk->pManTime = Abc_ManTimeStart(); pNtk->pManTime->tArrDef.Rise = Rise; pNtk->pManTime->tArrDef.Fall = Fall; - pNtk->pManTime->tArrDef.Worst = ABC_MAX( Rise, Fall ); + pNtk->pManTime->tArrDef.Worst = Abc_MaxInt( Rise, Fall ); } /**Function************************************************************* @@ -161,7 +161,7 @@ void Abc_NtkTimeSetDefaultRequired( Abc_Ntk_t * pNtk, float Rise, float Fall ) pNtk->pManTime = Abc_ManTimeStart(); pNtk->pManTime->tReqDef.Rise = Rise; pNtk->pManTime->tReqDef.Fall = Fall; - pNtk->pManTime->tReqDef.Worst = ABC_MAX( Rise, Fall ); + pNtk->pManTime->tReqDef.Worst = Abc_MaxInt( Rise, Fall ); } /**Function************************************************************* @@ -189,7 +189,7 @@ void Abc_NtkTimeSetArrival( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall pTime = (Abc_Time_t *)vTimes->pArray[ObjId]; pTime->Rise = Rise; pTime->Fall = Fall; - pTime->Worst = ABC_MAX( Rise, Fall ); + pTime->Worst = Abc_MaxInt( Rise, Fall ); } /**Function************************************************************* @@ -217,7 +217,7 @@ void Abc_NtkTimeSetRequired( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall pTime = (Abc_Time_t *)vTimes->pArray[ObjId]; pTime->Rise = Rise; pTime->Fall = Fall; - pTime->Worst = ABC_MAX( Rise, Fall ); + pTime->Worst = Abc_MaxInt( Rise, Fall ); } /**Function************************************************************* @@ -625,7 +625,7 @@ void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode ) } pPin = Mio_PinReadNext(pPin); } - pTimeOut->Worst = ABC_MAX( pTimeOut->Rise, pTimeOut->Fall ); + pTimeOut->Worst = Abc_MaxInt( pTimeOut->Rise, pTimeOut->Fall ); } @@ -647,7 +647,7 @@ 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) ); + Level = Abc_MaxInt( Level, Abc_ObjLevel(pFanin) ); return Level + 1; } @@ -669,7 +669,7 @@ int Abc_ObjReverseLevelNew( Abc_Obj_t * pObj ) Abc_ObjForEachFanout( pObj, pFanout, i ) { LevelCur = Abc_ObjReverseLevel( pFanout ); - Level = ABC_MAX( Level, LevelCur ); + Level = Abc_MaxInt( Level, LevelCur ); } return Level + 1; } @@ -827,7 +827,7 @@ void Abc_NtkUpdateLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ) assert( Abc_ObjLevel(pFanout) >= Lev ); Vec_VecPush( vLevels, Abc_ObjLevel(pFanout), pFanout ); // Counter++; -// CounterMax = ABC_MAX( CounterMax, Counter ); +// CounterMax = Abc_MaxInt( CounterMax, Counter ); pFanout->fMarkA = 1; } } diff --git a/src/base/abci/abcUnate.c b/src/base/abci/abcUnate.c index 829a83bd..a56973b6 100644 --- a/src/base/abci/abcUnate.c +++ b/src/base/abci/abcUnate.c @@ -18,8 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcUnreach.c b/src/base/abci/abcUnreach.c index f62ec7fc..72514029 100644 --- a/src/base/abci/abcUnreach.c +++ b/src/base/abci/abcUnreach.c @@ -18,8 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcVerify.c b/src/base/abci/abcVerify.c index 7a9a5239..9b88cb8a 100644 --- a/src/base/abci/abcVerify.c +++ b/src/base/abci/abcVerify.c @@ -18,15 +18,15 @@ ***********************************************************************/ -#include "abc.h" -#include "main.h" -#include "cmd.h" -#include "fraig.h" -#include "sim.h" -#include "aig.h" -#include "saig.h" -#include "gia.h" -#include "ssw.h" +#include "src/base/abc/abc.h" +#include "src/base/main/main.h" +#include "src/base/cmd/cmd.h" +#include "src/proof/fraig/fraig.h" +#include "src/opt/sim/sim.h" +#include "src/aig/aig/aig.h" +#include "src/aig/saig/saig.h" +#include "src/aig/gia/gia.h" +#include "src/proof/ssw/ssw.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/abcXsim.c b/src/base/abci/abcXsim.c index 12ad0e68..23bbbe1a 100644 --- a/src/base/abci/abcXsim.c +++ b/src/base/abci/abcXsim.c @@ -18,8 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "gia.h" +#include "src/base/abc/abc.h" +#include "src/aig/gia/gia.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/abci/fahout_cut.c b/src/base/abci/fahout_cut.c new file mode 100644 index 00000000..0b4b421f --- /dev/null +++ b/src/base/abci/fahout_cut.c @@ -0,0 +1,357 @@ +/**CFile**************************************************************** + + FileName [abcMerge.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [LUT merging algorithm.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcMerge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "base/abc/abc.h" +#include "aig/aig/aig.h" +#include "aig/nwk/nwkMerge.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Marks the fanins of the node with the current trav ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMarkFanins_rec( Abc_Obj_t * pLut, int nLevMin ) +{ + Abc_Obj_t * pNext; + int i; + if ( !Abc_ObjIsNode(pLut) ) + return; + if ( Abc_NodeIsTravIdCurrent( pLut ) ) + return; + Abc_NodeSetTravIdCurrent( pLut ); + if ( Abc_ObjLevel(pLut) < nLevMin ) + return; + Abc_ObjForEachFanin( pLut, pNext, i ) + Abc_NtkMarkFanins_rec( pNext, nLevMin ); +} + +/**Function************************************************************* + + Synopsis [Marks the fanouts of the node with the current trav ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMarkFanouts_rec( Abc_Obj_t * pLut, int nLevMax, int nFanMax ) +{ + Abc_Obj_t * pNext; + int i; + if ( !Abc_ObjIsNode(pLut) ) + return; + if ( Abc_NodeIsTravIdCurrent( pLut ) ) + return; + Abc_NodeSetTravIdCurrent( pLut ); + if ( Abc_ObjLevel(pLut) > nLevMax ) + return; + if ( Abc_ObjFanoutNum(pLut) > nFanMax ) + return; + Abc_ObjForEachFanout( pLut, pNext, i ) + Abc_NtkMarkFanouts_rec( pNext, nLevMax, nFanMax ); +} + +/**Function************************************************************* + + Synopsis [Collects the circle of nodes around the given set.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCollectCircle( Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, int nFanMax ) +{ + Abc_Obj_t * pObj, * pNext; + int i, k; + Vec_PtrClear( vNext ); + Vec_PtrForEachEntry( Vec_Int_t *, vStart, pObj, i ) + { + Abc_ObjForEachFanin( pObj, pNext, k ) + { + if ( !Abc_ObjIsNode(pNext) ) + continue; + if ( Abc_NodeIsTravIdCurrent( pNext ) ) + continue; + Abc_NodeSetTravIdCurrent( pNext ); + Vec_PtrPush( vNext, pNext ); + } + Abc_ObjForEachFanout( pObj, pNext, k ) + { + if ( !Abc_ObjIsNode(pNext) ) + continue; + if ( Abc_NodeIsTravIdCurrent( pNext ) ) + continue; + Abc_NodeSetTravIdCurrent( pNext ); + if ( Abc_ObjFanoutNum(pNext) > nFanMax ) + continue; + Vec_PtrPush( vNext, pNext ); + } + } +} + +/**Function************************************************************* + + Synopsis [Collects the circle of nodes removes from the given one.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCollectNonOverlapCands( Abc_Obj_t * pLut, Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars ) +{ + Vec_Ptr_t * vTemp; + Abc_Obj_t * pObj; + int i, k; + Vec_PtrClear( vCands ); + if ( pPars->nMaxSuppSize - Abc_ObjFaninNum(pLut) <= 1 ) + return; + + // collect nodes removed by this distance + assert( pPars->nMaxDistance > 0 ); + Vec_PtrClear( vStart ); + Vec_PtrPush( vStart, pLut ); + Abc_NtkIncrementTravId( pLut->pNtk ); + Abc_NodeSetTravIdCurrent( pLut ); + for ( i = 1; i <= pPars->nMaxDistance; i++ ) + { + Abc_NtkCollectCircle( vStart, vNext, pPars->nMaxFanout ); + vTemp = vStart; + vStart = vNext; + vNext = vTemp; + // collect the nodes in vStart + Vec_PtrForEachEntry( Vec_Int_t *, vStart, pObj, k ) + Vec_PtrPush( vCands, pObj ); + } + + // mark the TFI/TFO nodes + Abc_NtkIncrementTravId( pLut->pNtk ); + if ( pPars->fUseTfiTfo ) + Abc_NodeSetTravIdCurrent( pLut ); + else + { + Abc_NodeSetTravIdPrevious( pLut ); + Abc_NtkMarkFanins_rec( pLut, Abc_ObjLevel(pLut) - pPars->nMaxDistance ); + Abc_NodeSetTravIdPrevious( pLut ); + Abc_NtkMarkFanouts_rec( pLut, Abc_ObjLevel(pLut) + pPars->nMaxDistance, pPars->nMaxFanout ); + } + + // collect nodes satisfying the following conditions: + // - they are close enough in terms of distance + // - they are not in the TFI/TFO of the LUT + // - they have no more than the given number of fanins + // - they have no more than the given diff in delay + k = 0; + Vec_PtrForEachEntry( Vec_Int_t *, vCands, pObj, i ) + { + if ( Abc_NodeIsTravIdCurrent(pObj) ) + continue; + if ( Abc_ObjFaninNum(pLut) + Abc_ObjFaninNum(pObj) > pPars->nMaxSuppSize ) + continue; + if ( Abc_ObjLevel(pLut) - Abc_ObjLevel(pObj) > pPars->nMaxLevelDiff || + Abc_ObjLevel(pObj) - Abc_ObjLevel(pLut) > pPars->nMaxLevelDiff ) + continue; + Vec_PtrWriteEntry( vCands, k++, pObj ); + } + Vec_PtrShrink( vCands, k ); +} + + +/**Function************************************************************* + + Synopsis [Count the total number of fanins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCountTotalFanins( Abc_Obj_t * pLut, Abc_Obj_t * pCand ) +{ + Abc_Obj_t * pFanin; + int i, nCounter = Abc_ObjFaninNum(pLut); + Abc_ObjForEachFanin( pCand, pFanin, i ) + nCounter += !pFanin->fMarkC; + return nCounter; +} + +/**Function************************************************************* + + Synopsis [Collects overlapping candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCollectOverlapCands( Abc_Obj_t * pLut, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars ) +{ + Abc_Obj_t * pFanin, * pObj; + int i, k; + // mark fanins of pLut + Abc_ObjForEachFanin( pLut, pFanin, i ) + pFanin->fMarkC = 1; + // collect the matching fanouts of each fanin of the node + Vec_PtrClear( vCands ); + Abc_NtkIncrementTravId( pLut->pNtk ); + Abc_NodeSetTravIdCurrent( pLut ); + Abc_ObjForEachFanin( pLut, pFanin, i ) + { + if ( !Abc_ObjIsNode(pFanin) ) + continue; + if ( Abc_ObjFanoutNum(pFanin) > pPars->nMaxFanout ) + continue; + Abc_ObjForEachFanout( pFanin, pObj, k ) + { + if ( !Abc_ObjIsNode(pObj) ) + continue; + if ( Abc_NodeIsTravIdCurrent( pObj ) ) + continue; + Abc_NodeSetTravIdCurrent( pObj ); + // check the difference in delay + if ( Abc_ObjLevel(pLut) - Abc_ObjLevel(pObj) > pPars->nMaxLevelDiff || + Abc_ObjLevel(pObj) - Abc_ObjLevel(pLut) > pPars->nMaxLevelDiff ) + continue; + // check the total number of fanins of the node + if ( Abc_NtkCountTotalFanins(pLut, pObj) > pPars->nMaxSuppSize ) + continue; + Vec_PtrPush( vCands, pObj ); + } + } + // unmark fanins of pLut + Abc_ObjForEachFanin( pLut, pFanin, i ) + pFanin->fMarkC = 0; +} + +/**Function************************************************************* + + Synopsis [Performs LUT merging with parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkLutMerge( Abc_Ntk_t * pNtk, Nwk_LMPars_t * pPars ) +{ + Nwk_Grf_t * p; + Vec_Int_t * vResult; + Vec_Ptr_t * vStart, * vNext, * vCands1, * vCands2; + Abc_Obj_t * pLut, * pCand; + int i, k, nVertsMax, nCands, clk = clock(); + // count the number of vertices + nVertsMax = 0; + Abc_NtkForEachNode( pNtk, pLut, i ) + nVertsMax += (int)(Abc_ObjFaninNum(pLut) <= pPars->nMaxLutSize); + p = Nwk_ManGraphAlloc( nVertsMax ); + // create graph + vStart = Vec_PtrAlloc( 1000 ); + vNext = Vec_PtrAlloc( 1000 ); + vCands1 = Vec_PtrAlloc( 1000 ); + vCands2 = Vec_PtrAlloc( 1000 ); + nCands = 0; + Abc_NtkForEachNode( pNtk, pLut, i ) + { + if ( Abc_ObjFaninNum(pLut) > pPars->nMaxLutSize ) + continue; + Abc_NtkCollectOverlapCands( pLut, vCands1, pPars ); + if ( pPars->fUseDiffSupp ) + Abc_NtkCollectNonOverlapCands( pLut, vStart, vNext, vCands2, pPars ); + if ( Vec_PtrSize(vCands1) == 0 && Vec_PtrSize(vCands2) == 0 ) + continue; + nCands += Vec_PtrSize(vCands1) + Vec_PtrSize(vCands2); + // save candidates + Vec_PtrForEachEntry( Vec_Int_t *, vCands1, pCand, k ) + Nwk_ManGraphHashEdge( p, Abc_ObjId(pLut), Abc_ObjId(pCand) ); + Vec_PtrForEachEntry( Vec_Int_t *, vCands2, pCand, k ) + Nwk_ManGraphHashEdge( p, Abc_ObjId(pLut), Abc_ObjId(pCand) ); + // print statistics about this node + if ( pPars->fVeryVerbose ) + printf( "Node %6d : Fanins = %d. Fanouts = %3d. Cand1 = %3d. Cand2 = %3d.\n", + Abc_ObjId(pLut), Abc_ObjFaninNum(pLut), Abc_ObjFaninNum(pLut), + Vec_PtrSize(vCands1), Vec_PtrSize(vCands2) ); + } + Vec_PtrFree( vStart ); + Vec_PtrFree( vNext ); + Vec_PtrFree( vCands1 ); + Vec_PtrFree( vCands2 ); + if ( pPars->fVerbose ) + { + printf( "Mergable LUTs = %6d. Total cands = %6d. ", p->nVertsMax, nCands ); + ABC_PRT( "Deriving graph", clock() - clk ); + } + // solve the graph problem + clk = clock(); + Nwk_ManGraphSolve( p ); + if ( pPars->fVerbose ) + { + printf( "GRAPH: Nodes = %6d. Edges = %6d. Pairs = %6d. ", + p->nVerts, p->nEdges, Vec_IntSize(p->vPairs)/2 ); + ABC_PRT( "Solving", clock() - clk ); + Nwk_ManGraphReportMemoryUsage( p ); + } + vResult = p->vPairs; p->vPairs = NULL; +/* + for ( i = 0; i < vResult->nSize; i += 2 ) + printf( "(%d,%d) ", vResult->pArray[i], vResult->pArray[i+1] ); + printf( "\n" ); +*/ + Nwk_ManGraphFree( p ); + return vResult; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/base/abci/module.make b/src/base/abci/module.make index 965e0258..8b2ef27b 100644 --- a/src/base/abci/module.make +++ b/src/base/abci/module.make @@ -1,5 +1,4 @@ SRC += src/base/abci/abc.c \ - src/base/abci/abcAbc8.c \ src/base/abci/abcAttach.c \ src/base/abci/abcAuto.c \ src/base/abci/abcBalance.c \ diff --git a/src/base/cmd/cmd.c b/src/base/cmd/cmd.c index 35eb535a..6c8a3c2e 100644 --- a/src/base/cmd/cmd.c +++ b/src/base/cmd/cmd.c @@ -24,10 +24,10 @@ #include #endif -#include "abc.h" -#include "mainInt.h" +#include "src/base/abc/abc.h" +#include "src/base/main/mainInt.h" #include "cmdInt.h" -#include "utilSignal.h" +#include "src/misc/util/utilSignal.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/cmd/cmd.h b/src/base/cmd/cmd.h index 740cf758..f424f090 100644 --- a/src/base/cmd/cmd.h +++ b/src/base/cmd/cmd.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __CMD_H__ -#define __CMD_H__ +#ifndef ABC__base__cmd__cmd_h +#define ABC__base__cmd__cmd_h //////////////////////////////////////////////////////////////////////// diff --git a/src/base/cmd/cmdAlias.c b/src/base/cmd/cmdAlias.c index 6078927d..67cdc318 100644 --- a/src/base/cmd/cmdAlias.c +++ b/src/base/cmd/cmdAlias.c @@ -18,7 +18,7 @@ ***********************************************************************/ -#include "abc.h" +#include "src/base/abc/abc.h" #include "cmdInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/cmd/cmdApi.c b/src/base/cmd/cmdApi.c index 40c1dbf9..9357a93c 100644 --- a/src/base/cmd/cmdApi.c +++ b/src/base/cmd/cmdApi.c @@ -18,8 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "mainInt.h" +#include "src/base/abc/abc.h" +#include "src/base/main/mainInt.h" #include "cmdInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/cmd/cmdFlag.c b/src/base/cmd/cmdFlag.c index a220042b..7b46e8fc 100644 --- a/src/base/cmd/cmdFlag.c +++ b/src/base/cmd/cmdFlag.c @@ -18,8 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "mainInt.h" +#include "src/base/abc/abc.h" +#include "src/base/main/mainInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/cmd/cmdHist.c b/src/base/cmd/cmdHist.c index a2f64027..b6a4d535 100644 --- a/src/base/cmd/cmdHist.c +++ b/src/base/cmd/cmdHist.c @@ -18,8 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "mainInt.h" +#include "src/base/abc/abc.h" +#include "src/base/main/mainInt.h" #include "cmd.h" #include "cmdInt.h" diff --git a/src/base/cmd/cmdInt.h b/src/base/cmd/cmdInt.h index 0ea9b364..6c1add92 100644 --- a/src/base/cmd/cmdInt.h +++ b/src/base/cmd/cmdInt.h @@ -18,15 +18,15 @@ ***********************************************************************/ -#ifndef __CMD_INT_H__ -#define __CMD_INT_H__ +#ifndef ABC__base__cmd__cmdInt_h +#define ABC__base__cmd__cmdInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// -#include "mainInt.h" +#include "src/base/main/mainInt.h" #include "cmd.h" ABC_NAMESPACE_HEADER_START diff --git a/src/base/cmd/cmdLoad.c b/src/base/cmd/cmdLoad.c index 797275db..e4d8269a 100644 --- a/src/base/cmd/cmdLoad.c +++ b/src/base/cmd/cmdLoad.c @@ -18,11 +18,11 @@ ***********************************************************************/ -#include "abc.h" -#include "mainInt.h" +#include "src/base/abc/abc.h" +#include "src/base/main/mainInt.h" #include "cmd.h" #include "cmdInt.h" -#include "utilSignal.h" +#include "src/misc/util/utilSignal.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/cmd/cmdPlugin.c b/src/base/cmd/cmdPlugin.c index 8649d465..84e89cb1 100644 --- a/src/base/cmd/cmdPlugin.c +++ b/src/base/cmd/cmdPlugin.c @@ -25,11 +25,11 @@ #include #endif -#include "abc.h" -#include "mainInt.h" +#include "src/base/abc/abc.h" +#include "src/base/main/mainInt.h" #include "cmd.h" #include "cmdInt.h" -#include "utilSignal.h" +#include "src/misc/util/utilSignal.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/cmd/cmdUtils.c b/src/base/cmd/cmdUtils.c index 683d336e..e6dbed4e 100644 --- a/src/base/cmd/cmdUtils.c +++ b/src/base/cmd/cmdUtils.c @@ -18,8 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "mainInt.h" +#include "src/base/abc/abc.h" +#include "src/base/main/mainInt.h" #include "cmdInt.h" #include diff --git a/src/base/io/io.c b/src/base/io/io.c index 1cea2e37..92dbe9fc 100644 --- a/src/base/io/io.c +++ b/src/base/io/io.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "ioAbc.h" -#include "mainInt.h" -#include "saig.h" +#include "src/base/main/mainInt.h" +#include "src/aig/saig/saig.h" ABC_NAMESPACE_IMPL_START @@ -1998,7 +1998,7 @@ usage: ABC_NAMESPACE_IMPL_END -#include "fra.h" +#include "src/proof/fra/fra.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/io/ioAbc.h b/src/base/io/ioAbc.h index f3db4c15..7a38ae5c 100644 --- a/src/base/io/ioAbc.h +++ b/src/base/io/ioAbc.h @@ -18,16 +18,16 @@ ***********************************************************************/ -#ifndef __IO_H__ -#define __IO_H__ +#ifndef ABC__base__io__ioAbc_h +#define ABC__base__io__ioAbc_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" +#include "src/misc/extra/extra.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// diff --git a/src/base/io/ioInt.h b/src/base/io/ioInt.h index 9ded63e4..fed639a4 100644 --- a/src/base/io/ioInt.h +++ b/src/base/io/ioInt.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __IO_INT_H__ -#define __IO_INT_H__ +#ifndef ABC__base__io__ioInt_h +#define ABC__base__io__ioInt_h ABC_NAMESPACE_HEADER_START diff --git a/src/base/io/ioReadAiger.c b/src/base/io/ioReadAiger.c index 13987a1b..55ef16db 100644 --- a/src/base/io/ioReadAiger.c +++ b/src/base/io/ioReadAiger.c @@ -21,9 +21,9 @@ // The code in this file is developed in collaboration with Mark Jarvin of Toronto. -#include "bzlib.h" +#include "src/misc/bzlib/bzlib.h" #include "ioAbc.h" -#include "zlib.h" +#include "src/misc/zlib/zlib.h" ABC_NAMESPACE_IMPL_START @@ -358,7 +358,7 @@ Abc_Ntk_t * Io_ReadAiger( char * pFileName, int fCheck ) pObj = Abc_NtkCreatePo(pNtkNew); } // create the latches - nDigits = Extra_Base10Log( nLatches ); + nDigits = Abc_Base10Log( nLatches ); for ( i = 0; i < nLatches; i++ ) { pObj = Abc_NtkCreateLatch(pNtkNew); diff --git a/src/base/io/ioReadBblif.c b/src/base/io/ioReadBblif.c index 5b15c9d4..873a5671 100644 --- a/src/base/io/ioReadBblif.c +++ b/src/base/io/ioReadBblif.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "ioAbc.h" -#include "dec.h" -#include "bblif.h" +#include "src/bool/dec/dec.h" +#include "src/misc/bbl/bblif.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/io/ioReadBlif.c b/src/base/io/ioReadBlif.c index 9fd41261..faf0f53e 100644 --- a/src/base/io/ioReadBlif.c +++ b/src/base/io/ioReadBlif.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "ioAbc.h" -#include "main.h" -#include "mio.h" +#include "src/base/main/main.h" +#include "src/map/mio/mio.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/io/ioReadBlifAig.c b/src/base/io/ioReadBlifAig.c index 1ef61196..f365cb4d 100644 --- a/src/base/io/ioReadBlifAig.c +++ b/src/base/io/ioReadBlifAig.c @@ -18,9 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" -#include "vecPtr.h" +#include "src/base/abc/abc.h" +#include "src/misc/vec/vecPtr.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/io/ioReadBlifMv.c b/src/base/io/ioReadBlifMv.c index 20ec8aa1..3e226824 100644 --- a/src/base/io/ioReadBlifMv.c +++ b/src/base/io/ioReadBlifMv.c @@ -18,9 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" -#include "vecPtr.h" +#include "src/base/abc/abc.h" +#include "src/misc/vec/vecPtr.h" #include "ioAbc.h" ABC_NAMESPACE_IMPL_START @@ -2029,8 +2028,8 @@ Io_MvVar_t * Abc_NtkMvVarDup( Abc_Ntk_t * pNtk, Io_MvVar_t * pVar ) ABC_NAMESPACE_IMPL_END -#include "mio.h" -#include "main.h" +#include "src/map/mio/mio.h" +#include "src/base/main/main.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/io/ioReadDsd.c b/src/base/io/ioReadDsd.c index 3608507b..514c664a 100644 --- a/src/base/io/ioReadDsd.c +++ b/src/base/io/ioReadDsd.c @@ -241,7 +241,7 @@ Abc_Ntk_t * Io_ReadDsd( char * pForm ) nInputs = 0; for ( pCur = pForm; *pCur; pCur++ ) if ( *pCur >= 'a' && *pCur <= 'z' ) - nInputs = ABC_MAX( nInputs, *pCur - 'a' ); + nInputs = Abc_MaxInt( nInputs, *pCur - 'a' ); nInputs++; // create the network diff --git a/src/base/io/ioReadPla.c b/src/base/io/ioReadPla.c index 927cf7e5..46ab811e 100644 --- a/src/base/io/ioReadPla.c +++ b/src/base/io/ioReadPla.c @@ -158,7 +158,7 @@ Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p, int fZeros ) ABC_FREE( ppSops ); return NULL; } - nDigits = Extra_Base10Log( nInputs ); + nDigits = Abc_Base10Log( nInputs ); for ( i = 0; i < nInputs; i++ ) { sprintf( Buffer, "x%0*d", nDigits, i ); @@ -175,7 +175,7 @@ Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p, int fZeros ) ABC_FREE( ppSops ); return NULL; } - nDigits = Extra_Base10Log( nOutputs ); + nDigits = Abc_Base10Log( nOutputs ); for ( i = 0; i < nOutputs; i++ ) { sprintf( Buffer, "z%0*d", nDigits, i ); diff --git a/src/base/io/ioReadVerilog.c b/src/base/io/ioReadVerilog.c index 3a8c6045..da74d8d9 100644 --- a/src/base/io/ioReadVerilog.c +++ b/src/base/io/ioReadVerilog.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "ioAbc.h" -#include "ver.h" +#include "src/base/ver/ver.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/io/ioUtil.c b/src/base/io/ioUtil.c index 9a50c0c8..e8a018c2 100644 --- a/src/base/io/ioUtil.c +++ b/src/base/io/ioUtil.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "ioAbc.h" -#include "main.h" +#include "src/base/main/main.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/io/ioWriteAiger.c b/src/base/io/ioWriteAiger.c index 9ab0905e..0f725be3 100644 --- a/src/base/io/ioWriteAiger.c +++ b/src/base/io/ioWriteAiger.c @@ -21,11 +21,11 @@ // The code in this file is developed in collaboration with Mark Jarvin of Toronto. -#include "bzlib.h" +#include "src/misc/bzlib/bzlib.h" #include "ioAbc.h" #include -#include "zlib.h" +#include "src/misc/zlib/zlib.h" ABC_NAMESPACE_IMPL_START @@ -770,8 +770,8 @@ void Io_WriteAiger( Abc_Ntk_t * pNtk, char * pFileName, int fWriteSymbols, int f } -#include "giaAig.h" -#include "saig.h" +#include "src/aig/gia/giaAig.h" +#include "src/aig/saig/saig.h" /**Function************************************************************* @@ -825,8 +825,8 @@ void Io_WriteAigerCex( Abc_Cex_t * pCex, Abc_Ntk_t * pNtk, void * pG, char * pFi { for ( k = 0; k < pCex->nPis; k++ ) { - fprintf( pFile, "%d", Aig_InfoHasBit(pCex->pData, b) ); - Aig_ManPi( pAig, k )->fMarkA = Aig_InfoHasBit(pCex->pData, b++); + fprintf( pFile, "%d", Abc_InfoHasBit(pCex->pData, b) ); + Aig_ManPi( pAig, k )->fMarkA = Abc_InfoHasBit(pCex->pData, b++); } fprintf( pFile, " " ); Aig_ManForEachNode( pAig, pObj, k ) diff --git a/src/base/io/ioWriteBblif.c b/src/base/io/ioWriteBblif.c index 5cace190..09bb1da9 100644 --- a/src/base/io/ioWriteBblif.c +++ b/src/base/io/ioWriteBblif.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "ioAbc.h" -#include "bblif.h" +#include "src/misc/bbl/bblif.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/io/ioWriteBlif.c b/src/base/io/ioWriteBlif.c index 9dc96afb..d8d3f787 100644 --- a/src/base/io/ioWriteBlif.c +++ b/src/base/io/ioWriteBlif.c @@ -19,10 +19,10 @@ ***********************************************************************/ #include "ioAbc.h" -#include "main.h" -#include "mio.h" -#include "kit.h" -#include "if.h" +#include "src/base/main/main.h" +#include "src/map/mio/mio.h" +#include "src/bool/kit/kit.h" +#include "src/map/if/if.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/io/ioWriteBlifMv.c b/src/base/io/ioWriteBlifMv.c index 62028606..fd054d5f 100644 --- a/src/base/io/ioWriteBlifMv.c +++ b/src/base/io/ioWriteBlifMv.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "ioAbc.h" -#include "main.h" -#include "mio.h" +#include "src/base/main/main.h" +#include "src/map/mio/mio.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/io/ioWriteBook.c b/src/base/io/ioWriteBook.c index 45807ce6..ae717c8d 100644 --- a/src/base/io/ioWriteBook.c +++ b/src/base/io/ioWriteBook.c @@ -18,9 +18,11 @@ ***********************************************************************/ +#include + +#include "src/base/main/main.h" +#include "src/map/mio/mio.h" #include "ioAbc.h" -#include "main.h" -#include "mio.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/io/ioWriteCnf.c b/src/base/io/ioWriteCnf.c index 6cb82a0a..d5d377cc 100644 --- a/src/base/io/ioWriteCnf.c +++ b/src/base/io/ioWriteCnf.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "ioAbc.h" -#include "satSolver.h" +#include "src/sat/bsat/satSolver.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/io/ioWriteDot.c b/src/base/io/ioWriteDot.c index c1b9befc..9a9bcd82 100644 --- a/src/base/io/ioWriteDot.c +++ b/src/base/io/ioWriteDot.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "ioAbc.h" -#include "main.h" -#include "mio.h" +#include "src/base/main/main.h" +#include "src/map/mio/mio.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/io/ioWriteVerilog.c b/src/base/io/ioWriteVerilog.c index 7f9bee95..511eb9f0 100644 --- a/src/base/io/ioWriteVerilog.c +++ b/src/base/io/ioWriteVerilog.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "ioAbc.h" -#include "main.h" -#include "mio.h" +#include "src/base/main/main.h" +#include "src/map/mio/mio.h" ABC_NAMESPACE_IMPL_START @@ -492,7 +492,7 @@ void Io_WriteVerilogObjects( FILE * pFile, Abc_Ntk_t * pNtk ) int i, k, Counter, nDigits, Length; // write boxes - nDigits = Extra_Base10Log( Abc_NtkBoxNum(pNtk)-Abc_NtkLatchNum(pNtk) ); + nDigits = Abc_Base10Log( Abc_NtkBoxNum(pNtk)-Abc_NtkLatchNum(pNtk) ); Counter = 0; Abc_NtkForEachBox( pNtk, pObj, i ) { @@ -517,7 +517,7 @@ void Io_WriteVerilogObjects( FILE * pFile, Abc_Ntk_t * pNtk ) if ( Abc_NtkHasMapping(pNtk) ) { Length = Mio_LibraryReadGateNameMax((Mio_Library_t *)pNtk->pManFunc); - nDigits = Extra_Base10Log( Abc_NtkNodeNum(pNtk) ); + nDigits = Abc_Base10Log( Abc_NtkNodeNum(pNtk) ); Counter = 0; Abc_NtkForEachNode( pNtk, pObj, k ) { diff --git a/src/base/main/libSupport.c b/src/base/main/libSupport.c index 3c0b20c7..8c92a595 100644 --- a/src/base/main/libSupport.c +++ b/src/base/main/libSupport.c @@ -21,7 +21,7 @@ #include #include -#include "abc.h" +#include "src/base/abc/abc.h" #include "mainInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/main/main.c b/src/base/main/main.c index 16c6e362..27b4b0bd 100644 --- a/src/base/main/main.c +++ b/src/base/main/main.c @@ -18,7 +18,7 @@ ***********************************************************************/ -#include "abc.h" +#include "src/base/abc/abc.h" #include "mainInt.h" #ifdef ABC_PYTHON_EMBED diff --git a/src/base/main/main.h b/src/base/main/main.h index 134af6e2..33f8a110 100644 --- a/src/base/main/main.h +++ b/src/base/main/main.h @@ -18,30 +18,29 @@ ***********************************************************************/ -#ifndef __MAIN_H__ -#define __MAIN_H__ +#ifndef ABC__base__main__main_h +#define ABC__base__main__main_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// -// data structure packages -#include "extra.h" -#include "vec.h" -#include "st.h" - // core packages -#include "abc.h" -#include "gia.h" +#include "src/base/abc/abc.h" +#include "src/aig/gia/gia.h" + +// data structure packages +#include "src/misc/vec/vec.h" +#include "src/misc/st/st.h" ABC_NAMESPACE_HEADER_START // the framework containing all data typedef struct Abc_Frame_t_ Abc_Frame_t; ABC_NAMESPACE_HEADER_END -#include "cmd.h" -#include "ioAbc.h" +#include "src/base/cmd/cmd.h" +#include "src/base/io/ioAbc.h" ABC_NAMESPACE_HEADER_START diff --git a/src/base/main/mainFrame.c b/src/base/main/mainFrame.c index 658bc34e..d03acf28 100644 --- a/src/base/main/mainFrame.c +++ b/src/base/main/mainFrame.c @@ -18,9 +18,10 @@ ***********************************************************************/ -#include "abc.h" +#include "src/base/abc/abc.h" #include "mainInt.h" -#include "dec.h" +#include "src/bool/dec/dec.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/main/mainInit.c b/src/base/main/mainInit.c index c15ca872..73abd548 100644 --- a/src/base/main/mainInit.c +++ b/src/base/main/mainInit.c @@ -18,7 +18,7 @@ ***********************************************************************/ -#include "abc.h" +#include "src/base/abc/abc.h" #include "mainInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/main/mainInt.h b/src/base/main/mainInt.h index c008fc8b..979d376c 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__base__main__mainInt_h +#define ABC__base__main__mainInt_h //////////////////////////////////////////////////////////////////////// @@ -27,15 +27,16 @@ //////////////////////////////////////////////////////////////////////// #include "main.h" -#include "tim.h" -#include "if.h" -#include "aig.h" -#include "gia.h" -#include "ssw.h" -#include "fra.h" -#include "nwkMerge.h" -#include "ntlnwk.h" -#include "ext.h" +#include "src/misc/tim/tim.h" +#include "src/map/if/if.h" +#include "src/aig/aig/aig.h" +#include "src/aig/gia/gia.h" +#include "src/proof/ssw/ssw.h" +#include "src/proof/fra/fra.h" +//#include "src/aig/nwk/nwkMerge.h" +//#include "src/aig/ntl/ntlnwk.h" +#include "src/misc/ext/ext.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_HEADER_START @@ -89,12 +90,6 @@ struct Abc_Frame_t_ void * pLibVer; // the current Verilog library // new code - Ntl_Man_t * pAbc8Ntl; // the current design - Nwk_Man_t * pAbc8Nwk; // the current mapped network - Aig_Man_t * pAbc8Aig; // the current AIG - If_Lib_t * pAbc8Lib; // the current LUT library - If_Lib_t * pAbc85Lib; // the current LUT library - Gia_Man_t * pGia; Gia_Man_t * pGia2; Abc_Cex_t * pCex; diff --git a/src/base/main/mainLib.c b/src/base/main/mainLib.c index 39078ed9..83bae04f 100644 --- a/src/base/main/mainLib.c +++ b/src/base/main/mainLib.c @@ -18,7 +18,7 @@ ***********************************************************************/ -#include "abc.h" +#include "src/base/abc/abc.h" #include "mainInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/main/mainMC.c b/src/base/main/mainMC.c index 5e77db57..6d9f4c73 100644 --- a/src/base/main/mainMC.c +++ b/src/base/main/mainMC.c @@ -19,10 +19,10 @@ ***********************************************************************/ #include "mainInt.h" -#include "aig.h" -#include "saig.h" -#include "fra.h" -#include "ioa.h" +#include "aig/aig/aig.h" +#include "aig/saig/saig.h" +#include "aig/fra/fra.h" +#include "aig/ioa/ioa.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/main/mainUtils.c b/src/base/main/mainUtils.c index c849a53d..e263bc94 100644 --- a/src/base/main/mainUtils.c +++ b/src/base/main/mainUtils.c @@ -18,7 +18,7 @@ ***********************************************************************/ -#include "abc.h" +#include "src/base/abc/abc.h" #include "mainInt.h" #ifndef _WIN32 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 7faefe19..00000000 --- a/src/base/seq/seq.h +++ /dev/null @@ -1,105 +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__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 int 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 ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/base/seq/seqAigCore.c b/src/base/seq/seqAigCore.c deleted file mode 100644 index ce4563f9..00000000 --- a/src/base/seq/seqAigCore.c +++ /dev/null @@ -1,981 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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, int fForward ); -static Vec_Ptr_t * Abc_NtkUtilRetimingGetMoves( Abc_Ntk_t * pNtk, Vec_Int_t * vSteps, int 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( Abc_Obj_t *, 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( Abc_Obj_t *, 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( Abc_Obj_t *, 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( Abc_Obj_t *, 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 ); - - // 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( (Extra_MmFlex_t *)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( (Extra_MmFlex_t *)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( (Extra_MmFlex_t *)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, int 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( Abc_Obj_t *, 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, int 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( Abc_Obj_t *, vMoves, pNode, i ) - Abc_ObjRetimeBackwardTry( pNode, 1 ); - } - else - { - Vec_PtrForEachEntryReverse( Abc_Obj_t *, 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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/base/seq/seqAigIter.c b/src/base/seq/seqAigIter.c deleted file mode 100644 index b71312f7..00000000 --- a/src/base/seq/seqAigIter.c +++ /dev/null @@ -1,273 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/base/seq/seqCreate.c b/src/base/seq/seqCreate.c deleted file mode 100644 index ec4fa6aa..00000000 --- a/src/base/seq/seqCreate.c +++ /dev/null @@ -1,487 +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" - -ABC_NAMESPACE_IMPL_START - - -/* - 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( (Extra_MmFlex_t *)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( (Extra_MmFlex_t *)pNtkNew->pManFunc ); - continue; - } - pObj->pCopy->pData = Abc_SopCreateAnd2( (Extra_MmFlex_t *)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 [] - -***********************************************************************/ -int 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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/base/seq/seqFpgaCore.c b/src/base/seq/seqFpgaCore.c deleted file mode 100644 index 8ab97b43..00000000 --- a/src/base/seq/seqFpgaCore.c +++ /dev/null @@ -1,648 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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( Abc_Obj_t *, p->vMapAnds, pObj, i ) - Abc_NtkDupObj( pNtkNew, pObj, 0 ); - - // recursively construct the internals of each node - Vec_PtrForEachEntry( Abc_Obj_t *, 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( Abc_Obj_t *, p->vMapAnds, pObj, i ) - { - // get the leaves of the cut - vLeaves = Vec_VecEntry( p->vMapCuts, i ); - // convert the leaf nodes - Vec_PtrForEachEntry( Abc_Obj_t *, 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( Abc_Obj_t *, 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( Abc_Obj_t *, 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( Abc_Obj_t *, 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( Abc_Obj_t *, 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( Abc_Obj_t *, 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( Abc_Obj_t *, 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( Abc_Obj_t *, 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( Abc_Obj_t *, 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( Abc_Obj_t *, 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( Abc_Obj_t *, 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( Abc_Obj_t *, 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( Abc_Obj_t *, 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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/base/seq/seqFpgaIter.c b/src/base/seq/seqFpgaIter.c deleted file mode 100644 index c4551a73..00000000 --- a/src/base/seq/seqFpgaIter.c +++ /dev/null @@ -1,275 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/base/seq/seqInt.h b/src/base/seq/seqInt.h deleted file mode 100644 index 89ce6843..00000000 --- a/src/base/seq/seqInt.h +++ /dev/null @@ -1,260 +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__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "abc.h" -#include "cut.h" -#include "main.h" -#include "mio.h" -#include "mapper.h" -#include "fpga.h" -#include "seq.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -#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 ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/base/seq/seqLatch.c b/src/base/seq/seqLatch.c deleted file mode 100644 index f6384fcb..00000000 --- a/src/base/seq/seqLatch.c +++ /dev/null @@ -1,228 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/base/seq/seqMan.c b/src/base/seq/seqMan.c deleted file mode 100644 index d0697b36..00000000 --- a/src/base/seq/seqMan.c +++ /dev/null @@ -1,138 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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( void *, 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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/base/seq/seqMapCore.c b/src/base/seq/seqMapCore.c deleted file mode 100644 index db1da0bc..00000000 --- a/src/base/seq/seqMapCore.c +++ /dev/null @@ -1,657 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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( Seq_Match_t *, 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( Seq_Match_t *, 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( Abc_Obj_t *, 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( Seq_Match_t *, 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( Seq_Match_t *, p->vMapAnds, pMatch, i ) - { - // get the leaves of the cut - vLeaves = Vec_VecEntry( p->vMapCuts, i ); - // convert the leaf nodes - Vec_PtrForEachEntry( Abc_Obj_t *, 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( Seq_Match_t *, 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( Abc_Obj_t *, 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( Abc_Obj_t *, 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( Seq_Match_t *, 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( Seq_Match_t *, 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( Seq_Match_t *, 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( Abc_Obj_t *, 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( Abc_Obj_t *, 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( Abc_Obj_t *, 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( Abc_Obj_t *, 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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/base/seq/seqMapIter.c b/src/base/seq/seqMapIter.c deleted file mode 100644 index bb762d62..00000000 --- a/src/base/seq/seqMapIter.c +++ /dev/null @@ -1,628 +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" - -ABC_NAMESPACE_IMPL_START - - -// 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 /// -//////////////////////////////////////////////////////////////////////// -ABC_NAMESPACE_IMPL_END - diff --git a/src/base/seq/seqMaxMeanCycle.c b/src/base/seq/seqMaxMeanCycle.c deleted file mode 100644 index b62e4b33..00000000 --- a/src/base/seq/seqMaxMeanCycle.c +++ /dev/null @@ -1,572 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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( Abc_Obj_t *, 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 /// -//////////////////////////////////////////////////////////////////////// -ABC_NAMESPACE_IMPL_END - diff --git a/src/base/seq/seqRetCore.c b/src/base/seq/seqRetCore.c deleted file mode 100644 index 846a6707..00000000 --- a/src/base/seq/seqRetCore.c +++ /dev/null @@ -1,498 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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( Abc_Obj_t *, 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( Abc_Obj_t *, 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( Abc_Obj_t *, 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( Abc_Obj_t *, 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( Abc_Obj_t *, 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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/base/seq/seqRetIter.c b/src/base/seq/seqRetIter.c deleted file mode 100644 index 816e71a1..00000000 --- a/src/base/seq/seqRetIter.c +++ /dev/null @@ -1,408 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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( Abc_Obj_t *, 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( Abc_Obj_t *, p->vMapAnds, pNode, i ) -// Seq_NodeSetLValueP( pNode, Seq_NodeGetLValueP(pNode) - p->fEpsilon ); - - // save the retiming lags - // mark the nodes - Vec_PtrForEachEntry( Abc_Obj_t *, p->vMapAnds, pNode, i ) - pNode->fMarkA = 1; - // process the nodes - Vec_StrFill( p->vLags, p->nSize, 0 ); - Vec_PtrForEachEntry( Abc_Obj_t *, 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( Abc_Obj_t *, 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( Abc_Obj_t *, 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( Abc_Obj_t *, 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( Abc_Obj_t *, p->vMapAnds, pObj, Number ) - if ( pObj == pNode ) - break; - - // get the leaves - vLeaves = Vec_VecEntry( p->vMapCuts, Number ); - - // print the leaves - Vec_PtrForEachEntry( Abc_Obj_t *, 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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/base/seq/seqShare.c b/src/base/seq/seqShare.c deleted file mode 100644 index bccfff80..00000000 --- a/src/base/seq/seqShare.c +++ /dev/null @@ -1,393 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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( Abc_Obj_t *, 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( (int (*)(void))stmm_ptrcmp, (int (*)(void))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( (int (*)(void))stmm_ptrcmp, (int (*)(void))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( Abc_Obj_t *, vMapAnds, pObj, i ) - Vec_PtrPush( vNodes, pObj ); - } - else - { - Vec_PtrForEachEntry( Abc_Obj_t *, vMapAnds, pMatch, i ) - Vec_PtrPush( vNodes, pMatch->pAnd ); - } - - // process nodes used in the mapping - Vec_PtrForEachEntry( Abc_Obj_t *, 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 /// -//////////////////////////////////////////////////////////////////////// -ABC_NAMESPACE_IMPL_END - diff --git a/src/base/seq/seqUtil.c b/src/base/seq/seqUtil.c deleted file mode 100644 index 137151e2..00000000 --- a/src/base/seq/seqUtil.c +++ /dev/null @@ -1,602 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/base/test/test.c b/src/base/test/test.c index f603befd..92094d9a 100644 --- a/src/base/test/test.c +++ b/src/base/test/test.c @@ -18,7 +18,7 @@ ***********************************************************************/ -#include "main.h" +#include "src/base/main/main.h" ABC_NAMESPACE_IMPL_START diff --git a/src/base/ver/ver.h b/src/base/ver/ver.h index e421ff95..8c9d6e00 100644 --- a/src/base/ver/ver.h +++ b/src/base/ver/ver.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __VER_H__ -#define __VER_H__ +#ifndef ABC__base__ver__ver_h +#define ABC__base__ver__ver_h //////////////////////////////////////////////////////////////////////// @@ -27,8 +27,7 @@ //////////////////////////////////////////////////////////////////////// #include -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// diff --git a/src/base/ver/verCore.c b/src/base/ver/verCore.c index d2744402..1a924c31 100644 --- a/src/base/ver/verCore.c +++ b/src/base/ver/verCore.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "ver.h" -#include "mio.h" -#include "main.h" +#include "src/map/mio/mio.h" +#include "src/base/main/main.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cas/cas.h b/src/bdd/cas/cas.h index 33958325..9ef6f1fa 100644 --- a/src/bdd/cas/cas.h +++ b/src/bdd/cas/cas.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __CAS_H__ -#define __CAS_H__ +#ifndef ABC__bdd__cas__cas_h +#define ABC__bdd__cas__cas_h //////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/cas/casCore.c b/src/bdd/cas/casCore.c index 5511b8e7..b73b5b3f 100644 --- a/src/bdd/cas/casCore.c +++ b/src/bdd/cas/casCore.c @@ -23,9 +23,9 @@ #include #include -#include "main.h" -#include "cmd.h" -#include "extra.h" +#include "src/base/main/main.h" +#include "src/base/cmd/cmd.h" +#include "src/misc/extra/extraBdd.h" #include "cas.h" ABC_NAMESPACE_IMPL_START @@ -112,7 +112,7 @@ int Abc_CascadeExperiment( char * pFileGeneric, DdManager * dd, DdNode ** pOutpu // create the variables to encode the outputs - nVarsEnc = Extra_Base2Log( nOuts ); + nVarsEnc = Abc_Base2Log( nOuts ); for ( i = 0; i < nVarsEnc; i++ ) pbVarsEnc[i] = Cudd_bddNewVarAtLevel( dd, i ); @@ -704,7 +704,7 @@ DdNode * GetSingleOutputFunctionRemappedNewDD( DdManager * dd, DdNode ** pOutput } // select the encoding variables to follow immediately after the original variables - nVarsEnc = Extra_Base2Log(nOuts); + nVarsEnc = Abc_Base2Log(nOuts); /* for ( v = 0; v < nVarsEnc; v++ ) if ( nVarsMax + v < dd->size ) diff --git a/src/bdd/cas/casDec.c b/src/bdd/cas/casDec.c index 111f559e..ea132540 100644 --- a/src/bdd/cas/casDec.c +++ b/src/bdd/cas/casDec.c @@ -23,7 +23,7 @@ #include #include -#include "extra.h" +#include "src/misc/extra/extraBdd.h" #include "cas.h" ABC_NAMESPACE_IMPL_START @@ -175,7 +175,7 @@ int CreateDecomposedNetwork( DdManager * dd, DdNode * aFunc, char ** pNames, int p->nIns = s_LutSize; p->nInsP = PrevMulti; p->nCols = Profile[nNames-(nVarsRem-(s_LutSize-PrevMulti))]; - p->nMulti = Extra_Base2Log(p->nCols); + p->nMulti = Abc_Base2Log(p->nCols); p->Level = nNames-nVarsRem; nVarsRem = nVarsRem-(s_LutSize-PrevMulti); diff --git a/src/bdd/cudd/cudd.h b/src/bdd/cudd/cudd.h index 9231b5ab..fb1d6d58 100644 --- a/src/bdd/cudd/cudd.h +++ b/src/bdd/cudd/cudd.h @@ -54,16 +54,16 @@ ******************************************************************************/ -#ifndef _CUDD -#define _CUDD +#ifndef ABC__bdd__cudd__cudd_h +#define ABC__bdd__cudd__cudd_h /*---------------------------------------------------------------------------*/ /* Nested includes */ /*---------------------------------------------------------------------------*/ -#include "mtr.h" -#include "epd.h" +#include "src/bdd/mtr/mtr.h" +#include "src/bdd/epd/epd.h" ABC_NAMESPACE_HEADER_START diff --git a/src/bdd/cudd/cuddAPI.c b/src/bdd/cudd/cuddAPI.c index e2926ea2..6456d17c 100644 --- a/src/bdd/cudd/cuddAPI.c +++ b/src/bdd/cudd/cuddAPI.c @@ -191,7 +191,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddAddAbs.c b/src/bdd/cudd/cuddAddAbs.c index f420f99e..44c77d94 100644 --- a/src/bdd/cudd/cuddAddAbs.c +++ b/src/bdd/cudd/cuddAddAbs.c @@ -59,7 +59,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddAddApply.c b/src/bdd/cudd/cuddAddApply.c index 7bea5871..ec77229c 100644 --- a/src/bdd/cudd/cuddAddApply.c +++ b/src/bdd/cudd/cuddAddApply.c @@ -69,7 +69,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddAddFind.c b/src/bdd/cudd/cuddAddFind.c index 4d63965d..57343b1a 100644 --- a/src/bdd/cudd/cuddAddFind.c +++ b/src/bdd/cudd/cuddAddFind.c @@ -54,7 +54,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddAddInv.c b/src/bdd/cudd/cuddAddInv.c index cae00ca1..e15da46e 100644 --- a/src/bdd/cudd/cuddAddInv.c +++ b/src/bdd/cudd/cuddAddInv.c @@ -51,7 +51,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddAddIte.c b/src/bdd/cudd/cuddAddIte.c index 67f1cf14..b9b8c3e3 100644 --- a/src/bdd/cudd/cuddAddIte.c +++ b/src/bdd/cudd/cuddAddIte.c @@ -60,7 +60,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddAddNeg.c b/src/bdd/cudd/cuddAddNeg.c index c21c995a..192ea513 100644 --- a/src/bdd/cudd/cuddAddNeg.c +++ b/src/bdd/cudd/cuddAddNeg.c @@ -53,7 +53,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddAddWalsh.c b/src/bdd/cudd/cuddAddWalsh.c index e8e8a641..0ad53418 100644 --- a/src/bdd/cudd/cuddAddWalsh.c +++ b/src/bdd/cudd/cuddAddWalsh.c @@ -53,7 +53,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddAndAbs.c b/src/bdd/cudd/cuddAndAbs.c index b42f376d..00ba67b4 100644 --- a/src/bdd/cudd/cuddAndAbs.c +++ b/src/bdd/cudd/cuddAndAbs.c @@ -52,7 +52,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddAnneal.c b/src/bdd/cudd/cuddAnneal.c index 7a08b5ae..943265cc 100644 --- a/src/bdd/cudd/cuddAnneal.c +++ b/src/bdd/cudd/cuddAnneal.c @@ -62,7 +62,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddApa.c b/src/bdd/cudd/cuddApa.c index 82547b54..8515ee0a 100644 --- a/src/bdd/cudd/cuddApa.c +++ b/src/bdd/cudd/cuddApa.c @@ -70,7 +70,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddApprox.c b/src/bdd/cudd/cuddApprox.c index 1fdb595f..203c438d 100644 --- a/src/bdd/cudd/cuddApprox.c +++ b/src/bdd/cudd/cuddApprox.c @@ -78,7 +78,7 @@ #else #define DBL_MAX_EXP 1024 #endif -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddBddAbs.c b/src/bdd/cudd/cuddBddAbs.c index 9bcb32ad..7dc3ef56 100644 --- a/src/bdd/cudd/cuddBddAbs.c +++ b/src/bdd/cudd/cuddBddAbs.c @@ -62,7 +62,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddBddCorr.c b/src/bdd/cudd/cuddBddCorr.c index 62f48bde..4606ea48 100644 --- a/src/bdd/cudd/cuddBddCorr.c +++ b/src/bdd/cudd/cuddBddCorr.c @@ -57,7 +57,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddBddIte.c b/src/bdd/cudd/cuddBddIte.c index b4921fb2..d3386088 100644 --- a/src/bdd/cudd/cuddBddIte.c +++ b/src/bdd/cudd/cuddBddIte.c @@ -72,7 +72,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddBridge.c b/src/bdd/cudd/cuddBridge.c index c051666d..75a5fa2a 100644 --- a/src/bdd/cudd/cuddBridge.c +++ b/src/bdd/cudd/cuddBridge.c @@ -71,7 +71,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddCache.c b/src/bdd/cudd/cuddCache.c index b8978ab6..31545bd6 100644 --- a/src/bdd/cudd/cuddCache.c +++ b/src/bdd/cudd/cuddCache.c @@ -63,7 +63,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddCheck.c b/src/bdd/cudd/cuddCheck.c index 5526aaf2..c4b9b5c2 100644 --- a/src/bdd/cudd/cuddCheck.c +++ b/src/bdd/cudd/cuddCheck.c @@ -61,7 +61,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddClip.c b/src/bdd/cudd/cuddClip.c index 028474fe..6d4216a9 100644 --- a/src/bdd/cudd/cuddClip.c +++ b/src/bdd/cudd/cuddClip.c @@ -60,7 +60,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddCof.c b/src/bdd/cudd/cuddCof.c index 004689c2..f2d3c118 100644 --- a/src/bdd/cudd/cuddCof.c +++ b/src/bdd/cudd/cuddCof.c @@ -56,7 +56,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddCompose.c b/src/bdd/cudd/cuddCompose.c index 7c99ac62..6264513f 100644 --- a/src/bdd/cudd/cuddCompose.c +++ b/src/bdd/cudd/cuddCompose.c @@ -82,7 +82,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddDecomp.c b/src/bdd/cudd/cuddDecomp.c index 34eaef0c..99aa9348 100644 --- a/src/bdd/cudd/cuddDecomp.c +++ b/src/bdd/cudd/cuddDecomp.c @@ -61,7 +61,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddEssent.c b/src/bdd/cudd/cuddEssent.c index b3264715..dfd5bd9d 100644 --- a/src/bdd/cudd/cuddEssent.c +++ b/src/bdd/cudd/cuddEssent.c @@ -71,7 +71,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddExact.c b/src/bdd/cudd/cuddExact.c index 19fcbcd4..54560a44 100644 --- a/src/bdd/cudd/cuddExact.c +++ b/src/bdd/cudd/cuddExact.c @@ -67,7 +67,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddExport.c b/src/bdd/cudd/cuddExport.c index c0cac4ec..2f19e504 100644 --- a/src/bdd/cudd/cuddExport.c +++ b/src/bdd/cudd/cuddExport.c @@ -62,7 +62,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddGenCof.c b/src/bdd/cudd/cuddGenCof.c index 35c380c0..f5597f3d 100644 --- a/src/bdd/cudd/cuddGenCof.c +++ b/src/bdd/cudd/cuddGenCof.c @@ -75,7 +75,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddGenetic.c b/src/bdd/cudd/cuddGenetic.c index 8c168440..8c65875e 100644 --- a/src/bdd/cudd/cuddGenetic.c +++ b/src/bdd/cudd/cuddGenetic.c @@ -80,7 +80,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddGroup.c b/src/bdd/cudd/cuddGroup.c index fc848259..598cc9a1 100644 --- a/src/bdd/cudd/cuddGroup.c +++ b/src/bdd/cudd/cuddGroup.c @@ -76,7 +76,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddHarwell.c b/src/bdd/cudd/cuddHarwell.c index 75e328ea..b61af2e0 100644 --- a/src/bdd/cudd/cuddHarwell.c +++ b/src/bdd/cudd/cuddHarwell.c @@ -48,7 +48,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddInit.c b/src/bdd/cudd/cuddInit.c index 857e638c..c0dbaa0c 100644 --- a/src/bdd/cudd/cuddInit.c +++ b/src/bdd/cudd/cuddInit.c @@ -56,7 +56,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddInt.h b/src/bdd/cudd/cuddInt.h index ba8da8cf..3d4b3db9 100644 --- a/src/bdd/cudd/cuddInt.h +++ b/src/bdd/cudd/cuddInt.h @@ -48,8 +48,8 @@ ******************************************************************************/ -#ifndef _CUDDINT -#define _CUDDINT +#ifndef ABC__bdd__cudd__cuddInt_h +#define ABC__bdd__cudd__cuddInt_h /*---------------------------------------------------------------------------*/ @@ -59,8 +59,8 @@ #ifdef DD_MIS #include "array.h" #include "list.h" -#include "st.h" -#include "espresso.h" +#include "src/misc/st/st.h" +#include "src/misc/espresso/espresso.h" #include "node.h" #ifdef SIS #include "graph.h" @@ -71,7 +71,7 @@ #include #include "cudd.h" -#include "st.h" +#include "src/misc/st/st.h" ABC_NAMESPACE_HEADER_START diff --git a/src/bdd/cudd/cuddInteract.c b/src/bdd/cudd/cuddInteract.c index 1d335c2a..b0757d00 100644 --- a/src/bdd/cudd/cuddInteract.c +++ b/src/bdd/cudd/cuddInteract.c @@ -74,7 +74,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddLCache.c b/src/bdd/cudd/cuddLCache.c index 2d66264e..e08e0f00 100644 --- a/src/bdd/cudd/cuddLCache.c +++ b/src/bdd/cudd/cuddLCache.c @@ -72,7 +72,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddLevelQ.c b/src/bdd/cudd/cuddLevelQ.c index 43e730d6..987d39b4 100644 --- a/src/bdd/cudd/cuddLevelQ.c +++ b/src/bdd/cudd/cuddLevelQ.c @@ -77,7 +77,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddLinear.c b/src/bdd/cudd/cuddLinear.c index e137484c..601b6496 100644 --- a/src/bdd/cudd/cuddLinear.c +++ b/src/bdd/cudd/cuddLinear.c @@ -61,7 +61,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddLiteral.c b/src/bdd/cudd/cuddLiteral.c index b5895fcf..bc7ac3a0 100644 --- a/src/bdd/cudd/cuddLiteral.c +++ b/src/bdd/cudd/cuddLiteral.c @@ -52,7 +52,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddMatMult.c b/src/bdd/cudd/cuddMatMult.c index f78d037d..b3989e9e 100644 --- a/src/bdd/cudd/cuddMatMult.c +++ b/src/bdd/cudd/cuddMatMult.c @@ -56,7 +56,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddPriority.c b/src/bdd/cudd/cuddPriority.c index 188d2c9e..2ecc1636 100644 --- a/src/bdd/cudd/cuddPriority.c +++ b/src/bdd/cudd/cuddPriority.c @@ -73,7 +73,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddRead.c b/src/bdd/cudd/cuddRead.c index 06789589..8cb555d2 100644 --- a/src/bdd/cudd/cuddRead.c +++ b/src/bdd/cudd/cuddRead.c @@ -50,7 +50,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddRef.c b/src/bdd/cudd/cuddRef.c index 183d30ca..9592f4c2 100644 --- a/src/bdd/cudd/cuddRef.c +++ b/src/bdd/cudd/cuddRef.c @@ -65,7 +65,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddReorder.c b/src/bdd/cudd/cuddReorder.c index f9c08772..fef0768a 100644 --- a/src/bdd/cudd/cuddReorder.c +++ b/src/bdd/cudd/cuddReorder.c @@ -72,7 +72,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddSat.c b/src/bdd/cudd/cuddSat.c index c3a161b4..a01268e6 100644 --- a/src/bdd/cudd/cuddSat.c +++ b/src/bdd/cudd/cuddSat.c @@ -69,7 +69,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddSign.c b/src/bdd/cudd/cuddSign.c index 75d1f60c..5ece24ad 100644 --- a/src/bdd/cudd/cuddSign.c +++ b/src/bdd/cudd/cuddSign.c @@ -52,7 +52,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddSolve.c b/src/bdd/cudd/cuddSolve.c index 47570bf1..a1fb77ca 100644 --- a/src/bdd/cudd/cuddSolve.c +++ b/src/bdd/cudd/cuddSolve.c @@ -55,7 +55,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddSplit.c b/src/bdd/cudd/cuddSplit.c index 4ac243b5..d650ecbc 100644 --- a/src/bdd/cudd/cuddSplit.c +++ b/src/bdd/cudd/cuddSplit.c @@ -59,7 +59,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddSubsetHB.c b/src/bdd/cudd/cuddSubsetHB.c index 68902b09..21daf9ed 100644 --- a/src/bdd/cudd/cuddSubsetHB.c +++ b/src/bdd/cudd/cuddSubsetHB.c @@ -73,7 +73,7 @@ #else #define DBL_MAX_EXP 1024 #endif -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddSubsetSP.c b/src/bdd/cudd/cuddSubsetSP.c index cddc58ed..5eb3e099 100644 --- a/src/bdd/cudd/cuddSubsetSP.c +++ b/src/bdd/cudd/cuddSubsetSP.c @@ -68,7 +68,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddSymmetry.c b/src/bdd/cudd/cuddSymmetry.c index 3386e798..630c3778 100644 --- a/src/bdd/cudd/cuddSymmetry.c +++ b/src/bdd/cudd/cuddSymmetry.c @@ -65,7 +65,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddTable.c b/src/bdd/cudd/cuddTable.c index c83d1073..f64f1f8e 100644 --- a/src/bdd/cudd/cuddTable.c +++ b/src/bdd/cudd/cuddTable.c @@ -80,7 +80,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddUtil.c b/src/bdd/cudd/cuddUtil.c index ec21e928..046c1957 100644 --- a/src/bdd/cudd/cuddUtil.c +++ b/src/bdd/cudd/cuddUtil.c @@ -105,7 +105,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddWindow.c b/src/bdd/cudd/cuddWindow.c index 0a7c6705..d07f188f 100644 --- a/src/bdd/cudd/cuddWindow.c +++ b/src/bdd/cudd/cuddWindow.c @@ -58,7 +58,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddZddCount.c b/src/bdd/cudd/cuddZddCount.c index a422ad99..c91ef92b 100644 --- a/src/bdd/cudd/cuddZddCount.c +++ b/src/bdd/cudd/cuddZddCount.c @@ -61,7 +61,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddZddFuncs.c b/src/bdd/cudd/cuddZddFuncs.c index 41f7c64c..f4bae0aa 100644 --- a/src/bdd/cudd/cuddZddFuncs.c +++ b/src/bdd/cudd/cuddZddFuncs.c @@ -75,7 +75,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddZddGroup.c b/src/bdd/cudd/cuddZddGroup.c index 5d0409de..2d2a5049 100644 --- a/src/bdd/cudd/cuddZddGroup.c +++ b/src/bdd/cudd/cuddZddGroup.c @@ -67,7 +67,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddZddIsop.c b/src/bdd/cudd/cuddZddIsop.c index 1de9110a..a1e3b7b8 100644 --- a/src/bdd/cudd/cuddZddIsop.c +++ b/src/bdd/cudd/cuddZddIsop.c @@ -61,7 +61,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddZddLin.c b/src/bdd/cudd/cuddZddLin.c index c6e11561..09777b2f 100644 --- a/src/bdd/cudd/cuddZddLin.c +++ b/src/bdd/cudd/cuddZddLin.c @@ -59,7 +59,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddZddMisc.c b/src/bdd/cudd/cuddZddMisc.c index 4d28f6a7..14250322 100644 --- a/src/bdd/cudd/cuddZddMisc.c +++ b/src/bdd/cudd/cuddZddMisc.c @@ -60,7 +60,7 @@ ******************************************************************************/ #include -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddZddPort.c b/src/bdd/cudd/cuddZddPort.c index 76b46ca5..fbca346e 100644 --- a/src/bdd/cudd/cuddZddPort.c +++ b/src/bdd/cudd/cuddZddPort.c @@ -59,7 +59,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddZddReord.c b/src/bdd/cudd/cuddZddReord.c index c5fcb9fb..8a7ae526 100644 --- a/src/bdd/cudd/cuddZddReord.c +++ b/src/bdd/cudd/cuddZddReord.c @@ -73,7 +73,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddZddSetop.c b/src/bdd/cudd/cuddZddSetop.c index b4726b63..ec0c467c 100644 --- a/src/bdd/cudd/cuddZddSetop.c +++ b/src/bdd/cudd/cuddZddSetop.c @@ -73,7 +73,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddZddSymm.c b/src/bdd/cudd/cuddZddSymm.c index 52e26d88..4979968a 100644 --- a/src/bdd/cudd/cuddZddSymm.c +++ b/src/bdd/cudd/cuddZddSymm.c @@ -67,7 +67,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/cudd/cuddZddUtil.c b/src/bdd/cudd/cuddZddUtil.c index 1e89c610..e87f5af8 100644 --- a/src/bdd/cudd/cuddZddUtil.c +++ b/src/bdd/cudd/cuddZddUtil.c @@ -66,7 +66,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/dsd/dsd.h b/src/bdd/dsd/dsd.h index 00b38625..7bb6111f 100644 --- a/src/bdd/dsd/dsd.h +++ b/src/bdd/dsd/dsd.h @@ -25,8 +25,8 @@ ***********************************************************************/ -#ifndef __DSD_H__ -#define __DSD_H__ +#ifndef ABC__bdd__dsd__dsd_h +#define ABC__bdd__dsd__dsd_h //////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/dsd/dsdCheck.c b/src/bdd/dsd/dsdCheck.c index 4cecba59..4de75a92 100644 --- a/src/bdd/dsd/dsdCheck.c +++ b/src/bdd/dsd/dsdCheck.c @@ -68,7 +68,7 @@ void Dsd_CheckCacheAllocate( int nEntries ) memset( pCache, 0, sizeof(Dds_Cache_t) ); // check what is the size of the current cache - nRequested = Cudd_Prime( nEntries ); + nRequested = Abc_PrimeCudd( nEntries ); if ( pCache->nTableSize != nRequested ) { // the current size is different // deallocate the old, allocate the new diff --git a/src/bdd/dsd/dsdInt.h b/src/bdd/dsd/dsdInt.h index 78b7b154..11a8e82e 100644 --- a/src/bdd/dsd/dsdInt.h +++ b/src/bdd/dsd/dsdInt.h @@ -16,11 +16,11 @@ ***********************************************************************/ -#ifndef __DSD_INT_H__ -#define __DSD_INT_H__ +#ifndef ABC__bdd__dsd__dsdInt_h +#define ABC__bdd__dsd__dsdInt_h -#include "extra.h" +#include "src/misc/extra/extraBdd.h" #include "dsd.h" ABC_NAMESPACE_HEADER_START diff --git a/src/bdd/epd/epd.c b/src/bdd/epd/epd.c index 3f92af94..6a803e16 100644 --- a/src/bdd/epd/epd.c +++ b/src/bdd/epd/epd.c @@ -52,7 +52,7 @@ #include #include #include -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "epd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/epd/epd.h b/src/bdd/epd/epd.h index 1ca033d2..012380ed 100644 --- a/src/bdd/epd/epd.h +++ b/src/bdd/epd/epd.h @@ -48,8 +48,8 @@ ******************************************************************************/ -#ifndef _EPD -#define _EPD +#ifndef ABC__bdd__epd__epd_h +#define ABC__bdd__epd__epd_h ABC_NAMESPACE_HEADER_START diff --git a/src/bdd/mtr/mtr.h b/src/bdd/mtr/mtr.h index 5ac35313..db936ab8 100644 --- a/src/bdd/mtr/mtr.h +++ b/src/bdd/mtr/mtr.h @@ -56,8 +56,8 @@ ******************************************************************************/ -#ifndef __MTR -#define __MTR +#ifndef ABC__bdd__mtr__mtr_h +#define ABC__bdd__mtr__mtr_h /*---------------------------------------------------------------------------*/ /* Nested includes */ diff --git a/src/bdd/mtr/mtrBasic.c b/src/bdd/mtr/mtrBasic.c index a2420d4a..b710ef4a 100644 --- a/src/bdd/mtr/mtrBasic.c +++ b/src/bdd/mtr/mtrBasic.c @@ -60,7 +60,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "mtrInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/mtr/mtrGroup.c b/src/bdd/mtr/mtrGroup.c index 280108c9..b29fe32d 100644 --- a/src/bdd/mtr/mtrGroup.c +++ b/src/bdd/mtr/mtrGroup.c @@ -60,7 +60,7 @@ ******************************************************************************/ -#include "util_hack.h" +#include "src/misc/util/util_hack.h" #include "mtrInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/mtr/mtrInt.h b/src/bdd/mtr/mtrInt.h index 9c8c6e26..624c64a9 100644 --- a/src/bdd/mtr/mtrInt.h +++ b/src/bdd/mtr/mtrInt.h @@ -48,8 +48,8 @@ ******************************************************************************/ -#ifndef _MTRINT -#define _MTRINT +#ifndef ABC__bdd__mtr__mtrInt_h +#define ABC__bdd__mtr__mtrInt_h #include "mtr.h" diff --git a/src/bdd/parse/parse.h b/src/bdd/parse/parse.h index 5c97dd4e..584ec30a 100644 --- a/src/bdd/parse/parse.h +++ b/src/bdd/parse/parse.h @@ -16,8 +16,8 @@ ***********************************************************************/ -#ifndef __PARSE_H__ -#define __PARSE_H__ +#ifndef ABC__bdd__parse__parse_h +#define ABC__bdd__parse__parse_h ABC_NAMESPACE_HEADER_START diff --git a/src/bdd/parse/parseEqn.c b/src/bdd/parse/parseEqn.c index ed2599ca..a0b9ada8 100644 --- a/src/bdd/parse/parseEqn.c +++ b/src/bdd/parse/parseEqn.c @@ -22,8 +22,8 @@ //////////////////////////////////////////////////////////////////////// #include "parseInt.h" -#include "vec.h" -#include "hop.h" +#include "src/misc/vec/vec.h" +#include "src/aig/hop/hop.h" ABC_NAMESPACE_IMPL_START diff --git a/src/bdd/parse/parseInt.h b/src/bdd/parse/parseInt.h index f0f3f302..78766612 100644 --- a/src/bdd/parse/parseInt.h +++ b/src/bdd/parse/parseInt.h @@ -16,8 +16,8 @@ ***********************************************************************/ -#ifndef __PARSE_INT_H__ -#define __PARSE_INT_H__ +#ifndef ABC__bdd__parse__parseInt_h +#define ABC__bdd__parse__parseInt_h //////////////////////////////////////////////////////////////////////// @@ -26,8 +26,7 @@ #include -#include "extra.h" -#include "cuddInt.h" +#include "src/misc/extra/extraBdd.h" #include "parse.h" ABC_NAMESPACE_HEADER_START diff --git a/src/bdd/reo/reo.h b/src/bdd/reo/reo.h index 9d82329c..9381a350 100644 --- a/src/bdd/reo/reo.h +++ b/src/bdd/reo/reo.h @@ -16,13 +16,13 @@ ***********************************************************************/ -#ifndef __REO_H__ -#define __REO_H__ +#ifndef ABC__bdd__reo__reo_h +#define ABC__bdd__reo__reo_h #include #include -#include "extra.h" +#include "src/misc/extra/extraBdd.h" //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// diff --git a/src/bool/bdc/bdc.h b/src/bool/bdc/bdc.h new file mode 100644 index 00000000..6c88857a --- /dev/null +++ b/src/bool/bdc/bdc.h @@ -0,0 +1,92 @@ +/**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 ABC__aig__bdc__bdc_h +#define ABC__aig__bdc__bdc_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Bdc_Fun_t_ Bdc_Fun_t; +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 +}; + +// working with complemented attributes of objects +static inline int Bdc_IsComplement( Bdc_Fun_t * p ) { return (int)((ABC_PTRUINT_T)p & (ABC_PTRUINT_T)01); } +static inline Bdc_Fun_t * Bdc_Regular( Bdc_Fun_t * p ) { return (Bdc_Fun_t *)((ABC_PTRUINT_T)p & ~(ABC_PTRUINT_T)01); } +static inline Bdc_Fun_t * Bdc_Not( Bdc_Fun_t * p ) { return (Bdc_Fun_t *)((ABC_PTRUINT_T)p ^ (ABC_PTRUINT_T)01); } +static inline Bdc_Fun_t * Bdc_NotCond( Bdc_Fun_t * p, int c ) { return (Bdc_Fun_t *)((ABC_PTRUINT_T)p ^ (ABC_PTRUINT_T)(c!=0)); } + +//////////////////////////////////////////////////////////////////////// +/// 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 nNodesMax ); +extern Bdc_Fun_t * Bdc_ManFunc( Bdc_Man_t * p, int i ); +extern Bdc_Fun_t * Bdc_ManRoot( Bdc_Man_t * p ); +extern int Bdc_ManNodeNum( Bdc_Man_t * p ); +extern Bdc_Fun_t * Bdc_FuncFanin0( Bdc_Fun_t * p ); +extern Bdc_Fun_t * Bdc_FuncFanin1( Bdc_Fun_t * p ); +extern void * Bdc_FuncCopy( Bdc_Fun_t * p ); +extern int Bdc_FuncCopyInt( Bdc_Fun_t * p ); +extern void Bdc_FuncSetCopy( Bdc_Fun_t * p, void * pCopy ); +extern void Bdc_FuncSetCopyInt( Bdc_Fun_t * p, int iCopy ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/bool/bdc/bdcCore.c b/src/bool/bdc/bdcCore.c new file mode 100644 index 00000000..58324f81 --- /dev/null +++ b/src/bool/bdc/bdcCore.c @@ -0,0 +1,314 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Accessing contents of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bdc_Fun_t * Bdc_ManFunc( Bdc_Man_t * p, int i ) { return Bdc_FunWithId(p, i); } +Bdc_Fun_t * Bdc_ManRoot( Bdc_Man_t * p ) { return p->pRoot; } +int Bdc_ManNodeNum( Bdc_Man_t * p ) { return p->nNodes; } +Bdc_Fun_t * Bdc_FuncFanin0( Bdc_Fun_t * p ) { return p->pFan0; } +Bdc_Fun_t * Bdc_FuncFanin1( Bdc_Fun_t * p ) { return p->pFan1; } +void * Bdc_FuncCopy( Bdc_Fun_t * p ) { return p->pCopy; } +int Bdc_FuncCopyInt( Bdc_Fun_t * p ) { return p->iCopy; } +void Bdc_FuncSetCopy( Bdc_Fun_t * p, void * pCopy ) { p->pCopy = pCopy; } +void Bdc_FuncSetCopyInt( Bdc_Fun_t * p, int iCopy ) { p->iCopy = iCopy; } + +/**Function************************************************************* + + Synopsis [Allocate resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bdc_Man_t * Bdc_ManAlloc( Bdc_Par_t * pPars ) +{ + Bdc_Man_t * p; + p = ABC_ALLOC( Bdc_Man_t, 1 ); + memset( p, 0, sizeof(Bdc_Man_t) ); + assert( pPars->nVarsMax > 1 && pPars->nVarsMax < 16 ); + p->pPars = pPars; + p->nWords = Kit_TruthWordNum( pPars->nVarsMax ); + p->nDivsLimit = 200; + // internal nodes + p->nNodesAlloc = 512; + p->pNodes = ABC_ALLOC( Bdc_Fun_t, p->nNodesAlloc ); + // memory + p->vMemory = Vec_IntStart( 8 * p->nWords * p->nNodesAlloc ); + Vec_IntClear(p->vMemory); + // set up hash table + p->nTableSize = (1 << p->pPars->nVarsMax); + p->pTable = ABC_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_PtrAllocTruthTables( p->pPars->nVarsMax ); + p->puTemp1 = ABC_ALLOC( unsigned, 4 * p->nWords ); + p->puTemp2 = p->puTemp1 + p->nWords; + p->puTemp3 = p->puTemp2 + p->nWords; + p->puTemp4 = p->puTemp3 + p->nWords; + // 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 ) +{ + if ( p->pPars->fVerbose ) + { + printf( "Bi-decomposition stats: Calls = %d. Nodes = %d. Reuse = %d.\n", + p->numCalls, p->numNodes, p->numReuse ); + printf( "ANDs = %d. ORs = %d. Weak = %d. Muxes = %d. Memory = %.2f K\n", + p->numAnds, p->numOrs, p->numWeaks, p->numMuxes, 4.0 * Vec_IntSize(p->vMemory) / (1<<10) ); + ABC_PRT( "Cache", p->timeCache ); + ABC_PRT( "Check", p->timeCheck ); + ABC_PRT( "Muxes", p->timeMuxes ); + ABC_PRT( "Supps", p->timeSupps ); + ABC_PRT( "TOTAL", p->timeTotal ); + } + Vec_IntFree( p->vMemory ); + Vec_IntFree( p->vSpots ); + Vec_PtrFree( p->vTruths ); + ABC_FREE( p->puTemp1 ); + ABC_FREE( p->pNodes ); + ABC_FREE( p->pTable ); + ABC_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 = 0; + p->nNodesNew = - 1 - p->nVars - (vDivs? Vec_PtrSize(vDivs) : 0); + // add constant 1 + pNode = Bdc_FunNew( p ); + pNode->Type = BDC_TYPE_CONST1; + pNode->puFunc = (unsigned *)Vec_IntFetch(p->vMemory, p->nWords); + Kit_TruthFill( pNode->puFunc, p->nVars ); + pNode->uSupp = 0; + Bdc_TableAdd( p, pNode ); + // add variables + for ( i = 0; i < p->nVars; i++ ) + { + pNode = Bdc_FunNew( p ); + pNode->Type = BDC_TYPE_PI; + pNode->puFunc = (unsigned *)Vec_PtrEntry( p->vTruths, i ); + pNode->uSupp = (1 << i); + Bdc_TableAdd( p, pNode ); + } + // add the divisors + if ( vDivs ) + Vec_PtrForEachEntry( unsigned *, 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; + } + assert( p->nNodesNew == 0 ); +} + +/**Function************************************************************* + + Synopsis [Clears the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bdc_ManDecPrint( Bdc_Man_t * p ) +{ + Bdc_Fun_t * pNode; + int i; + printf( " 0 : Const 1\n" ); + for ( i = 1; i < p->nNodes; i++ ) + { + printf( " %d : ", i ); + pNode = p->pNodes + i; + if ( pNode->Type == BDC_TYPE_PI ) + printf( "PI " ); + else + { + printf( "%s%d &", Bdc_IsComplement(pNode->pFan0)? "-":"", Bdc_FunId(p,Bdc_Regular(pNode->pFan0)) ); + printf( " %s%d ", Bdc_IsComplement(pNode->pFan1)? "-":"", Bdc_FunId(p,Bdc_Regular(pNode->pFan1)) ); + } + Extra_PrintBinary( stdout, pNode->puFunc, (1<nVars) ); + printf( "\n" ); + } + printf( "Root = %s%d.\n", Bdc_IsComplement(p->pRoot)? "-":"", Bdc_FunId(p,Bdc_Regular(p->pRoot)) ); +} + +/**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; + int clk = clock(); + assert( nVars <= p->pPars->nVarsMax ); + // set current manager parameters + p->nVars = nVars; + p->nWords = Kit_TruthWordNum( nVars ); + p->nNodesMax = nNodesMax; + Bdc_ManPrepare( p, vDivs ); + if ( puCare && Kit_TruthIsConst0( puCare, nVars ) ) + { + p->pRoot = Bdc_Not(p->pNodes); + return 0; + } + // copy the function + Bdc_IsfStart( p, pIsf ); + if ( puCare ) + { + Kit_TruthAnd( pIsf->puOn, puCare, puFunc, p->nVars ); + Kit_TruthSharp( pIsf->puOff, puCare, puFunc, p->nVars ); + } + else + { + Kit_TruthCopy( pIsf->puOn, puFunc, p->nVars ); + Kit_TruthNot( pIsf->puOff, puFunc, p->nVars ); + } + Bdc_SuppMinimize( p, pIsf ); + // call decomposition + p->pRoot = Bdc_ManDecompose_rec( p, pIsf ); + p->timeTotal += clock() - clk; + p->numCalls++; + p->numNodes += p->nNodesNew; + if ( p->pRoot == NULL ) + return -1; + if ( !Bdc_ManNodeVerify( p, pIsf, p->pRoot ) ) + printf( "Bdc_ManDecompose(): Internal verification failed.\n" ); +// assert( Bdc_ManNodeVerify( p, pIsf, p->pRoot ) ); + return p->nNodesNew; +} + +/**Function************************************************************* + + Synopsis [Performs decomposition of one function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bdc_ManDecomposeTest( unsigned uTruth, int nVars ) +{ + static int Counter = 0; + static int Total = 0; + Bdc_Par_t Pars = {0}, * pPars = &Pars; + Bdc_Man_t * p; + int RetValue; +// unsigned uCare = ~0x888f888f; + unsigned uCare = ~0; +// unsigned uFunc = 0x88888888; +// unsigned uFunc = 0xf888f888; +// unsigned uFunc = 0x117e117e; +// unsigned uFunc = 0x018b018b; + unsigned uFunc = uTruth; + + pPars->nVarsMax = 8; + p = Bdc_ManAlloc( pPars ); + RetValue = Bdc_ManDecompose( p, &uFunc, &uCare, nVars, NULL, 1000 ); + Total += RetValue; + printf( "%5d : Nodes = %5d. Total = %8d.\n", ++Counter, RetValue, Total ); +// Bdc_ManDecPrint( p ); + Bdc_ManFree( p ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bool/bdc/bdcDec.c b/src/bool/bdc/bdcDec.c new file mode 100644 index 00000000..61f46f17 --- /dev/null +++ b/src/bool/bdc/bdcDec.c @@ -0,0 +1,751 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Minimizes the support of the ISF.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bdc_SuppMinimize2( Bdc_Man_t * p, Bdc_Isf_t * pIsf ) +{ + int v; + int clk = 0; // Suppress "might be used uninitialized" + if ( p->pPars->fVerbose ) + clk = clock(); + // compute support + pIsf->uSupp = Kit_TruthSupport( pIsf->puOn, p->nVars ) | + Kit_TruthSupport( pIsf->puOff, p->nVars ); + // 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; +// if ( !Kit_TruthVarIsVacuous( pIsf->puOn, pIsf->puOff, p->nVars, v ) ) +// continue; + // remove the variable + Kit_TruthCopy( pIsf->puOn, p->puTemp1, p->nVars ); + Kit_TruthCopy( pIsf->puOff, p->puTemp2, p->nVars ); +// Kit_TruthExist( pIsf->puOn, p->nVars, v ); +// Kit_TruthExist( pIsf->puOff, p->nVars, v ); + pIsf->uSupp &= ~(1 << v); + } + if ( p->pPars->fVerbose ) + p->timeSupps += clock() - clk; +} + +/**Function************************************************************* + + Synopsis [Minimizes the support of the ISF.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bdc_SuppMinimize( Bdc_Man_t * p, Bdc_Isf_t * pIsf ) +{ + int v; + int clk = 0; // Suppress "might be used uninitialized" + if ( p->pPars->fVerbose ) + clk = clock(); + // go through the support variables + pIsf->uSupp = 0; + for ( v = 0; v < p->nVars; v++ ) + { + if ( !Kit_TruthVarInSupport( pIsf->puOn, p->nVars, v ) && + !Kit_TruthVarInSupport( pIsf->puOff, p->nVars, v ) ) + continue; + if ( Kit_TruthVarIsVacuous( pIsf->puOn, pIsf->puOff, p->nVars, v ) ) + { + Kit_TruthExist( pIsf->puOn, p->nVars, v ); + Kit_TruthExist( pIsf->puOff, p->nVars, v ); + continue; + } + pIsf->uSupp |= (1 << v); + } + if ( p->pPars->fVerbose ) + p->timeSupps += clock() - clk; +} + +/**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, Bdc_Fun_t * pFunc0, Bdc_Type_t Type ) +{ + unsigned * puTruth = p->puTemp1; + // get the truth table of the left branch + if ( Bdc_IsComplement(pFunc0) ) + Kit_TruthNot( puTruth, Bdc_Regular(pFunc0)->puFunc, p->nVars ); + else + Kit_TruthCopy( puTruth, pFunc0->puFunc, p->nVars ); + // split into parts + 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->uUniq ); + Kit_TruthExistSet( pIsfR->puOff, pIsf->puOff, p->nVars, pIsfL->uUniq ); +// assert( Kit_TruthIsDisjoint(pIsfR->puOn, pIsfR->puOff, p->nVars) ); + 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_TruthAnd( pIsfR->puOff, pIsf->puOff, puTruth, p->nVars ); + Kit_TruthExistSet( pIsfR->puOff, pIsfR->puOff, p->nVars, pIsfL->uUniq ); + Kit_TruthExistSet( pIsfR->puOn, pIsf->puOn, p->nVars, pIsfL->uUniq ); +// assert( Kit_TruthIsDisjoint(pIsfR->puOn, pIsfR->puOff, p->nVars) ); + assert( !Kit_TruthIsConst0(pIsfR->puOn, p->nVars) ); + return Kit_TruthIsConst0(pIsfR->puOff, 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->uUniq = (1 << pVars[Beg]); + pIsfR->uUniq = (1 << pVars[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; + int VarBest = -1; // Suppress "might be used uninitialized" + int Cost, VarCostBest = 0; + + for ( v = 0; v < p->nVars; v++ ) + { + if ( (pIsf->uSupp & (1 << v)) == 0 ) + continue; +// 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 ) + + Kit_TruthExistNew( p->puTemp1, pIsf->puOff, p->nVars, v ); + 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->uUniq = (1 << VarBest); + pIsfR->uUniq = 0; + +// assert( pL->Q != b0 ); +// assert( pL->R != b0 ); +// assert( Cudd_bddIteConstant( dd, pL->Q, pL->R, b0 ) == b0 ); +// assert( Kit_TruthIsDisjoint(pIsfL->puOn, pIsfL->puOff, p->nVars) ); + + // 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 uSupportRem; + int v, nLeftVars = 1, nRightVars = 1; + // clean the var sets + Bdc_IsfStart( p, pIsfL ); + Bdc_IsfStart( p, pIsfR ); + // check that the support is correct + assert( Kit_TruthSupport(pIsf->puOn, p->nVars) == Kit_TruthSupport(pIsf->puOff, p->nVars) ); + assert( pIsf->uSupp == Kit_TruthSupport(pIsf->puOn, p->nVars) ); + // 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_TruthExistSet( p->puTemp1, pIsf->puOff, p->nVars, pIsfL->uUniq ); + Kit_TruthExistSet( p->puTemp2, pIsf->puOff, p->nVars, pIsfR->uUniq ); + // go through the remaining variables + uSupportRem = pIsf->uSupp & ~pIsfL->uUniq & ~pIsfR->uUniq; + for ( v = 0; v < p->nVars; v++ ) + { + if ( (uSupportRem & (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->uUniq |= (1 << v); + nLeftVars++; + Kit_TruthCopy( p->puTemp1, p->puTemp3, p->nVars ); + } +// 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->uUniq |= (1 << v); + nRightVars++; + Kit_TruthCopy( p->puTemp2, p->puTemp4, p->nVars ); + } + } + 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->uUniq |= (1 << v); + nRightVars++; + Kit_TruthCopy( p->puTemp2, p->puTemp4, p->nVars ); + } +// 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->uUniq |= (1 << v); + nLeftVars++; + Kit_TruthCopy( p->puTemp1, p->puTemp3, p->nVars ); + } + } + } + + // 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->uUniq ); + Kit_TruthCopy( pIsfL->puOff, p->puTemp2, 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) ); + + // 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->uUniq ); + Kit_TruthCopy( pIsfR->puOff, p->puTemp1, p->nVars ); + + assert( !Kit_TruthIsConst0(pIsfR->puOn, p->nVars) ); + assert( !Kit_TruthIsConst0(pIsfR->puOff, p->nVars) ); +// assert( Kit_TruthIsDisjoint(pIsfR->puOn, pIsfR->puOff, p->nVars) ); + + assert( pIsfL->uUniq ); + assert( pIsfR->uUniq ); + 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 WeightOr, WeightAnd, WeightOrL, WeightOrR, WeightAndL, WeightAndR; + + Bdc_IsfClean( p->pIsfOL ); + Bdc_IsfClean( p->pIsfOR ); + Bdc_IsfClean( p->pIsfAL ); + Bdc_IsfClean( p->pIsfAR ); + + // perform OR decomposition + WeightOr = Bdc_DecomposeOr( p, pIsf, p->pIsfOL, p->pIsfOR ); + + // perform AND decomposition + Bdc_IsfNot( pIsf ); + WeightAnd = Bdc_DecomposeOr( p, pIsf, p->pIsfAL, p->pIsfAR ); + Bdc_IsfNot( pIsf ); + Bdc_IsfNot( p->pIsfAL ); + Bdc_IsfNot( p->pIsfAR ); + + // check the case when decomposition does not exist + if ( WeightOr == 0 && WeightAnd == 0 ) + { + Bdc_IsfCopy( pIsfL, p->pIsfOL ); + Bdc_IsfCopy( pIsfR, p->pIsfOR ); + return BDC_TYPE_MUX; + } + // check the hash table + assert( WeightOr || WeightAnd ); + WeightOrL = WeightOrR = 0; + if ( WeightOr ) + { + if ( p->pIsfOL->uUniq ) + { + Bdc_SuppMinimize( p, p->pIsfOL ); + WeightOrL = (Bdc_TableLookup(p, p->pIsfOL) != NULL); + } + if ( p->pIsfOR->uUniq ) + { + Bdc_SuppMinimize( p, p->pIsfOR ); + WeightOrR = (Bdc_TableLookup(p, p->pIsfOR) != NULL); + } + } + WeightAndL = WeightAndR = 0; + if ( WeightAnd ) + { + if ( p->pIsfAL->uUniq ) + { + Bdc_SuppMinimize( p, p->pIsfAL ); + WeightAndL = (Bdc_TableLookup(p, p->pIsfAL) != NULL); + } + if ( p->pIsfAR->uUniq ) + { + Bdc_SuppMinimize( p, p->pIsfAR ); + WeightAndR = (Bdc_TableLookup(p, p->pIsfAR) != NULL); + } + } + + // check if there is any reuse for the components + if ( WeightOrL + WeightOrR > WeightAndL + WeightAndR ) + { + p->numReuse++; + p->numOrs++; + Bdc_IsfCopy( pIsfL, p->pIsfOL ); + Bdc_IsfCopy( pIsfR, p->pIsfOR ); + return BDC_TYPE_OR; + } + if ( WeightOrL + WeightOrR < WeightAndL + WeightAndR ) + { + p->numReuse++; + p->numAnds++; + Bdc_IsfCopy( pIsfL, p->pIsfAL ); + Bdc_IsfCopy( pIsfR, p->pIsfAR ); + return BDC_TYPE_AND; + } + + // compare the two-component costs + if ( WeightOr > WeightAnd ) + { + if ( WeightOr < BDC_SCALE ) + p->numWeaks++; + p->numOrs++; + Bdc_IsfCopy( pIsfL, p->pIsfOL ); + Bdc_IsfCopy( pIsfR, p->pIsfOR ); + return BDC_TYPE_OR; + } + if ( WeightAnd < BDC_SCALE ) + p->numWeaks++; + p->numAnds++; + Bdc_IsfCopy( pIsfL, p->pIsfAL ); + Bdc_IsfCopy( pIsfR, p->pIsfAR ); + return BDC_TYPE_AND; +} + +/**Function************************************************************* + + Synopsis [Find variable that leads to minimum sum of support sizes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bdc_DecomposeStepMux( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR ) +{ + int Var, VarMin, nSuppMin, nSuppCur; + unsigned uSupp0, uSupp1; + int clk = 0; // Suppress "might be used uninitialized" + if ( p->pPars->fVerbose ) + clk = clock(); + VarMin = -1; + nSuppMin = 1000; + for ( Var = 0; Var < p->nVars; Var++ ) + { + if ( (pIsf->uSupp & (1 << Var)) == 0 ) + continue; + Kit_TruthCofactor0New( pIsfL->puOn, pIsf->puOn, p->nVars, Var ); + Kit_TruthCofactor0New( pIsfL->puOff, pIsf->puOff, p->nVars, Var ); + Kit_TruthCofactor1New( pIsfR->puOn, pIsf->puOn, p->nVars, Var ); + Kit_TruthCofactor1New( pIsfR->puOff, pIsf->puOff, p->nVars, Var ); + uSupp0 = Kit_TruthSupport( pIsfL->puOn, p->nVars ) & Kit_TruthSupport( pIsfL->puOff, p->nVars ); + uSupp1 = Kit_TruthSupport( pIsfR->puOn, p->nVars ) & Kit_TruthSupport( pIsfR->puOff, p->nVars ); + nSuppCur = Kit_WordCountOnes(uSupp0) + Kit_WordCountOnes(uSupp1); + if ( nSuppMin > nSuppCur ) + { + nSuppMin = nSuppCur; + VarMin = Var; + break; + } + } + if ( VarMin >= 0 ) + { + Kit_TruthCofactor0New( pIsfL->puOn, pIsf->puOn, p->nVars, VarMin ); + Kit_TruthCofactor0New( pIsfL->puOff, pIsf->puOff, p->nVars, VarMin ); + Kit_TruthCofactor1New( pIsfR->puOn, pIsf->puOn, p->nVars, VarMin ); + Kit_TruthCofactor1New( pIsfR->puOff, pIsf->puOff, p->nVars, VarMin ); + Bdc_SuppMinimize( p, pIsfL ); + Bdc_SuppMinimize( p, pIsfR ); + } + if ( p->pPars->fVerbose ) + p->timeMuxes += clock() - clk; + return VarMin; +} + +/**Function************************************************************* + + Synopsis [Creates gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bdc_ManNodeVerify( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Fun_t * pFunc ) +{ + unsigned * puTruth = p->puTemp1; + if ( Bdc_IsComplement(pFunc) ) + Kit_TruthNot( puTruth, Bdc_Regular(pFunc)->puFunc, p->nVars ); + else + Kit_TruthCopy( puTruth, pFunc->puFunc, p->nVars ); + return Bdc_TableCheckContainment( p, pIsf, puTruth ); +} + +/**Function************************************************************* + + Synopsis [Creates gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bdc_Fun_t * Bdc_ManCreateGate( Bdc_Man_t * p, Bdc_Fun_t * pFunc0, Bdc_Fun_t * pFunc1, Bdc_Type_t Type ) +{ + Bdc_Fun_t * pFunc; + pFunc = Bdc_FunNew( p ); + if ( pFunc == NULL ) + return NULL; + pFunc->Type = Type; + pFunc->pFan0 = pFunc0; + pFunc->pFan1 = pFunc1; + pFunc->puFunc = (unsigned *)Vec_IntFetch(p->vMemory, p->nWords); + // get the truth table of the left branch + if ( Bdc_IsComplement(pFunc0) ) + Kit_TruthNot( p->puTemp1, Bdc_Regular(pFunc0)->puFunc, p->nVars ); + else + Kit_TruthCopy( p->puTemp1, pFunc0->puFunc, p->nVars ); + // get the truth table of the right branch + if ( Bdc_IsComplement(pFunc1) ) + Kit_TruthNot( p->puTemp2, Bdc_Regular(pFunc1)->puFunc, p->nVars ); + else + Kit_TruthCopy( p->puTemp2, pFunc1->puFunc, p->nVars ); + // compute the function of node + if ( pFunc->Type == BDC_TYPE_AND ) + { + Kit_TruthAnd( pFunc->puFunc, p->puTemp1, p->puTemp2, p->nVars ); + } + else if ( pFunc->Type == BDC_TYPE_OR ) + { + Kit_TruthOr( pFunc->puFunc, p->puTemp1, p->puTemp2, p->nVars ); + // transform to AND gate + 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); + } + else + assert( 0 ); + // add to table + Bdc_Regular(pFunc)->uSupp = Kit_TruthSupport( Bdc_Regular(pFunc)->puFunc, p->nVars ); + Bdc_TableAdd( p, Bdc_Regular(pFunc) ); + return pFunc; +} + +/**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 ) +{ +// int static Counter = 0; +// int LocalCounter = Counter++; + Bdc_Type_t Type; + Bdc_Fun_t * pFunc, * pFunc0, * pFunc1; + Bdc_Isf_t IsfL, * pIsfL = &IsfL; + Bdc_Isf_t IsfB, * pIsfR = &IsfB; + int iVar; + int clk = 0; // Suppress "might be used uninitialized" +/* +printf( "Init function (%d):\n", LocalCounter ); +Extra_PrintBinary( stdout, pIsf->puOn, 1<<4 );printf("\n"); +Extra_PrintBinary( stdout, pIsf->puOff, 1<<4 );printf("\n"); +*/ + // check computed results + assert( Kit_TruthIsDisjoint(pIsf->puOn, pIsf->puOff, p->nVars) ); + if ( p->pPars->fVerbose ) + clk = clock(); + pFunc = Bdc_TableLookup( p, pIsf ); + if ( p->pPars->fVerbose ) + p->timeCache += clock() - clk; + if ( pFunc ) + return pFunc; + // decide on the decomposition type + if ( p->pPars->fVerbose ) + clk = clock(); + Type = Bdc_DecomposeStep( p, pIsf, pIsfL, pIsfR ); + if ( p->pPars->fVerbose ) + p->timeCheck += clock() - clk; + if ( Type == BDC_TYPE_MUX ) + { + if ( p->pPars->fVerbose ) + clk = clock(); + iVar = Bdc_DecomposeStepMux( p, pIsf, pIsfL, pIsfR ); + if ( p->pPars->fVerbose ) + p->timeMuxes += clock() - clk; + p->numMuxes++; + pFunc0 = Bdc_ManDecompose_rec( p, pIsfL ); + pFunc1 = Bdc_ManDecompose_rec( p, pIsfR ); + if ( pFunc0 == NULL || pFunc1 == NULL ) + return NULL; + pFunc = Bdc_FunWithId( p, iVar + 1 ); + pFunc0 = Bdc_ManCreateGate( p, Bdc_Not(pFunc), pFunc0, BDC_TYPE_AND ); + pFunc1 = Bdc_ManCreateGate( p, pFunc, pFunc1, BDC_TYPE_AND ); + if ( pFunc0 == NULL || pFunc1 == NULL ) + return NULL; + pFunc = Bdc_ManCreateGate( p, pFunc0, pFunc1, BDC_TYPE_OR ); + } + else + { + pFunc0 = Bdc_ManDecompose_rec( p, pIsfL ); + if ( pFunc0 == NULL ) + return NULL; + // decompose the right branch + if ( Bdc_DecomposeUpdateRight( p, pIsf, pIsfL, pIsfR, pFunc0, Type ) ) + { + p->nNodesNew--; + return pFunc0; + } + Bdc_SuppMinimize( p, pIsfR ); + pFunc1 = Bdc_ManDecompose_rec( p, pIsfR ); + if ( pFunc1 == NULL ) + return NULL; + // create new gate + pFunc = Bdc_ManCreateGate( p, pFunc0, pFunc1, Type ); + } + return pFunc; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bool/bdc/bdcInt.h b/src/bool/bdc/bdcInt.h new file mode 100644 index 00000000..05ce20b6 --- /dev/null +++ b/src/bool/bdc/bdcInt.h @@ -0,0 +1,165 @@ +/**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 ABC__aig__bdc__bdcInt_h +#define ABC__aig__bdc__bdcInt_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "src/bool/kit/kit.h" +#include "bdc.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +#define BDC_SCALE 1000 // 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, // 3: AND-gate + BDC_TYPE_OR, // 4: OR-gate (temporary) + BDC_TYPE_XOR, // 5: XOR-gate + BDC_TYPE_MUX, // 6: MUX-gate + BDC_TYPE_OTHER // 7: unused +} Bdc_Type_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 + unsigned uSupp; // bit mask of current support + unsigned * puFunc; // the function of the node + Bdc_Fun_t * pNext; // next function with same support + union { int iCopy; // the literal of the node (AIG) + void * pCopy; }; // the function of the node (BDD or AIG) + +}; + +typedef struct Bdc_Isf_t_ Bdc_Isf_t; +struct Bdc_Isf_t_ +{ + unsigned uSupp; // the complete support of this component + unsigned uUniq; // the unique variables of this component + 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 nNodesMax; // 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 nNodesAlloc; // the number of nodes allocated + int nNodes; // the number of all nodes created so far + int nNodesNew; // the number of new AND nodes created so far + 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 + // statistics + int numCalls; + int numNodes; + int numMuxes; + int numAnds; + int numOrs; + int numWeaks; + int numReuse; + // runtime + int timeCache; + int timeCheck; + int timeMuxes; + int timeSupps; + int timeTotal; +}; + +static inline Bdc_Fun_t * Bdc_FunNew( Bdc_Man_t * p ) { Bdc_Fun_t * pRes; if ( p->nNodes >= p->nNodesAlloc || p->nNodesNew >= p->nNodesMax ) return NULL; pRes = p->pNodes + p->nNodes++; p->nNodesNew++; memset( pRes, 0, sizeof(Bdc_Fun_t) ); return pRes; } +static inline Bdc_Fun_t * Bdc_FunWithId( Bdc_Man_t * p, int Id ) { assert( Id < p->nNodes ); return p->pNodes + Id; } +static inline int Bdc_FunId( Bdc_Man_t * p, Bdc_Fun_t * pFun ) { return pFun - p->pNodes; } +static inline void Bdc_IsfStart( Bdc_Man_t * p, Bdc_Isf_t * pF ) { pF->uSupp = 0; pF->uUniq = 0; pF->puOn = Vec_IntFetch( p->vMemory, p->nWords ); pF->puOff = Vec_IntFetch( p->vMemory, p->nWords ); assert( pF->puOff && pF->puOn ); } +static inline void Bdc_IsfClean( Bdc_Isf_t * p ) { p->uSupp = 0; p->uUniq = 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 ); +extern void Bdc_SuppMinimize( Bdc_Man_t * p, Bdc_Isf_t * pIsf ); +extern int Bdc_ManNodeVerify( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Fun_t * pFunc ); +/*=== 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 int Bdc_TableCheckContainment( Bdc_Man_t * p, Bdc_Isf_t * pIsf, unsigned * puTruth ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/bool/bdc/bdcSpfd.c b/src/bool/bdc/bdcSpfd.c new file mode 100644 index 00000000..83a35c11 --- /dev/null +++ b/src/bool/bdc/bdcSpfd.c @@ -0,0 +1,1176 @@ +/**CFile**************************************************************** + + FileName [bdcSpfd.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: bdcSpfd.c,v 1.00 2007/01/30 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "bdcInt.h" +#include "src/aig/aig/aig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Bdc_Nod_t_ Bdc_Nod_t; +struct Bdc_Nod_t_ +{ + unsigned iFan0g : 8; + unsigned iFan0n : 12; + unsigned Type : 12; // 0-3 = AND; 4 = XOR + + unsigned iFan1g : 8; + unsigned iFan1n : 12; + unsigned Weight : 12; + + word Truth; +}; + +static word Truths[6] = { + 0xAAAAAAAAAAAAAAAA, + 0xCCCCCCCCCCCCCCCC, + 0xF0F0F0F0F0F0F0F0, + 0xFF00FF00FF00FF00, + 0xFFFF0000FFFF0000, + 0xFFFFFFFF00000000 +}; + +static inline int Bdc_CountOnes( word t ) +{ + t = (t & 0x5555555555555555) + ((t>> 1) & 0x5555555555555555); + t = (t & 0x3333333333333333) + ((t>> 2) & 0x3333333333333333); + t = (t & 0x0F0F0F0F0F0F0F0F) + ((t>> 4) & 0x0F0F0F0F0F0F0F0F); + t = (t & 0x00FF00FF00FF00FF) + ((t>> 8) & 0x00FF00FF00FF00FF); + t = (t & 0x0000FFFF0000FFFF) + ((t>>16) & 0x0000FFFF0000FFFF); + return (t & 0x00000000FFFFFFFF) + (t>>32); +} + +static inline int Bdc_CountSpfd( word t, word f ) +{ + int n00 = Bdc_CountOnes( ~t & ~f ); + int n01 = Bdc_CountOnes( t & ~f ); + int n10 = Bdc_CountOnes( ~t & f ); + int n11 = Bdc_CountOnes( t & f ); + return n00 * n11 + n10 * n01; +} + +static inline word Bdc_Cof6( word t, int iVar, int fCof1 ) +{ + assert( iVar >= 0 && iVar < 6 ); + if ( fCof1 ) + return (t & Truths[iVar]) | ((t & Truths[iVar]) >> (1< 0 ); + printf( "(" ); + + if ( pNode->Type & 1 ) + printf( "!" ); + if ( pNode->iFan0g == 0 ) + printf( "%c", 'a' + pNode->iFan0n ); + else + { + Bdc_Nod_t * pNode0 = (Bdc_Nod_t *)Vec_PtrEntry(vLevels, pNode->iFan0g); + Bdc_SpfdPrint_rec( pNode0 + pNode->iFan0n, pNode->iFan0g, vLevels ); + } + + if ( pNode->Type & 4 ) + printf( "+" ); + else + printf( "*" ); + + if ( pNode->Type & 2 ) + printf( "!" ); + if ( pNode->iFan1g == 0 ) + printf( "%c", 'a' + pNode->iFan1n ); + else + { + Bdc_Nod_t * pNode1 = (Bdc_Nod_t *)Vec_PtrEntry(vLevels, pNode->iFan1g); + Bdc_SpfdPrint_rec( pNode1 + pNode->iFan1n, pNode->iFan1g, vLevels ); + } + + printf( ")" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bdc_SpfdPrint( Bdc_Nod_t * pNode, int Level, Vec_Ptr_t * vLevels, word Truth ) +{ + word Diff = Truth ^ pNode->Truth; + Extra_PrintHex( stdout, (unsigned *)&pNode->Truth, 6 ); printf( " " ); + Extra_PrintHex( stdout, (unsigned *)&Diff, 6 ); printf( " " ); + Bdc_SpfdPrint_rec( pNode, Level, vLevels ); + printf( " %d\n", pNode->Weight ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bdc_SpfdDecompose( word Truth, int nVars, int nCands, int nGatesMax ) +{ + int nSize = nCands * nCands * (nGatesMax + 1) * 5; + Vec_Ptr_t * vLevels; + Vec_Int_t * vBegs, * vWeight; + Bdc_Nod_t * pNode, * pNode0, * pNode1, * pNode2; + int Count0, Count1, * pPerm; + int i, j, k, c, n, clk; + assert( nGatesMax < (1<<8) ); + assert( nCands < (1<<12) ); + assert( (1<<(nVars-1))*(1<<(nVars-1)) < (1<<12) ); // max SPFD + + printf( "Storage size = %d (%d * %d * %d * %d).\n", nSize, nCands, nCands, nGatesMax + 1, 5 ); + + printf( "SPFD = %d.\n", Bdc_CountOnes(Truth) * Bdc_CountOnes(~Truth) ); + + // consider elementary functions + if ( Truth == 0 || Truth == ~0 ) + { + printf( "Function is a constant.\n" ); + return; + } + for ( i = 0; i < nVars; i++ ) + if ( Truth == Truths[i] || Truth == ~Truths[i] ) + { + printf( "Function is an elementary variable.\n" ); + return; + } + + // allocate + vLevels = Vec_PtrAlloc( 100 ); + vBegs = Vec_IntAlloc( 100 ); + vWeight = Vec_IntAlloc( 100 ); + + // initialize elementary variables + pNode = ABC_CALLOC( Bdc_Nod_t, nVars ); + for ( i = 0; i < nVars; i++ ) + pNode[i].Truth = Truths[i]; + for ( i = 0; i < nVars; i++ ) + pNode[i].Weight = Bdc_CountSpfd( pNode[i].Truth, Truth ); + Vec_PtrPush( vLevels, pNode ); + Vec_IntPush( vBegs, nVars ); + + // the next level +clk = clock(); + pNode0 = pNode; + pNode = ABC_CALLOC( Bdc_Nod_t, 5 * nVars * (nVars - 1) / 2 ); + for ( c = i = 0; i < nVars; i++ ) + for ( j = i+1; j < nVars; j++ ) + { + pNode[c].Truth = pNode0[i].Truth & pNode0[j].Truth; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 0; + pNode[c].Truth = ~pNode0[i].Truth & pNode0[j].Truth; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 1; + pNode[c].Truth = pNode0[i].Truth & ~pNode0[j].Truth; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 2; + pNode[c].Truth = ~pNode0[i].Truth & ~pNode0[j].Truth; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 3; + pNode[c].Truth = pNode0[i].Truth ^ pNode0[j].Truth; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 4; + } + assert( c == 5 * nVars * (nVars - 1) / 2 ); + Vec_PtrPush( vLevels, pNode ); + Vec_IntPush( vBegs, c ); + for ( i = 0; i < c; i++ ) + { + pNode[i].Weight = Bdc_CountSpfd( pNode[i].Truth, Truth ); +//Bdc_SpfdPrint( pNode + i, 1, vLevels ); + if ( Truth == pNode[i].Truth || Truth == ~pNode[i].Truth ) + { + printf( "Function can be implemented using 1 gate.\n" ); + pNode = NULL; + goto cleanup; + } + } +printf( "Selected %6d gates on level %2d. ", c, 1 ); +Abc_PrintTime( 1, "Time", clock() - clk ); + + + // iterate through levels + pNode = ABC_CALLOC( Bdc_Nod_t, nSize ); + for ( n = 2; n <= nGatesMax; n++ ) + { +clk = clock(); + c = 0; + pNode1 = (Bdc_Nod_t *)Vec_PtrEntry( vLevels, n-1 ); + Count1 = Vec_IntEntry( vBegs, n-1 ); + // go through previous levels + for ( k = 0; k < n-1; k++ ) + { + pNode0 = (Bdc_Nod_t *)Vec_PtrEntry( vLevels, k ); + Count0 = Vec_IntEntry( vBegs, k ); + for ( i = 0; i < Count0; i++ ) + for ( j = 0; j < Count1; j++ ) + { + pNode[c].Truth = pNode0[i].Truth & pNode1[j].Truth; pNode[c].iFan0g = k; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 0; + pNode[c].Truth = ~pNode0[i].Truth & pNode1[j].Truth; pNode[c].iFan0g = k; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 1; + pNode[c].Truth = pNode0[i].Truth & ~pNode1[j].Truth; pNode[c].iFan0g = k; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 2; + pNode[c].Truth = ~pNode0[i].Truth & ~pNode1[j].Truth; pNode[c].iFan0g = k; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 3; + pNode[c].Truth = pNode0[i].Truth ^ pNode1[j].Truth; pNode[c].iFan0g = k; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 4; + } + assert( c < nSize ); + } + // go through current level + for ( i = 0; i < Count1; i++ ) + for ( j = i+1; j < Count1; j++ ) + { + pNode[c].Truth = pNode1[i].Truth & pNode1[j].Truth; pNode[c].iFan0g = n-1; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 0; + pNode[c].Truth = ~pNode1[i].Truth & pNode1[j].Truth; pNode[c].iFan0g = n-1; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 1; + pNode[c].Truth = pNode1[i].Truth & ~pNode1[j].Truth; pNode[c].iFan0g = n-1; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 2; + pNode[c].Truth = ~pNode1[i].Truth & ~pNode1[j].Truth; pNode[c].iFan0g = n-1; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 3; + pNode[c].Truth = pNode1[i].Truth ^ pNode1[j].Truth; pNode[c].iFan0g = n-1; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 4; + } + assert( c < nSize ); + // sort + Vec_IntClear( vWeight ); + for ( i = 0; i < c; i++ ) + { + pNode[i].Weight = Bdc_CountSpfd( pNode[i].Truth, Truth ); +if ( pNode[i].Weight > 300 ) +Bdc_SpfdPrint( pNode + i, 1, vLevels, Truth ); + Vec_IntPush( vWeight, pNode[i].Weight ); + + if ( Truth == pNode[i].Truth || Truth == ~pNode[i].Truth ) + { + printf( "Function can be implemented using %d gates.\n", n ); + Bdc_SpfdPrint( pNode + i, n, vLevels, Truth ); + goto cleanup; + } + } + pPerm = Abc_SortCost( Vec_IntArray(vWeight), c ); + assert( Vec_IntEntry(vWeight, pPerm[0]) <= Vec_IntEntry(vWeight, pPerm[c-1]) ); + + printf( "Best SPFD = %d.\n", Vec_IntEntry(vWeight, pPerm[c-1]) ); +// for ( i = 0; i < c; i++ ) +//printf( "%d ", Vec_IntEntry(vWeight, pPerm[i]) ); + + // choose the best ones + pNode2 = ABC_CALLOC( Bdc_Nod_t, nCands ); + for ( j = 0, i = c-1; i >= 0; i-- ) + { + pNode2[j++] = pNode[pPerm[i]]; + if ( j == nCands ) + break; + } + ABC_FREE( pPerm ); + Vec_PtrPush( vLevels, pNode2 ); + Vec_IntPush( vBegs, j ); + +printf( "Selected %6d gates (out of %6d) on level %2d. ", j, c, n ); +Abc_PrintTime( 1, "Time", clock() - clk ); + + for ( i = 0; i < 10; i++ ) + Bdc_SpfdPrint( pNode2 + i, n, vLevels, Truth ); + } + +cleanup: + ABC_FREE( pNode ); + Vec_PtrForEachEntry( Bdc_Nod_t *, vLevels, pNode, i ) + ABC_FREE( pNode ); + Vec_PtrFree( vLevels ); + Vec_IntFree( vBegs ); + Vec_IntFree( vWeight ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bdc_SpfdDecomposeTest_() +{ + int fTry = 0; +// word T[17]; +// int i; + +// word Truth = Truths[0] & ~Truths[3]; +// word Truth = (Truths[0] & Truths[1]) | (Truths[2] & Truths[3]) | (Truths[4] & Truths[5]); +// word Truth = (Truths[0] & Truths[1]) | ((Truths[2] & ~Truths[3]) ^ (Truths[4] & ~Truths[5])); +// word Truth = (Truths[0] & Truths[1]) | (Truths[2] & Truths[3]); +// word Truth = 0x9ef7a8d9c7193a0f; // AAFFAAFF0A0F0A0F +// word Truth = 0x34080226CD163000; + word Truth = 0x5052585a0002080a; + int nVars = 6; + int nCands = 200;// 75; + int nGatesMax = 20; + + if ( fTry ) + Bdc_SpfdDecompose( Truth, nVars, nCands, nGatesMax ); +/* + for ( i = 0; i < 6; i++ ) + T[i] = Truths[i]; + T[7] = 0; + T[8] = ~T[1] & T[3]; + T[9] = ~T[8] & T[0]; + T[10] = T[1] & T[4]; + T[11] = T[10] & T[2]; + T[12] = T[11] & T[9]; + T[13] = ~T[0] & T[5]; + T[14] = T[2] & T[13]; + T[15] = ~T[12] & ~T[14]; + T[16] = ~T[15]; +// if ( T[16] != Truth ) +// printf( "Failed\n" ); + + for ( i = 0; i < 17; i++ ) + { +// printf( "%2d = %3d ", i, Bdc_CountSpfd(T[i], Truth) ); + printf( "%2d = %3d ", i, Bdc_CountSpfd(T[i], T[16]) ); + Extra_PrintBinary( stdout, (unsigned *)&T[i], 64 ); printf( "\n" ); + } +// Extra_PrintBinary( stdout, (unsigned *)&Truth, 64 ); printf( "\n" ); +*/ +} + + + + +typedef struct Bdc_Ent_t_ Bdc_Ent_t; // 24 bytes +struct Bdc_Ent_t_ +{ + unsigned iFan0 : 29; + unsigned fCompl0 : 1; + unsigned fCompl : 1; + unsigned fMark0 : 1; + unsigned iFan1 : 29; + unsigned fCompl1 : 1; + unsigned fExor : 1; + unsigned fMark1 : 1; + int iNext; + int iList; + word Truth; +}; + +#define BDC_TERM 0x1FFFFFFF + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bdc_SpfdMark0( Bdc_Ent_t * p, Bdc_Ent_t * pEnt ) +{ + if ( pEnt->iFan0 == BDC_TERM ) + return 0; + if ( pEnt->fMark0 ) + return 0; + pEnt->fMark0 = 1; + return pEnt->fMark1 + + Bdc_SpfdMark0(p, p + pEnt->iFan0) + + Bdc_SpfdMark0(p, p + pEnt->iFan1); +} +int Bdc_SpfdMark1( Bdc_Ent_t * p, Bdc_Ent_t * pEnt ) +{ + if ( pEnt->iFan0 == BDC_TERM ) + return 0; + if ( pEnt->fMark1 ) + return 0; + pEnt->fMark1 = 1; + return pEnt->fMark0 + + Bdc_SpfdMark1(p, p + pEnt->iFan0) + + Bdc_SpfdMark1(p, p + pEnt->iFan1); +} +void Bdc_SpfdUnmark0( Bdc_Ent_t * p, Bdc_Ent_t * pEnt ) +{ + if ( pEnt->iFan0 == BDC_TERM ) + return; + pEnt->fMark0 = 0; + Bdc_SpfdUnmark0( p, p + pEnt->iFan0 ); + Bdc_SpfdUnmark0( p, p + pEnt->iFan1 ); +} +void Bdc_SpfdUnmark1( Bdc_Ent_t * p, Bdc_Ent_t * pEnt ) +{ + if ( pEnt->iFan0 == BDC_TERM ) + return; + pEnt->fMark1 = 0; + Bdc_SpfdUnmark1( p, p + pEnt->iFan0 ); + Bdc_SpfdUnmark1( p, p + pEnt->iFan1 ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bdc_SpfdCheckOverlap( Bdc_Ent_t * p, Bdc_Ent_t * pEnt0, Bdc_Ent_t * pEnt1 ) +{ + int RetValue; + RetValue = Bdc_SpfdMark0( p, pEnt0 ); + assert( RetValue == 0 ); + RetValue = Bdc_SpfdMark1( p, pEnt1 ); + Bdc_SpfdUnmark0( p, pEnt0 ); + Bdc_SpfdUnmark1( p, pEnt1 ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bdc_SpfdHashValue( word t, int Size ) +{ + // http://planetmath.org/encyclopedia/GoodHashTablePrimes.html + // 53, + // 97, + // 193, + // 389, + // 769, + // 1543, + // 3079, + // 6151, + // 12289, + // 24593, + // 49157, + // 98317, + // 196613, + // 393241, + // 786433, + // 1572869, + // 3145739, + // 6291469, + // 12582917, + // 25165843, + // 50331653, + // 100663319, + // 201326611, + // 402653189, + // 805306457, + // 1610612741, + static unsigned BigPrimes[8] = {12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741}; + unsigned char * s = (unsigned char *)&t; + unsigned i, Value = 0; + for ( i = 0; i < 8; i++ ) + Value ^= BigPrimes[i] * s[i]; + return Value % Size; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Bdc_SpfdHashLookup( Bdc_Ent_t * p, int Size, word t ) +{ + Bdc_Ent_t * pBin = p + Bdc_SpfdHashValue( t, Size ); + if ( pBin->iList == 0 ) + return &pBin->iList; + for ( pBin = p + pBin->iList; ; pBin = p + pBin->iNext ) + { + if ( pBin->Truth == t ) + return NULL; + if ( pBin->iNext == 0 ) + return &pBin->iNext; + } + assert( 0 ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wrd_t * Bdc_SpfdDecomposeTest__( Vec_Int_t ** pvWeights ) +{ +// int nFuncs = 8000000; // the number of functions to compute +// int nSize = 2777111; // the hash table size to use +// int Limit = 6; + +// int nFuncs = 51000000; // the number of functions to compute +// int nSize = 50331653; // the hash table size to use +// int Limit = 6; + + int nFuncs = 250000000; // the number of functions to compute + int nSize = 201326611; // the hash table size to use + int Limit = 6; + + int * pPlace, i, n, m, k, s, fCompl, clk = clock(), clk2; + Vec_Int_t * vStops; + Vec_Wrd_t * vTruths; + Vec_Int_t * vWeights; + Bdc_Ent_t * p, * q, * pBeg0, * pEnd0, * pBeg1, * pEnd1, * pThis0, * pThis1; + word t0, t1, t; + assert( nSize <= nFuncs ); + + printf( "Allocating %.2f Mb of internal memory.\n", 1.0*sizeof(Bdc_Ent_t)*nFuncs/(1<<20) ); + + p = (Bdc_Ent_t *)calloc( nFuncs, sizeof(Bdc_Ent_t) ); + memset( p, 255, sizeof(Bdc_Ent_t) ); + p->iList = 0; + for ( q = p; q < p+nFuncs; q++ ) + q->iList = 0; + q = p + 1; + printf( "Added %d + %d + 0 = %d. Total = %8d.\n", 0, 0, 0, q-p ); + + vTruths = Vec_WrdStart( nFuncs ); + vWeights = Vec_IntStart( nFuncs ); + Vec_WrdClear( vTruths ); + Vec_IntClear( vWeights ); + + // create elementary vars + vStops = Vec_IntAlloc( 10 ); + Vec_IntPush( vStops, 1 ); + for ( i = 0; i < 6; i++ ) + { + q->iFan0 = BDC_TERM; + q->iFan1 = i; + q->Truth = Truths[i]; + pPlace = Bdc_SpfdHashLookup( p, nSize, q->Truth ); + *pPlace = q-p; + q++; + Vec_WrdPush( vTruths, Truths[i] ); + Vec_IntPush( vWeights, 0 ); + } + Vec_IntPush( vStops, 7 ); + printf( "Added %d + %d + 0 = %d. Total = %8d.\n", 0, 0, 0, q-p ); + + // create gates + for ( n = 0; n < Limit; n++ ) + { + // try previous + for ( k = 0; k < Limit; k++ ) + for ( m = 0; m < Limit; m++ ) + { + if ( k + m != n || k > m ) + continue; + // set the start and stop + pBeg0 = p + Vec_IntEntry( vStops, k ); + pEnd0 = p + Vec_IntEntry( vStops, k+1 ); + // set the start and stop + pBeg1 = p + Vec_IntEntry( vStops, m ); + pEnd1 = p + Vec_IntEntry( vStops, m+1 ); + + clk2 = clock(); + printf( "Trying %7d x %7d. ", pEnd0-pBeg0, pEnd1-pBeg1 ); + for ( pThis0 = pBeg0; pThis0 < pEnd0; pThis0++ ) + for ( pThis1 = pBeg1; pThis1 < pEnd1; pThis1++ ) + if ( k < m || pThis1 > pThis0 ) +// if ( n < 5 || Bdc_SpfdCheckOverlap(p, pThis0, pThis1) ) + for ( s = 0; s < 5; s++ ) + { + t0 = (s&1) ? ~pThis0->Truth : pThis0->Truth; + t1 = ((s>>1)&1) ? ~pThis1->Truth : pThis1->Truth; + t = ((s>>2)&1) ? t0 ^ t1 : t0 & t1; + fCompl = t & 1; + if ( fCompl ) + t = ~t; + if ( t == 0 ) + continue; + pPlace = Bdc_SpfdHashLookup( p, nSize, t ); + if ( pPlace == NULL ) + continue; + q->iFan0 = pThis0-p; + q->fCompl0 = s&1; + q->iFan1 = pThis1-p; + q->fCompl1 = (s>>1)&1; + q->fExor = (s>>2)&1; + q->Truth = t; + q->fCompl = fCompl; + *pPlace = q-p; + q++; + Vec_WrdPush( vTruths, t ); +// Vec_IntPush( vWeights, n == 5 ? n : n+1 ); + Vec_IntPush( vWeights, n+1 ); + if ( q-p == nFuncs ) + { + printf( "Reached limit of %d functions.\n", nFuncs ); + goto finish; + } + } + printf( "Added %d + %d + 1 = %d. Total = %8d. ", k, m, n+1, q-p ); + Abc_PrintTime( 1, "Time", clock() - clk2 ); + } + Vec_IntPush( vStops, q-p ); + } + Abc_PrintTime( 1, "Time", clock() - clk ); + + + { + FILE * pFile = fopen( "func6v6n_bin.txt", "wb" ); + fwrite( Vec_WrdArray(vTruths), sizeof(word), Vec_WrdSize(vTruths), pFile ); + fclose( pFile ); + } + { + FILE * pFile = fopen( "func6v6nW_bin.txt", "wb" ); + fwrite( Vec_IntArray(vWeights), sizeof(int), Vec_IntSize(vWeights), pFile ); + fclose( pFile ); + } + + +finish: + Vec_IntFree( vStops ); + free( p ); + + *pvWeights = vWeights; +// Vec_WrdFree( vTruths ); + return vTruths; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wrd_t * Bdc_SpfdReadFiles5( Vec_Int_t ** pvWeights ) +{ + Vec_Int_t * vWeights; + Vec_Wrd_t * vDivs; + FILE * pFile; + + vDivs = Vec_WrdStart( 3863759 ); + pFile = fopen( "func6v5n_bin.txt", "rb" ); + fread( Vec_WrdArray(vDivs), sizeof(word), Vec_WrdSize(vDivs), pFile ); + fclose( pFile ); + + vWeights = Vec_IntStart( 3863759 ); + pFile = fopen( "func6v5nW_bin.txt", "rb" ); + fread( Vec_IntArray(vWeights), sizeof(int), Vec_IntSize(vWeights), pFile ); + fclose( pFile ); + + *pvWeights = vWeights; + return vDivs; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wrd_t * Bdc_SpfdReadFiles6( Vec_Int_t ** pvWeights ) +{ + Vec_Int_t * vWeights; + Vec_Wrd_t * vDivs = Vec_WrdStart( 12776759 ); + FILE * pFile = fopen( "func6v6n_bin.txt", "rb" ); + fread( Vec_WrdArray(vDivs), sizeof(word), Vec_WrdSize(vDivs), pFile ); + fclose( pFile ); + + vWeights = Vec_IntStart( 12776759 ); + pFile = fopen( "func6v6nW_bin.txt", "rb" ); + fread( Vec_IntArray(vWeights), sizeof(int), Vec_IntSize(vWeights), pFile ); + fclose( pFile ); + + *pvWeights = vWeights; + return vDivs; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bdc_SpfdComputeCost( word f, int i, Vec_Int_t * vWeights ) +{ + int Ones = Bdc_CountOnes(f); + if ( Ones == 0 ) + return -1; + return 7*Ones + 10*(8 - Vec_IntEntry(vWeights, i)); +// return Bdc_CountOnes(f); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +word Bdc_SpfdFindBest( Vec_Wrd_t * vDivs, Vec_Int_t * vWeights, word F0, word F1, int * pCost ) +{ + word Func, FuncBest; + int i, Cost, CostBest = -1, NumBest; + Vec_WrdForEachEntry( vDivs, Func, i ) + { + if ( (Func & F0) == 0 ) + { + Cost = Bdc_SpfdComputeCost(Func & F1, i, vWeights); + if ( CostBest < Cost ) + { + CostBest = Cost; + FuncBest = Func; + NumBest = i; + } + } + if ( (Func & F1) == 0 ) + { + Cost = Bdc_SpfdComputeCost(Func & F0, i, vWeights); + if ( CostBest < Cost ) + { + CostBest = Cost; + FuncBest = Func; + NumBest = i; + } + } + if ( (~Func & F0) == 0 ) + { + Cost = Bdc_SpfdComputeCost(~Func & F1, i, vWeights); + if ( CostBest < Cost ) + { + CostBest = Cost; + FuncBest = ~Func; + NumBest = i; + } + } + if ( (~Func & F1) == 0 ) + { + Cost = Bdc_SpfdComputeCost(~Func & F0, i, vWeights); + if ( CostBest < Cost ) + { + CostBest = Cost; + FuncBest = ~Func; + NumBest = i; + } + } + } + (*pCost) += Vec_IntEntry(vWeights, NumBest); + assert( CostBest > 0 ); + printf( "Selected %8d with cost %2d and weight %d: ", NumBest, 0, Vec_IntEntry(vWeights, NumBest) ); + Extra_PrintHex( stdout, (unsigned *)&FuncBest, 6 ); printf( "\n" ); + return FuncBest; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bdc_SpfdDecomposeTestOne( word t, Vec_Wrd_t * vDivs, Vec_Int_t * vWeights ) +{ + word F1 = t; + word F0 = ~F1; + word Func; + int i, Cost = 0; + printf( "Trying: " ); + Extra_PrintHex( stdout, (unsigned *)&t, 6 ); printf( "\n" ); +// Abc_Show6VarFunc( F0, F1 ); + for ( i = 0; F0 && F1; i++ ) + { + printf( "*** ITER %2d ", i ); + Func = Bdc_SpfdFindBest( vDivs, vWeights, F0, F1, &Cost ); + F0 &= ~Func; + F1 &= ~Func; +// Abc_Show6VarFunc( F0, F1 ); + } + Cost += (i-1); + printf( "Produce solution with cost %2d (with adj cost %4d).\n", Cost, Bdc_SpfdAdjCost(t) ); + return Cost; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bdc_SpfdDecomposeTest44() +{ +// word t = 0x5052585a0002080a; + + word t = 0x9ef7a8d9c7193a0f; +// word t = 0x6BFDA276C7193A0F; +// word t = 0xA3756AFE0B1DF60B; + +// word t = 0xFEF7AEBFCE80AA0F; +// word t = 0x9EF7FDBFC77F6F0F; +// word t = 0xDEF7FDFF377F6FFF; + +// word t = 0x345D02736DB390A5; // xor with var 0 + +// word t = 0x3EFDA2736D139A0F; // best solution after changes + + Vec_Int_t * vWeights; + Vec_Wrd_t * vDivs; + word c0, c1, s, tt, tbest; + int i, j, Cost, CostBest = 100000; + int clk = clock(); + + return; + +// printf( "%d\n", RAND_MAX ); + + vDivs = Bdc_SpfdDecomposeTest__( &vWeights ); +// vDivs = Bdc_SpfdReadFiles5( &vWeights ); + +// Abc_Show6VarFunc( ~t, t ); + + // try function + tt = t; + Cost = Bdc_SpfdDecomposeTestOne( tt, vDivs, vWeights ); + if ( CostBest > Cost ) + { + CostBest = Cost; + tbest = tt; + } + printf( "\n" ); + + // try complemented output + for ( i = 0; i < 6; i++ ) + { + tt = t ^ Truths[i]; + Cost = Bdc_SpfdDecomposeTestOne( tt, vDivs, vWeights ); + if ( CostBest > Cost ) + { + CostBest = Cost; + tbest = tt; + } + } + printf( "\n" ); + + // try complemented input + for ( i = 0; i < 6; i++ ) + for ( j = 0; j < 6; j++ ) + { + if ( i == j ) + continue; + c0 = Bdc_Cof6( t, i, 0 ); + c1 = Bdc_Cof6( t, i, 1 ); + s = Truths[i] ^ Truths[j]; + tt = (~s & c0) | (s & c1); + + Cost = Bdc_SpfdDecomposeTestOne( tt, vDivs, vWeights ); + if ( CostBest > Cost ) + { + CostBest = Cost; + tbest = tt; + } + } + +/* + for ( i = 0; i < 6; i++ ) + for ( j = 0; j < 6; j++ ) + { + if ( i == j ) + continue; + c0 = Bdc_Cof6( t, i, 0 ); + c1 = Bdc_Cof6( t, i, 1 ); + s = Truths[i] ^ Truths[j]; + tt = (~s & c0) | (s & c1); + + for ( k = 0; k < 6; k++ ) + for ( n = 0; n < 6; n++ ) + { + if ( k == n ) + continue; + c0 = Bdc_Cof6( tt, k, 0 ); + c1 = Bdc_Cof6( tt, k, 1 ); + s = Truths[k] ^ Truths[n]; + ttt= (~s & c0) | (s & c1); + + Cost = Bdc_SpfdDecomposeTestOne( ttt, vDivs, vWeights ); + if ( CostBest > Cost ) + { + CostBest = Cost; + tbest = ttt; + } + } + } +*/ + + printf( "Best solution found with cost %d. ", CostBest ); + Extra_PrintHex( stdout, (unsigned *)&tbest, 6 ); //printf( "\n" ); + Abc_PrintTime( 1, " Time", clock() - clk ); + + Vec_WrdFree( vDivs ); + Vec_IntFree( vWeights ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bdc_SpfdDecomposeTest3() +{ + int nSizeM = (1 << 26); + int nSizeK = (1 << 3); + Vec_Wrd_t * v1M; + Vec_Wrd_t * v1K; + int i, k, Counter, clk; +// int EntryM, EntryK; + Aig_ManRandom64( 1 ); + + v1M = Vec_WrdAlloc( nSizeM ); + for ( i = 0; i < nSizeM; i++ ) + Vec_WrdPush( v1M, Aig_ManRandom64(0) ); + + v1K = Vec_WrdAlloc( nSizeK ); + for ( i = 0; i < nSizeK; i++ ) + Vec_WrdPush( v1K, Aig_ManRandom64(0) ); + + clk = clock(); + Counter = 0; + for ( i = 0; i < nSizeM; i++ ) + for ( k = 0; k < nSizeK; k++ ) + Counter += ((v1M->pArray[i] & v1K->pArray[k]) == v1K->pArray[k]); +// Vec_WrdForEachEntry( v1M, EntryM, i ) +// Vec_WrdForEachEntry( v1K, EntryK, k ) +// Counter += ((EntryM & EntryK) == EntryK); + + printf( "Total = %8d. ", Counter ); + Abc_PrintTime( 1, "Time", clock() - clk ); + + clk = clock(); + Counter = 0; + for ( k = 0; k < nSizeK; k++ ) + for ( i = 0; i < nSizeM; i++ ) + Counter += ((v1M->pArray[i] & v1K->pArray[k]) == v1K->pArray[k]); + printf( "Total = %8d. ", Counter ); + Abc_PrintTime( 1, "Time", clock() - clk ); + +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bdc_SpfdDecomposeTest8() +{ +// word t = 0x9ef7a8d9c7193a0f; +// word t = 0x9EF7FDBFC77F6F0F; + word t = 0x513B57150819050F; + + Vec_Int_t * vWeights; + Vec_Wrd_t * vDivs; + word Func, FuncBest; + int Cost, CostBest = ABC_INFINITY; + int i, clk = clock(); + +// return; + + vDivs = Bdc_SpfdReadFiles5( &vWeights ); + + printf( "Best init = %4d. ", Bdc_SpfdAdjCost(t) ); + Extra_PrintHex( stdout, (unsigned *)&t, 6 ); //printf( "\n" ); + Abc_PrintTime( 1, " Time", clock() - clk ); + + Vec_WrdForEachEntry( vDivs, Func, i ) + { + Cost = Bdc_SpfdAdjCost( t ^ Func ); + if ( CostBest > Cost ) + { + CostBest = Cost; + FuncBest = Func; + } + } + + printf( "Best cost = %4d. ", CostBest ); + Extra_PrintHex( stdout, (unsigned *)&FuncBest, 6 ); //printf( "\n" ); + Abc_PrintTime( 1, " Time", clock() - clk ); + +Abc_Show6VarFunc( 0, t ); +Abc_Show6VarFunc( 0, FuncBest ); +Abc_Show6VarFunc( 0, (FuncBest ^ t) ); + + FuncBest ^= t; + Extra_PrintHex( stdout, (unsigned *)&FuncBest, 6 ); printf( "\n" ); + +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bdc_SpfdDecomposeTest() +{ + int nSizeM = (1 << 26); // big array size + int nSizeK = (1 << 3); // small array size + Vec_Wrd_t * v1M, * v1K; + int EntryM, EntryK; + int i, k, Counter, clk; + + Aig_ManRandom64( 1 ); + + v1M = Vec_WrdAlloc( nSizeM ); + for ( i = 0; i < nSizeM; i++ ) + Vec_WrdPush( v1M, Aig_ManRandom64(0) ); + + v1K = Vec_WrdAlloc( nSizeK ); + for ( i = 0; i < nSizeK; i++ ) + Vec_WrdPush( v1K, Aig_ManRandom64(0) ); + + clk = clock(); + Counter = 0; +// for ( i = 0; i < nSizeM; i++ ) +// for ( k = 0; k < nSizeK; k++ ) +// Counter += ((v1M->pArray[i] & v1K->pArray[k]) == v1K->pArray[k]); + Vec_WrdForEachEntry( v1M, EntryM, i ) + Vec_WrdForEachEntry( v1K, EntryK, k ) + Counter += ((EntryM & EntryK) == EntryK); + printf( "Total = %8d. ", Counter ); + Abc_PrintTime( 1, "Time", clock() - clk ); + + clk = clock(); + Counter = 0; +// for ( k = 0; k < nSizeK; k++ ) +// for ( i = 0; i < nSizeM; i++ ) +// Counter += ((v1M->pArray[i] & v1K->pArray[k]) == v1K->pArray[k]); + Vec_WrdForEachEntry( v1K, EntryK, k ) + Vec_WrdForEachEntry( v1M, EntryM, i ) + Counter += ((EntryM & EntryK) == EntryK); + printf( "Total = %8d. ", Counter ); + Abc_PrintTime( 1, "Time", clock() - clk ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bool/bdc/bdcTable.c b/src/bool/bdc/bdcTable.c new file mode 100644 index 00000000..69f35d88 --- /dev/null +++ b/src/bool/bdc/bdcTable.c @@ -0,0 +1,134 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**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( puTruth, pIsf->puOff, 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 ) +{ + int fDisableCache = 0; + Bdc_Fun_t * pFunc; + if ( fDisableCache && Kit_WordCountOnes(pIsf->uSupp) > 1 ) + return NULL; + if ( pIsf->uSupp == 0 ) + { + assert( p->pTable[pIsf->uSupp] == p->pNodes ); + if ( Kit_TruthIsConst1( pIsf->puOn, p->nVars ) ) + return p->pNodes; + assert( Kit_TruthIsConst1( pIsf->puOff, p->nVars ) ); + return Bdc_Not(p->pNodes); + } + for ( pFunc = p->pTable[pIsf->uSupp]; pFunc; pFunc = pFunc->pNext ) + if ( Bdc_TableCheckContainment( p, pIsf, pFunc->puFunc ) ) + return pFunc; + Bdc_IsfNot( pIsf ); + for ( pFunc = p->pTable[pIsf->uSupp]; pFunc; pFunc = pFunc->pNext ) + if ( Bdc_TableCheckContainment( p, pIsf, pFunc->puFunc ) ) + { + Bdc_IsfNot( pIsf ); + return Bdc_Not(pFunc); + } + Bdc_IsfNot( pIsf ); + 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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bool/bdc/bdc_.c b/src/bool/bdc/bdc_.c new file mode 100644 index 00000000..b29d4f5e --- /dev/null +++ b/src/bool/bdc/bdc_.c @@ -0,0 +1,54 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bool/bdc/module.make b/src/bool/bdc/module.make new file mode 100644 index 00000000..0bd5084e --- /dev/null +++ b/src/bool/bdc/module.make @@ -0,0 +1,5 @@ +SRC += src/bool/bdc/bdcCore.c \ + src/bool/bdc/bdcDec.c \ + src/bool/bdc/bdcSpfd.c \ + src/bool/bdc/bdcTable.c + diff --git a/src/bool/dec/dec.h b/src/bool/dec/dec.h new file mode 100644 index 00000000..07bf9f6b --- /dev/null +++ b/src/bool/dec/dec.h @@ -0,0 +1,725 @@ +/**CFile**************************************************************** + + FileName [dec.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [A simple decomposition tree/node data structure and its APIs.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: dec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__opt__dec__dec_h +#define ABC__opt__dec__dec_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 + union { int iFunc; // the literal of the node (AIG) + void * pFunc; }; // the function of the node (BDD or AIG) + unsigned Level : 14; // the level of this node in the global AIG + // printing info + unsigned fNodeOr : 1; // marks the original OR node + unsigned fCompl0 : 1; // marks the original complemented edge + unsigned fCompl1 : 1; // marks the original complemented edge + // latch info + unsigned nLat0 : 5; // the number of latches on the first edge + unsigned nLat1 : 5; // the number of latches on the second edge + unsigned nLat2 : 5; // the number of latches on the output edge +}; + +typedef struct Dec_Graph_t_ Dec_Graph_t; +struct Dec_Graph_t_ +{ + int fConst; // marks the constant 1 graph + int nLeaves; // the number of leaves + int nSize; // the number of nodes (including the leaves) + int nCap; // the number of allocated nodes + Dec_Node_t * pNodes; // the array of leaves and internal nodes + Dec_Edge_t eRoot; // the pointer to the topmost node +}; + +typedef struct Dec_Man_t_ Dec_Man_t; +struct Dec_Man_t_ +{ + void * pMvcMem; // memory manager for MVC cover (used for factoring) + Vec_Int_t * vCubes; // storage for cubes + Vec_Int_t * vLits; // storage for literals + // precomputation information about 4-variable functions + unsigned short * puCanons; // canonical forms + char * pPhases; // canonical phases + char * pPerms; // canonical permutations + unsigned char * pMap; // mapping of functions into class numbers +}; + + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +// interator throught the leaves +#define Dec_GraphForEachLeaf( pGraph, pLeaf, i ) \ + for ( i = 0; (i < (pGraph)->nLeaves) && (((pLeaf) = Dec_GraphNode(pGraph, i)), 1); i++ ) +// interator throught the internal nodes +#define Dec_GraphForEachNode( pGraph, pAnd, i ) \ + for ( i = (pGraph)->nLeaves; (i < (pGraph)->nSize) && (((pAnd) = Dec_GraphNode(pGraph, i)), 1); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== decAbc.c ========================================================*/ +/*=== decFactor.c ========================================================*/ +extern Dec_Graph_t * Dec_Factor( char * pSop ); +/*=== decMan.c ========================================================*/ +extern Dec_Man_t * Dec_ManStart(); +extern void Dec_ManStop( Dec_Man_t * p ); +/*=== decPrint.c ========================================================*/ +extern void Dec_GraphPrint( FILE * pFile, Dec_Graph_t * pGraph, char * pNamesIn[], char * pNameOut ); +/*=== decUtil.c ========================================================*/ +extern unsigned Dec_GraphDeriveTruth( Dec_Graph_t * pGraph ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates an edge pointing to the node in the given polarity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Edge_t Dec_EdgeCreate( int Node, int fCompl ) +{ + Dec_Edge_t eEdge = { fCompl, Node }; + return eEdge; +} + +/**Function************************************************************* + + Synopsis [Converts the edge into unsigned integer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Dec_EdgeToInt( Dec_Edge_t eEdge ) +{ + return (eEdge.Node << 1) | eEdge.fCompl; +} + +/**Function************************************************************* + + Synopsis [Converts unsigned integer into the edge.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Edge_t Dec_IntToEdge( unsigned Edge ) +{ + return Dec_EdgeCreate( Edge >> 1, Edge & 1 ); +} + +/**Function************************************************************* + + Synopsis [Converts the edge into unsigned integer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Dec_EdgeToInt_( Dec_Edge_t m ) { union { Dec_Edge_t x; unsigned y; } v; v.x = m; return v.y; } +/* +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 m ) { union { Dec_Edge_t x; unsigned y; } v; v.y = m; return v.x; } +/* +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 = ABC_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 = ABC_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 = ABC_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 = ABC_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 ) +{ + ABC_FREE( pGraph->pNodes ); + ABC_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 = ABC_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; +} + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/bool/dec/decAbc.c b/src/bool/dec/decAbc.c new file mode 100644 index 00000000..65f69f9b --- /dev/null +++ b/src/bool/dec/decAbc.c @@ -0,0 +1,358 @@ +/**CFile**************************************************************** + + FileName [decAbc.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Interface between the decomposition package and ABC network.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: decAbc.c,v 1.1 2003/05/22 19:20:05 alanmi Exp $] + +***********************************************************************/ + +#include "src/base/abc/abc.h" +#include "src/aig/ivy/ivy.h" +#include "dec.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Transforms the decomposition graph into the AIG.] + + Description [AIG nodes for the fanins should be assigned to pNode->pFunc + of the leaves of the graph before calling this procedure.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Dec_GraphToNetwork( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph ) +{ + Abc_Obj_t * pAnd0, * pAnd1; + Dec_Node_t * pNode = NULL; // Suppress "might be used uninitialized" + 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( (Abc_Obj_t *)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( (Abc_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); + pAnd1 = Abc_ObjNotCond( (Abc_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); + pNode->pFunc = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, pAnd0, pAnd1 ); + } + // complement the result if necessary + return Abc_ObjNotCond( (Abc_Obj_t *)pNode->pFunc, Dec_GraphIsComplement(pGraph) ); +} + +/**Function************************************************************* + + Synopsis [Transforms the decomposition graph into the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Dec_SopToAig( Abc_Ntk_t * pNtk, char * pSop, Vec_Ptr_t * vFaninAigs ) +{ + Abc_Obj_t * pFunc; + Dec_Graph_t * pFForm; + Dec_Node_t * pNode; + int i; + pFForm = Dec_Factor( pSop ); + Dec_GraphForEachLeaf( pFForm, pNode, i ) + pNode->pFunc = Vec_PtrEntry( vFaninAigs, i ); + pFunc = Dec_GraphToNetwork( pNtk, pFForm ); + Dec_GraphFree( pFForm ); + return pFunc; +} + +/**Function************************************************************* + + Synopsis [Transforms the decomposition graph into the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Dec_GraphToAig( Abc_Ntk_t * pNtk, Dec_Graph_t * pFForm, Vec_Ptr_t * vFaninAigs ) +{ + Abc_Obj_t * pFunc; + Dec_Node_t * pNode; + int i; + Dec_GraphForEachLeaf( pFForm, pNode, i ) + pNode->pFunc = Vec_PtrEntry( vFaninAigs, i ); + pFunc = Dec_GraphToNetwork( pNtk, pFForm ); + return pFunc; +} + +/**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 = NULL; // Suppress "might be used uninitialized" + 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( (Abc_Obj_t *)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( (Abc_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); + pAnd1 = Abc_ObjNotCond( (Abc_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); +// pNode->pFunc = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, pAnd0, pAnd1 ); + pAnd = Abc_NtkCreateNode( pNtk ); + Abc_ObjAddFanin( pAnd, pAnd0 ); + Abc_ObjAddFanin( pAnd, pAnd1 ); + pNode->pFunc = pAnd; + } + // complement the result if necessary + return Abc_ObjNotCond( (Abc_Obj_t *)pNode->pFunc, Dec_GraphIsComplement(pGraph) ); +} + +/**Function************************************************************* + + Synopsis [Counts the number of new nodes added when using this graph.] + + Description [AIG nodes for the fanins should be assigned to pNode->pFunc + of the leaves of the graph before calling this procedure. + Returns -1 if the number of nodes and levels exceeded the given limit or + the number of levels exceeded the maximum allowed level.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dec_GraphToNetworkCount( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax ) +{ + Abc_Aig_t * pMan = (Abc_Aig_t *)pRoot->pNtk->pManFunc; + Dec_Node_t * pNode, * pNode0, * pNode1; + Abc_Obj_t * pAnd, * pAnd0, * pAnd1; + int i, Counter, LevelNew, LevelOld; + // check for constant function or a literal + if ( Dec_GraphIsConst(pGraph) || Dec_GraphIsVar(pGraph) ) + return 0; + // set the levels of the leaves + Dec_GraphForEachLeaf( pGraph, pNode, i ) + pNode->Level = Abc_ObjRegular((Abc_Obj_t *)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 = (Abc_Obj_t *)pNode0->pFunc; + pAnd1 = (Abc_Obj_t *)pNode1->pFunc; + if ( pAnd0 && pAnd1 ) + { + // if they are both present, find the resulting node + pAnd0 = Abc_ObjNotCond( pAnd0, pNode->eEdge0.fCompl ); + pAnd1 = Abc_ObjNotCond( pAnd1, pNode->eEdge1.fCompl ); + pAnd = Abc_AigAndLookup( pMan, pAnd0, pAnd1 ); + // return -1 if the node is the same as the original root + if ( Abc_ObjRegular(pAnd) == pRoot ) + return -1; + } + else + pAnd = NULL; + // count the number of added nodes + if ( pAnd == NULL || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pAnd)) ) + { + if ( ++Counter > NodeMax ) + return -1; + } + // count the number of new levels + LevelNew = 1 + Abc_MaxInt( pNode0->Level, pNode1->Level ); + if ( pAnd ) + { + if ( Abc_ObjRegular(pAnd) == Abc_AigConst1(pRoot->pNtk) ) + LevelNew = 0; + else if ( Abc_ObjRegular(pAnd) == Abc_ObjRegular(pAnd0) ) + LevelNew = (int)Abc_ObjRegular(pAnd0)->Level; + else if ( Abc_ObjRegular(pAnd) == Abc_ObjRegular(pAnd1) ) + LevelNew = (int)Abc_ObjRegular(pAnd1)->Level; + LevelOld = (int)Abc_ObjRegular(pAnd)->Level; +// assert( LevelNew == LevelOld ); + } + if ( LevelNew > LevelMax ) + return -1; + pNode->pFunc = pAnd; + pNode->Level = LevelNew; + } + return Counter; +} + + +/**Function************************************************************* + + Synopsis [Replaces MFFC of the node by the new factored form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, 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 ); + // remove the old nodes + Abc_AigReplace( (Abc_Aig_t *)pNtk->pManFunc, pRoot, pRootNew, fUpdateLevel ); + // compare the gains + nNodesNew = Abc_NtkNodeNum(pNtk); + assert( nGain <= nNodesOld - nNodesNew ); +} + + +/**Function************************************************************* + + Synopsis [Transforms the decomposition graph into the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Dec_GraphToNetworkAig( Hop_Man_t * pMan, Dec_Graph_t * pGraph ) +{ + Dec_Node_t * pNode = NULL; // Suppress "might be used uninitialized" + 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( (Hop_Obj_t *)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( (Hop_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); + pAnd1 = Hop_NotCond( (Hop_Obj_t *)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( (Hop_Obj_t *)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 = NULL; // Suppress "might be used uninitialized" + 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( (Ivy_Obj_t *)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( (Ivy_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); + pAnd1 = Ivy_NotCond( (Ivy_Obj_t *)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( (Ivy_Obj_t *)pNode->pFunc, Dec_GraphIsComplement(pGraph) ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bool/dec/decFactor.c b/src/bool/dec/decFactor.c new file mode 100644 index 00000000..faed9e74 --- /dev/null +++ b/src/bool/dec/decFactor.c @@ -0,0 +1,399 @@ +/**CFile**************************************************************** + + FileName [ftFactor.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Procedures for algebraic factoring.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: ftFactor.c,v 1.3 2003/09/01 04:56:43 alanmi Exp $] + +***********************************************************************/ + +#include "src/base/abc/abc.h" +#include "src/base/main/main.h" +#include "src/misc/mvc/mvc.h" +#include "src/misc/extra/extraBdd.h" +#include "dec.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Dec_Edge_t Dec_Factor_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover ); +static Dec_Edge_t Dec_FactorLF_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cover_t * pSimple ); +static Dec_Edge_t Dec_FactorTrivial( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover ); +static Dec_Edge_t Dec_FactorTrivialCube( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cube_t * pCube, Vec_Int_t * vEdgeLits ); +static Dec_Edge_t Dec_FactorTrivialTree_rec( Dec_Graph_t * pFForm, Dec_Edge_t * peNodes, int nNodes, int fNodeOr ); +static int Dec_FactorVerify( char * pSop, Dec_Graph_t * pFForm ); +static Mvc_Cover_t * Dec_ConvertSopToMvc( char * pSop ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Factors the cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Dec_Factor( char * pSop ) +{ + Mvc_Cover_t * pCover; + Dec_Graph_t * pFForm; + Dec_Edge_t eRoot; + + // derive the cover from the SOP representation + pCover = Dec_ConvertSopToMvc( pSop ); + + // make sure the cover is CCS free (should be done before CST) + Mvc_CoverContain( pCover ); + // check for trivial functions + if ( Mvc_CoverIsEmpty(pCover) ) + { + Mvc_CoverFree( pCover ); + return Dec_GraphCreateConst0(); + } + if ( Mvc_CoverIsTautology(pCover) ) + { + Mvc_CoverFree( pCover ); + return Dec_GraphCreateConst1(); + } + + // perform CST + Mvc_CoverInverse( pCover ); // CST + // start the factored form + pFForm = Dec_GraphCreate( Abc_SopGetVarNum(pSop) ); + // factor the cover + eRoot = Dec_Factor_rec( pFForm, pCover ); + // finalize the factored form + Dec_GraphSetRoot( pFForm, eRoot ); + // complement the factored form if SOP is complemented + if ( Abc_SopIsComplement(pSop) ) + Dec_GraphComplement( pFForm ); + // verify the factored form +// if ( !Dec_FactorVerify( pSop, pFForm ) ) +// printf( "Verification has failed.\n" ); +// Mvc_CoverInverse( pCover ); // undo CST + Mvc_CoverFree( pCover ); + return pFForm; +} + +/**Function************************************************************* + + Synopsis [Internal recursive factoring procedure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Edge_t Dec_Factor_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover ) +{ + Mvc_Cover_t * pDiv, * pQuo, * pRem, * pCom; + Dec_Edge_t eNodeDiv, eNodeQuo, eNodeRem; + Dec_Edge_t eNodeAnd, eNode; + + // make sure the cover contains some cubes + assert( Mvc_CoverReadCubeNum(pCover) ); + + // get the divisor + pDiv = Mvc_CoverDivisor( pCover ); + if ( pDiv == NULL ) + return Dec_FactorTrivial( pFForm, pCover ); + + // divide the cover by the divisor + Mvc_CoverDivideInternal( pCover, pDiv, &pQuo, &pRem ); + assert( Mvc_CoverReadCubeNum(pQuo) ); + + Mvc_CoverFree( pDiv ); + Mvc_CoverFree( pRem ); + + // check the trivial case + if ( Mvc_CoverReadCubeNum(pQuo) == 1 ) + { + eNode = Dec_FactorLF_rec( pFForm, pCover, pQuo ); + Mvc_CoverFree( pQuo ); + return eNode; + } + + // make the quotient cube ABC_FREE + Mvc_CoverMakeCubeFree( pQuo ); + + // divide the cover by the quotient + Mvc_CoverDivideInternal( pCover, pQuo, &pDiv, &pRem ); + + // check the trivial case + if ( Mvc_CoverIsCubeFree( pDiv ) ) + { + eNodeDiv = Dec_Factor_rec( pFForm, pDiv ); + eNodeQuo = Dec_Factor_rec( pFForm, pQuo ); + Mvc_CoverFree( pDiv ); + Mvc_CoverFree( pQuo ); + eNodeAnd = Dec_GraphAddNodeAnd( pFForm, eNodeDiv, eNodeQuo ); + if ( Mvc_CoverReadCubeNum(pRem) == 0 ) + { + Mvc_CoverFree( pRem ); + return eNodeAnd; + } + else + { + eNodeRem = Dec_Factor_rec( pFForm, pRem ); + Mvc_CoverFree( pRem ); + return Dec_GraphAddNodeOr( pFForm, eNodeAnd, eNodeRem ); + } + } + + // get the common cube + pCom = Mvc_CoverCommonCubeCover( pDiv ); + Mvc_CoverFree( pDiv ); + Mvc_CoverFree( pQuo ); + Mvc_CoverFree( pRem ); + + // solve the simple problem + eNode = Dec_FactorLF_rec( pFForm, pCover, pCom ); + Mvc_CoverFree( pCom ); + return eNode; +} + + +/**Function************************************************************* + + Synopsis [Internal recursive factoring procedure for the leaf case.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Edge_t Dec_FactorLF_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cover_t * pSimple ) +{ + Dec_Man_t * pManDec = (Dec_Man_t *)Abc_FrameReadManDec(); + Vec_Int_t * vEdgeLits = pManDec->vLits; + Mvc_Cover_t * pDiv, * pQuo, * pRem; + Dec_Edge_t eNodeDiv, eNodeQuo, eNodeRem; + Dec_Edge_t eNodeAnd; + + // get the most often occurring literal + pDiv = Mvc_CoverBestLiteralCover( pCover, pSimple ); + // divide the cover by the literal + Mvc_CoverDivideByLiteral( pCover, pDiv, &pQuo, &pRem ); + // get the node pointer for the literal + eNodeDiv = Dec_FactorTrivialCube( pFForm, pDiv, Mvc_CoverReadCubeHead(pDiv), vEdgeLits ); + Mvc_CoverFree( pDiv ); + // factor the quotient and remainder + eNodeQuo = Dec_Factor_rec( pFForm, pQuo ); + Mvc_CoverFree( pQuo ); + eNodeAnd = Dec_GraphAddNodeAnd( pFForm, eNodeDiv, eNodeQuo ); + if ( Mvc_CoverReadCubeNum(pRem) == 0 ) + { + Mvc_CoverFree( pRem ); + return eNodeAnd; + } + else + { + eNodeRem = Dec_Factor_rec( pFForm, pRem ); + Mvc_CoverFree( pRem ); + return Dec_GraphAddNodeOr( pFForm, eNodeAnd, eNodeRem ); + } +} + + + +/**Function************************************************************* + + Synopsis [Factoring the cover, which has no algebraic divisors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Edge_t Dec_FactorTrivial( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover ) +{ + Dec_Man_t * pManDec = (Dec_Man_t *)Abc_FrameReadManDec(); + Vec_Int_t * vEdgeCubes = pManDec->vCubes; + Vec_Int_t * vEdgeLits = pManDec->vLits; + Dec_Edge_t eNode; + Mvc_Cube_t * pCube; + // create the factored form for each cube + Vec_IntClear( vEdgeCubes ); + Mvc_CoverForEachCube( pCover, pCube ) + { + eNode = Dec_FactorTrivialCube( pFForm, pCover, pCube, vEdgeLits ); + Vec_IntPush( vEdgeCubes, Dec_EdgeToInt_(eNode) ); + } + // balance the factored forms + return Dec_FactorTrivialTree_rec( pFForm, (Dec_Edge_t *)vEdgeCubes->pArray, vEdgeCubes->nSize, 1 ); +} + +/**Function************************************************************* + + Synopsis [Factoring the cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Edge_t Dec_FactorTrivialCube( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cube_t * pCube, Vec_Int_t * vEdgeLits ) +{ + Dec_Edge_t eNode; + int iBit, Value; + // create the factored form for each literal + Vec_IntClear( vEdgeLits ); + Mvc_CubeForEachBit( pCover, pCube, iBit, Value ) + if ( Value ) + { + eNode = Dec_EdgeCreate( iBit/2, iBit%2 ); // CST + Vec_IntPush( vEdgeLits, Dec_EdgeToInt_(eNode) ); + } + // balance the factored forms + return Dec_FactorTrivialTree_rec( pFForm, (Dec_Edge_t *)vEdgeLits->pArray, vEdgeLits->nSize, 0 ); +} + +/**Function************************************************************* + + Synopsis [Create the well-balanced tree of nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Edge_t Dec_FactorTrivialTree_rec( Dec_Graph_t * pFForm, Dec_Edge_t * peNodes, int nNodes, int fNodeOr ) +{ + Dec_Edge_t eNode1, eNode2; + int nNodes1, nNodes2; + + if ( nNodes == 1 ) + return peNodes[0]; + + // split the nodes into two parts + nNodes1 = nNodes/2; + nNodes2 = nNodes - nNodes1; +// nNodes2 = nNodes/2; +// nNodes1 = nNodes - nNodes2; + + // recursively construct the tree for the parts + eNode1 = Dec_FactorTrivialTree_rec( pFForm, peNodes, nNodes1, fNodeOr ); + eNode2 = Dec_FactorTrivialTree_rec( pFForm, peNodes + nNodes1, nNodes2, fNodeOr ); + + if ( fNodeOr ) + return Dec_GraphAddNodeOr( pFForm, eNode1, eNode2 ); + else + return Dec_GraphAddNodeAnd( pFForm, eNode1, eNode2 ); +} + + + +/**Function************************************************************* + + Synopsis [Converts SOP into MVC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mvc_Cover_t * Dec_ConvertSopToMvc( char * pSop ) +{ + Dec_Man_t * pManDec = (Dec_Man_t *)Abc_FrameReadManDec(); + Mvc_Manager_t * pMem = (Mvc_Manager_t *)pManDec->pMvcMem; + Mvc_Cover_t * pMvc; + Mvc_Cube_t * pMvcCube; + char * pCube; + int nVars, Value, v; + + // start the cover + nVars = Abc_SopGetVarNum(pSop); + pMvc = Mvc_CoverAlloc( pMem, nVars * 2 ); + // check the logic function of the node + Abc_SopForEachCube( pSop, nVars, pCube ) + { + // create and add the cube + pMvcCube = Mvc_CubeAlloc( pMvc ); + Mvc_CoverAddCubeTail( pMvc, pMvcCube ); + // fill in the literals + Mvc_CubeBitFill( pMvcCube ); + Abc_CubeForEachVar( pCube, Value, v ) + { + if ( Value == '0' ) + Mvc_CubeBitRemove( pMvcCube, v * 2 + 1 ); + else if ( Value == '1' ) + Mvc_CubeBitRemove( pMvcCube, v * 2 ); + } + } + return pMvc; +} + +/**Function************************************************************* + + Synopsis [Verifies that the factoring is correct.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dec_FactorVerify( char * pSop, Dec_Graph_t * pFForm ) +{ + extern DdNode * Abc_ConvertSopToBdd( DdManager * dd, char * pSop, DdNode ** pbVars ); + extern DdNode * Dec_GraphDeriveBdd( DdManager * dd, Dec_Graph_t * pGraph ); + DdManager * dd = (DdManager *)Abc_FrameReadManDd(); + DdNode * bFunc1, * bFunc2; + int RetValue; + bFunc1 = Abc_ConvertSopToBdd( dd, pSop, NULL ); Cudd_Ref( bFunc1 ); + bFunc2 = Dec_GraphDeriveBdd( dd, pFForm ); Cudd_Ref( bFunc2 ); +//Extra_bddPrint( dd, bFunc1 ); printf("\n"); +//Extra_bddPrint( dd, bFunc2 ); printf("\n"); + RetValue = (bFunc1 == bFunc2); + if ( bFunc1 != bFunc2 ) + { + int s; + Extra_bddPrint( dd, bFunc1 ); printf("\n"); + Extra_bddPrint( dd, bFunc2 ); printf("\n"); + s = 0; + } + Cudd_RecursiveDeref( dd, bFunc1 ); + Cudd_RecursiveDeref( dd, bFunc2 ); + return RetValue; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bool/dec/decMan.c b/src/bool/dec/decMan.c new file mode 100644 index 00000000..cfca58c5 --- /dev/null +++ b/src/bool/dec/decMan.c @@ -0,0 +1,88 @@ +/**CFile**************************************************************** + + FileName [decMan.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Decomposition manager.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: decMan.c,v 1.1 2003/05/22 19:20:05 alanmi Exp $] + +***********************************************************************/ + +#include "src/base/abc/abc.h" +#include "src/misc/mvc/mvc.h" +#include "dec.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Start the MVC manager used in the factoring package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Man_t * Dec_ManStart() +{ + Dec_Man_t * p; +// int clk = clock(); + p = ABC_ALLOC( Dec_Man_t, 1 ); + p->pMvcMem = Mvc_ManagerStart(); + p->vCubes = Vec_IntAlloc( 8 ); + p->vLits = Vec_IntAlloc( 8 ); + // canonical forms, phases, perms + Extra_Truth4VarNPN( &p->puCanons, &p->pPhases, &p->pPerms, &p->pMap ); +//ABC_PRT( "NPN classes precomputation time", clock() - clk ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the MVC maanager used in the factoring package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dec_ManStop( Dec_Man_t * p ) +{ + Mvc_ManagerFree( (Mvc_Manager_t *)p->pMvcMem ); + Vec_IntFree( p->vCubes ); + Vec_IntFree( p->vLits ); + ABC_FREE( p->puCanons ); + ABC_FREE( p->pPhases ); + ABC_FREE( p->pPerms ); + ABC_FREE( p->pMap ); + ABC_FREE( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bool/dec/decPrint.c b/src/bool/dec/decPrint.c new file mode 100644 index 00000000..208c7e8e --- /dev/null +++ b/src/bool/dec/decPrint.c @@ -0,0 +1,289 @@ +/**CFile**************************************************************** + + FileName [decPrint.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Procedures to print the decomposition graphs (factored forms).] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: decPrint.c,v 1.1 2003/05/22 19:20:05 alanmi Exp $] + +***********************************************************************/ + +#include "src/base/abc/abc.h" +#include "dec.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Dec_GraphPrint_rec( FILE * pFile, Dec_Graph_t * pGraph, Dec_Node_t * pNode, int fCompl, char * pNamesIn[], int * pPos, int LitSizeMax ); +static int Dec_GraphPrintGetLeafName( FILE * pFile, int iLeaf, int fCompl, char * pNamesIn[] ); +static void Dec_GraphPrintUpdatePos( FILE * pFile, int * pPos, int LitSizeMax ); +static int Dec_GraphPrintOutputName( FILE * pFile, char * pNameOut, int fCompl ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Prints the decomposition graph.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dec_GraphPrint( FILE * pFile, Dec_Graph_t * pGraph, char * pNamesIn[], char * pNameOut ) +{ + Vec_Ptr_t * vNamesIn = NULL; + int LitSizeMax, LitSizeCur, Pos, i; + + // create the names if not given by the user + if ( pNamesIn == NULL ) + { + vNamesIn = Abc_NodeGetFakeNames( Dec_GraphLeaveNum(pGraph) ); + pNamesIn = (char **)vNamesIn->pArray; + } + if ( pNameOut == NULL ) + pNameOut = "F"; + + // get the size of the longest literal + LitSizeMax = 0; + for ( i = 0; i < Dec_GraphLeaveNum(pGraph); i++ ) + { + LitSizeCur = strlen(pNamesIn[i]); + if ( LitSizeMax < LitSizeCur ) + LitSizeMax = LitSizeCur; + } + if ( LitSizeMax > 50 ) + LitSizeMax = 20; + + // write the decomposition graph (factored form) + if ( Dec_GraphIsConst(pGraph) ) // constant + { + Pos = Dec_GraphPrintOutputName( pFile, pNameOut, 0 ); + fprintf( pFile, "Constant %d", !Dec_GraphIsComplement(pGraph) ); + } + else if ( Dec_GraphIsVar(pGraph) ) // literal + { + Pos = Dec_GraphPrintOutputName( pFile, pNameOut, 0 ); + Dec_GraphPrintGetLeafName( pFile, Dec_GraphVarInt(pGraph), Dec_GraphIsComplement(pGraph), pNamesIn ); + } + else + { + Pos = Dec_GraphPrintOutputName( pFile, pNameOut, Dec_GraphIsComplement(pGraph) ); + Dec_GraphPrint_rec( pFile, pGraph, Dec_GraphNodeLast(pGraph), 0, pNamesIn, &Pos, LitSizeMax ); + } + fprintf( pFile, "\n" ); + + if ( vNamesIn ) + Abc_NodeFreeNames( vNamesIn ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dec_GraphPrint2_rec( FILE * pFile, Dec_Graph_t * pGraph, Dec_Node_t * pNode, int fCompl, char * pNamesIn[], int * pPos, int LitSizeMax ) +{ + Dec_Node_t * pNode0, * pNode1; + pNode0 = Dec_GraphNode(pGraph, pNode->eEdge0.Node); + pNode1 = Dec_GraphNode(pGraph, pNode->eEdge1.Node); + if ( Dec_GraphNodeIsVar(pGraph, pNode) ) // FT_NODE_LEAF ) + { + (*pPos) += Dec_GraphPrintGetLeafName( pFile, Dec_GraphNodeInt(pGraph,pNode), fCompl, pNamesIn ); + return; + } + if ( !pNode->fNodeOr ) // FT_NODE_AND ) + { + if ( !pNode0->fNodeOr ) // != FT_NODE_OR ) + Dec_GraphPrint_rec( pFile, pGraph, pNode0, pNode->fCompl0, pNamesIn, pPos, LitSizeMax ); + else + { + fprintf( pFile, "(" ); + (*pPos)++; + Dec_GraphPrint_rec( pFile, pGraph, pNode0, pNode->fCompl0, pNamesIn, pPos, LitSizeMax ); + fprintf( pFile, ")" ); + (*pPos)++; + } + fprintf( pFile, " " ); + (*pPos)++; + + Dec_GraphPrintUpdatePos( pFile, pPos, LitSizeMax ); + + if ( !pNode1->fNodeOr ) // != FT_NODE_OR ) + Dec_GraphPrint_rec( pFile, pGraph, pNode1, pNode->fCompl1, pNamesIn, pPos, LitSizeMax ); + else + { + fprintf( pFile, "(" ); + (*pPos)++; + Dec_GraphPrint_rec( pFile, pGraph, pNode1, pNode->fCompl1, pNamesIn, pPos, LitSizeMax ); + fprintf( pFile, ")" ); + (*pPos)++; + } + return; + } + if ( pNode->fNodeOr ) // FT_NODE_OR ) + { + Dec_GraphPrint_rec( pFile, pGraph, pNode0, pNode->fCompl0, pNamesIn, pPos, LitSizeMax ); + fprintf( pFile, " + " ); + (*pPos) += 3; + + Dec_GraphPrintUpdatePos( pFile, pPos, LitSizeMax ); + + Dec_GraphPrint_rec( pFile, pGraph, pNode1, pNode->fCompl1, pNamesIn, pPos, LitSizeMax ); + return; + } + assert( 0 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dec_GraphPrint_rec( FILE * pFile, Dec_Graph_t * pGraph, Dec_Node_t * pNode, int fCompl, char * pNamesIn[], int * pPos, int LitSizeMax ) +{ + Dec_Node_t * pNode0, * pNode1; + Dec_Node_t * pNode00, * pNode01, * pNode10, * pNode11; + pNode0 = Dec_GraphNode(pGraph, pNode->eEdge0.Node); + pNode1 = Dec_GraphNode(pGraph, pNode->eEdge1.Node); + if ( Dec_GraphNodeIsVar(pGraph, pNode) ) // FT_NODE_LEAF ) + { + (*pPos) += Dec_GraphPrintGetLeafName( pFile, Dec_GraphNodeInt(pGraph,pNode), fCompl, pNamesIn ); + return; + } + if ( !Dec_GraphNodeIsVar(pGraph, pNode0) && !Dec_GraphNodeIsVar(pGraph, pNode1) ) + { + pNode00 = Dec_GraphNode(pGraph, pNode0->eEdge0.Node); + pNode01 = Dec_GraphNode(pGraph, pNode0->eEdge1.Node); + pNode10 = Dec_GraphNode(pGraph, pNode1->eEdge0.Node); + pNode11 = Dec_GraphNode(pGraph, pNode1->eEdge1.Node); + if ( (pNode00 == pNode10 || pNode00 == pNode11) && (pNode01 == pNode10 || pNode01 == pNode11) ) + { + fprintf( pFile, "(" ); + (*pPos)++; + Dec_GraphPrint_rec( pFile, pGraph, pNode00, pNode00->fCompl0, pNamesIn, pPos, LitSizeMax ); + fprintf( pFile, " # " ); + (*pPos) += 3; + Dec_GraphPrint_rec( pFile, pGraph, pNode01, pNode01->fCompl1, pNamesIn, pPos, LitSizeMax ); + fprintf( pFile, ")" ); + (*pPos)++; + return; + } + } + if ( fCompl ) + { + fprintf( pFile, "(" ); + (*pPos)++; + Dec_GraphPrint_rec( pFile, pGraph, pNode0, !pNode->fCompl0, pNamesIn, pPos, LitSizeMax ); + fprintf( pFile, " + " ); + (*pPos) += 3; + Dec_GraphPrint_rec( pFile, pGraph, pNode1, !pNode->fCompl1, pNamesIn, pPos, LitSizeMax ); + fprintf( pFile, ")" ); + (*pPos)++; + } + else + { + fprintf( pFile, "(" ); + (*pPos)++; + Dec_GraphPrint_rec( pFile, pGraph, pNode0, pNode->fCompl0, pNamesIn, pPos, LitSizeMax ); + Dec_GraphPrint_rec( pFile, pGraph, pNode1, pNode->fCompl1, pNamesIn, pPos, LitSizeMax ); + fprintf( pFile, ")" ); + (*pPos)++; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dec_GraphPrintGetLeafName( FILE * pFile, int iLeaf, int fCompl, char * pNamesIn[] ) +{ + static char Buffer[100]; + sprintf( Buffer, "%s%s", pNamesIn[iLeaf], fCompl? "\'" : "" ); + fprintf( pFile, "%s", Buffer ); + return strlen( Buffer ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dec_GraphPrintUpdatePos( FILE * pFile, int * pPos, int LitSizeMax ) +{ + int i; + if ( *pPos + LitSizeMax < 77 ) + return; + fprintf( pFile, "\n" ); + for ( i = 0; i < 10; i++ ) + fprintf( pFile, " " ); + *pPos = 10; +} + +/**Function************************************************************* + + Synopsis [Starts the printout for a decomposition graph.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dec_GraphPrintOutputName( FILE * pFile, char * pNameOut, int fCompl ) +{ + if ( pNameOut == NULL ) + return 0; + fprintf( pFile, "%6s%s = ", pNameOut, fCompl? "\'" : " " ); + return 10; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bool/dec/decUtil.c b/src/bool/dec/decUtil.c new file mode 100644 index 00000000..0350b3e2 --- /dev/null +++ b/src/bool/dec/decUtil.c @@ -0,0 +1,141 @@ +/**CFile**************************************************************** + + FileName [decUtil.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Decomposition unitilies.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: decUtil.c,v 1.1 2003/05/22 19:20:05 alanmi Exp $] + +***********************************************************************/ + +#include "src/base/abc/abc.h" +#include "src/misc/extra/extraBdd.h" +#include "dec.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Converts graph to BDD.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Dec_GraphDeriveBdd( DdManager * dd, Dec_Graph_t * pGraph ) +{ + DdNode * bFunc, * bFunc0, * bFunc1; + Dec_Node_t * pNode = NULL; // Suppress "might be used uninitialized" + int i; + + // sanity checks + assert( Dec_GraphLeaveNum(pGraph) >= 0 ); + assert( Dec_GraphLeaveNum(pGraph) <= pGraph->nSize ); + + // check for constant function + if ( Dec_GraphIsConst(pGraph) ) + return Cudd_NotCond( b1, Dec_GraphIsComplement(pGraph) ); + // check for a literal + if ( Dec_GraphIsVar(pGraph) ) + return Cudd_NotCond( Cudd_bddIthVar(dd, Dec_GraphVarInt(pGraph)), Dec_GraphIsComplement(pGraph) ); + + // assign the elementary variables + Dec_GraphForEachLeaf( pGraph, pNode, i ) + pNode->pFunc = Cudd_bddIthVar( dd, i ); + + // compute the function for each internal node + Dec_GraphForEachNode( pGraph, pNode, i ) + { + bFunc0 = Cudd_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); + bFunc1 = Cudd_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); + pNode->pFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( (DdNode *)pNode->pFunc ); + } + + // deref the intermediate results + bFunc = (DdNode *)pNode->pFunc; Cudd_Ref( bFunc ); + Dec_GraphForEachNode( pGraph, pNode, i ) + Cudd_RecursiveDeref( dd, (DdNode *)pNode->pFunc ); + Cudd_Deref( bFunc ); + + // complement the result if necessary + return Cudd_NotCond( bFunc, Dec_GraphIsComplement(pGraph) ); +} + +/**Function************************************************************* + + Synopsis [Derives the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Dec_GraphDeriveTruth( Dec_Graph_t * pGraph ) +{ + unsigned uTruths[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; + unsigned uTruth = 0; // Suppress "might be used uninitialized" + unsigned uTruth0, uTruth1; + Dec_Node_t * pNode; + int i; + + // sanity checks + assert( Dec_GraphLeaveNum(pGraph) >= 0 ); + assert( Dec_GraphLeaveNum(pGraph) <= pGraph->nSize ); + assert( Dec_GraphLeaveNum(pGraph) <= 5 ); + + // check for constant function + if ( Dec_GraphIsConst(pGraph) ) + return Dec_GraphIsComplement(pGraph)? 0 : ~((unsigned)0); + // check for a literal + if ( Dec_GraphIsVar(pGraph) ) + return Dec_GraphIsComplement(pGraph)? ~uTruths[Dec_GraphVarInt(pGraph)] : uTruths[Dec_GraphVarInt(pGraph)]; + + // assign the elementary variables + Dec_GraphForEachLeaf( pGraph, pNode, i ) + pNode->pFunc = (void *)(ABC_PTRUINT_T)uTruths[i]; + + // compute the function for each internal node + Dec_GraphForEachNode( pGraph, pNode, i ) + { + uTruth0 = (unsigned)(ABC_PTRUINT_T)Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc; + uTruth1 = (unsigned)(ABC_PTRUINT_T)Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc; + uTruth0 = pNode->eEdge0.fCompl? ~uTruth0 : uTruth0; + uTruth1 = pNode->eEdge1.fCompl? ~uTruth1 : uTruth1; + uTruth = uTruth0 & uTruth1; + pNode->pFunc = (void *)(ABC_PTRUINT_T)uTruth; + } + + // complement the result if necessary + return Dec_GraphIsComplement(pGraph)? ~uTruth : uTruth; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bool/dec/module.make b/src/bool/dec/module.make new file mode 100644 index 00000000..34e58d30 --- /dev/null +++ b/src/bool/dec/module.make @@ -0,0 +1,5 @@ +SRC += src/bool/dec/decAbc.c \ + src/bool/dec/decFactor.c \ + src/bool/dec/decMan.c \ + src/bool/dec/decPrint.c \ + src/bool/dec/decUtil.c diff --git a/src/bool/deco/deco.h b/src/bool/deco/deco.h new file mode 100644 index 00000000..a1db47ce --- /dev/null +++ b/src/bool/deco/deco.h @@ -0,0 +1,714 @@ +/**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 ABC__aig__deco__deco_h +#define ABC__aig__deco__deco_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 + union { int iFunc; // the literal of the node (AIG) + 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 m ) { union { Dec_Edge_t x; unsigned y; } v; v.x = m; return v.y; } +/* +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 m ) { union { Dec_Edge_t x; unsigned y; } v; v.y = m; return v.x; } +/* +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 = ABC_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 = ABC_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 = ABC_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 = ABC_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 ) +{ + ABC_FREE( pGraph->pNodes ); + ABC_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 = ABC_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; +} + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/bool/deco/module.make b/src/bool/deco/module.make new file mode 100644 index 00000000..d6d908e7 --- /dev/null +++ b/src/bool/deco/module.make @@ -0,0 +1 @@ +SRC += diff --git a/src/bool/kit/cloud.c b/src/bool/kit/cloud.c new file mode 100644 index 00000000..1ab53c00 --- /dev/null +++ b/src/bool/kit/cloud.c @@ -0,0 +1,993 @@ +/**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 +#include "cloud.h" + +ABC_NAMESPACE_IMPL_START + + +// 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 = ABC_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 = ABC_CALLOC( CloudNode, dd->nNodesAlloc ); + dd->nMemUsed += sizeof(CloudNode) * dd->nNodesAlloc; +clk2 = clock(); +//ABC_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 = NULL; + dd->tUnique[0].t = NULL; + 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 = ABC_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; + ABC_FREE( dd->ppNodes ); + ABC_FREE( dd->tUnique ); + ABC_FREE( dd->vars ); + for ( i = 0; i < 4; i++ ) + ABC_FREE( dd->tCaches[i] ); + ABC_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 *)ABC_CALLOC( CloudCacheEntry1, nCacheEntries ); + dd->nMemUsed += sizeof(CloudCacheEntry1) * nCacheEntries; + } + else if ( CacheSize[oper] == 2 ) + { + dd->tCaches[oper] = (CloudCacheEntry2 *)ABC_CALLOC( CloudCacheEntry2, nCacheEntries ); + dd->nMemUsed += sizeof(CloudCacheEntry2) * nCacheEntries; + } + else if ( CacheSize[oper] == 3 ) + { + dd->tCaches[oper] = (CloudCacheEntry2 *)ABC_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 != NULL ) + 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 NULL; + } + // 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 != NULL ) + { + 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 == NULL ) + return NULL; + + if ( fnv <= gnv ) + e = cloudBddAnd( dd, fnv, gnv ); + else + e = cloudBddAnd( dd, gnv, fnv ); + + if ( e == NULL ) + return NULL; + + if ( t == e ) + r = t; + else + { + if ( Cloud_IsComplement(t) ) + { + r = cloudMakeNode( dd, var, Cloud_Not(t), Cloud_Not(e) ); + if ( r == NULL ) + return NULL; + r = Cloud_Not(r); + } + else + { + r = cloudMakeNode( dd, var, t, e ); + if ( r == NULL ) + return NULL; + } + } + 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) == NULL || Cloud_Regular(g) == NULL ) + return NULL; + 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) == NULL || Cloud_Regular(g) == NULL ) + return NULL; + 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 != NULL ); + 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) == NULL || Cloud_Regular(g) == NULL ) + return NULL; + 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 == NULL ) + return NULL; + t1 = cloudBddAnd_gate( dd, Cloud_Not(f), g ); + if ( t1 == NULL ) + return NULL; + 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 = ABC_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 == NULL ) + break; + } + ABC_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 = ABC_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++; + } + + ABC_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 = ABC_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 == NULL ) + return NULL; + + 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 == NULL ) + return NULL; + 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 == NULL || 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 /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bool/kit/cloud.h b/src/bool/kit/cloud.h new file mode 100644 index 00000000..208a47ec --- /dev/null +++ b/src/bool/kit/cloud.h @@ -0,0 +1,255 @@ +/**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 ABC__aig__kit__cloud_h +#define ABC__aig__kit__cloud_h + + +#include +#include +#include +#include + +#include "src/misc/util/abc_global.h" + + + +ABC_NAMESPACE_HEADER_START + + +#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_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)(ABC_PTRUINT_T)(f) * DD_P1 + (unsigned)(ABC_PTRUINT_T)(g)) * DD_P2) >> (s)) +#define cloudHashCudd3(f,g,h,s) (((((unsigned)(ABC_PTRUINT_T)(f) * DD_P1 + (unsigned)(ABC_PTRUINT_T)(g)) * DD_P2 + (unsigned)(ABC_PTRUINT_T)(h)) * DD_P3) >> (s)) + +// node complementation (using node) +#define Cloud_Regular(p) ((CloudNode*)(((ABC_PTRUINT_T)(p)) & ~01)) // get the regular node (w/o bubble) +#define Cloud_Not(p) ((CloudNode*)(((ABC_PTRUINT_T)(p)) ^ 01)) // complement the node +#define Cloud_NotCond(p,c) ((CloudNode*)(((ABC_PTRUINT_T)(p)) ^ (c))) // complement the node conditionally +#define Cloud_IsComplement(p) ((int)(((ABC_PTRUINT_T)(p)) & 01)) // 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): (0)) +#define cloudCacheLookup2(p,sign,f,g) (((p)->s == (sign) && (p)->a == (f) && (p)->b == (g))? ((p)->r): (0)) +#define cloudCacheLookup3(p,sign,f,g,h) (((p)->s == (sign) && (p)->a == (f) && (p)->b == (g) && (p)->c == (h))? ((p)->r): (0)) +// 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) + +//////////////////////////////////////////////////////////////////////// +/// 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 ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/src/bool/kit/kit.h b/src/bool/kit/kit.h new file mode 100644 index 00000000..4ca75622 --- /dev/null +++ b/src/bool/kit/kit.h @@ -0,0 +1,645 @@ +/**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 ABC__aig__kit__kit_h +#define ABC__aig__kit__kit_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + +#include "src/misc/vec/vec.h" +#include "src/misc/extra/extraBdd.h" +#include "cloud.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 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, Abc_Lit2Var(pNtk->Root) ); } +static inline int Kit_DsdLitIsLeaf( Kit_DsdNtk_t * pNtk, int Lit ) { int Id = Abc_Lit2Var(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 = Abc_Lit2Var(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 < (int)(pObj)->nFans) && ((iLit) = (pObj)->pFans[i], 1); i++ ) +#define Kit_DsdObjForEachFaninReverse( pNtk, pObj, iLit, i ) \ + for ( i = (int)(pObj)->nFans - 1; (i >= 0) && ((iLit) = (pObj)->pFans[i], 1); i-- ) + +#define Kit_PlaForEachCube( pSop, nFanins, pCube ) \ + for ( pCube = (pSop); *pCube; pCube += (nFanins) + 3 ) +#define Kit_PlaCubeForEachVar( pCube, Value, i ) \ + for ( i = 0; (pCube[i] != ' ') && (Value = pCube[i]); 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) + +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 unsigned Kit_EdgeToInt_( Kit_Edge_t m ) { union { Kit_Edge_t x; unsigned y; } v; v.x = m; return v.y; } +static inline Kit_Edge_t Kit_IntToEdge_( unsigned m ) { union { Kit_Edge_t x; unsigned y; } v; v.y = m; return v.x; } + +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_SuppIsMinBase( int Supp ) { return (Supp & (Supp+1)) == 0; } + +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_TruthIsEqualWithCare( unsigned * pIn0, unsigned * pIn1, unsigned * pCare, int nVars ) +{ + int w; + for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) + if ( (pIn0[w] & pCare[w]) != (pIn1[w] & pCare[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_TruthOrPhase( 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 void Kit_DsdPrintFromTruth2( FILE * pFile, unsigned * pTruth, int nVars ); +extern void Kit_DsdWriteFromTruth( char * pBuffer, 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 Kit_DsdObj_t * Kit_DsdNonDsdPrimeMax( 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 ); +/*=== kitPla.c ==========================================================*/ +extern int Kit_PlaIsConst0( char * pSop ); +extern int Kit_PlaIsConst1( char * pSop ); +extern int Kit_PlaIsBuf( char * pSop ); +extern int Kit_PlaIsInv( char * pSop ); +extern int Kit_PlaGetVarNum( char * pSop ); +extern int Kit_PlaGetCubeNum( char * pSop ); +extern int Kit_PlaIsComplement( char * pSop ); +extern void Kit_PlaComplement( char * pSop ); +extern char * Kit_PlaStart( void * p, int nCubes, int nVars ); +extern char * Kit_PlaCreateFromIsop( void * p, int nVars, Vec_Int_t * vCover ); +extern void Kit_PlaToIsop( char * pSop, Vec_Int_t * vCover ); +extern char * Kit_PlaStoreSop( void * p, char * pSop ); +extern char * Kit_PlaFromTruth( void * p, unsigned * pTruth, int nVars, Vec_Int_t * vCover ); +extern char * Kit_PlaFromTruthNew( unsigned * pTruth, int nVars, Vec_Int_t * vCover, Vec_Str_t * vStr ); +extern ABC_UINT64_T Kit_PlaToTruth6( char * pSop, int nVars ); +extern void Kit_PlaToTruth( char * pSop, int nVars, Vec_Ptr_t * vVars, unsigned * pTemp, unsigned * pTruth ); +/*=== 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_TruthPermute( unsigned * pOut, unsigned * pIn, int nVars, char * pPerm, 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 int Kit_TruthVarIsVacuous( unsigned * pOnset, unsigned * pOffset, 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_TruthVarsSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1, unsigned * pCof0, unsigned * pCof1 ); +extern int Kit_TruthVarsAntiSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1, unsigned * pCof0, unsigned * pCof1 ); +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_TruthCountOnesInCofs0( 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 ); +extern void Kit_TruthPrintProfile( unsigned * pTruth, int nVars ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/bool/kit/kitAig.c b/src/bool/kit/kitAig.c new file mode 100644 index 00000000..95fccbad --- /dev/null +++ b/src/bool/kit/kitAig.c @@ -0,0 +1,126 @@ +/**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 "src/aig/aig/aig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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( (Aig_Obj_t *)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( (Aig_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); + pAnd1 = Aig_NotCond( (Aig_Obj_t *)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( (Aig_Obj_t *)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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bool/kit/kitBdd.c b/src/bool/kit/kitBdd.c new file mode 100644 index 00000000..0d12d0dc --- /dev/null +++ b/src/bool/kit/kitBdd.c @@ -0,0 +1,236 @@ +/**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 "src/misc/extra/extraBdd.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 = NULL; // Suppress "might be used uninitialized" + 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( (DdNode *)pNode->pFunc ); + } + + // deref the intermediate results + bFunc = (DdNode *)pNode->pFunc; Cudd_Ref( bFunc ); + Kit_GraphForEachNode( pGraph, pNode, i ) + Cudd_RecursiveDeref( dd, (DdNode *)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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bool/kit/kitCloud.c b/src/bool/kit/kitCloud.c new file mode 100644 index 00000000..dea56749 --- /dev/null +++ b/src/bool/kit/kitCloud.c @@ -0,0 +1,378 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 +}; + +static inline int Kit_Mux2Int( Kit_Mux_t m ) { union { Kit_Mux_t x; int y; } v; v.x = m; return v.y; } +static inline Kit_Mux_t Kit_Int2Mux( int m ) { union { Kit_Mux_t x; int y; } v; v.y = m; return v.x; } + +//////////////////////////////////////////////////////////////////////// +/// 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, Kit_Mux2Int(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 = (unsigned *)Vec_PtrEntry( vStore, 0 ); + Kit_TruthFill( pThis, nVars ); + Vec_IntForEachEntryStart( vNodes, Entry, i, 1 ) + { + Mux = Kit_Int2Mux(Entry); + assert( (int)Mux.e < i && (int)Mux.t < i && (int)Mux.v < nVars ); + pFan0 = (unsigned *)Vec_PtrEntry( vStore, Mux.e ); + pFan1 = (unsigned *)Vec_PtrEntry( vStore, Mux.t ); + pThis = (unsigned *)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 = (unsigned *)Vec_PtrEntry( vStore, 0 ); + Kit_TruthFill( pThis, nVarsAll ); + Vec_IntForEachEntryStart( vNodes, Entry, i, 1 ) + { + Mux = Kit_Int2Mux(Entry); + pFan0 = (unsigned *)Vec_PtrEntry( vStore, Mux.e ); + pFan1 = (unsigned *)Vec_PtrEntry( vStore, Mux.t ); + pThis = (unsigned *)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; + unsigned * pThis = NULL; // Suppress "might be used uninitialized" + unsigned * 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 = (unsigned *)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_Int2Mux(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<nVarsMax = nVarsMax; + p->nWordsMax = Kit_TruthWordNum( p->nVarsMax ); + p->vTruthVars = Vec_PtrAllocTruthTables( p->nVarsMax ); + p->vTruthNodes = Vec_PtrAllocSimInfo( 64, p->nWordsMax ); + p->vLutsIn = Vec_IntAlloc( 50 ); + p->vSuppIn = Vec_IntAlloc( 50 ); + p->vLutsOut = Vec_IntAlloc( 50 ); + p->vSuppOut = Vec_IntAlloc( 50 ); + p->pTruthIn = ABC_ALLOC( unsigned, p->nWordsMax ); + p->pTruthOut = ABC_ALLOC( unsigned, p->nWordsMax ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops Decmetry manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_ManDecStop( Kit_ManDec_t * p ) +{ + ABC_FREE( p->pTruthIn ); + ABC_FREE( p->pTruthOut ); + Vec_IntFreeP( &p->vLutsIn ); + Vec_IntFreeP( &p->vSuppIn ); + Vec_IntFreeP( &p->vLutsOut ); + Vec_IntFreeP( &p->vSuppOut ); + Vec_PtrFreeP( &p->vTruthVars ); + Vec_PtrFreeP( &p->vTruthNodes ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [Deriving timing information for the decomposed structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_DecComputeOuputArrival( int nVars, Vec_Int_t * vSupps, int LutSize, char ATimesIn[], char ATimesOut[] ) +{ + int i, v, iVar, nLuts, Delay; + nLuts = Vec_IntSize(vSupps) / LutSize; + assert( nLuts > 0 ); + assert( Vec_IntSize(vSupps) % LutSize == 0 ); + for ( v = 0; v < nVars; v++ ) + ATimesOut[v] = ATimesIn[v]; + for ( v = 0; v < nLuts; v++ ) + { + Delay = 0; + for ( i = 0; i < LutSize; i++ ) + { + iVar = Vec_IntEntry( vSupps, v * LutSize + i ); + assert( iVar < nVars + v ); + Delay = Abc_MaxInt( Delay, ATimesOut[iVar] ); + } + ATimesOut[nVars + v] = Delay + 1; + } + return ATimesOut[nVars + nLuts - 1]; +} + +/**Function************************************************************* + + Synopsis [Derives the truth table] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_DecComputeTruthOne( int LutSize, unsigned * pTruthLut, int nVars, unsigned * pTruths[], unsigned * pTemp, unsigned * pRes ) +{ + int i, v; + Kit_TruthClear( pRes, nVars ); + for ( i = 0; i < (1< 0 ); + assert( Vec_IntSize(vSupps) % LutSize == 0 ); + assert( nLuts * nTruthLutWords == Vec_IntSize(vLuts) ); + for ( v = 0; v < nLuts; v++ ) + { + for ( i = 0; i < LutSize; i++ ) + { + iVar = Vec_IntEntry( vSupps, v * LutSize + i ); + assert( iVar < nVars + v ); + pTruths[i] = (iVar < nVars)? (unsigned *)Vec_PtrEntry(p->vTruthVars, iVar) : (unsigned *)Vec_PtrEntry(p->vTruthNodes, iVar-nVars); + } + pResult = (v == nLuts - 1) ? pRes : (unsigned *)Vec_PtrEntry(p->vTruthNodes, v); + Kit_DecComputeTruthOne( LutSize, pTruthLuts, nVars, pTruths, (unsigned *)Vec_PtrEntry(p->vTruthNodes, v+1), pResult ); + pTruthLuts += nTruthLutWords; + } +} + +/**Function************************************************************* + + Synopsis [Derives the truth table] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_DecComputePattern( int nVars, unsigned * pTruth, int LutSize, int Pattern[] ) +{ + int nCofs = (1 << LutSize); + int i, k, nMyu = 0; + assert( LutSize <= 6 ); + assert( LutSize < nVars ); + if ( nVars - LutSize <= 5 ) + { + unsigned uCofs[64]; + int nBits = (1 << (nVars - LutSize)); + for ( i = 0; i < nCofs; i++ ) + uCofs[i] = (pTruth[(i*nBits)/32] >> ((i*nBits)%32)) & ((1<= 0 && Shared1[m] >= 0 && Shared0[u] == Shared1[m] ) + { + Shared[nShared++] = Shared0[u]; + Shared0[u] = Shared1[m] = -1; + } + return nShared; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns the number of shared variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_DecComputeShared( int Pattern[], int LutSize, int Shared[] ) +{ + int i, Vars[6]; + assert( LutSize <= 6 ); + for ( i = 0; i < LutSize; i++ ) + Vars[i] = i; + return Kit_DecComputeShared_rec( Pattern, Vars, LutSize, Shared, 0 ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bool/kit/kitDsd.c b/src/bool/kit/kitDsd.c new file mode 100644 index 00000000..3df16d8c --- /dev/null +++ b/src/bool/kit/kitDsd.c @@ -0,0 +1,3200 @@ +/**CFile**************************************************************** + + FileName [kitDsd.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Computation kit.] + + Synopsis [Performs disjoint-support decomposition based on truth tables.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - Dec 6, 2006.] + + Revision [$Id: kitDsd.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "kit.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates the DSD manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_DsdMan_t * Kit_DsdManAlloc( int nVars, int nNodes ) +{ + Kit_DsdMan_t * p; + p = ABC_ALLOC( Kit_DsdMan_t, 1 ); + memset( p, 0, sizeof(Kit_DsdMan_t) ); + p->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 ); + ABC_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 *)ABC_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 = ABC_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 ) +{ + ABC_FREE( pObj ); +} + +/**Function************************************************************* + + Synopsis [Allocates the DSD network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_DsdNtk_t * Kit_DsdNtkAlloc( int nVars ) +{ + Kit_DsdNtk_t * pNtk; + pNtk = ABC_ALLOC( Kit_DsdNtk_t, 1 ); + memset( pNtk, 0, sizeof(Kit_DsdNtk_t) ); + pNtk->pNodes = ABC_ALLOC( Kit_DsdObj_t *, nVars+1 ); + pNtk->nVars = nVars; + pNtk->nNodesAlloc = nVars+1; + pNtk->pMem = ABC_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 ) + ABC_FREE( pObj ); + ABC_FREE( pNtk->pSupps ); + ABC_FREE( pNtk->pNodes ); + ABC_FREE( pNtk->pMem ); + ABC_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 [Prints the hex unsigned into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Kit_DsdWriteHex( char * pBuff, 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 ) + *pBuff++ = '0' + Digit; + else + *pBuff++ = 'A' + Digit-10; + } + return pBuff; +} + +/**Function************************************************************* + + Synopsis [Recursively print the DSD formula.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_DsdPrint2_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 ) + fprintf( pFile, "[" ); + else + fprintf( pFile, "(" ); + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + { + if ( Abc_LitIsCompl(iLit) ) + fprintf( pFile, "!" ); + Kit_DsdPrint2_rec( pFile, pNtk, Abc_Lit2Var(iLit) ); + if ( i < pObj->nFans - 1 ) + fprintf( pFile, "%c", Symbol ); + } + if ( pObj->Type == KIT_DSD_PRIME ) + fprintf( pFile, "]" ); + else + fprintf( pFile, ")" ); +} + +/**Function************************************************************* + + Synopsis [Print the DSD formula.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_DsdPrint2( FILE * pFile, Kit_DsdNtk_t * pNtk ) +{ +// fprintf( pFile, "F = " ); + if ( Abc_LitIsCompl(pNtk->Root) ) + fprintf( pFile, "!" ); + Kit_DsdPrint2_rec( pFile, pNtk, Abc_Lit2Var(pNtk->Root) ); +// fprintf( pFile, "\n" ); +} + +/**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( pFile, Kit_DsdObjTruth(pObj), pObj->nFans ); + + fprintf( pFile, "(" ); + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + { + if ( Abc_LitIsCompl(iLit) ) + fprintf( pFile, "!" ); + Kit_DsdPrint_rec( pFile, pNtk, Abc_Lit2Var(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 ( Abc_LitIsCompl(pNtk->Root) ) + fprintf( pFile, "!" ); + Kit_DsdPrint_rec( pFile, pNtk, Abc_Lit2Var(pNtk->Root) ); +// fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Recursively print the DSD formula.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Kit_DsdWrite_rec( char * pBuff, 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 ); + *pBuff++ = 'a' + Id; + return pBuff; + } + + if ( pObj->Type == KIT_DSD_CONST1 ) + { + assert( pObj->nFans == 0 ); + sprintf( pBuff, "%s", "Const1" ); + return pBuff + strlen("Const1"); + } + + 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 ) + pBuff = Kit_DsdWriteHex( pBuff, Kit_DsdObjTruth(pObj), pObj->nFans ); + + *pBuff++ = '('; + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + { + if ( Abc_LitIsCompl(iLit) ) + *pBuff++ = '!'; + pBuff = Kit_DsdWrite_rec( pBuff, pNtk, Abc_Lit2Var(iLit) ); + if ( i < pObj->nFans - 1 ) + *pBuff++ = Symbol; + } + *pBuff++ = ')'; + return pBuff; +} + +/**Function************************************************************* + + Synopsis [Print the DSD formula.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_DsdWrite( char * pBuff, Kit_DsdNtk_t * pNtk ) +{ + if ( Abc_LitIsCompl(pNtk->Root) ) + *pBuff++ = '!'; + pBuff = Kit_DsdWrite_rec( pBuff, pNtk, Abc_Lit2Var(pNtk->Root) ); + *pBuff = 0; +} + +/**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, * pTemp2; +// pTemp = Kit_DsdDecomposeMux( pTruth, nVars, 5 ); + pTemp = Kit_DsdDecomposeMux( pTruth, nVars, 8 ); +// Kit_DsdPrintExpanded( pTemp ); + pTemp2 = Kit_DsdExpand( pTemp ); + Kit_DsdPrint( stdout, pTemp2 ); + Kit_DsdVerify( pTemp2, pTruth, nVars ); + Kit_DsdNtkFree( pTemp2 ); + Kit_DsdNtkFree( pTemp ); +} + +/**Function************************************************************* + + Synopsis [Print the DSD formula.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_DsdPrintFromTruth2( FILE * pFile, unsigned * pTruth, int nVars ) +{ + Kit_DsdNtk_t * pTemp, * pTemp2; + pTemp = Kit_DsdDecomposeMux( pTruth, nVars, 0 ); + pTemp2 = Kit_DsdExpand( pTemp ); + Kit_DsdPrint2( pFile, pTemp2 ); + Kit_DsdVerify( pTemp2, pTruth, nVars ); + Kit_DsdNtkFree( pTemp2 ); + Kit_DsdNtkFree( pTemp ); +} + +/**Function************************************************************* + + Synopsis [Print the DSD formula.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_DsdWriteFromTruth( char * pBuffer, unsigned * pTruth, int nVars ) +{ + Kit_DsdNtk_t * pTemp, * pTemp2; +// pTemp = Kit_DsdDecomposeMux( pTruth, nVars, 5 ); + pTemp = Kit_DsdDecomposeMux( pTruth, nVars, 8 ); +// Kit_DsdPrintExpanded( pTemp ); + pTemp2 = Kit_DsdExpand( pTemp ); + Kit_DsdWrite( pBuffer, pTemp2 ); + Kit_DsdVerify( pTemp2, pTruth, nVars ); + Kit_DsdNtkFree( pTemp2 ); + 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 = (unsigned *)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, Abc_Lit2Var(iLit) ); + if ( Abc_LitIsCompl(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, Abc_Lit2Var(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, Abc_LitIsCompl(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 ^= Abc_LitIsCompl(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 ); + } +*/ + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + if ( Abc_LitIsCompl(iLit) ) + Kit_TruthNot( pTruthFans[i], pTruthFans[i], pNtk->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( (unsigned *)Vec_PtrEntry(p->vTtNodes, i), (unsigned *)Vec_PtrEntry(p->vTtElems, i), p->nVars ); + // compute truth table for each node + pTruthRes = Kit_DsdTruthComputeNode_rec( p, pNtk, Abc_Lit2Var(pNtk->Root) ); + // complement the truth table if needed + if ( Abc_LitIsCompl(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 = (unsigned *)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, Abc_Lit2Var(iLit), uSupp ); + if ( Abc_LitIsCompl(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, Abc_Lit2Var(iLit), uSupp ); + else + { + pTruthFans[i] = NULL; + nPartial = 1; + } + } + else + { + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + pTruthFans[i] = Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Abc_Lit2Var(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, Abc_LitIsCompl(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 ^= Abc_LitIsCompl(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 ); + } +*/ + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + if ( Abc_LitIsCompl(iLit) ) + Kit_TruthNot( pTruthFans[i], pTruthFans[i], pNtk->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( (unsigned *)Vec_PtrEntry(p->vTtNodes, i), (unsigned *)Vec_PtrEntry(p->vTtElems, i), p->nVars ); + // compute truth table for each node + pTruthRes = Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Abc_Lit2Var(pNtk->Root), uSupp ); + // complement the truth table if needed + if ( Abc_LitIsCompl(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 = (unsigned *)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, Abc_Lit2Var(iLit), uSupp, iVar, pTruthDec ); + else + pTruthFans[i] = Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Abc_Lit2Var(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, Abc_LitIsCompl(iLit) ); + return pTruthRes; + } + if ( pObj->Type == KIT_DSD_XOR ) + { + Kit_TruthClear( pTruthRes, pNtk->nVars ); + fCompl = 0; + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + { + fCompl ^= Abc_LitIsCompl(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, Abc_Lit2Var(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, Abc_LitIsCompl(iLit) ); + else + Kit_TruthAndPhase( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars, 0, Abc_LitIsCompl(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 ^= Abc_LitIsCompl(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( !Abc_LitIsCompl(iLit) ); + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + if ( Abc_LitIsCompl(iLit) ) + Kit_TruthNot( pTruthFans[i], pTruthFans[i], pNtk->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_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( (unsigned *)Vec_PtrEntry(p->vTtNodes, i), (unsigned *)Vec_PtrEntry(p->vTtElems, i), p->nVars ); + // compute truth table for each node + pTruthRes = Kit_DsdTruthComputeNodeTwo_rec( p, pNtk, Abc_Lit2Var(pNtk->Root), uSupp, iVar, pTruthDec ); + // complement the truth table if needed + if ( Abc_LitIsCompl(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, Abc_Lit2Var(pObj->pFans[0]), pCounter ); + Res1 = Kit_DsdCountLuts_rec( pNtk, nLutSize, Abc_Lit2Var(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, Abc_Lit2Var(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, Abc_Lit2Var(pNtk->Root), &Counter ); + if ( Counter >= 1000 ) + return -1; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns the size of the largest non-DSD block.] + + 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 [Returns the largest non-DSD block.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_DsdObj_t * Kit_DsdNonDsdPrimeMax( Kit_DsdNtk_t * pNtk ) +{ + Kit_DsdObj_t * pObj, * pObjMax = NULL; + unsigned i, nSizeMax = 0; + Kit_DsdNtkForEachObj( pNtk, pObj, i ) + { + if ( pObj->Type != KIT_DSD_PRIME ) + continue; + if ( nSizeMax < pObj->nFans ) + { + nSizeMax = pObj->nFans; + pObjMax = pObj; + } + } + return pObjMax; +} + +/**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; +// ABC_FREE( pNtk->pSupps ); + Kit_DsdGetSupports( pNtk ); + Kit_DsdNtkForEachObj( pNtk, pObj, i ) + { + if ( pObj->Type != KIT_DSD_PRIME ) + continue; + uSupport |= Kit_DsdLitSupport( pNtk, Abc_Var2Lit(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, unsigned iLit, unsigned * piLitsNew, int * nLitsNew ) +{ + Kit_DsdObj_t * pObj; + unsigned i, iLitFanin; + // check the end of the supergate + pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit) ); + if ( Abc_LitIsCompl(iLit) || Abc_Lit2Var(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, unsigned iLit, unsigned * piLitsNew, int * nLitsNew ) +{ + Kit_DsdObj_t * pObj; + unsigned i, iLitFanin; + // check the end of the supergate + pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit) ); + if ( Abc_Lit2Var(iLit) < p->nVars || pObj->Type != KIT_DSD_XOR ) + { + piLitsNew[(*nLitsNew)++] = iLit; + return; + } + // iterate through the fanins + pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(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 ( Abc_LitIsCompl(iLit) ) + piLitsNew[0] = Abc_LitNot( 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, Abc_Lit2Var(iLit) ); + if ( pObj == NULL ) + return iLit; + if ( pObj->Type == KIT_DSD_AND ) + { + Kit_DsdExpandCollectAnd_rec( p, Abc_LitRegular(iLit), piLitsNew, (int *)&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 Abc_Var2Lit( pObjNew->Id, Abc_LitIsCompl(iLit) ); + } + if ( pObj->Type == KIT_DSD_XOR ) + { + int fCompl = Abc_LitIsCompl(iLit); + Kit_DsdExpandCollectXor_rec( p, Abc_LitRegular(iLit), piLitsNew, (int *)&nLitsNew ); + pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_XOR, nLitsNew ); + for ( i = 0; i < pObjNew->nFans; i++ ) + { + pObjNew->pFans[i] = Kit_DsdExpandNode_rec( pNew, p, Abc_LitRegular(piLitsNew[i]) ); + fCompl ^= Abc_LitIsCompl(piLitsNew[i]); + } + return Abc_Var2Lit( 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 ( Abc_LitIsCompl(pObjNew->pFans[i]) ) + { + pObjNew->pFans[i] = Abc_LitRegular(pObjNew->pFans[i]); + Kit_TruthChangePhase( pTruthNew, pObjNew->nFans, i ); + } + } + + if ( pObj->nFans == 3 && + (pTruthNew[0] == 0xCACACACA || pTruthNew[0] == 0xC5C5C5C5 || + pTruthNew[0] == 0x3A3A3A3A || pTruthNew[0] == 0x35353535) ) + { + // translate into regular MUXes + if ( pTruthNew[0] == 0xC5C5C5C5 ) + pObjNew->pFans[0] = Abc_LitNot(pObjNew->pFans[0]); + else if ( pTruthNew[0] == 0x3A3A3A3A ) + pObjNew->pFans[1] = Abc_LitNot(pObjNew->pFans[1]); + else if ( pTruthNew[0] == 0x35353535 ) + { + pObjNew->pFans[0] = Abc_LitNot(pObjNew->pFans[0]); + pObjNew->pFans[1] = Abc_LitNot(pObjNew->pFans[1]); + } + pTruthNew[0] = 0xCACACACA; + // resolve the complemented control input + if ( Abc_LitIsCompl(pObjNew->pFans[2]) ) + { + unsigned char Temp = pObjNew->pFans[0]; + pObjNew->pFans[0] = pObjNew->pFans[1]; + pObjNew->pFans[1] = Temp; + pObjNew->pFans[2] = Abc_LitNot(pObjNew->pFans[2]); + } + // resolve the complemented true input + if ( Abc_LitIsCompl(pObjNew->pFans[1]) ) + { + iLit = Abc_LitNot(iLit); + pObjNew->pFans[0] = Abc_LitNot(pObjNew->pFans[0]); + pObjNew->pFans[1] = Abc_LitNot(pObjNew->pFans[1]); + } + return Abc_Var2Lit( pObjNew->Id, Abc_LitIsCompl(iLit) ); + } + else + { + // if the incoming phase is complemented, absorb it into the prime node + if ( Abc_LitIsCompl(iLit) ) + Kit_TruthNot( pTruthNew, pTruthNew, pObj->nFans ); + return Abc_Var2Lit( 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 = Abc_Var2Lit( pObjNew->Id, Abc_LitIsCompl(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 = Abc_Var2Lit( pObjNew->Id, Abc_LitIsCompl(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, unsigned 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; + Kit_DsdObj_t * pObjNew = NULL; // Suppress "might be used uninitialized" + unsigned * pTruth, * pTruthNew; + unsigned i, piLitsNew[16], uSupps[16]; + int iLitFanin, iLitNew; + + // consider the case of simple gate + pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(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 = Abc_Var2Lit( pObjNew->Id, 0 ); + } + return Abc_Var2Lit( pObjNew->Id, Abc_LitIsCompl(iLit) ); + } + if ( pObj->Type == KIT_DSD_XOR ) + { + // get the supports + Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i ) + { + assert( !Abc_LitIsCompl(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 = Abc_Var2Lit( pObjNew->Id, 0 ); + } + return Abc_Var2Lit( pObjNew->Id, Abc_LitIsCompl(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 ( Abc_LitIsCompl(pObjNew->pFans[i]) ) + { + pObjNew->pFans[i] = Abc_LitRegular(pObjNew->pFans[i]); + Kit_TruthChangePhase( pTruthNew, pObjNew->nFans, i ); + } + } + // if the incoming phase is complemented, absorb it into the prime node + if ( Abc_LitIsCompl(iLit) ) + Kit_TruthNot( pTruthNew, pTruthNew, pObj->nFans ); + return Abc_Var2Lit( 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 = Abc_Var2Lit( pObjNew->Id, Abc_LitIsCompl(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 = Abc_Var2Lit( pObjNew->Id, Abc_LitIsCompl(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, Abc_Lit2Var(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 = ABC_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, Abc_Lit2Var(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, Abc_Lit2Var(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 ( Abc_Lit2Var(pObj0->pFans[i]) >= 4 ) + continue; + for ( k = 0; k < pObj1->nFans; k++ ) + if ( Abc_Lit2Var(pObj0->pFans[i]) == Abc_Lit2Var(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] = Abc_LitNot(pObj->pFans[0]); + else + assert( pTruth[0] == 0xAAAAAAAA ); + // update the parent pointer + *pPar = Abc_LitNotCond( pObj->pFans[0], Abc_LitIsCompl(*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 = Abc_LitNotCond( 2 * pRes->Id, Abc_LitIsCompl(*pPar) ); + // consider different decompositions + if ( fEquals[0][0] ) + { + Kit_TruthCopy( pTruth, pCofs2[1], pObj->nFans ); + } + else if ( fEquals[0][1] ) + { + pRes->pFans[0] = Abc_LitNot(pRes->pFans[0]); + Kit_TruthCopy( pTruth, pCofs2[0], pObj->nFans ); + } + else if ( fEquals[1][0] ) + { + *pPar = Abc_LitNot(*pPar); + pRes->pFans[1] = Abc_LitNot(pRes->pFans[1]); + Kit_TruthCopy( pTruth, pCofs2[1], pObj->nFans ); + } + else if ( fEquals[1][1] ) + { + *pPar = Abc_LitNot(*pPar); + pRes->pFans[0] = Abc_LitNot(pRes->pFans[0]); + pRes->pFans[1] = Abc_LitNot(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] = Abc_LitNot(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] = Abc_LitNot(pRes->pFans[0]); + pRes->pFans[1] = Abc_LitNot(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] = Abc_LitNot(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] = Abc_LitNot(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[2] = pObj->pFans[iBestVar]; + 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 ); + } + +} + +/**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 = Abc_Var2Lit( 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] = Abc_Var2Lit( 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 = Abc_LitNot(pNtk->Root); + return pNtk; + } + if ( nVarsReal == 1 ) + { + pObj->Type = KIT_DSD_VAR; + pObj->nFans = 1; + pObj->pFans[0] = Abc_Var2Lit( 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 ) +{ +/* + Kit_DsdNtk_t * pNew; + Kit_DsdObj_t * pObjNew; + assert( nVars <= 16 ); + // create a new network + pNew = Kit_DsdNtkAlloc( nVars ); + // consider simple special cases + if ( nVars == 0 ) + { + pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_CONST1, 0 ); + pNew->Root = Abc_Var2Lit( pObjNew->Id, (int)(pTruth[0] == 0) ); + return pNew; + } + if ( nVars == 1 ) + { + pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_VAR, 1 ); + pObjNew->pFans[0] = Abc_Var2Lit( 0, 0 ); + pNew->Root = Abc_Var2Lit( pObjNew->Id, (int)(pTruth[0] != 0xAAAAAAAA) ); + return pNew; + } +*/ + 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 ), printf( "\n" ); + } + 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 ), printf( "\n" ); + } + + 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 ), printf( "\n" ); + } + +// 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, Abc_Lit2Var(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 ), printf( "\n" ); + +// if ( Kit_DsdFindLargeBox(pNtk, Abc_Lit2Var(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 ), printf( "\n" ); + + 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 = Abc_Lit2Var( 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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} + }; + Kit_DsdNtk_t * 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] = ABC_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( "\n" ); + printf( "Cof%d%d: ", nStep+1, 2*i+1 ); + Kit_DsdPrint( stdout, ppNtks[nStep+1][2*i+1] ), printf( "\n" ); + } + } + } + + // free the networks + for ( i = 0; i < 5; i++ ) + for ( k = 0; k < 16; k++ ) + if ( ppNtks[i][k] ) + Kit_DsdNtkFree( ppNtks[i][k] ); + ABC_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] ), printf( "\n" ); + Kit_DsdNtkFree( ppNtks[0] ); + + // allocate storage for cofactors + nMemSize = Kit_TruthWordNum(nVars); + ppCofs[0][0] = ABC_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] ), printf( "\n" ); + } + // 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] ), printf( "\n" ); + } + // 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] ), printf( "\n" ); + } + // 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] ), printf( "\n" ); + } + // 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 ); + } + + + ABC_FREE( ppCofs[0][0] ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char ** Kit_DsdNpn4ClassNames() +{ + static const char * pNames[222] = { + "F = 0", /* 0 */ + "F = (!d*(!c*(!b*!a)))", /* 1 */ + "F = (!d*(!c*!b))", /* 2 */ + "F = (!d*(!c*(b+a)))", /* 3 */ + "F = (!d*(!c*!(b*a)))", /* 4 */ + "F = (!d*!c)", /* 5 */ + "F = (!d*16(a,b,c))", /* 6 */ + "F = (!d*17(a,b,c))", /* 7 */ + "F = (!d*18(a,b,c))", /* 8 */ + "F = (!d*19(a,b,c))", /* 9 */ + "F = (!d*CA(!b,!c,a))", /* 10 */ + "F = (!d*(c+!(!b*!a)))", /* 11 */ + "F = (!d*!(c*!(!b*!a)))", /* 12 */ + "F = (!d*(c+b))", /* 13 */ + "F = (!d*3D(a,b,c))", /* 14 */ + "F = (!d*!(c*b))", /* 15 */ + "F = (!d*(c+(b+!a)))", /* 16 */ + "F = (!d*6B(a,b,c))", /* 17 */ + "F = (!d*!(c*!(b+a)))", /* 18 */ + "F = (!d*7E(a,b,c))", /* 19 */ + "F = (!d*!(c*(b*a)))", /* 20 */ + "F = (!d)", /* 21 */ + "F = 0116(a,b,c,d)", /* 22 */ + "F = 0117(a,b,c,d)", /* 23 */ + "F = 0118(a,b,c,d)", /* 24 */ + "F = 0119(a,b,c,d)", /* 25 */ + "F = 011A(a,b,c,d)", /* 26 */ + "F = 011B(a,b,c,d)", /* 27 */ + "F = 29((!b*!a),c,d)", /* 28 */ + "F = 2B((!b*!a),c,d)", /* 29 */ + "F = 012C(a,b,c,d)", /* 30 */ + "F = 012D(a,b,c,d)", /* 31 */ + "F = 012F(a,b,c,d)", /* 32 */ + "F = 013C(a,b,c,d)", /* 33 */ + "F = 013D(a,b,c,d)", /* 34 */ + "F = 013E(a,b,c,d)", /* 35 */ + "F = 013F(a,b,c,d)", /* 36 */ + "F = 0168(a,b,c,d)", /* 37 */ + "F = 0169(a,b,c,d)", /* 38 */ + "F = 016A(a,b,c,d)", /* 39 */ + "F = 016B(a,b,c,d)", /* 40 */ + "F = 016E(a,b,c,d)", /* 41 */ + "F = 016F(a,b,c,d)", /* 42 */ + "F = 017E(a,b,c,d)", /* 43 */ + "F = 017F(a,b,c,d)", /* 44 */ + "F = 0180(a,b,c,d)", /* 45 */ + "F = 0181(a,b,c,d)", /* 46 */ + "F = 0182(a,b,c,d)", /* 47 */ + "F = 0183(a,b,c,d)", /* 48 */ + "F = 0186(a,b,c,d)", /* 49 */ + "F = 0187(a,b,c,d)", /* 50 */ + "F = 0189(a,b,c,d)", /* 51 */ + "F = 018B(a,b,c,d)", /* 52 */ + "F = 018F(a,b,c,d)", /* 53 */ + "F = 0196(a,b,c,d)", /* 54 */ + "F = 0197(a,b,c,d)", /* 55 */ + "F = 0198(a,b,c,d)", /* 56 */ + "F = 0199(a,b,c,d)", /* 57 */ + "F = 019A(a,b,c,d)", /* 58 */ + "F = 019B(a,b,c,d)", /* 59 */ + "F = 019E(a,b,c,d)", /* 60 */ + "F = 019F(a,b,c,d)", /* 61 */ + "F = 42(a,(!c*!b),d)", /* 62 */ + "F = 46(a,(!c*!b),d)", /* 63 */ + "F = 4A(a,(!c*!b),d)", /* 64 */ + "F = CA((!c*!b),!d,a)", /* 65 */ + "F = 01AC(a,b,c,d)", /* 66 */ + "F = 01AD(a,b,c,d)", /* 67 */ + "F = 01AE(a,b,c,d)", /* 68 */ + "F = 01AF(a,b,c,d)", /* 69 */ + "F = 01BC(a,b,c,d)", /* 70 */ + "F = 01BD(a,b,c,d)", /* 71 */ + "F = 01BE(a,b,c,d)", /* 72 */ + "F = 01BF(a,b,c,d)", /* 73 */ + "F = 01E8(a,b,c,d)", /* 74 */ + "F = 01E9(a,b,c,d)", /* 75 */ + "F = 01EA(a,b,c,d)", /* 76 */ + "F = 01EB(a,b,c,d)", /* 77 */ + "F = 25((!b*!a),c,d)", /* 78 */ + "F = !CA(d,c,(!b*!a))", /* 79 */ + "F = (d+!(!c*(!b*!a)))", /* 80 */ + "F = 16(b,c,d)", /* 81 */ + "F = 033D(a,b,c,d)", /* 82 */ + "F = 17(b,c,d)", /* 83 */ + "F = ((!d*!a)+(!c*!b))", /* 84 */ + "F = !(!(!c*!b)*!(!d*!a))", /* 85 */ + "F = 0358(a,b,c,d)", /* 86 */ + "F = 0359(a,b,c,d)", /* 87 */ + "F = 035A(a,b,c,d)", /* 88 */ + "F = 035B(a,b,c,d)", /* 89 */ + "F = 035E(a,b,c,d)", /* 90 */ + "F = 035F(a,b,c,d)", /* 91 */ + "F = 0368(a,b,c,d)", /* 92 */ + "F = 0369(a,b,c,d)", /* 93 */ + "F = 036A(a,b,c,d)", /* 94 */ + "F = 036B(a,b,c,d)", /* 95 */ + "F = 036C(a,b,c,d)", /* 96 */ + "F = 036D(a,b,c,d)", /* 97 */ + "F = 036E(a,b,c,d)", /* 98 */ + "F = 036F(a,b,c,d)", /* 99 */ + "F = 037C(a,b,c,d)", /* 100 */ + "F = 037D(a,b,c,d)", /* 101 */ + "F = 037E(a,b,c,d)", /* 102 */ + "F = 18(b,c,d)", /* 103 */ + "F = 03C1(a,b,c,d)", /* 104 */ + "F = 19(b,c,d)", /* 105 */ + "F = 03C5(a,b,c,d)", /* 106 */ + "F = 03C6(a,b,c,d)", /* 107 */ + "F = 03C7(a,b,c,d)", /* 108 */ + "F = CA(!c,!d,b)", /* 109 */ + "F = 03D4(a,b,c,d)", /* 110 */ + "F = 03D5(a,b,c,d)", /* 111 */ + "F = 03D6(a,b,c,d)", /* 112 */ + "F = 03D7(a,b,c,d)", /* 113 */ + "F = 03D8(a,b,c,d)", /* 114 */ + "F = 03D9(a,b,c,d)", /* 115 */ + "F = 03DB(a,b,c,d)", /* 116 */ + "F = 03DC(a,b,c,d)", /* 117 */ + "F = 03DD(a,b,c,d)", /* 118 */ + "F = 03DE(a,b,c,d)", /* 119 */ + "F = (d+!(!c*!b))", /* 120 */ + "F = ((d+c)*(b+a))", /* 121 */ + "F = 0661(a,b,c,d)", /* 122 */ + "F = 0662(a,b,c,d)", /* 123 */ + "F = 0663(a,b,c,d)", /* 124 */ + "F = (!(d*c)*(b+a))", /* 125 */ + "F = 0667(a,b,c,d)", /* 126 */ + "F = 29((b+a),c,d)", /* 127 */ + "F = 066B(a,b,c,d)", /* 128 */ + "F = 2B((b+a),c,d)", /* 129 */ + "F = 0672(a,b,c,d)", /* 130 */ + "F = 0673(a,b,c,d)", /* 131 */ + "F = 0676(a,b,c,d)", /* 132 */ + "F = 0678(a,b,c,d)", /* 133 */ + "F = 0679(a,b,c,d)", /* 134 */ + "F = 067A(a,b,c,d)", /* 135 */ + "F = 067B(a,b,c,d)", /* 136 */ + "F = 067E(a,b,c,d)", /* 137 */ + "F = 24((b+a),c,d)", /* 138 */ + "F = 0691(a,b,c,d)", /* 139 */ + "F = 0693(a,b,c,d)", /* 140 */ + "F = 26((b+a),c,d)", /* 141 */ + "F = 0697(a,b,c,d)", /* 142 */ + "F = !CA(d,c,(b+a))", /* 143 */ + "F = 06B0(a,b,c,d)", /* 144 */ + "F = 06B1(a,b,c,d)", /* 145 */ + "F = 06B2(a,b,c,d)", /* 146 */ + "F = 06B3(a,b,c,d)", /* 147 */ + "F = 06B4(a,b,c,d)", /* 148 */ + "F = 06B5(a,b,c,d)", /* 149 */ + "F = 06B6(a,b,c,d)", /* 150 */ + "F = 06B7(a,b,c,d)", /* 151 */ + "F = 06B9(a,b,c,d)", /* 152 */ + "F = 06BD(a,b,c,d)", /* 153 */ + "F = 2C((b+a),c,d)", /* 154 */ + "F = 06F1(a,b,c,d)", /* 155 */ + "F = 06F2(a,b,c,d)", /* 156 */ + "F = CA((b+a),!d,c)", /* 157 */ + "F = (d+!(!c*!(b+!a)))", /* 158 */ + "F = 0776(a,b,c,d)", /* 159 */ + "F = 16((b*a),c,d)", /* 160 */ + "F = 0779(a,b,c,d)", /* 161 */ + "F = 077A(a,b,c,d)", /* 162 */ + "F = 077E(a,b,c,d)", /* 163 */ + "F = 07B0(a,b,c,d)", /* 164 */ + "F = 07B1(a,b,c,d)", /* 165 */ + "F = 07B4(a,b,c,d)", /* 166 */ + "F = 07B5(a,b,c,d)", /* 167 */ + "F = 07B6(a,b,c,d)", /* 168 */ + "F = 07BC(a,b,c,d)", /* 169 */ + "F = 07E0(a,b,c,d)", /* 170 */ + "F = 07E1(a,b,c,d)", /* 171 */ + "F = 07E2(a,b,c,d)", /* 172 */ + "F = 07E3(a,b,c,d)", /* 173 */ + "F = 07E6(a,b,c,d)", /* 174 */ + "F = 07E9(a,b,c,d)", /* 175 */ + "F = 1C((b*a),c,d)", /* 176 */ + "F = 07F1(a,b,c,d)", /* 177 */ + "F = 07F2(a,b,c,d)", /* 178 */ + "F = (d+!(!c*!(b*a)))", /* 179 */ + "F = (d+c)", /* 180 */ + "F = 1668(a,b,c,d)", /* 181 */ + "F = 1669(a,b,c,d)", /* 182 */ + "F = 166A(a,b,c,d)", /* 183 */ + "F = 166B(a,b,c,d)", /* 184 */ + "F = 166E(a,b,c,d)", /* 185 */ + "F = 167E(a,b,c,d)", /* 186 */ + "F = 1681(a,b,c,d)", /* 187 */ + "F = 1683(a,b,c,d)", /* 188 */ + "F = 1686(a,b,c,d)", /* 189 */ + "F = 1687(a,b,c,d)", /* 190 */ + "F = 1689(a,b,c,d)", /* 191 */ + "F = 168B(a,b,c,d)", /* 192 */ + "F = 168E(a,b,c,d)", /* 193 */ + "F = 1696(a,b,c,d)", /* 194 */ + "F = 1697(a,b,c,d)", /* 195 */ + "F = 1698(a,b,c,d)", /* 196 */ + "F = 1699(a,b,c,d)", /* 197 */ + "F = 169A(a,b,c,d)", /* 198 */ + "F = 169B(a,b,c,d)", /* 199 */ + "F = 169E(a,b,c,d)", /* 200 */ + "F = 16A9(a,b,c,d)", /* 201 */ + "F = 16AC(a,b,c,d)", /* 202 */ + "F = 16AD(a,b,c,d)", /* 203 */ + "F = 16BC(a,b,c,d)", /* 204 */ + "F = (d+E9(a,b,c))", /* 205 */ + "F = 177E(a,b,c,d)", /* 206 */ + "F = 178E(a,b,c,d)", /* 207 */ + "F = 1796(a,b,c,d)", /* 208 */ + "F = 1798(a,b,c,d)", /* 209 */ + "F = 179A(a,b,c,d)", /* 210 */ + "F = 17AC(a,b,c,d)", /* 211 */ + "F = (d+E8(a,b,c))", /* 212 */ + "F = (d+E7(a,b,c))", /* 213 */ + "F = 19E1(a,b,c,d)", /* 214 */ + "F = 19E3(a,b,c,d)", /* 215 */ + "F = (d+E6(a,b,c))", /* 216 */ + "F = 1BD8(a,b,c,d)", /* 217 */ + "F = (d+CA(b,c,a))", /* 218 */ + "F = (d+(c+(!b*!a)))", /* 219 */ + "F = (d+(c+!b))", /* 220 */ + "F = (d+(c+(b+a)))" /* 221 */ + }; + return (char **)pNames; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bool/kit/kitFactor.c b/src/bool/kit/kitFactor.c new file mode 100644 index 00000000..ec4775ca --- /dev/null +++ b/src/bool/kit/kitFactor.c @@ -0,0 +1,344 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// factoring fails if intermediate memory usage exceed this limit +#define KIT_FACTOR_MEM_LIMIT (1<<20) + +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 ABC_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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bool/kit/kitGraph.c b/src/bool/kit/kitGraph.c new file mode 100644 index 00000000..e4eea885 --- /dev/null +++ b/src/bool/kit/kitGraph.c @@ -0,0 +1,402 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 = ABC_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 = ABC_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 = ABC_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 = ABC_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 ) +{ + ABC_FREE( pGraph->pNodes ); + ABC_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 = ABC_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) > (1<<16) ) + 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 /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bool/kit/kitHop.c b/src/bool/kit/kitHop.c new file mode 100644 index 00000000..28f4e714 --- /dev/null +++ b/src/bool/kit/kitHop.c @@ -0,0 +1,155 @@ +/**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 "src/aig/hop/hop.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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( (Hop_Obj_t *)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( (Hop_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); + pAnd1 = Hop_NotCond( (Hop_Obj_t *)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( (Hop_Obj_t *)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 ); + if ( pGraph == NULL ) + { + printf( "Kit_TruthToHop(): Converting truth table to AIG has failed for function:\n" ); + Kit_DsdPrintFromTruth( pTruth, nVars ); printf( "\n" ); + } + // 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 + Vec_IntClear( vMemory ); + 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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bool/kit/kitIsop.c b/src/bool/kit/kitIsop.c new file mode 100644 index 00000000..fc017c0e --- /dev/null +++ b/src/bool/kit/kitIsop.c @@ -0,0 +1,330 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// ISOP computation fails if intermediate memory usage exceed this limit +#define KIT_ISOP_MEM_LIMIT (1<<20) + +// 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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bool/kit/kitPerm.c b/src/bool/kit/kitPerm.c new file mode 100644 index 00000000..d3e9ff5a --- /dev/null +++ b/src/bool/kit/kitPerm.c @@ -0,0 +1,355 @@ +/**CFile**************************************************************** + + FileName [kitPerm.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Computation kit.] + + Synopsis [Procedures for permuting truth tables.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - Oct 26, 2011.] + + Revision [$Id: kitPerm.c,v 1.00 2011/11/26 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include +#include +#include +#include + +#define inline __inline // compatible with MS VS 6.0 + +//ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef unsigned __int64 word; +typedef unsigned short shot; +typedef unsigned char byte; + +static shot S[256] = +{ + 0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015, + 0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055, + 0x0100, 0x0101, 0x0104, 0x0105, 0x0110, 0x0111, 0x0114, 0x0115, + 0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155, + 0x0400, 0x0401, 0x0404, 0x0405, 0x0410, 0x0411, 0x0414, 0x0415, + 0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455, + 0x0500, 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515, + 0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554, 0x0555, + 0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015, + 0x1040, 0x1041, 0x1044, 0x1045, 0x1050, 0x1051, 0x1054, 0x1055, + 0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115, + 0x1140, 0x1141, 0x1144, 0x1145, 0x1150, 0x1151, 0x1154, 0x1155, + 0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415, + 0x1440, 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455, + 0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514, 0x1515, + 0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555, + 0x4000, 0x4001, 0x4004, 0x4005, 0x4010, 0x4011, 0x4014, 0x4015, + 0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055, + 0x4100, 0x4101, 0x4104, 0x4105, 0x4110, 0x4111, 0x4114, 0x4115, + 0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155, + 0x4400, 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415, + 0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454, 0x4455, + 0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515, + 0x4540, 0x4541, 0x4544, 0x4545, 0x4550, 0x4551, 0x4554, 0x4555, + 0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015, + 0x5040, 0x5041, 0x5044, 0x5045, 0x5050, 0x5051, 0x5054, 0x5055, + 0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115, + 0x5140, 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155, + 0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414, 0x5415, + 0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455, + 0x5500, 0x5501, 0x5504, 0x5505, 0x5510, 0x5511, 0x5514, 0x5515, + 0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555 +}; + +static byte P[256] = +{ + 0x00, 0x01, 0x10, 0x11, 0x04, 0x05, 0x14, 0x15, 0x40, 0x41, 0x50, 0x51, 0x44, 0x45, 0x54, 0x55, + 0x02, 0x03, 0x12, 0x13, 0x06, 0x07, 0x16, 0x17, 0x42, 0x43, 0x52, 0x53, 0x46, 0x47, 0x56, 0x57, + 0x20, 0x21, 0x30, 0x31, 0x24, 0x25, 0x34, 0x35, 0x60, 0x61, 0x70, 0x71, 0x64, 0x65, 0x74, 0x75, + 0x22, 0x23, 0x32, 0x33, 0x26, 0x27, 0x36, 0x37, 0x62, 0x63, 0x72, 0x73, 0x66, 0x67, 0x76, 0x77, + 0x08, 0x09, 0x18, 0x19, 0x0c, 0x0d, 0x1c, 0x1d, 0x48, 0x49, 0x58, 0x59, 0x4c, 0x4d, 0x5c, 0x5d, + 0x0a, 0x0b, 0x1a, 0x1b, 0x0e, 0x0f, 0x1e, 0x1f, 0x4a, 0x4b, 0x5a, 0x5b, 0x4e, 0x4f, 0x5e, 0x5f, + 0x28, 0x29, 0x38, 0x39, 0x2c, 0x2d, 0x3c, 0x3d, 0x68, 0x69, 0x78, 0x79, 0x6c, 0x6d, 0x7c, 0x7d, + 0x2a, 0x2b, 0x3a, 0x3b, 0x2e, 0x2f, 0x3e, 0x3f, 0x6a, 0x6b, 0x7a, 0x7b, 0x6e, 0x6f, 0x7e, 0x7f, + 0x80, 0x81, 0x90, 0x91, 0x84, 0x85, 0x94, 0x95, 0xc0, 0xc1, 0xd0, 0xd1, 0xc4, 0xc5, 0xd4, 0xd5, + 0x82, 0x83, 0x92, 0x93, 0x86, 0x87, 0x96, 0x97, 0xc2, 0xc3, 0xd2, 0xd3, 0xc6, 0xc7, 0xd6, 0xd7, + 0xa0, 0xa1, 0xb0, 0xb1, 0xa4, 0xa5, 0xb4, 0xb5, 0xe0, 0xe1, 0xf0, 0xf1, 0xe4, 0xe5, 0xf4, 0xf5, + 0xa2, 0xa3, 0xb2, 0xb3, 0xa6, 0xa7, 0xb6, 0xb7, 0xe2, 0xe3, 0xf2, 0xf3, 0xe6, 0xe7, 0xf6, 0xf7, + 0x88, 0x89, 0x98, 0x99, 0x8c, 0x8d, 0x9c, 0x9d, 0xc8, 0xc9, 0xd8, 0xd9, 0xcc, 0xcd, 0xdc, 0xdd, + 0x8a, 0x8b, 0x9a, 0x9b, 0x8e, 0x8f, 0x9e, 0x9f, 0xca, 0xcb, 0xda, 0xdb, 0xce, 0xcf, 0xde, 0xdf, + 0xa8, 0xa9, 0xb8, 0xb9, 0xac, 0xad, 0xbc, 0xbd, 0xe8, 0xe9, 0xf8, 0xf9, 0xec, 0xed, 0xfc, 0xfd, + 0xaa, 0xab, 0xba, 0xbb, 0xae, 0xaf, 0xbe, 0xbf, 0xea, 0xeb, 0xfa, 0xfb, 0xee, 0xef, 0xfe, 0xff +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_PermCreateS() +{ + int i, n, r; + for ( i = 0; i < 256; i++ ) + { + if ( i % 8 == 0 ) + printf( "\n" ); + for ( r = n = 0; n < 8; n++ ) + r |= ((i & (1 << n)) << n); + printf( "0x%04x, ", r ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_PermCreateP() +{ + int i, s1, s2, r; + for ( i = 0; i < 256; i++ ) + { + if ( i % 16 == 0 ) + printf( "\n" ); + s1 = i & 0x0A; + s2 = i & 0x50; + r = i ^ s1 ^ s2 ^ (s1 << 3) ^ (s2 >> 3); + assert( r < 256 ); + printf( "0x%02x, ", r ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Kit_PermCycleOne( shot * s, byte * b, int v ) +{ + int i, n = (1 << (v-3)); + assert( v > 2 && v < 16 ); + for ( i = 0; i < n; i++ ) + s[i] = S[b[i]] | (S[b[i+n]] << 1); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Kit_PermCycleMany( shot * s, byte * b, int V, int v ) +{ + int i, n = (1 << (V - 1 - v)), m = (1 << (v-2)); + assert( v > 2 && v < V ); + for ( i = 0; i < n; i++, s += (m >> 1), b += m ) + Kit_PermCycleOne( s, b, v ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_PermCompute( word * o, word * i, int V ) +{ + word * t; + int v, n = (1 << (V-3)); + assert( V >= 6 && V <= 16 ); + for ( v = 0; v < n; v++ ) + ((byte *)i)[v] = P[((byte *)i)[v]]; + for ( v = 3; v < V; v++ ) + { + Kit_PermCycleMany( (shot *)o, (byte *)i, V, v ); + t = i; i = o; o = t; + } + if ( V & 1 ) + { + n = (1 << (V-6)); + for ( v = 0; v < n; v++ ) + o[v] = i[v]; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_PermComputeNaive( word * F, int nVars ) +{ + extern void If_CluReverseOrder( word * pF, int nVars, int * V2P, int * P2V, int iVarStart ); + int i, V2P[16], P2V[16]; + for ( i = 0; i < nVars; i++ ) + V2P[i] = P2V[i] = i; + If_CluReverseOrder( F, nVars, V2P, P2V, 0 ); +} + + +word M ( word f1, word f2, int n) +{ + word temp = 0; + word a = 1; + int i; + for( i = 0; i < n; i++) + temp = temp + (((f1>>i)&a) << (2*i) ) + (((f2>>i)&a) << (2*i+1)); + return temp; +} + +word Tf ( word f, int n) +{ + if(n==1) + return f; + else + { +// int x = (int)pow(2,n-1); + int x; + x = (1 << (n-1)); + return ( M (Tf( (f << x) >> x, n-1), Tf( (f >> x), n-1), x) ); //def. of M just below the function + } +} + + +#define ABC_PRT(a,t) (printf("%s = ", (a)), printf("%7.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC))) +#define NFUNCS (1<<20) + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_PermComputeTest() +{ + word * T = (word *)malloc( 8 * NFUNCS ); + word i, o, w = 0; + int k, b, clk; + + srand( 0 ); + + clk = clock(); + for ( k = 0; k < NFUNCS; k++ ) + for ( b = 0; b < 8; b++ ) + ((byte *)(T + k))[b] = (byte)(rand() & 0xFF); + ABC_PRT( "Assign", clock() - clk ); + +// T[0] = 0xacaccacaaccaacca; +// Kit_DsdPrintFromTruth( T, 6 ); + + // perform measurements + clk = clock(); + for ( k = 0; k < NFUNCS; k++ ) + { + i = T[k]; +// Kit_PermComputeNaive( &i, 6 ); + Tf( i, 6 ); + } + ABC_PRT( "Perm1 ", clock() - clk ); + + // perform measurements + clk = clock(); + for ( k = 0; k < NFUNCS; k++ ) + { + i = T[k]; + Kit_PermCompute( &o, &i, 6 ); + +// w = T[k]; +// Kit_PermComputeNaive( &w, 6 ); +// assert( w == o ); + } + ABC_PRT( "Perm2 ", clock() - clk ); + + assert( w == 0 ); + free( T ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] +` +***********************************************************************/ +void Kit_PermComputeTest_() +{ + word t, s; + t = 0xacaccacaaccaacca; +// Kit_DsdPrintFromTruth( &t, 6 ); printf( "\n" ); + s = Tf( t, 6 ); +// Kit_PermComputeNaive( &t, 6 ); +// Kit_DsdPrintFromTruth( &s, 6 ); printf( "\n" ); +} + +/* + { + extern void Kit_PermComputeTest(); + Kit_PermComputeTest(); + } +*/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +//ABC_NAMESPACE_IMPL_END + diff --git a/src/bool/kit/kitPla.c b/src/bool/kit/kitPla.c new file mode 100644 index 00000000..acc163fc --- /dev/null +++ b/src/bool/kit/kitPla.c @@ -0,0 +1,535 @@ +/**CFile**************************************************************** + + FileName [kitPla.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Computation kit.] + + Synopsis [Manipulating SOP in the form of a C-string.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - Dec 6, 2006.] + + Revision [$Id: kitPla.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "kit.h" +#include "src/aig/aig/aig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks if the cover is constant 0.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_PlaIsConst0( char * pSop ) +{ + return pSop[0] == ' ' && pSop[1] == '0'; +} + +/**Function************************************************************* + + Synopsis [Checks if the cover is constant 1.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_PlaIsConst1( char * pSop ) +{ + return pSop[0] == ' ' && pSop[1] == '1'; +} + +/**Function************************************************************* + + Synopsis [Checks if the cover is a buffer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_PlaIsBuf( char * pSop ) +{ + if ( pSop[4] != 0 ) + return 0; + if ( (pSop[0] == '1' && pSop[2] == '1') || (pSop[0] == '0' && pSop[2] == '0') ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Checks if the cover is an inverter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_PlaIsInv( char * pSop ) +{ + if ( pSop[4] != 0 ) + return 0; + if ( (pSop[0] == '0' && pSop[2] == '1') || (pSop[0] == '1' && pSop[2] == '0') ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Reads the number of variables in the cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_PlaGetVarNum( char * pSop ) +{ + char * pCur; + for ( pCur = pSop; *pCur != '\n'; pCur++ ) + if ( *pCur == 0 ) + return -1; + return pCur - pSop - 2; +} + +/**Function************************************************************* + + Synopsis [Reads the number of cubes in the cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_PlaGetCubeNum( 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 Kit_PlaIsComplement( 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 Kit_PlaComplement( 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 * Kit_PlaStart( void * p, int nCubes, int nVars ) +{ + Aig_MmFlex_t * pMan = (Aig_MmFlex_t *)p; + 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 * Kit_PlaCreateFromIsop( void * p, int nVars, Vec_Int_t * vCover ) +{ + Aig_MmFlex_t * pMan = (Aig_MmFlex_t *)p; + char * pSop, * pCube; + int i, k, Entry, Literal; + assert( Vec_IntSize(vCover) > 0 ); + if ( Vec_IntSize(vCover) == 0 ) + return NULL; + // start the cover + pSop = Kit_PlaStart( 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 [Creates the cover from the ISOP computed from TT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_PlaToIsop( char * pSop, Vec_Int_t * vCover ) +{ + char * pCube; + int k, nVars, Entry; + nVars = Kit_PlaGetVarNum( pSop ); + assert( nVars > 0 ); + // create cubes + Vec_IntClear( vCover ); + for ( pCube = pSop; *pCube; pCube += nVars + 3 ) + { + Entry = 0; + for ( k = nVars - 1; k >= 0; k-- ) + if ( pCube[k] == '0' ) + Entry = (Entry << 2) | 1; + else if ( pCube[k] == '1' ) + Entry = (Entry << 2) | 2; + else if ( pCube[k] == '-' ) + Entry = (Entry << 2); + else + assert( 0 ); + Vec_IntPush( vCover, Entry ); + } +} + +/**Function************************************************************* + + Synopsis [Allocates memory and copies the SOP into it.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Kit_PlaStoreSop( void * p, char * pSop ) +{ + Aig_MmFlex_t * pMan = (Aig_MmFlex_t *)p; + char * pStore; + pStore = Aig_MmFlexEntryFetch( pMan, strlen(pSop) + 1 ); + strcpy( pStore, pSop ); + return pStore; +} + +/**Function************************************************************* + + Synopsis [Transforms truth table into the SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Kit_PlaFromTruth( void * p, unsigned * pTruth, int nVars, Vec_Int_t * vCover ) +{ + Aig_MmFlex_t * pMan = (Aig_MmFlex_t *)p; + char * pSop; + int RetValue; + if ( Kit_TruthIsConst0(pTruth, nVars) ) + return Kit_PlaStoreSop( pMan, " 0\n" ); + if ( Kit_TruthIsConst1(pTruth, nVars) ) + return Kit_PlaStoreSop( pMan, " 1\n" ); + RetValue = Kit_TruthIsop( pTruth, nVars, vCover, 0 ); // 1 ); + assert( RetValue == 0 || RetValue == 1 ); + pSop = Kit_PlaCreateFromIsop( pMan, nVars, vCover ); + if ( RetValue ) + Kit_PlaComplement( pSop ); + return pSop; +} + + +/**Function************************************************************* + + Synopsis [Creates the cover from the ISOP computed from TT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Kit_PlaFromIsop( Vec_Str_t * vStr, int nVars, Vec_Int_t * vCover ) +{ + int i, k, Entry, Literal; + assert( Vec_IntSize(vCover) > 0 ); + if ( Vec_IntSize(vCover) == 0 ) + return NULL; + Vec_StrClear( vStr ); + Vec_IntForEachEntry( vCover, Entry, i ) + { + for ( k = 0; k < nVars; k++ ) + { + Literal = 3 & (Entry >> (k << 1)); + if ( Literal == 1 ) + Vec_StrPush( vStr, '0' ); + else if ( Literal == 2 ) + Vec_StrPush( vStr, '1' ); + else if ( Literal == 0 ) + Vec_StrPush( vStr, '-' ); + else + assert( 0 ); + } + Vec_StrPush( vStr, ' ' ); + Vec_StrPush( vStr, '1' ); + Vec_StrPush( vStr, '\n' ); + } + Vec_StrPush( vStr, '\0' ); + return Vec_StrArray( vStr ); +} + +/**Function************************************************************* + + Synopsis [Creates the SOP from TT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Kit_PlaFromTruthNew( unsigned * pTruth, int nVars, Vec_Int_t * vCover, Vec_Str_t * vStr ) +{ + char * pResult; + // transform truth table into the SOP + int RetValue = Kit_TruthIsop( pTruth, nVars, 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 ); + Vec_StrClear( vStr ); + Vec_StrAppend( vStr, (Vec_IntSize(vCover) == 0) ? " 0\n" : " 1\n" ); + Vec_StrPush( vStr, '\0' ); + return Vec_StrArray( vStr ); + } + pResult = Kit_PlaFromIsop( vStr, nVars, vCover ); + if ( RetValue ) + Kit_PlaComplement( pResult ); + if ( nVars < 6 ) + assert( pTruth[0] == (unsigned)Kit_PlaToTruth6(pResult, nVars) ); + else if ( nVars == 6 ) + assert( *((ABC_UINT64_T*)pTruth) == Kit_PlaToTruth6(pResult, nVars) ); + return pResult; +} + +/**Function************************************************************* + + Synopsis [Converts SOP into a truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +ABC_UINT64_T Kit_PlaToTruth6( char * pSop, int nVars ) +{ + static ABC_UINT64_T Truth[8] = { + 0xAAAAAAAAAAAAAAAA, + 0xCCCCCCCCCCCCCCCC, + 0xF0F0F0F0F0F0F0F0, + 0xFF00FF00FF00FF00, + 0xFFFF0000FFFF0000, + 0xFFFFFFFF00000000, + 0x0000000000000000, + 0xFFFFFFFFFFFFFFFF + }; + ABC_UINT64_T valueAnd, valueOr = Truth[6]; + int v, lit = 0; + assert( nVars < 7 ); + do { + valueAnd = Truth[7]; + for ( v = 0; v < nVars; v++, lit++ ) + { + if ( pSop[lit] == '1' ) + valueAnd &= Truth[v]; + else if ( pSop[lit] == '0' ) + valueAnd &= ~Truth[v]; + else if ( pSop[lit] != '-' ) + assert( 0 ); + } + valueOr |= valueAnd; + assert( pSop[lit] == ' ' ); + lit++; + lit++; + assert( pSop[lit] == '\n' ); + lit++; + } while ( pSop[lit] ); + if ( Kit_PlaIsComplement(pSop) ) + valueOr = ~valueOr; + return valueOr; +} + +/**Fnction************************************************************* + + Synopsis [Converting SOP into a truth table.] + + Description [The SOP is represented as a C-string, as documented in + file "bblif.h". The truth table is returned as a bit-string composed + of 2^nVars bits. For functions of less than 6 variables, the full + machine word is returned. (The truth table looks as if the function + had 5 variables.) The use of this procedure should be limited to + Boolean functions with no more than 16 inputs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_PlaToTruth( char * pSop, int nVars, Vec_Ptr_t * vVars, unsigned * pTemp, unsigned * pTruth ) +{ + int v, c, nCubes, fCompl = 0; + assert( pSop != NULL ); + assert( nVars >= 0 ); + if ( strlen(pSop) % (nVars + 3) != 0 ) + { + printf( "Kit_PlaToTruth(): SOP is represented incorrectly.\n" ); + return; + } + // iterate through the cubes + Kit_TruthClear( pTruth, nVars ); + nCubes = strlen(pSop) / (nVars + 3); + for ( c = 0; c < nCubes; c++ ) + { + fCompl = (pSop[nVars+1] == '0'); + Kit_TruthFill( pTemp, nVars ); + // iterate through the literals of the cube + for ( v = 0; v < nVars; v++ ) + if ( pSop[v] == '1' ) + Kit_TruthAnd( pTemp, pTemp, (unsigned *)Vec_PtrEntry(vVars, v), nVars ); + else if ( pSop[v] == '0' ) + Kit_TruthSharp( pTemp, pTemp, (unsigned *)Vec_PtrEntry(vVars, v), nVars ); + // add cube to storage + Kit_TruthOr( pTruth, pTruth, pTemp, nVars ); + // go to the next cube + pSop += (nVars + 3); + } + if ( fCompl ) + Kit_TruthNot( pTruth, pTruth, nVars ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bool/kit/kitSop.c b/src/bool/kit/kitSop.c new file mode 100644 index 00000000..21ea69b8 --- /dev/null +++ b/src/bool/kit/kitSop.c @@ -0,0 +1,579 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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; + unsigned uCube2 = 0; // Suppress "might be used uninitialized" + unsigned 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-ABC_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-ABC_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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bool/kit/kitTruth.c b/src/bool/kit/kitTruth.c new file mode 100644 index 00000000..bd8bbb1c --- /dev/null +++ b/src/bool/kit/kitTruth.c @@ -0,0 +1,2222 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 [The input truth table is modified.] + + 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) shows what variables should remain.] + + SideEffects [The input truth table is modified.] + + 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 [Implement give permutation.] + + Description [The input and output truth tables are in pIn/pOut. + The number of variables is nVars. Permutation is in pPerm.] + + SideEffects [The input truth table is modified.] + + SeeAlso [] + +***********************************************************************/ +void Kit_TruthPermute( unsigned * pOut, unsigned * pIn, int nVars, char * pPerm, int fReturnIn ) +{ + unsigned * pTemp; + int i, Temp, fChange, Counter = 0; + do { + fChange = 0; + for ( i = 0; i < nVars-1; i++ ) + { + assert( pPerm[i] != pPerm[i+1] ); + if ( pPerm[i] <= pPerm[i+1] ) + continue; + Counter++; + fChange = 1; + + Temp = pPerm[i]; + pPerm[i] = pPerm[i+1]; + pPerm[i+1] = Temp; + + Kit_TruthSwapAdjacentVars( pOut, pIn, nVars, i ); + pTemp = pIn; pIn = pOut; pOut = pTemp; + } + } while ( fChange ); + if ( fReturnIn ^ !(Counter & 1) ) + Kit_TruthCopy( pOut, pIn, nVars ); +} + +/**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 negative cofactor of the function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_TruthCofactor0Count( unsigned * pTruth, int nVars, int iVar ) +{ + int nWords = Kit_TruthWordNum( nVars ); + int i, k, Step, Counter = 0; + + assert( iVar < nVars ); + switch ( iVar ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + Counter += Kit_WordCountOnes(pTruth[i] & 0x55555555); + return Counter; + case 1: + for ( i = 0; i < nWords; i++ ) + Counter += Kit_WordCountOnes(pTruth[i] & 0x33333333); + return Counter; + case 2: + for ( i = 0; i < nWords; i++ ) + Counter += Kit_WordCountOnes(pTruth[i] & 0x0F0F0F0F); + return Counter; + case 3: + for ( i = 0; i < nWords; i++ ) + Counter += Kit_WordCountOnes(pTruth[i] & 0x00FF00FF); + return Counter; + case 4: + for ( i = 0; i < nWords; i++ ) + Counter += Kit_WordCountOnes(pTruth[i] & 0x0000FFFF); + return Counter; + default: + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 2*Step ) + { + for ( i = 0; i < Step; i++ ) + Counter += Kit_WordCountOnes(pTruth[i]); + pTruth += 2*Step; + } + return Counter; + } +} + +/**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 [Computes negative cofactor of the function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_TruthVarIsVacuous( unsigned * pOnset, unsigned * pOffset, 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 ( ((pOnset[i] & (pOffset[i] >> 1)) | (pOffset[i] & (pOnset[i] >> 1))) & 0x55555555 ) + return 0; + return 1; + case 1: + for ( i = 0; i < nWords; i++ ) + if ( ((pOnset[i] & (pOffset[i] >> 2)) | (pOffset[i] & (pOnset[i] >> 2))) & 0x33333333 ) + return 0; + return 1; + case 2: + for ( i = 0; i < nWords; i++ ) + if ( ((pOnset[i] & (pOffset[i] >> 4)) | (pOffset[i] & (pOnset[i] >> 4))) & 0x0F0F0F0F ) + return 0; + return 1; + case 3: + for ( i = 0; i < nWords; i++ ) + if ( ((pOnset[i] & (pOffset[i] >> 8)) | (pOffset[i] & (pOnset[i] >> 8))) & 0x00FF00FF ) + return 0; + return 1; + case 4: + for ( i = 0; i < nWords; i++ ) + if ( ((pOnset[i] & (pOffset[i] >> 16)) | (pOffset[i] & (pOnset[i] >> 16))) & 0x0000FFFF ) + return 0; + return 1; + default: + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 2*Step ) + { + for ( i = 0; i < Step; i++ ) + if ( (pOnset[i] & pOffset[Step+i]) | (pOffset[i] & pOnset[Step+i]) ) + return 0; + pOnset += 2*Step; + pOffset += 2*Step; + } + return 1; + } +} + + +/**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 [Returns the number of minterms in the Boolean difference.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_TruthBooleanDiffCount( unsigned * pTruth, int nVars, int iVar ) +{ + int nWords = Kit_TruthWordNum( nVars ); + int i, k, Step, Counter = 0; + + assert( iVar < nVars ); + switch ( iVar ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + Counter += Kit_WordCountOnes( (pTruth[i] ^ (pTruth[i] >> 1)) & 0x55555555 ); + return Counter; + case 1: + for ( i = 0; i < nWords; i++ ) + Counter += Kit_WordCountOnes( (pTruth[i] ^ (pTruth[i] >> 2)) & 0x33333333 ); + return Counter; + case 2: + for ( i = 0; i < nWords; i++ ) + Counter += Kit_WordCountOnes( (pTruth[i] ^ (pTruth[i] >> 4)) & 0x0F0F0F0F ); + return Counter; + case 3: + for ( i = 0; i < nWords; i++ ) + Counter += Kit_WordCountOnes( (pTruth[i] ^ (pTruth[i] >> 8)) & 0x00FF00FF ); + return Counter; + case 4: + for ( i = 0; i < nWords; i++ ) + Counter += Kit_WordCountOnes( (pTruth[i] ^ (pTruth[i] >>16)) & 0x0000FFFF ); + return Counter; + default: + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 2*Step ) + { + for ( i = 0; i < Step; i++ ) + Counter += Kit_WordCountOnes( pTruth[i] ^ pTruth[Step+i] ); + pTruth += 2*Step; + } + return Counter; + } +} + +/**Function************************************************************* + + Synopsis [Returns the number of minterms in the Boolean difference.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_TruthXorCount( unsigned * pTruth0, unsigned * pTruth1, int nVars ) +{ + int nWords = Kit_TruthWordNum( nVars ); + int i, Counter = 0; + for ( i = 0; i < nWords; i++ ) + Counter += Kit_WordCountOnes( pTruth0[i] ^ pTruth1[i] ); + return Counter; +} + +/**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, unsigned * pCof0, unsigned * pCof1 ) +{ + static unsigned uTemp0[32], uTemp1[32]; + if ( pCof0 == NULL ) + { + assert( nVars <= 10 ); + pCof0 = uTemp0; + } + if ( pCof1 == NULL ) + { + assert( nVars <= 10 ); + pCof1 = uTemp1; + } + // compute Cof01 + Kit_TruthCopy( pCof0, pTruth, nVars ); + Kit_TruthCofactor0( pCof0, nVars, iVar0 ); + Kit_TruthCofactor1( pCof0, nVars, iVar1 ); + // compute Cof10 + Kit_TruthCopy( pCof1, pTruth, nVars ); + Kit_TruthCofactor1( pCof1, nVars, iVar0 ); + Kit_TruthCofactor0( pCof1, nVars, iVar1 ); + // compare + return Kit_TruthIsEqual( pCof0, pCof1, nVars ); +} + +/**Function************************************************************* + + Synopsis [Checks antisymmetry of two variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_TruthVarsAntiSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1, unsigned * pCof0, unsigned * pCof1 ) +{ + static unsigned uTemp0[32], uTemp1[32]; + if ( pCof0 == NULL ) + { + assert( nVars <= 10 ); + pCof0 = uTemp0; + } + if ( pCof1 == NULL ) + { + assert( nVars <= 10 ); + pCof1 = uTemp1; + } + // compute Cof00 + Kit_TruthCopy( pCof0, pTruth, nVars ); + Kit_TruthCofactor0( pCof0, nVars, iVar0 ); + Kit_TruthCofactor0( pCof0, nVars, iVar1 ); + // compute Cof11 + Kit_TruthCopy( pCof1, pTruth, nVars ); + Kit_TruthCofactor1( pCof1, nVars, iVar0 ); + Kit_TruthCofactor1( pCof1, nVars, iVar1 ); + // compare + return Kit_TruthIsEqual( pCof0, pCof1, 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 negative cofactor.] + + Description [The resulting numbers are stored in the array of shorts, + whose length is 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_TruthCountOnesInCofs0( unsigned * pTruth, int nVars, short * pStore ) +{ + int nWords = Kit_TruthWordNum( nVars ); + int i, k, Counter; + memset( pStore, 0, sizeof(short) * nVars ); + if ( nVars <= 5 ) + { + if ( nVars > 0 ) + pStore[0] = Kit_WordCountOnes( pTruth[0] & 0x55555555 ); + if ( nVars > 1 ) + pStore[1] = Kit_WordCountOnes( pTruth[0] & 0x33333333 ); + if ( nVars > 2 ) + pStore[2] = Kit_WordCountOnes( pTruth[0] & 0x0F0F0F0F ); + if ( nVars > 3 ) + pStore[3] = Kit_WordCountOnes( pTruth[0] & 0x00FF00FF ); + if ( nVars > 4 ) + pStore[4] = Kit_WordCountOnes( pTruth[0] & 0x0000FFFF ); + 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))) == 0 ) + pStore[i] += Counter; + } + // count 1's for the first five variables + for ( k = 0; k < nWords/2; k++ ) + { + pStore[0] += Kit_WordCountOnes( (pTruth[0] & 0x55555555) | ((pTruth[1] & 0x55555555) << 1) ); + pStore[1] += Kit_WordCountOnes( (pTruth[0] & 0x33333333) | ((pTruth[1] & 0x33333333) << 2) ); + pStore[2] += Kit_WordCountOnes( (pTruth[0] & 0x0F0F0F0F) | ((pTruth[1] & 0x0F0F0F0F) << 4) ); + pStore[3] += Kit_WordCountOnes( (pTruth[0] & 0x00FF00FF) | ((pTruth[1] & 0x00FF00FF) << 8) ); + pStore[4] += Kit_WordCountOnes( (pTruth[0] & 0x0000FFFF) | ((pTruth[1] & 0x0000FFFF) << 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(pIn[0] & 1) + 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 * pBytesInit ) +{ + // 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 * pBytes = pBytesInit; + 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] += pBytesInit[i]; + pBytesInit[i] += pBytesInit[i+Step]; + } + assert( pBytesInit[0] == nTotal ); + assert( iVar == nVars ); + + for ( i = 0; i < nVars; i++ ) + assert( pRes[i] == Kit_TruthCofactor0Count(pTruth, nVars, i) ); + 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; +} + + +/**Function************************************************************* + + Synopsis [Dumps truth table into a file.] + + Description [Generates script file for reading into ABC.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_TruthPrintProfile_int( unsigned * pTruth, int nVars ) +{ + int Mints[20]; + int Mints0[20]; + int Mints1[20]; + int Unique1[20]; + int Total2[20][20]; + int Unique2[20][20]; + int Common2[20][20]; + int nWords = Kit_TruthWordNum( nVars ); + int * pBytes = ABC_ALLOC( int, nWords * 4 ); + unsigned * pIn = ABC_ALLOC( unsigned, nWords ); + unsigned * pOut = ABC_ALLOC( unsigned, nWords ); + unsigned * pCof00 = ABC_ALLOC( unsigned, nWords ); + unsigned * pCof01 = ABC_ALLOC( unsigned, nWords ); + unsigned * pCof10 = ABC_ALLOC( unsigned, nWords ); + unsigned * pCof11 = ABC_ALLOC( unsigned, nWords ); + unsigned * pTemp; + int nTotalMints, nTotalMints0, nTotalMints1; + int v, u, i, iVar, nMints1; + int Cof00, Cof01, Cof10, Cof11; + int Coz00, Coz01, Coz10, Coz11; + assert( nVars <= 20 ); + assert( nVars >= 6 ); + + nTotalMints = Kit_TruthCountMinterms( pTruth, nVars, Mints, pBytes ); + for ( v = 0; v < nVars; v++ ) + Unique1[v] = Kit_TruthBooleanDiffCount( pTruth, nVars, v ); + + for ( v = 0; v < nVars; v++ ) + for ( u = 0; u < nVars; u++ ) + Total2[v][u] = Unique2[v][u] = Common2[v][u] = -1; + + nMints1 = (1<<(nVars-2)); + for ( v = 0; v < nVars; v++ ) + { + // move this var to be the first + Kit_TruthCopy( pIn, pTruth, nVars ); +// Extra_PrintBinary( stdout, pIn, (1<= 0 && Cof00 <= nMints1 ); + assert( Cof01 >= 0 && Cof01 <= nMints1 ); + assert( Cof10 >= 0 && Cof10 <= nMints1 ); + assert( Cof11 >= 0 && Cof11 <= nMints1 ); + + assert( Coz00 >= 0 && Coz00 <= nMints1 ); + assert( Coz01 >= 0 && Coz01 <= nMints1 ); + assert( Coz10 >= 0 && Coz10 <= nMints1 ); + assert( Coz11 >= 0 && Coz11 <= nMints1 ); + + Common2[v][iVar] = Common2[iVar][v] = Cof00 * Coz11 + Coz00 * Cof11 + Cof01 * Coz10 + Coz01 * Cof10; + + Total2[v][iVar] = Total2[iVar][v] = + Cof00 * Coz01 + Coz00 * Cof01 + + Cof00 * Coz10 + Coz00 * Cof10 + + Cof00 * Coz11 + Coz00 * Cof11 + + Cof01 * Coz10 + Coz01 * Cof10 + + Cof01 * Coz11 + Coz01 * Cof11 + + Cof10 * Coz11 + Coz10 * Cof11 ; + + + Kit_TruthCofactor0New( pCof00, pIn, nVars-1, u ); + Kit_TruthCofactor1New( pCof01, pIn, nVars-1, u ); + Kit_TruthCofactor0New( pCof10, pIn+nWords/2, nVars-1, u ); + Kit_TruthCofactor1New( pCof11, pIn+nWords/2, nVars-1, u ); + + Unique2[v][iVar] = Unique2[iVar][v] = + Kit_TruthXorCount( pCof00, pCof01, nVars-1 ) + + Kit_TruthXorCount( pCof00, pCof10, nVars-1 ) + + Kit_TruthXorCount( pCof00, pCof11, nVars-1 ) + + Kit_TruthXorCount( pCof01, pCof10, nVars-1 ) + + Kit_TruthXorCount( pCof01, pCof11, nVars-1 ) + + Kit_TruthXorCount( pCof10, pCof11, nVars-1 ); + } + } + + printf( "\n" ); + printf( " V: " ); + for ( v = 0; v < nVars; v++ ) + printf( "%8c ", v+'a' ); + printf( "\n" ); + + printf( " M: " ); + for ( v = 0; v < nVars; v++ ) + printf( "%8d ", Mints[v] ); + printf( "\n" ); + + printf( " U: " ); + for ( v = 0; v < nVars; v++ ) + printf( "%8d ", Unique1[v] ); + printf( "\n" ); + printf( "\n" ); + + printf( "Unique:\n" ); + for ( i = 0; i < nVars; i++ ) + { + printf( " %2d ", i ); + for ( v = 0; v < nVars; v++ ) + printf( "%8d ", Unique2[i][v] ); + printf( "\n" ); + } + + printf( "Common:\n" ); + for ( i = 0; i < nVars; i++ ) + { + printf( " %2d ", i ); + for ( v = 0; v < nVars; v++ ) + printf( "%8d ", Common2[i][v] ); + printf( "\n" ); + } + + printf( "Total:\n" ); + for ( i = 0; i < nVars; i++ ) + { + printf( " %2d ", i ); + for ( v = 0; v < nVars; v++ ) + printf( "%8d ", Total2[i][v] ); + printf( "\n" ); + } + + ABC_FREE( pIn ); + ABC_FREE( pOut ); + ABC_FREE( pCof00 ); + ABC_FREE( pCof01 ); + ABC_FREE( pCof10 ); + ABC_FREE( pCof11 ); + ABC_FREE( pBytes ); +} + +/**Function************************************************************* + + Synopsis [Dumps truth table into a file.] + + Description [Generates script file for reading into ABC.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_TruthPrintProfile( unsigned * pTruth, int nVars ) +{ + unsigned uTruth[2]; + if ( nVars >= 6 ) + { + Kit_TruthPrintProfile_int( pTruth, nVars ); + return; + } + assert( nVars >= 2 ); + uTruth[0] = pTruth[0]; + uTruth[1] = pTruth[0]; + Kit_TruthPrintProfile( uTruth, 6 ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bool/kit/kit_.c b/src/bool/kit/kit_.c new file mode 100644 index 00000000..37be0b49 --- /dev/null +++ b/src/bool/kit/kit_.c @@ -0,0 +1,53 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bool/kit/module.make b/src/bool/kit/module.make new file mode 100644 index 00000000..ac29f1f7 --- /dev/null +++ b/src/bool/kit/module.make @@ -0,0 +1,11 @@ +SRC += src/bool/kit/kitAig.c \ + src/bool/kit/kitBdd.c \ + src/bool/kit/kitCloud.c src/bool/kit/cloud.c \ + src/bool/kit/kitDsd.c \ + src/bool/kit/kitFactor.c \ + src/bool/kit/kitGraph.c \ + src/bool/kit/kitHop.c \ + src/bool/kit/kitIsop.c \ + src/bool/kit/kitPla.c \ + src/bool/kit/kitSop.c \ + src/bool/kit/kitTruth.c diff --git a/src/generic.h b/src/generic.h index 923cddd3..92fd554b 100644 --- a/src/generic.h +++ b/src/generic.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __zzz_H__ -#define __zzz_H__ +#ifndef ABC__generic_h +#define ABC__generic_h //////////////////////////////////////////////////////////////////////// diff --git a/src/map/amap/amap.h b/src/map/amap/amap.h index de7fcc18..0a0c7cc0 100644 --- a/src/map/amap/amap.h +++ b/src/map/amap/amap.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __AMAP_H__ -#define __AMAP_H__ +#ifndef ABC__map__amap__amap_h +#define ABC__map__amap__amap_h //////////////////////////////////////////////////////////////////////// diff --git a/src/map/amap/amapCore.c b/src/map/amap/amapCore.c index 4f2d2310..ce1f61bd 100644 --- a/src/map/amap/amapCore.c +++ b/src/map/amap/amapCore.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "amapInt.h" -#include "main.h" +#include "src/base/main/main.h" ABC_NAMESPACE_IMPL_START diff --git a/src/map/amap/amapGraph.c b/src/map/amap/amapGraph.c index bc0878d1..c346ca98 100644 --- a/src/map/amap/amapGraph.c +++ b/src/map/amap/amapGraph.c @@ -141,9 +141,9 @@ Amap_Obj_t * Amap_ManCreateAnd( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pObj->Type = AMAP_OBJ_AND; pObj->Fan[0] = Amap_ObjToLit(pFan0); Amap_Regular(pFan0)->nRefs++; pObj->Fan[1] = Amap_ObjToLit(pFan1); Amap_Regular(pFan1)->nRefs++; - assert( Amap_Lit2Var(pObj->Fan[0]) != Amap_Lit2Var(pObj->Fan[1]) ); + assert( Abc_Lit2Var(pObj->Fan[0]) != Abc_Lit2Var(pObj->Fan[1]) ); pObj->fPhase = Amap_ObjPhaseReal(pFan0) & Amap_ObjPhaseReal(pFan1); - pObj->Level = 1 + ABC_MAX( Amap_Regular(pFan0)->Level, Amap_Regular(pFan1)->Level ); + pObj->Level = 1 + Abc_MaxInt( Amap_Regular(pFan0)->Level, Amap_Regular(pFan1)->Level ); if ( p->nLevelMax < (int)pObj->Level ) p->nLevelMax = (int)pObj->Level; assert( p->nLevelMax < 4094 ); // 2^12-2 @@ -170,7 +170,7 @@ Amap_Obj_t * Amap_ManCreateXor( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pObj->Fan[0] = Amap_ObjToLit(pFan0); Amap_Regular(pFan0)->nRefs++; pObj->Fan[1] = Amap_ObjToLit(pFan1); Amap_Regular(pFan1)->nRefs++; pObj->fPhase = Amap_ObjPhaseReal(pFan0) ^ Amap_ObjPhaseReal(pFan1); - pObj->Level = 2 + ABC_MAX( Amap_Regular(pFan0)->Level, Amap_Regular(pFan1)->Level ); + pObj->Level = 2 + Abc_MaxInt( Amap_Regular(pFan0)->Level, Amap_Regular(pFan1)->Level ); if ( p->nLevelMax < (int)pObj->Level ) p->nLevelMax = (int)pObj->Level; assert( p->nLevelMax < 4094 ); // 2^12-2 @@ -199,8 +199,8 @@ Amap_Obj_t * Amap_ManCreateMux( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pObj->Fan[2] = Amap_ObjToLit(pFanC); Amap_Regular(pFanC)->nRefs++; pObj->fPhase = (Amap_ObjPhaseReal(pFan1) & Amap_ObjPhaseReal(pFanC)) | (Amap_ObjPhaseReal(pFan0) & ~Amap_ObjPhaseReal(pFanC)); - pObj->Level = ABC_MAX( Amap_Regular(pFan0)->Level, Amap_Regular(pFan1)->Level ); - pObj->Level = 2 + ABC_MAX( pObj->Level, Amap_Regular(pFanC)->Level ); + pObj->Level = Abc_MaxInt( Amap_Regular(pFan0)->Level, Amap_Regular(pFan1)->Level ); + pObj->Level = 2 + Abc_MaxInt( pObj->Level, Amap_Regular(pFanC)->Level ); if ( p->nLevelMax < (int)pObj->Level ) p->nLevelMax = (int)pObj->Level; assert( p->nLevelMax < 4094 ); // 2^12-2 @@ -228,7 +228,7 @@ void Amap_ManCreateChoice( Amap_Man_t * p, Amap_Obj_t * pObj ) // update the level of this node (needed for correct required time computation) for ( pTemp = pObj; pTemp; pTemp = Amap_ObjChoice(p, pTemp) ) { - pObj->Level = ABC_MAX( pObj->Level, pTemp->Level ); + pObj->Level = Abc_MaxInt( pObj->Level, pTemp->Level ); // pTemp->nVisits++; pTemp->nVisitsCopy++; } // mark the largest level diff --git a/src/map/amap/amapInt.h b/src/map/amap/amapInt.h index 92e77e10..86e3e18f 100644 --- a/src/map/amap/amapInt.h +++ b/src/map/amap/amapInt.h @@ -18,15 +18,15 @@ ***********************************************************************/ -#ifndef __AMAP_INT_H__ -#define __AMAP_INT_H__ +#ifndef ABC__map__amap__amapInt_h +#define ABC__map__amap__amapInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// -#include "aig.h" +#include "src/aig/aig/aig.h" #include "amap.h" //////////////////////////////////////////////////////////////////////// @@ -216,13 +216,6 @@ struct Amap_Obj_t_ Amap_Mat_t Best; // the best match of the node }; -static inline int Amap_Var2Lit( int Var, int fCompl ) { return Var + Var + fCompl; } -static inline int Amap_Lit2Var( int Lit ) { return Lit >> 1; } -static inline int Amap_LitIsCompl( int Lit ) { return Lit & 1; } -static inline int Amap_LitNot( int Lit ) { return Lit ^ 1; } -static inline int Amap_LitNotCond( int Lit, int c ) { return Lit ^ (int)(c > 0); } -static inline int Amap_LitRegular( int Lit ) { return Lit & ~01; } - static inline Amap_Obj_t * Amap_Regular( Amap_Obj_t * p ) { return (Amap_Obj_t *)((ABC_PTRUINT_T)(p) & ~01); } static inline Amap_Obj_t * Amap_Not( Amap_Obj_t * p ) { return (Amap_Obj_t *)((ABC_PTRUINT_T)(p) ^ 01); } static inline Amap_Obj_t * Amap_NotCond( Amap_Obj_t * p, int c ) { return (Amap_Obj_t *)((ABC_PTRUINT_T)(p) ^ (c)); } @@ -249,13 +242,13 @@ static inline int Amap_ObjIsXor( Amap_Obj_t * pObj ) static inline int Amap_ObjIsMux( Amap_Obj_t * pObj ) { return pObj->Type == AMAP_OBJ_MUX; } static inline int Amap_ObjIsNode( Amap_Obj_t * pObj ) { return pObj->Type == AMAP_OBJ_AND || pObj->Type == AMAP_OBJ_XOR || pObj->Type == AMAP_OBJ_MUX; } -static inline int Amap_ObjToLit( Amap_Obj_t * pObj ) { return Amap_Var2Lit( Amap_Regular(pObj)->Id, Amap_IsComplement(pObj) ); } -static inline Amap_Obj_t * Amap_ObjFanin0( Amap_Man_t * p, Amap_Obj_t * pObj ) { return Amap_ManObj(p, Amap_Lit2Var(pObj->Fan[0])); } -static inline Amap_Obj_t * Amap_ObjFanin1( Amap_Man_t * p, Amap_Obj_t * pObj ) { return Amap_ManObj(p, Amap_Lit2Var(pObj->Fan[1])); } -static inline Amap_Obj_t * Amap_ObjFanin2( Amap_Man_t * p, Amap_Obj_t * pObj ) { return Amap_ManObj(p, Amap_Lit2Var(pObj->Fan[2])); } -static inline int Amap_ObjFaninC0( Amap_Obj_t * pObj ) { return Amap_LitIsCompl(pObj->Fan[0]); } -static inline int Amap_ObjFaninC1( Amap_Obj_t * pObj ) { return Amap_LitIsCompl(pObj->Fan[1]); } -static inline int Amap_ObjFaninC2( Amap_Obj_t * pObj ) { return Amap_LitIsCompl(pObj->Fan[2]); } +static inline int Amap_ObjToLit( Amap_Obj_t * pObj ) { return Abc_Var2Lit( Amap_Regular(pObj)->Id, Amap_IsComplement(pObj) ); } +static inline Amap_Obj_t * Amap_ObjFanin0( Amap_Man_t * p, Amap_Obj_t * pObj ) { return Amap_ManObj(p, Abc_Lit2Var(pObj->Fan[0])); } +static inline Amap_Obj_t * Amap_ObjFanin1( Amap_Man_t * p, Amap_Obj_t * pObj ) { return Amap_ManObj(p, Abc_Lit2Var(pObj->Fan[1])); } +static inline Amap_Obj_t * Amap_ObjFanin2( Amap_Man_t * p, Amap_Obj_t * pObj ) { return Amap_ManObj(p, Abc_Lit2Var(pObj->Fan[2])); } +static inline int Amap_ObjFaninC0( Amap_Obj_t * pObj ) { return Abc_LitIsCompl(pObj->Fan[0]); } +static inline int Amap_ObjFaninC1( Amap_Obj_t * pObj ) { return Abc_LitIsCompl(pObj->Fan[1]); } +static inline int Amap_ObjFaninC2( Amap_Obj_t * pObj ) { return Abc_LitIsCompl(pObj->Fan[2]); } static inline void * Amap_ObjCopy( Amap_Obj_t * pObj ) { return pObj->pData; } static inline int Amap_ObjLevel( Amap_Obj_t * pObj ) { return pObj->Level; } static inline void Amap_ObjSetLevel( Amap_Obj_t * pObj, int Level ) { pObj->Level = Level; } @@ -313,14 +306,14 @@ extern void Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars ); // iterates through each fanin of the match #define Amap_MatchForEachFaninCompl( p, pM, pFanin, fCompl, i ) \ for ( i = 0; i < (int)(pM)->pCut->nFans && \ - ((pFanin = Amap_ManObj((p), Amap_Lit2Var((pM)->pCut->Fans[Amap_Lit2Var((pM)->pSet->Ins[i])]))), 1) && \ - ((fCompl = Amap_LitIsCompl((pM)->pSet->Ins[i]) ^ Amap_LitIsCompl((pM)->pCut->Fans[Amap_Lit2Var((pM)->pSet->Ins[i])])), 1); \ + ((pFanin = Amap_ManObj((p), Abc_Lit2Var((pM)->pCut->Fans[Abc_Lit2Var((pM)->pSet->Ins[i])]))), 1) && \ + ((fCompl = Abc_LitIsCompl((pM)->pSet->Ins[i]) ^ Abc_LitIsCompl((pM)->pCut->Fans[Abc_Lit2Var((pM)->pSet->Ins[i])])), 1); \ i++ ) // iterates through each fanin of the match #define Amap_MatchForEachFanin( p, pM, pFanin, i ) \ for ( i = 0; i < (int)(pM)->pCut->nFans && \ - ((pFanin = Amap_ManObj((p), Amap_Lit2Var((pM)->pCut->Fans[Amap_Lit2Var((pM)->pSet->Ins[i])]))), 1); \ + ((pFanin = Amap_ManObj((p), Abc_Lit2Var((pM)->pCut->Fans[Abc_Lit2Var((pM)->pSet->Ins[i])]))), 1); \ i++ ) //////////////////////////////////////////////////////////////////////// diff --git a/src/map/amap/amapLib.c b/src/map/amap/amapLib.c index 74017dde..bbf76a64 100644 --- a/src/map/amap/amapLib.c +++ b/src/map/amap/amapLib.c @@ -277,7 +277,7 @@ Vec_Ptr_t * Amap_LibSelectGates( Amap_Lib_t * p, int fVerbose ) continue; if ( pGate2->nPins != pGate->nPins ) continue; - if ( !memcmp( pGate2->pFunc, pGate->pFunc, sizeof(unsigned) * Aig_TruthWordNum(pGate->nPins) ) ) + if ( !memcmp( pGate2->pFunc, pGate->pFunc, sizeof(unsigned) * Abc_TruthWordNum(pGate->nPins) ) ) break; } if ( k < i ) diff --git a/src/map/amap/amapLiberty.c b/src/map/amap/amapLiberty.c index 8006d61d..9a213d2a 100644 --- a/src/map/amap/amapLiberty.c +++ b/src/map/amap/amapLiberty.c @@ -843,7 +843,7 @@ Amap_Tree_t * Amap_LibertyStart( char * pFileName ) fclose( pFile ); p->pContents[p->nContents] = 0; // other - p->pFileName = Aig_UtilStrsav( pFileName ); + p->pFileName = Abc_UtilStrsav( pFileName ); p->nItermAlloc = 10 + Amap_LibertyCountItems( p->pContents, p->pContents+p->nContents ); p->pItems = ABC_CALLOC( Amap_Item_t, p->nItermAlloc ); p->nItems = 0; diff --git a/src/map/amap/amapMatch.c b/src/map/amap/amapMatch.c index ca513e61..40409e0d 100644 --- a/src/map/amap/amapMatch.c +++ b/src/map/amap/amapMatch.c @@ -105,7 +105,7 @@ float Amap_ManMaxDelay( Amap_Man_t * p ) float Delay = 0.0; int i; Amap_ManForEachPo( p, pObj, i ) - Delay = ABC_MAX( Delay, Amap_ObjFanin0(p,pObj)->Best.Delay ); + Delay = Abc_MaxInt( Delay, Amap_ObjFanin0(p,pObj)->Best.Delay ); return Delay; } @@ -157,9 +157,9 @@ float Amap_ManComputeMapping_rec( Amap_Man_t * p, Amap_Obj_t * pObj, int fCompl Area = pGate->dArea; for ( i = 0; i < (int)pGate->nPins; i++ ) { - iFanin = Amap_Lit2Var( pM->pSet->Ins[i] ); - pFanin = Amap_ManObj( p, Amap_Lit2Var(pM->pCut->Fans[iFanin]) ); - fComplFanin = Amap_LitIsCompl( pM->pSet->Ins[i] ) ^ Amap_LitIsCompl( pM->pCut->Fans[iFanin] ); + iFanin = Abc_Lit2Var( pM->pSet->Ins[i] ); + pFanin = Amap_ManObj( p, Abc_Lit2Var(pM->pCut->Fans[iFanin]) ); + fComplFanin = Abc_LitIsCompl( pM->pSet->Ins[i] ) ^ Abc_LitIsCompl( pM->pCut->Fans[iFanin] ); Area += Amap_ManComputeMapping_rec( p, pFanin, fComplFanin ); } return Area; @@ -376,7 +376,7 @@ static inline void Amap_ManMatchGetFlows( Amap_Man_t * p, Amap_Mat_t * pM ) Amap_MatchForEachFanin( p, pM, pFanin, i ) { pMFanin = &pFanin->Best; - pM->Delay = ABC_MAX( pM->Delay, pMFanin->Delay ); + pM->Delay = Abc_MaxInt( pM->Delay, pMFanin->Delay ); pM->AveFan += Amap_ObjRefsTotal(pFanin); if ( Amap_ObjRefsTotal(pFanin) == 0 ) pM->Area += pMFanin->Area; @@ -412,7 +412,7 @@ static inline void Amap_ManMatchGetExacts( Amap_Man_t * p, Amap_Obj_t * pNode, A Amap_MatchForEachFanin( p, pM, pFanin, i ) { pMFanin = &pFanin->Best; - pM->Delay = ABC_MAX( pM->Delay, pMFanin->Delay ); + pM->Delay = Abc_MaxInt( pM->Delay, pMFanin->Delay ); pM->AveFan += Amap_ObjRefsTotal(pFanin); } pM->AveFan /= pGate->nPins; diff --git a/src/map/amap/amapMerge.c b/src/map/amap/amapMerge.c index ecf11b07..c52642e3 100644 --- a/src/map/amap/amapMerge.c +++ b/src/map/amap/amapMerge.c @@ -54,7 +54,7 @@ Amap_Cut_t * Amap_ManSetupPis( Amap_Man_t * p ) pCut->iMat = 0; pCut->fInv = 0; pCut->nFans = 1; - pCut->Fans[0] = Amap_Var2Lit( pObj->Id, 0 ); + pCut->Fans[0] = Abc_Var2Lit( pObj->Id, 0 ); pObj->pData = pCut; pObj->nCuts = 1; pObj->EstRefs = (float)1.0; @@ -83,7 +83,7 @@ Amap_Cut_t * Amap_ManCutStore( Amap_Man_t * p, Amap_Cut_t * pCut, int fCompl ) pNew->nFans = pCut->nFans; memcpy( pNew->Fans, pCut->Fans, sizeof(int) * pCut->nFans ); // add it to storage - iFan = Amap_Var2Lit( pNew->iMat, pNew->fInv ); + iFan = Abc_Var2Lit( pNew->iMat, pNew->fInv ); if ( p->ppCutsTemp[ iFan ] == NULL ) Vec_IntPushOrder( p->vTemp, iFan ); *Amap_ManCutNextP( pNew ) = p->ppCutsTemp[ iFan ]; @@ -198,7 +198,7 @@ void Amap_ManCutSaveStored( Amap_Man_t * p, Amap_Obj_t * pNode ) pNext->iMat = 0; pNext->fInv = 0; pNext->nFans = 1; - pNext->Fans[0] = Amap_Var2Lit(pNode->Id, 0); + pNext->Fans[0] = Abc_Var2Lit(pNode->Id, 0); pNext = (Amap_Cut_t *)(pBuffer + 2); // add other cuts nCuts2 = 1; @@ -224,7 +224,7 @@ void Amap_ManCutSaveStored( Amap_Man_t * p, Amap_Obj_t * pNode ) if ( p->ppCutsTemp[i] != NULL ) printf( "Amap_ManCutSaveStored(): Error!\n" ); pNode->pData = (Amap_Cut_t *)pBuffer; - pNode->nCuts = ABC_MIN( nCuts, nMaxCuts-1 ); + pNode->nCuts = Abc_MinInt( nCuts, nMaxCuts-1 ); assert( nCuts < (1<<20) ); // printf("%d ", nCuts ); // verify cuts @@ -263,8 +263,8 @@ int Amap_ManMergeCountCuts( Amap_Man_t * p, Amap_Obj_t * pNode ) { iCompl0 = pCut0->fInv ^ Amap_ObjFaninC0(pNode); iCompl1 = pCut1->fInv ^ Amap_ObjFaninC1(pNode); - iFan0 = !pCut0->iMat? 0: Amap_Var2Lit( pCut0->iMat, iCompl0 ); - iFan1 = !pCut1->iMat? 0: Amap_Var2Lit( pCut1->iMat, iCompl1 ); + iFan0 = !pCut0->iMat? 0: Abc_Var2Lit( pCut0->iMat, iCompl0 ); + iFan1 = !pCut1->iMat? 0: Abc_Var2Lit( pCut1->iMat, iCompl1 ); Entry = Amap_LibFindNode( p->pLib, iFan0, iFan1, pNode->Type == AMAP_OBJ_XOR ); Counter += ( Entry >=0 ); // if ( Entry >=0 ) @@ -300,7 +300,7 @@ void Amap_ManPrintCuts( Amap_Obj_t * pNode ) { printf( "%3d : Mat= %3d Inv=%d ", c, pCut->iMat, pCut->fInv ); for ( i = 0; i < (int)pCut->nFans; i++ ) - printf( "%d%c ", Amap_Lit2Var(pCut->Fans[i]), Amap_LitIsCompl(pCut->Fans[i])?'-':'+' ); + printf( "%d%c ", Abc_Lit2Var(pCut->Fans[i]), Abc_LitIsCompl(pCut->Fans[i])?'-':'+' ); printf( "\n" ); } } @@ -356,7 +356,7 @@ int Amap_ManFindCut( Amap_Obj_t * pNode, Amap_Obj_t * pFanin, int fComplFanin, i Amap_NodeForEachCut( pFanin, pCut, c ) { iCompl = pCut->fInv ^ fComplFanin; - iFan = !pCut->iMat? 0: Amap_Var2Lit( pCut->iMat, iCompl ); + iFan = !pCut->iMat? 0: Abc_Var2Lit( pCut->iMat, iCompl ); if ( iFan == Val ) Vec_PtrPush( vCuts, pCut ); } @@ -406,20 +406,20 @@ void Amap_ManMergeNodeCutsMux( Amap_Man_t * p, Amap_Obj_t * pNode ) continue; // complement literals if ( pCut0->nFans == 1 && (pCut0->fInv ^ fComplFanin0) ) - pCut0->Fans[0] = Amap_LitNot(pCut0->Fans[0]); + pCut0->Fans[0] = Abc_LitNot(pCut0->Fans[0]); if ( pCut1->nFans == 1 && (pCut1->fInv ^ fComplFanin1) ) - pCut1->Fans[0] = Amap_LitNot(pCut1->Fans[0]); + pCut1->Fans[0] = Abc_LitNot(pCut1->Fans[0]); if ( pCut2->nFans == 1 && (pCut2->fInv ^ fComplFanin2) ) - pCut2->Fans[0] = Amap_LitNot(pCut2->Fans[0]); + pCut2->Fans[0] = Abc_LitNot(pCut2->Fans[0]); // create new cut Amap_ManCutCreate3( p, pCut0, pCut1, pCut2, Vec_IntEntry(vRules, x+3) ); // uncomplement literals if ( pCut0->nFans == 1 && (pCut0->fInv ^ fComplFanin0) ) - pCut0->Fans[0] = Amap_LitNot(pCut0->Fans[0]); + pCut0->Fans[0] = Abc_LitNot(pCut0->Fans[0]); if ( pCut1->nFans == 1 && (pCut1->fInv ^ fComplFanin1) ) - pCut1->Fans[0] = Amap_LitNot(pCut1->Fans[0]); + pCut1->Fans[0] = Abc_LitNot(pCut1->Fans[0]); if ( pCut2->nFans == 1 && (pCut2->fInv ^ fComplFanin2) ) - pCut2->Fans[0] = Amap_LitNot(pCut2->Fans[0]); + pCut2->Fans[0] = Abc_LitNot(pCut2->Fans[0]); } } Amap_ManCutSaveStored( p, pNode ); @@ -457,10 +457,10 @@ void Amap_ManMergeNodeCuts( Amap_Man_t * p, Amap_Obj_t * pNode ) Amap_NodeForEachCut( pFanin0, pCut0, c ) { iCompl0 = pCut0->fInv ^ Amap_ObjFaninC0(pNode); - iFan0 = !pCut0->iMat? 0: Amap_Var2Lit( pCut0->iMat, iCompl0 ); + iFan0 = !pCut0->iMat? 0: Abc_Var2Lit( pCut0->iMat, iCompl0 ); // complement literals if ( pCut0->nFans == 1 && iCompl0 ) - pCut0->Fans[0] = Amap_LitNot(pCut0->Fans[0]); + pCut0->Fans[0] = Abc_LitNot(pCut0->Fans[0]); // label resulting sets for ( i = 0; (Entry = pRules[iFan0][i]); i++ ) p->pMatsTemp[Entry & 0xffff] = (Entry >> 16); @@ -468,12 +468,12 @@ void Amap_ManMergeNodeCuts( Amap_Man_t * p, Amap_Obj_t * pNode ) Amap_NodeForEachCut( pFanin1, pCut1, k ) { iCompl1 = pCut1->fInv ^ Amap_ObjFaninC1(pNode); - iFan1 = !pCut1->iMat? 0: Amap_Var2Lit( pCut1->iMat, iCompl1 ); + iFan1 = !pCut1->iMat? 0: Abc_Var2Lit( pCut1->iMat, iCompl1 ); if ( p->pMatsTemp[iFan1] == 0 ) continue; // complement literals if ( pCut1->nFans == 1 && iCompl1 ) - pCut1->Fans[0] = Amap_LitNot(pCut1->Fans[0]); + pCut1->Fans[0] = Abc_LitNot(pCut1->Fans[0]); // create new cut if ( iFan0 >= iFan1 ) Amap_ManCutCreate( p, pCut0, pCut1, p->pMatsTemp[iFan1] ); @@ -481,11 +481,11 @@ void Amap_ManMergeNodeCuts( Amap_Man_t * p, Amap_Obj_t * pNode ) Amap_ManCutCreate( p, pCut1, pCut0, p->pMatsTemp[iFan1] ); // uncomplement literals if ( pCut1->nFans == 1 && iCompl1 ) - pCut1->Fans[0] = Amap_LitNot(pCut1->Fans[0]); + pCut1->Fans[0] = Abc_LitNot(pCut1->Fans[0]); } // uncomplement literals if ( pCut0->nFans == 1 && iCompl0 ) - pCut0->Fans[0] = Amap_LitNot(pCut0->Fans[0]); + pCut0->Fans[0] = Abc_LitNot(pCut0->Fans[0]); // label resulting sets for ( i = 0; (Entry = pRules[iFan0][i]); i++ ) p->pMatsTemp[Entry & 0xffff] = 0; diff --git a/src/map/amap/amapParse.c b/src/map/amap/amapParse.c index 49c1eb66..6fa469a9 100644 --- a/src/map/amap/amapParse.c +++ b/src/map/amap/amapParse.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "amapInt.h" -#include "hop.h" -#include "kit.h" +#include "src/aig/hop/hop.h" +#include "src/bool/kit/kit.h" ABC_NAMESPACE_IMPL_START @@ -437,8 +437,8 @@ int Amap_LibParseEquations( Amap_Lib_t * p, int fVerbose ) printf( "Skipping gate \"%s\" because its output \"%s\" does not depend on all input variables.\n", pGate->pName, pGate->pForm ); continue; } - pGate->pFunc = (unsigned *)Aig_MmFlexEntryFetch( p->pMemGates, sizeof(unsigned)*Aig_TruthWordNum(pGate->nPins) ); - memcpy( pGate->pFunc, pTruth, sizeof(unsigned)*Aig_TruthWordNum(pGate->nPins) ); + pGate->pFunc = (unsigned *)Aig_MmFlexEntryFetch( p->pMemGates, sizeof(unsigned)*Abc_TruthWordNum(pGate->nPins) ); + memcpy( pGate->pFunc, pTruth, sizeof(unsigned)*Abc_TruthWordNum(pGate->nPins) ); } Vec_PtrFree( vNames ); Vec_IntFree( vTruth ); diff --git a/src/map/amap/amapPerm.c b/src/map/amap/amapPerm.c index 71d4749a..0177a66c 100644 --- a/src/map/amap/amapPerm.c +++ b/src/map/amap/amapPerm.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "amapInt.h" -#include "kit.h" +#include "src/bool/kit/kit.h" ABC_NAMESPACE_IMPL_START @@ -51,13 +51,13 @@ void Amap_LibCollectFanins_rec( Amap_Lib_t * pLib, Amap_Nod_t * pNod, Vec_Int_t Vec_IntPush( vFanins, 0 ); return; } - pFan0 = Amap_LibNod( pLib, Amap_Lit2Var(pNod->iFan0) ); - if ( Amap_LitIsCompl(pNod->iFan0) || pFan0->Type != pNod->Type ) + pFan0 = Amap_LibNod( pLib, Abc_Lit2Var(pNod->iFan0) ); + if ( Abc_LitIsCompl(pNod->iFan0) || pFan0->Type != pNod->Type ) Vec_IntPush( vFanins, pNod->iFan0 ); else Amap_LibCollectFanins_rec( pLib, pFan0, vFanins ); - pFan1 = Amap_LibNod( pLib, Amap_Lit2Var(pNod->iFan1) ); - if ( Amap_LitIsCompl(pNod->iFan1) || pFan1->Type != pNod->Type ) + pFan1 = Amap_LibNod( pLib, Abc_Lit2Var(pNod->iFan1) ); + if ( Abc_LitIsCompl(pNod->iFan1) || pFan1->Type != pNod->Type ) Vec_IntPush( vFanins, pNod->iFan1 ); else Amap_LibCollectFanins_rec( pLib, pFan1, vFanins ); @@ -98,8 +98,8 @@ Vec_Int_t * Amap_LibDeriveGatePerm_rec( Amap_Lib_t * pLib, Kit_DsdNtk_t * pNtk, Kit_DsdObj_t * pDsdObj, * pDsdFanin; Amap_Nod_t * pNodFanin; int iDsdFanin, iNodFanin, Value, iDsdLit, i, k, j; - assert( !Kit_DsdLitIsCompl(iLit) ); - pDsdObj = Kit_DsdNtkObj( pNtk, Kit_DsdLit2Var(iLit) ); + assert( !Abc_LitIsCompl(iLit) ); + pDsdObj = Kit_DsdNtkObj( pNtk, Abc_Lit2Var(iLit) ); if ( pDsdObj == NULL ) { vPerm = Vec_IntAlloc( 1 ); @@ -110,22 +110,22 @@ Vec_Int_t * Amap_LibDeriveGatePerm_rec( Amap_Lib_t * pLib, Kit_DsdNtk_t * pNtk, { vPerm = Vec_IntAlloc( 10 ); - iDsdFanin = Kit_DsdLitRegular(pDsdObj->pFans[0]); - pNodFanin = Amap_LibNod( pLib, Amap_Lit2Var(pNod->iFan0) ); + iDsdFanin = Abc_LitRegular(pDsdObj->pFans[0]); + pNodFanin = Amap_LibNod( pLib, Abc_Lit2Var(pNod->iFan0) ); vPermFanin = Amap_LibDeriveGatePerm_rec( pLib, pNtk, iDsdFanin, pNodFanin ); Vec_IntForEachEntry( vPermFanin, Value, k ) Vec_IntPush( vPerm, Value ); Vec_IntFree( vPermFanin ); - iDsdFanin = Kit_DsdLitRegular(pDsdObj->pFans[1]); - pNodFanin = Amap_LibNod( pLib, Amap_Lit2Var(pNod->iFan1) ); + iDsdFanin = Abc_LitRegular(pDsdObj->pFans[1]); + pNodFanin = Amap_LibNod( pLib, Abc_Lit2Var(pNod->iFan1) ); vPermFanin = Amap_LibDeriveGatePerm_rec( pLib, pNtk, iDsdFanin, pNodFanin ); Vec_IntForEachEntry( vPermFanin, Value, k ) Vec_IntPush( vPerm, Value ); Vec_IntFree( vPermFanin ); - iDsdFanin = Kit_DsdLitRegular(pDsdObj->pFans[2]); - pNodFanin = Amap_LibNod( pLib, Amap_Lit2Var(pNod->iFan2) ); + iDsdFanin = Abc_LitRegular(pDsdObj->pFans[2]); + pNodFanin = Amap_LibNod( pLib, Abc_Lit2Var(pNod->iFan2) ); vPermFanin = Amap_LibDeriveGatePerm_rec( pLib, pNtk, iDsdFanin, pNodFanin ); Vec_IntForEachEntry( vPermFanin, Value, k ) Vec_IntPush( vPerm, Value ); @@ -149,7 +149,7 @@ Vec_Int_t * Amap_LibDeriveGatePerm_rec( Amap_Lib_t * pLib, Kit_DsdNtk_t * pNtk, vDsdLits = Vec_IntAlloc( 10 ); Kit_DsdObjForEachFaninReverse( pNtk, pDsdObj, iDsdFanin, i ) { - pDsdFanin = Kit_DsdNtkObj( pNtk, Kit_DsdLit2Var(iDsdFanin) ); + pDsdFanin = Kit_DsdNtkObj( pNtk, Abc_Lit2Var(iDsdFanin) ); if ( pDsdFanin ) pDsdFanin->fMark = 0; else @@ -166,10 +166,10 @@ Vec_Int_t * Amap_LibDeriveGatePerm_rec( Amap_Lib_t * pLib, Kit_DsdNtk_t * pNtk, continue; } // find a matching component - pNodFanin = Amap_LibNod( pLib, Amap_Lit2Var(iNodFanin) ); + pNodFanin = Amap_LibNod( pLib, Abc_Lit2Var(iNodFanin) ); Kit_DsdObjForEachFaninReverse( pNtk, pDsdObj, iDsdFanin, i ) { - pDsdFanin = Kit_DsdNtkObj( pNtk, Kit_DsdLit2Var(iDsdFanin) ); + pDsdFanin = Kit_DsdNtkObj( pNtk, Abc_Lit2Var(iDsdFanin) ); if ( pDsdFanin == NULL ) continue; if ( pDsdFanin->fMark == 1 ) @@ -178,7 +178,7 @@ Vec_Int_t * Amap_LibDeriveGatePerm_rec( Amap_Lib_t * pLib, Kit_DsdNtk_t * pNtk, (pDsdFanin->Type == KIT_DSD_XOR && pNodFanin->Type == AMAP_OBJ_XOR) || (pDsdFanin->Type == KIT_DSD_PRIME && pNodFanin->Type == AMAP_OBJ_MUX)) ) continue; - vPermFanin = Amap_LibDeriveGatePerm_rec( pLib, pNtk, Kit_DsdLitRegular(iDsdFanin), pNodFanin ); + vPermFanin = Amap_LibDeriveGatePerm_rec( pLib, pNtk, Abc_LitRegular(iDsdFanin), pNodFanin ); if ( vPermFanin == NULL ) continue; pDsdFanin->fMark = 1; @@ -214,24 +214,24 @@ unsigned * Amap_LibVerifyPerm_rec( Amap_Lib_t * pLib, Amap_Nod_t * pNod, assert( pNod->Type != AMAP_OBJ_MUX ); if ( pNod->Id == 0 ) return (unsigned *)Vec_PtrEntry( vTtElems, (*piInput)++ ); - pFan0 = Amap_LibNod( pLib, Amap_Lit2Var(pNod->iFan0) ); + pFan0 = Amap_LibNod( pLib, Abc_Lit2Var(pNod->iFan0) ); pTruth0 = Amap_LibVerifyPerm_rec( pLib, pFan0, vTtElems, vTruth, nWords, piInput ); - pFan1 = Amap_LibNod( pLib, Amap_Lit2Var(pNod->iFan1) ); + pFan1 = Amap_LibNod( pLib, Abc_Lit2Var(pNod->iFan1) ); pTruth1 = Amap_LibVerifyPerm_rec( pLib, pFan1, vTtElems, vTruth, nWords, piInput ); pTruth = Vec_IntFetch( vTruth, nWords ); if ( pNod->Type == AMAP_OBJ_XOR ) for ( i = 0; i < nWords; i++ ) pTruth[i] = pTruth0[i] ^ pTruth1[i]; - else if ( !Amap_LitIsCompl(pNod->iFan0) && !Amap_LitIsCompl(pNod->iFan1) ) + else if ( !Abc_LitIsCompl(pNod->iFan0) && !Abc_LitIsCompl(pNod->iFan1) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = pTruth0[i] & pTruth1[i]; - else if ( !Amap_LitIsCompl(pNod->iFan0) && Amap_LitIsCompl(pNod->iFan1) ) + else if ( !Abc_LitIsCompl(pNod->iFan0) && Abc_LitIsCompl(pNod->iFan1) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = pTruth0[i] & ~pTruth1[i]; - else if ( Amap_LitIsCompl(pNod->iFan0) && !Amap_LitIsCompl(pNod->iFan1) ) + else if ( Abc_LitIsCompl(pNod->iFan0) && !Abc_LitIsCompl(pNod->iFan1) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = ~pTruth0[i] & pTruth1[i]; - else // if ( Amap_LitIsCompl(pNod->iFan0) && Hop_ObjFaninC1(pObj) ) + else // if ( Abc_LitIsCompl(pNod->iFan0) && Hop_ObjFaninC1(pObj) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = ~pTruth0[i] & ~pTruth1[i]; return pTruth; @@ -265,8 +265,8 @@ void Amap_LibVerifyPerm( Amap_Lib_t * pLib, Amap_Gat_t * pGate, Kit_DsdNtk_t * p vTtElemsPol = Vec_PtrAlloc( pGate->nPins ); for ( i = 0; i < (int)pGate->nPins; i++ ) { - pTruth = (unsigned *)Vec_PtrEntry( vTtElems, Amap_Lit2Var(pArray[i]) ); - if ( Amap_LitIsCompl( pArray[i] ) ) + pTruth = (unsigned *)Vec_PtrEntry( vTtElems, Abc_Lit2Var(pArray[i]) ); + if ( Abc_LitIsCompl( pArray[i] ) ) Kit_TruthNot( pTruth, pTruth, pGate->nPins ); Vec_PtrPush( vTtElemsPol, pTruth ); } @@ -275,7 +275,7 @@ void Amap_LibVerifyPerm( Amap_Lib_t * pLib, Amap_Gat_t * pGate, Kit_DsdNtk_t * p // compute the truth table recursively pTruth = Amap_LibVerifyPerm_rec( pLib, pNod, vTtElemsPol, vTruth, nWords, &iInput ); assert( iInput == (int)pGate->nPins ); - if ( Kit_DsdLitIsCompl(pNtk->Root) ) + if ( Abc_LitIsCompl(pNtk->Root) ) Kit_TruthNot( pTruth, pTruth, pGate->nPins ); //Extra_PrintBinary( stdout, pTruth, 4 ); printf("\n" ); //Extra_PrintBinary( stdout, pGate->pFunc, 4 ); printf("\n" ); @@ -304,14 +304,14 @@ int Amap_LibDeriveGatePerm( Amap_Lib_t * pLib, Amap_Gat_t * pGate, Kit_DsdNtk_t int fVerbose = 0; Vec_Int_t * vPerm; int Entry, Entry2, i, k; - vPerm = Amap_LibDeriveGatePerm_rec( pLib, pNtk, Kit_DsdLitRegular(pNtk->Root), pNod ); + vPerm = Amap_LibDeriveGatePerm_rec( pLib, pNtk, Abc_LitRegular(pNtk->Root), pNod ); if ( vPerm == NULL ) return 0; // check that the permutation is valid assert( Vec_IntSize(vPerm) == (int)pNod->nSuppSize ); Vec_IntForEachEntry( vPerm, Entry, i ) Vec_IntForEachEntryStart( vPerm, Entry2, k, i+1 ) - if ( Amap_Lit2Var(Entry) == Amap_Lit2Var(Entry2) ) + if ( Abc_Lit2Var(Entry) == Abc_Lit2Var(Entry2) ) { Vec_IntFree( vPerm ); return 0; @@ -321,9 +321,9 @@ int Amap_LibDeriveGatePerm( Amap_Lib_t * pLib, Amap_Gat_t * pGate, Kit_DsdNtk_t Vec_IntForEachEntry( vPerm, Entry, i ) { assert( Entry < 2 * (int)pNod->nSuppSize ); - pArray[Kit_DsdLit2Var(Entry)] = Amap_Var2Lit( i, Kit_DsdLitIsCompl(Entry) ); + pArray[Abc_Lit2Var(Entry)] = Abc_Var2Lit( i, Abc_LitIsCompl(Entry) ); // pArray[i] = Entry; -//printf( "%d=%d%c ", Kit_DsdLit2Var(Entry), i, Kit_DsdLitIsCompl(Entry)?'-':'+' ); +//printf( "%d=%d%c ", Abc_Lit2Var(Entry), i, Abc_LitIsCompl(Entry)?'-':'+' ); } //printf( "\n" ); // if ( Kit_DsdNonDsdSizeMax(pNtk) < 3 ) @@ -334,7 +334,7 @@ int Amap_LibDeriveGatePerm( Amap_Lib_t * pLib, Amap_Gat_t * pGate, Kit_DsdNtk_t { printf( "node %4d : ", pNod->Id ); for ( i = 0; i < (int)pNod->nSuppSize; i++ ) - printf( "%d=%d%c ", i, Amap_Lit2Var(pArray[i]), Amap_LitIsCompl(pArray[i])?'-':'+' ); + printf( "%d=%d%c ", i, Abc_Lit2Var(pArray[i]), Abc_LitIsCompl(pArray[i])?'-':'+' ); printf( "\n" ); } return 1; diff --git a/src/map/amap/amapRead.c b/src/map/amap/amapRead.c index 77292099..5776c3ff 100644 --- a/src/map/amap/amapRead.c +++ b/src/map/amap/amapRead.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "amapInt.h" -#include "ioAbc.h" +#include "src/base/io/ioAbc.h" ABC_NAMESPACE_IMPL_START diff --git a/src/map/amap/amapRule.c b/src/map/amap/amapRule.c index 8308a197..0f6c7708 100644 --- a/src/map/amap/amapRule.c +++ b/src/map/amap/amapRule.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "amapInt.h" -#include "kit.h" +#include "src/bool/kit/kit.h" ABC_NAMESPACE_IMPL_START @@ -59,7 +59,7 @@ Vec_Int_t * Amap_CreateRulesPrime( Amap_Lib_t * p, Vec_Int_t * vNods0, Vec_Int_t iNod = Amap_LibFindMux( p, iNod0, iNod1, iNod2 ); if ( iNod == -1 ) iNod = Amap_LibCreateMux( p, iNod0, iNod1, iNod2 ); - Vec_IntPush( vRes, Amap_Var2Lit(iNod, 0) ); + Vec_IntPush( vRes, Abc_Var2Lit(iNod, 0) ); } return vRes; } @@ -84,7 +84,7 @@ void Amap_CreateRulesTwo( Amap_Lib_t * p, Vec_Int_t * vNods, Vec_Int_t * vNods0, iNod = Amap_LibFindNode( p, iNod0, iNod1, fXor ); if ( iNod == -1 ) iNod = Amap_LibCreateNode( p, iNod0, iNod1, fXor ); - Vec_IntPushUnique( vNods, Amap_Var2Lit(iNod, 0) ); + Vec_IntPushUnique( vNods, Abc_Var2Lit(iNod, 0) ); } } @@ -196,20 +196,20 @@ Vec_Int_t * Amap_CreateRulesFromDsd_rec( Amap_Lib_t * pLib, Kit_DsdNtk_t * p, in Kit_DsdObj_t * pObj; unsigned i; int iFanin, iNod, k; - assert( !Kit_DsdLitIsCompl(iLit) ); - pObj = Kit_DsdNtkObj( p, Kit_DsdLit2Var(iLit) ); + assert( !Abc_LitIsCompl(iLit) ); + pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit) ); if ( pObj == NULL ) return Vec_IntStartNatural( 1 ); // solve for the inputs vVecNods = Vec_PtrAlloc( pObj->nFans ); Kit_DsdObjForEachFanin( p, pObj, iFanin, i ) { - vNodsFanin = Amap_CreateRulesFromDsd_rec( pLib, p, Kit_DsdLitRegular(iFanin) ); - if ( Kit_DsdLitIsCompl(iFanin) ) + vNodsFanin = Amap_CreateRulesFromDsd_rec( pLib, p, Abc_LitRegular(iFanin) ); + if ( Abc_LitIsCompl(iFanin) ) { Vec_IntForEachEntry( vNodsFanin, iNod, k ) if ( iNod > 0 ) - Vec_IntWriteEntry( vNodsFanin, k, Amap_LitNot(iNod) ); + Vec_IntWriteEntry( vNodsFanin, k, Abc_LitNot(iNod) ); } Vec_PtrPush( vVecNods, vNodsFanin ); } @@ -247,13 +247,13 @@ Vec_Int_t * Amap_CreateRulesFromDsd( Amap_Lib_t * pLib, Kit_DsdNtk_t * p ) Vec_Int_t * vNods; int iNod, i; assert( p->nVars >= 2 ); - vNods = Amap_CreateRulesFromDsd_rec( pLib, p, Kit_DsdLitRegular(p->Root) ); + vNods = Amap_CreateRulesFromDsd_rec( pLib, p, Abc_LitRegular(p->Root) ); if ( vNods == NULL ) return NULL; - if ( Kit_DsdLitIsCompl(p->Root) ) + if ( Abc_LitIsCompl(p->Root) ) { Vec_IntForEachEntry( vNods, iNod, i ) - Vec_IntWriteEntry( vNods, i, Amap_LitNot(iNod) ); + Vec_IntWriteEntry( vNods, i, Abc_LitNot(iNod) ); } return vNods; } @@ -298,12 +298,12 @@ Kit_DsdPrint( stdout, pNtk ); Vec_IntForEachEntry( vNods, iNod, i ) { assert( iNod > 1 ); - pNod = Amap_LibNod( pLib, Amap_Lit2Var(iNod) ); + pNod = Amap_LibNod( pLib, Abc_Lit2Var(iNod) ); // assert( pNod->Type == AMAP_OBJ_MUX || pNod->nSuppSize == pGate->nPins ); pSet = (Amap_Set_t *)Aig_MmFlexEntryFetch( pLib->pMemSet, sizeof(Amap_Set_t) ); memset( pSet, 0, sizeof(Amap_Set_t) ); pSet->iGate = pGate->Id; - pSet->fInv = Amap_LitIsCompl(iNod); + pSet->fInv = Abc_LitIsCompl(iNod); pSet->nIns = pGate->nPins; if ( Amap_LibDeriveGatePerm( pLib, pGate, pNtk, pNod, pSet->Ins ) == 0 ) { diff --git a/src/map/amap/amapUniq.c b/src/map/amap/amapUniq.c index a2375389..dd858c96 100644 --- a/src/map/amap/amapUniq.c +++ b/src/map/amap/amapUniq.c @@ -198,14 +198,14 @@ int Amap_LibCreateNode( Amap_Lib_t * p, int iFan0, int iFan1, int fXor ) } pNode = Amap_LibCreateObj( p ); pNode->Type = fXor? AMAP_OBJ_XOR : AMAP_OBJ_AND; - pNode->nSuppSize = p->pNodes[Amap_Lit2Var(iFan0)].nSuppSize + p->pNodes[Amap_Lit2Var(iFan1)].nSuppSize; + pNode->nSuppSize = p->pNodes[Abc_Lit2Var(iFan0)].nSuppSize + p->pNodes[Abc_Lit2Var(iFan1)].nSuppSize; pNode->iFan0 = iFan0; pNode->iFan1 = iFan1; if ( p->fVerbose ) printf( "Creating node %5d %c : iFan0 = %5d%c iFan1 = %5d%c\n", pNode->Id, (fXor?'x':' '), -Amap_Lit2Var(iFan0), (Amap_LitIsCompl(iFan0)?'-':'+'), -Amap_Lit2Var(iFan1), (Amap_LitIsCompl(iFan1)?'-':'+') ); +Abc_Lit2Var(iFan0), (Abc_LitIsCompl(iFan0)?'-':'+'), +Abc_Lit2Var(iFan1), (Abc_LitIsCompl(iFan1)?'-':'+') ); if ( fXor ) { @@ -246,16 +246,16 @@ int Amap_LibCreateMux( Amap_Lib_t * p, int iFan0, int iFan1, int iFan2 ) Amap_Nod_t * pNode; pNode = Amap_LibCreateObj( p ); pNode->Type = AMAP_OBJ_MUX; - pNode->nSuppSize = p->pNodes[Amap_Lit2Var(iFan0)].nSuppSize + p->pNodes[Amap_Lit2Var(iFan1)].nSuppSize + p->pNodes[Amap_Lit2Var(iFan2)].nSuppSize; + pNode->nSuppSize = p->pNodes[Abc_Lit2Var(iFan0)].nSuppSize + p->pNodes[Abc_Lit2Var(iFan1)].nSuppSize + p->pNodes[Abc_Lit2Var(iFan2)].nSuppSize; pNode->iFan0 = iFan0; pNode->iFan1 = iFan1; pNode->iFan2 = iFan2; if ( p->fVerbose ) printf( "Creating node %5d %c : iFan0 = %5d%c iFan1 = %5d%c iFan2 = %5d%c\n", pNode->Id, 'm', -Amap_Lit2Var(iFan0), (Amap_LitIsCompl(iFan0)?'-':'+'), -Amap_Lit2Var(iFan1), (Amap_LitIsCompl(iFan1)?'-':'+'), -Amap_Lit2Var(iFan2), (Amap_LitIsCompl(iFan2)?'-':'+') ); +Abc_Lit2Var(iFan0), (Abc_LitIsCompl(iFan0)?'-':'+'), +Abc_Lit2Var(iFan1), (Abc_LitIsCompl(iFan1)?'-':'+'), +Abc_Lit2Var(iFan2), (Abc_LitIsCompl(iFan2)?'-':'+') ); Vec_IntPush( p->vRules3, iFan0 ); Vec_IntPush( p->vRules3, iFan1 ); diff --git a/src/map/cov/cov.h b/src/map/cov/cov.h index 80ef1925..135fee8c 100644 --- a/src/map/cov/cov.h +++ b/src/map/cov/cov.h @@ -18,11 +18,10 @@ ***********************************************************************/ -#ifndef __COV_H__ -#define __COV_H__ +#ifndef ABC__map__cov__cov_h +#define ABC__map__cov__cov_h -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" #include "covInt.h" diff --git a/src/map/cov/covCore.c b/src/map/cov/covCore.c index a53f6b49..b128ed65 100644 --- a/src/map/cov/covCore.c +++ b/src/map/cov/covCore.c @@ -447,7 +447,7 @@ int Abc_NodeCovPropagate( Cov_Man_t * p, Abc_Obj_t * pObj ) // count statistics p->nSupps++; - p->nSuppsMax = ABC_MAX( p->nSuppsMax, p->nSupps ); + p->nSuppsMax = Abc_MaxInt( p->nSuppsMax, p->nSupps ); return 1; } @@ -732,7 +732,7 @@ int Abc_NodeCovPropagateEsop( Cov_Man_t * p, Abc_Obj_t * pObj, Abc_Obj_t * pObj0 // count statistics p->nSupps++; - p->nSuppsMax = ABC_MAX( p->nSuppsMax, p->nSupps ); + p->nSuppsMax = Abc_MaxInt( p->nSuppsMax, p->nSupps ); // set the covers assert( Abc_ObjGetSupp(pObj) == NULL ); @@ -835,7 +835,7 @@ int Abc_NodeCovPropagateSop( Cov_Man_t * p, Abc_Obj_t * pObj, Abc_Obj_t * pObj0, // count statistics p->nSupps++; - p->nSuppsMax = ABC_MAX( p->nSuppsMax, p->nSupps ); + p->nSuppsMax = Abc_MaxInt( p->nSuppsMax, p->nSupps ); // set the covers assert( Abc_ObjGetSupp(pObj) == NULL ); diff --git a/src/map/cov/covInt.h b/src/map/cov/covInt.h index 73c6bc20..5a75a8f3 100644 --- a/src/map/cov/covInt.h +++ b/src/map/cov/covInt.h @@ -18,11 +18,10 @@ ***********************************************************************/ -#ifndef __COV_INT_H__ -#define __COV_INT_H__ +#ifndef ABC__map__cov__covInt_h +#define ABC__map__cov__covInt_h -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" ABC_NAMESPACE_HEADER_START diff --git a/src/map/fpga/fpga.c b/src/map/fpga/fpga.c index 08adb52e..94a84ffd 100644 --- a/src/map/fpga/fpga.c +++ b/src/map/fpga/fpga.c @@ -17,7 +17,7 @@ ***********************************************************************/ #include "fpgaInt.h" -#include "main.h" +#include "src/base/main/main.h" ABC_NAMESPACE_IMPL_START diff --git a/src/map/fpga/fpga.h b/src/map/fpga/fpga.h index 082e6635..b63d2448 100644 --- a/src/map/fpga/fpga.h +++ b/src/map/fpga/fpga.h @@ -16,8 +16,8 @@ ***********************************************************************/ -#ifndef __FPGA_H__ -#define __FPGA_H__ +#ifndef ABC__map__fpga__fpga_h +#define ABC__map__fpga__fpga_h //////////////////////////////////////////////////////////////////////// diff --git a/src/map/fpga/fpgaCreate.c b/src/map/fpga/fpgaCreate.c index 168b69c6..64f6d750 100644 --- a/src/map/fpga/fpgaCreate.c +++ b/src/map/fpga/fpgaCreate.c @@ -17,7 +17,7 @@ ***********************************************************************/ #include "fpgaInt.h" -#include "main.h" +#include "src/base/main/main.h" ABC_NAMESPACE_IMPL_START @@ -346,7 +346,7 @@ Fpga_Node_t * Fpga_NodeCreate( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p void Fpga_TableCreate( Fpga_Man_t * pMan ) { assert( pMan->pBins == NULL ); - pMan->nBins = Cudd_Prime(50000); + pMan->nBins = Abc_PrimeCudd(50000); pMan->pBins = ABC_ALLOC( Fpga_Node_t *, pMan->nBins ); memset( pMan->pBins, 0, sizeof(Fpga_Node_t *) * pMan->nBins ); pMan->nNodes = 0; @@ -430,7 +430,7 @@ void Fpga_TableResize( Fpga_Man_t * pMan ) clk = clock(); // get the new table size - nBinsNew = Cudd_Prime(2 * pMan->nBins); + nBinsNew = Abc_PrimeCudd(2 * pMan->nBins); // allocate a new array pBinsNew = ABC_ALLOC( Fpga_Node_t *, nBinsNew ); memset( pBinsNew, 0, sizeof(Fpga_Node_t *) * nBinsNew ); diff --git a/src/map/fpga/fpgaCut.c b/src/map/fpga/fpgaCut.c index 5f46be18..2e9ea77e 100644 --- a/src/map/fpga/fpgaCut.c +++ b/src/map/fpga/fpgaCut.c @@ -918,7 +918,7 @@ Fpga_CutTable_t * Fpga_CutTableStart( Fpga_Man_t * pMan ) // allocate the table p = ABC_ALLOC( Fpga_CutTable_t, 1 ); memset( p, 0, sizeof(Fpga_CutTable_t) ); - p->nBins = Cudd_Prime( 10 * FPGA_CUTS_MAX_COMPUTE ); + p->nBins = Abc_PrimeCudd( 10 * FPGA_CUTS_MAX_COMPUTE ); p->pBins = ABC_ALLOC( Fpga_Cut_t *, p->nBins ); memset( p->pBins, 0, sizeof(Fpga_Cut_t *) * p->nBins ); p->pCuts = ABC_ALLOC( int, 2 * FPGA_CUTS_MAX_COMPUTE ); diff --git a/src/map/fpga/fpgaInt.h b/src/map/fpga/fpgaInt.h index 26de9b80..c9272154 100644 --- a/src/map/fpga/fpgaInt.h +++ b/src/map/fpga/fpgaInt.h @@ -16,8 +16,8 @@ ***********************************************************************/ -#ifndef __FPGA_INT_H__ -#define __FPGA_INT_H__ +#ifndef ABC__map__fpga__fpgaInt_h +#define ABC__map__fpga__fpgaInt_h //////////////////////////////////////////////////////////////////////// @@ -27,7 +27,7 @@ #include #include #include -#include "extra.h" +#include "src/misc/extra/extra.h" #include "fpga.h" ABC_NAMESPACE_HEADER_START @@ -378,9 +378,6 @@ extern int Fpga_MappingMaxLevel( Fpga_Man_t * pMan ); extern void Fpga_ManReportChoices( Fpga_Man_t * pMan ); extern void Fpga_MappingSetChoiceLevels( Fpga_Man_t * pMan ); -/*=== CUDD package.c ===============================================================*/ -extern unsigned int Cudd_Prime( unsigned int p ); - ABC_NAMESPACE_HEADER_END diff --git a/src/map/fpga/fpgaTruth.c b/src/map/fpga/fpgaTruth.c index d37ff81d..d41b1184 100644 --- a/src/map/fpga/fpgaTruth.c +++ b/src/map/fpga/fpgaTruth.c @@ -17,7 +17,7 @@ ***********************************************************************/ #include "fpgaInt.h" -#include "cudd.h" +#include "src/bdd/cudd/cudd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/map/if/if.h b/src/map/if/if.h index 9f04902b..09be93e0 100644 --- a/src/map/if/if.h +++ b/src/map/if/if.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __IF_H__ -#define __IF_H__ +#ifndef ABC__map__if__if_h +#define ABC__map__if__if_h //////////////////////////////////////////////////////////////////////// @@ -31,9 +31,9 @@ #include #include #include -#include "vec.h" -#include "mem.h" -#include "tim.h" +#include "src/misc/vec/vec.h" +#include "src/misc/mem/mem.h" +#include "src/misc/tim/tim.h" diff --git a/src/map/if/ifDec07.c b/src/map/if/ifDec07.c index 41949a2f..074ac6ef 100644 --- a/src/map/if/ifDec07.c +++ b/src/map/if/ifDec07.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "if.h" -#include "extra.h" -#include "kit.h" +#include "src/misc/extra/extra.h" +#include "src/bool/kit/kit.h" ABC_NAMESPACE_IMPL_START diff --git a/src/map/if/ifDec08.c b/src/map/if/ifDec08.c index 06081414..54eff63e 100644 --- a/src/map/if/ifDec08.c +++ b/src/map/if/ifDec08.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "if.h" -#include "extra.h" -#include "kit.h" +#include "src/misc/extra/extra.h" +#include "src/bool/kit/kit.h" ABC_NAMESPACE_IMPL_START diff --git a/src/map/if/ifDec10.c b/src/map/if/ifDec10.c index 9280e193..01aa32ae 100644 --- a/src/map/if/ifDec10.c +++ b/src/map/if/ifDec10.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "if.h" -#include "extra.h" -#include "kit.h" +#include "src/misc/extra/extra.h" +#include "src/bool/kit/kit.h" ABC_NAMESPACE_IMPL_START diff --git a/src/map/if/ifDec16.c b/src/map/if/ifDec16.c index 5972c2ea..c1e87aaa 100644 --- a/src/map/if/ifDec16.c +++ b/src/map/if/ifDec16.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "if.h" -#include "kit.h" +#include "src/bool/kit/kit.h" ABC_NAMESPACE_IMPL_START diff --git a/src/map/if/ifTime.c b/src/map/if/ifTime.c index b901a363..b5e2a3d0 100644 --- a/src/map/if/ifTime.c +++ b/src/map/if/ifTime.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "if.h" -#include "kit.h" +#include "src/bool/kit/kit.h" ABC_NAMESPACE_IMPL_START @@ -143,7 +143,7 @@ If_And_t If_CutDelaySopCube( Vec_Wrd_t * vCube, Vec_Wrd_t * vAnds, int fOrGate ) Next.fCompl1 = This.fCompl ^ fOrGate; Next.Id = Vec_WrdSize(vAnds); Next.fCompl = fOrGate; - Next.Delay = 1 + ABC_MAX( This.Delay, Prev.Delay ); + Next.Delay = 1 + Abc_MaxInt( This.Delay, Prev.Delay ); // add new If_AndInsertSorted( vCube, Next ); Vec_WrdPush( vAnds, If_AndToWrd(Next) ); @@ -313,7 +313,7 @@ int If_CutDelayLeafDepth_rec( Vec_Wrd_t * vAnds, If_And_t And, int iLeaf ) return -IF_BIG_CHAR; Depth0 = If_CutDelayLeafDepth_rec( vAnds, If_WrdToAnd(Vec_WrdEntry(vAnds, And.iFan0)), iLeaf ); Depth1 = If_CutDelayLeafDepth_rec( vAnds, If_WrdToAnd(Vec_WrdEntry(vAnds, And.iFan1)), iLeaf ); - Depth = ABC_MAX( Depth0, Depth1 ); + Depth = Abc_MaxInt( Depth0, Depth1 ); Depth = (Depth == -IF_BIG_CHAR) ? -IF_BIG_CHAR : Depth + 1; return Depth; } diff --git a/src/map/mapper/mapper.c b/src/map/mapper/mapper.c index f13a7641..87a0d4b8 100644 --- a/src/map/mapper/mapper.c +++ b/src/map/mapper/mapper.c @@ -16,9 +16,9 @@ ***********************************************************************/ -#include "abc.h" -#include "mainInt.h" -#include "mio.h" +#include "src/base/abc/abc.h" +#include "src/base/main/mainInt.h" +#include "src/map/mio/mio.h" #include "mapperInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/map/mapper/mapper.h b/src/map/mapper/mapper.h index aaad08ee..3fd5fd9e 100644 --- a/src/map/mapper/mapper.h +++ b/src/map/mapper/mapper.h @@ -16,8 +16,8 @@ ***********************************************************************/ -#ifndef __MAPPER_H__ -#define __MAPPER_H__ +#ifndef ABC__map__mapper__mapper_h +#define ABC__map__mapper__mapper_h //////////////////////////////////////////////////////////////////////// diff --git a/src/map/mapper/mapperCreate.c b/src/map/mapper/mapperCreate.c index af1a858f..73ccdb19 100644 --- a/src/map/mapper/mapperCreate.c +++ b/src/map/mapper/mapperCreate.c @@ -390,7 +390,7 @@ Map_Node_t * Map_NodeCreate( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 ) void Map_TableCreate( Map_Man_t * pMan ) { assert( pMan->pBins == NULL ); - pMan->nBins = Cudd_Prime(5000); + pMan->nBins = Abc_PrimeCudd(5000); pMan->pBins = ABC_ALLOC( Map_Node_t *, pMan->nBins ); memset( pMan->pBins, 0, sizeof(Map_Node_t *) * pMan->nBins ); pMan->nNodes = 0; @@ -474,7 +474,7 @@ void Map_TableResize( Map_Man_t * pMan ) clk = clock(); // get the new table size - nBinsNew = Cudd_Prime(2 * pMan->nBins); + nBinsNew = Abc_PrimeCudd(2 * pMan->nBins); // allocate a new array pBinsNew = ABC_ALLOC( Map_Node_t *, nBinsNew ); memset( pBinsNew, 0, sizeof(Map_Node_t *) * nBinsNew ); diff --git a/src/map/mapper/mapperCut.c b/src/map/mapper/mapperCut.c index e0afa792..29861531 100644 --- a/src/map/mapper/mapperCut.c +++ b/src/map/mapper/mapperCut.c @@ -814,7 +814,7 @@ Map_CutTable_t * Map_CutTableStart( Map_Man_t * pMan ) // allocate the table p = ABC_ALLOC( Map_CutTable_t, 1 ); memset( p, 0, sizeof(Map_CutTable_t) ); - p->nBins = Cudd_Prime( 10 * MAP_CUTS_MAX_COMPUTE ); + p->nBins = Abc_PrimeCudd( 10 * MAP_CUTS_MAX_COMPUTE ); p->pBins = ABC_ALLOC( Map_Cut_t *, p->nBins ); memset( p->pBins, 0, sizeof(Map_Cut_t *) * p->nBins ); p->pCuts = ABC_ALLOC( int, 2 * MAP_CUTS_MAX_COMPUTE ); diff --git a/src/map/mapper/mapperInt.h b/src/map/mapper/mapperInt.h index ac8110fc..08a27e68 100644 --- a/src/map/mapper/mapperInt.h +++ b/src/map/mapper/mapperInt.h @@ -16,8 +16,8 @@ ***********************************************************************/ -#ifndef __MAPPER_INT_H__ -#define __MAPPER_INT_H__ +#ifndef ABC__map__mapper__mapperInt_h +#define ABC__map__mapper__mapperInt_h //////////////////////////////////////////////////////////////////////// @@ -28,10 +28,10 @@ #include #include #include -#include "main.h" -#include "mio.h" +#include "src/base/main/main.h" +#include "src/map/mio/mio.h" #include "mapper.h" -#include "cuddInt.h" +#include "src/misc/extra/extraBdd.h" ABC_NAMESPACE_HEADER_START diff --git a/src/map/mapper/mapperTable.c b/src/map/mapper/mapperTable.c index 2120b5ce..7e12d8dc 100644 --- a/src/map/mapper/mapperTable.c +++ b/src/map/mapper/mapperTable.c @@ -53,7 +53,7 @@ Map_HashTable_t * Map_SuperTableCreate( Map_SuperLib_t * pLib ) memset( p, 0, sizeof(Map_HashTable_t) ); p->mmMan = pLib->mmEntries; // allocate and clean the bins - p->nBins = Cudd_Prime(20000); + p->nBins = Abc_PrimeCudd(20000); p->pBins = ABC_ALLOC( Map_HashEntry_t *, p->nBins ); memset( p->pBins, 0, sizeof(Map_HashEntry_t *) * p->nBins ); return p; @@ -237,7 +237,7 @@ void Map_SuperTableResize( Map_HashTable_t * p ) int nBinsNew, Counter, i; unsigned Key; // get the new table size - nBinsNew = Cudd_Prime(2 * p->nBins); + nBinsNew = Abc_PrimeCudd(2 * p->nBins); // allocate a new array pBinsNew = ABC_ALLOC( Map_HashEntry_t *, nBinsNew ); memset( pBinsNew, 0, sizeof(Map_HashEntry_t *) * nBinsNew ); diff --git a/src/map/mio/exp.h b/src/map/mio/exp.h index fa643325..40dff2e8 100644 --- a/src/map/mio/exp.h +++ b/src/map/mio/exp.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __EXP_H__ -#define __EXP_H__ +#ifndef ABC__map__mio__exp_h +#define ABC__map__mio__exp_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// diff --git a/src/map/mio/mio.c b/src/map/mio/mio.c index a034e549..f7eddab2 100644 --- a/src/map/mio/mio.c +++ b/src/map/mio/mio.c @@ -22,10 +22,10 @@ #include #endif -#include "main.h" +#include "src/base/main/main.h" #include "mio.h" -#include "mapper.h" -#include "amap.h" +#include "src/map/mapper/mapper.h" +#include "src/map/amap/amap.h" ABC_NAMESPACE_IMPL_START diff --git a/src/map/mio/mio.h b/src/map/mio/mio.h index de35b637..a31e2e2b 100644 --- a/src/map/mio/mio.h +++ b/src/map/mio/mio.h @@ -16,8 +16,8 @@ ***********************************************************************/ -#ifndef __MIO_H__ -#define __MIO_H__ +#ifndef ABC__map__mio__mio_h +#define ABC__map__mio__mio_h //////////////////////////////////////////////////////////////////////// diff --git a/src/map/mio/mioForm.c b/src/map/mio/mioForm.c index 5c7a48e6..b3b962c0 100644 --- a/src/map/mio/mioForm.c +++ b/src/map/mio/mioForm.c @@ -17,7 +17,7 @@ ***********************************************************************/ #include "mioInt.h" -#include "parse.h" +#include "bdd/parse/parse.h" ABC_NAMESPACE_IMPL_START diff --git a/src/map/mio/mioInt.h b/src/map/mio/mioInt.h index 0752e29a..02f081fa 100644 --- a/src/map/mio/mioInt.h +++ b/src/map/mio/mioInt.h @@ -16,8 +16,8 @@ ***********************************************************************/ -#ifndef __MIO_INT_H__ -#define __MIO_INT_H__ +#ifndef ABC__map__mio__mioInt_h +#define ABC__map__mio__mioInt_h //////////////////////////////////////////////////////////////////////// @@ -28,9 +28,9 @@ #include #include #include -#include "vec.h" -#include "mem.h" -#include "st.h" +#include "src/misc/vec/vec.h" +#include "src/misc/mem/mem.h" +#include "src/misc/st/st.h" #include "mio.h" ABC_NAMESPACE_HEADER_START diff --git a/src/map/mio/mioRead.c b/src/map/mio/mioRead.c index dd57d766..ccbc0ac6 100644 --- a/src/map/mio/mioRead.c +++ b/src/map/mio/mioRead.c @@ -18,7 +18,7 @@ #include #include "mioInt.h" -#include "ioAbc.h" +#include "src/base/io/ioAbc.h" ABC_NAMESPACE_IMPL_START diff --git a/src/map/mio/mioUtils.c b/src/map/mio/mioUtils.c index 09f1ec96..d9447085 100644 --- a/src/map/mio/mioUtils.c +++ b/src/map/mio/mioUtils.c @@ -17,7 +17,7 @@ ***********************************************************************/ #include "mioInt.h" -#include "main.h" +#include "src/base/main/main.h" #include "exp.h" ABC_NAMESPACE_IMPL_START diff --git a/src/map/super/super.c b/src/map/super/super.c index 2cc52a44..2cbf0718 100644 --- a/src/map/super/super.c +++ b/src/map/super/super.c @@ -17,8 +17,8 @@ ***********************************************************************/ #include "superInt.h" -#include "mainInt.h" -#include "mio.h" +#include "src/base/main/mainInt.h" +#include "src/map/mio/mio.h" ABC_NAMESPACE_IMPL_START diff --git a/src/map/super/super.h b/src/map/super/super.h index 246ea092..e2af9a85 100644 --- a/src/map/super/super.h +++ b/src/map/super/super.h @@ -16,8 +16,8 @@ ***********************************************************************/ -#ifndef __SUPER_H__ -#define __SUPER_H__ +#ifndef ABC__map__super__super_h +#define ABC__map__super__super_h //////////////////////////////////////////////////////////////////////// diff --git a/src/map/super/superInt.h b/src/map/super/superInt.h index 0d4215ff..63df0f38 100644 --- a/src/map/super/superInt.h +++ b/src/map/super/superInt.h @@ -16,19 +16,19 @@ ***********************************************************************/ -#ifndef __super_INT_H__ -#define __super_INT_H__ +#ifndef ABC__map__super__superInt_h +#define ABC__map__super__superInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// -#include "abc.h" -#include "mainInt.h" -#include "mvc.h" -#include "mio.h" -#include "stmm.h" +#include "src/base/abc/abc.h" +#include "src/base/main/mainInt.h" +#include "src/misc/mvc/mvc.h" +#include "src/map/mio/mio.h" +#include "src/misc/st/stmm.h" #include "super.h" ABC_NAMESPACE_HEADER_START diff --git a/src/misc/avl/avl.h b/src/misc/avl/avl.h index 50a06b69..141e4f56 100644 --- a/src/misc/avl/avl.h +++ b/src/misc/avl/avl.h @@ -7,8 +7,8 @@ * $Date: 1994/07/15 23:00:40 $ * */ -#ifndef AVL_INCLUDED -#define AVL_INCLUDED +#ifndef ABC__misc__avl__avl_h +#define ABC__misc__avl__avl_h ABC_NAMESPACE_HEADER_START diff --git a/src/misc/bar/bar.c b/src/misc/bar/bar.c new file mode 100644 index 00000000..565a969e --- /dev/null +++ b/src/misc/bar/bar.c @@ -0,0 +1,187 @@ +/**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 "src/misc/util/abc_global.h" +#include "src/base/main/main.h" +#include "bar.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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; + Abc_Frame_t * pFrame; + pFrame = Abc_FrameReadGlobalFrame(); + if ( pFrame == NULL ) + return NULL; + if ( !Abc_FrameShowProgress(pFrame) ) return NULL; + p = ABC_ALLOC( Bar_Progress_t, 1 ); + 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 ); + ABC_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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/misc/bar/bar.h b/src/misc/bar/bar.h new file mode 100644 index 00000000..c66e302e --- /dev/null +++ b/src/misc/bar/bar.h @@ -0,0 +1,78 @@ +/**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 ABC__aig__bar__bar_h +#define ABC__aig__bar__bar_h + + +#ifdef _WIN32 +#define inline __inline // compatible with MS VS 6.0 +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +#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); } + + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/misc/bar/module.make b/src/misc/bar/module.make new file mode 100644 index 00000000..7234e386 --- /dev/null +++ b/src/misc/bar/module.make @@ -0,0 +1 @@ +SRC += src/misc/bar/bar.c diff --git a/src/misc/bbl/bblif.c b/src/misc/bbl/bblif.c new file mode 100644 index 00000000..fc227760 --- /dev/null +++ b/src/misc/bbl/bblif.c @@ -0,0 +1,1518 @@ +/**CFile**************************************************************** + + FileName [bblif.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Binary BLIF representation for logic networks.] + + Synopsis [Main implementation module.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 28, 2009.] + + Revision [$Id: bblif.c,v 1.00 2009/02/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include +#include +#include +#include + +#include "src/misc/util/abc_global.h" +#include "bblif.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// vector of integers +typedef struct Vec_Int_t_ Vec_Int_t; +struct Vec_Int_t_ +{ + int nCap; + int nSize; + int * pArray; +}; + +// vector of characters +typedef struct Vec_Str_t_ Vec_Str_t; +struct Vec_Str_t_ +{ + int nCap; + int nSize; + char * pArray; +}; + +// network object +struct Bbl_Obj_t_ +{ + int Id; // user ID + int Fnc; // functionality + unsigned fCi : 1; // combinational input + unsigned fCo : 1; // combinational output + unsigned fBox : 1; // subcircuit + unsigned fMark : 1; // temporary mark + unsigned nFanins : 28; // fanin number + int pFanins[0]; // fanin array +}; + +// object function +typedef struct Bbl_Fnc_t_ Bbl_Fnc_t; +struct Bbl_Fnc_t_ +{ + int nWords; // word number + int pWords[0]; // word array +}; + +// object function +typedef struct Bbl_Ent_t_ Bbl_Ent_t; +struct Bbl_Ent_t_ +{ + int iFunc; // function handle + int iNext; // next entry handle +}; + +// data manager +struct Bbl_Man_t_ +{ + // data pool + Vec_Str_t * pName; // design name + Vec_Str_t * pObjs; // vector of objects + Vec_Str_t * pFncs; // vector of functions + // construction + Vec_Int_t * vId2Obj; // mapping user IDs into objects + Vec_Int_t * vObj2Id; // mapping objects into user IDs + Vec_Int_t * vFaninNums; // mapping user IDs into fanin number + // file contents + int nFileSize; // file size + char * pFileData; // file contents + // other data + Vec_Str_t * pEnts; // vector of entries + int SopMap[17][17]; // mapping vars x cubes into entry handles +}; + +static inline int Bbl_ObjIsCi( Bbl_Obj_t * pObj ) { return pObj->fCi; } +static inline int Bbl_ObjIsCo( Bbl_Obj_t * pObj ) { return pObj->fCo; } +static inline int Bbl_ObjIsNode( Bbl_Obj_t * pObj ) { return!pObj->fCi && !pObj->fCo; } + +static inline int Bbl_ObjFaninNum( Bbl_Obj_t * pObj ) { return pObj->nFanins; } +static inline Bbl_Obj_t * Bbl_ObjFanin( Bbl_Obj_t * pObj, int i ) { return (Bbl_Obj_t *)(((char *)pObj) - pObj->pFanins[i]); } + +static inline int Bbl_ObjSize( Bbl_Obj_t * pObj ) { return sizeof(Bbl_Obj_t) + sizeof(int) * pObj->nFanins; } +static inline int Bbl_FncSize( Bbl_Fnc_t * pFnc ) { return sizeof(Bbl_Fnc_t) + sizeof(int) * pFnc->nWords; } + +static inline Bbl_Obj_t * Bbl_VecObj( Vec_Str_t * p, int h ) { return (Bbl_Obj_t *)(p->pArray + h); } +static inline Bbl_Fnc_t * Bbl_VecFnc( Vec_Str_t * p, int h ) { return (Bbl_Fnc_t *)(p->pArray + h); } +static inline Bbl_Ent_t * Bbl_VecEnt( Vec_Str_t * p, int h ) { return (Bbl_Ent_t *)(p->pArray + h); } + +static inline char * Bbl_ManSop( Bbl_Man_t * p, int h ) { return (char *)Bbl_VecFnc(p->pFncs, h)->pWords; } +static inline Bbl_Obj_t * Bbl_ManObj( Bbl_Man_t * p, int Id ) { return Bbl_VecObj(p->pObjs, p->vId2Obj->pArray[Id]); } + +#define Bbl_ManForEachObj_int( p, pObj, h ) \ + for ( h = 0; (h < p->nSize) && (pObj = Bbl_VecObj(p,h)); h += Bbl_ObjSize(pObj) ) +#define Bbl_ManForEachFnc_int( p, pObj, h ) \ + for ( h = 0; (h < p->nSize) && (pObj = Bbl_VecFnc(p,h)); h += Bbl_FncSize(pObj) ) +#define Bbl_ObjForEachFanin_int( pObj, pFanin, i ) \ + for ( i = 0; (i < (int)pObj->nFanins) && (pFanin = Bbl_ObjFanin(pObj,i)); i++ ) + +#define BBLIF_ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) +#define BBLIF_CALLOC(type, num) ((type *) calloc((num), sizeof(type))) +#define BBLIF_FALLOC(type, num) ((type *) memset(malloc(sizeof(type) * (num)), 0xff, sizeof(type) * (num))) +#define BBLIF_FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) +#define BBLIF_REALLOC(type, obj, num) \ + ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ + ((type *) malloc(sizeof(type) * (num)))) + +//////////////////////////////////////////////////////////////////////// +/// 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 = BBLIF_ALLOC( Vec_Int_t, 1 ); + if ( nCap > 0 && nCap < 16 ) + nCap = 16; + p->nSize = 0; + p->nCap = nCap; + p->pArray = p->nCap? BBLIF_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 = BBLIF_ALLOC( Vec_Int_t, 1 ); + p->nSize = nSize; + p->nCap = nSize; + p->pArray = pArray; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_IntFree( Vec_Int_t * p ) +{ + BBLIF_FREE( p->pArray ); + BBLIF_FREE( p ); +} + +/**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 = BBLIF_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 Fill ) +{ + int i; + Vec_IntGrow( p, nSize ); + for ( i = 0; i < nSize; i++ ) + p->pArray[i] = Fill; + 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 Fill ) +{ + int i; + if ( p->nSize >= nSize ) + return; + if ( nSize > 2 * p->nCap ) + Vec_IntGrow( p, nSize ); + else if ( nSize > p->nCap ) + Vec_IntGrow( p, 2 * p->nCap ); + for ( i = p->nSize; i < nSize; i++ ) + p->pArray[i] = Fill; + p->nSize = nSize; +} + +/**Function************************************************************* + + Synopsis [Returns the entry even if the place not exist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_IntGetEntry( Vec_Int_t * p, int i ) +{ + Vec_IntFillExtra( p, i + 1, 0 ); + return Vec_IntEntry( p, i ); +} + +/**Function************************************************************* + + Synopsis [Inserts the entry even if the place does not exist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_IntSetEntry( Vec_Int_t * p, int i, int Entry ) +{ + Vec_IntFillExtra( p, i + 1, 0 ); + Vec_IntWriteEntry( p, i, Entry ); +} + +/**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 [Allocates a vector with the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Str_t * Vec_StrAlloc( int nCap ) +{ + Vec_Str_t * p; + p = BBLIF_ALLOC( Vec_Str_t, 1 ); + if ( nCap > 0 && nCap < 16 ) + nCap = 16; + p->nSize = 0; + p->nCap = nCap; + p->pArray = p->nCap? BBLIF_ALLOC( char, p->nCap ) : NULL; + return p; +} + +/**Function************************************************************* + + Synopsis [Creates the vector from an array of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Str_t * Vec_StrAllocArray( char * pArray, int nSize ) +{ + Vec_Str_t * p; + p = BBLIF_ALLOC( Vec_Str_t, 1 ); + p->nSize = nSize; + p->nCap = nSize; + p->pArray = pArray; + return p; +} + +/**Fnction************************************************************* + + Synopsis [Returns a piece of memory.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Vec_StrFetch( Vec_Str_t * p, int nBytes ) +{ + while ( p->nSize + nBytes > p->nCap ) + { + p->pArray = BBLIF_REALLOC( char, p->pArray, 3 * p->nCap ); + p->nCap *= 3; + } + p->nSize += nBytes; + return p->pArray + p->nSize - nBytes; +} + +/**Fnction************************************************************* + + Synopsis [Write vector into file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Vec_StrWrite( FILE * pFile, Vec_Str_t * p ) +{ + fwrite( &p->nSize, sizeof(int), 1, pFile ); + fwrite( p->pArray, sizeof(char), p->nSize, pFile ); +} + +/**Fnction************************************************************* + + Synopsis [Write vector into file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Str_t * Vec_StrRead( char ** ppStr ) +{ + Vec_Str_t * p; + char * pStr = *ppStr; + p = Vec_StrAlloc( 0 ); + p->nSize = *(int *)pStr; + p->pArray = pStr + sizeof(int); + *ppStr = pStr + sizeof(int) + p->nSize * sizeof(char); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_StrSize( Vec_Str_t * p ) +{ + return p->nSize; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_StrFree( Vec_Str_t * p ) +{ + BBLIF_FREE( p->pArray ); + BBLIF_FREE( p ); +} + + + + + +/**Fnction************************************************************* + + Synopsis [Returns the file size.] + + Description [The file should be closed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bbl_ManFileSize( char * pFileName ) +{ + FILE * pFile; + int nFileSize; + pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + { + printf( "Bbl_ManFileSize(): The file is unavailable (absent or open).\n" ); + return 0; + } + fseek( pFile, 0, SEEK_END ); + nFileSize = ftell( pFile ); + fclose( pFile ); + return nFileSize; +} + +/**Fnction************************************************************* + + Synopsis [Read data from file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Bbl_ManFileRead( char * pFileName ) +{ + FILE * pFile; + char * pContents; + int nFileSize; + nFileSize = Bbl_ManFileSize( pFileName ); + pFile = fopen( pFileName, "rb" ); + pContents = BBLIF_ALLOC( char, nFileSize ); + fread( pContents, nFileSize, 1, pFile ); + fclose( pFile ); + return pContents; +} + + + +/**Fnction************************************************************* + + Synopsis [Writes data into file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbl_ManDumpBinaryBlif( Bbl_Man_t * p, char * pFileName ) +{ + FILE * pFile; + pFile = fopen( pFileName, "wb" ); + Vec_StrWrite( pFile, p->pName ); + Vec_StrWrite( pFile, p->pObjs ); + Vec_StrWrite( pFile, p->pFncs ); + fclose( pFile ); +} + +/**Fnction************************************************************* + + Synopsis [Creates manager after reading.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bbl_Man_t * Bbl_ManReadBinaryBlif( char * pFileName ) +{ + Bbl_Man_t * p; + Bbl_Obj_t * pObj; + char * pBuffer; + int h; + p = BBLIF_ALLOC( Bbl_Man_t, 1 ); + memset( p, 0, sizeof(Bbl_Man_t) ); + p->nFileSize = Bbl_ManFileSize( pFileName ); + p->pFileData = Bbl_ManFileRead( pFileName ); + // extract three managers + pBuffer = p->pFileData; + p->pName = Vec_StrRead( &pBuffer ); + p->pObjs = Vec_StrRead( &pBuffer ); + p->pFncs = Vec_StrRead( &pBuffer ); + assert( pBuffer - p->pFileData == p->nFileSize ); + // remember original IDs in the objects + p->vObj2Id = Vec_IntAlloc( 1000 ); + Bbl_ManForEachObj_int( p->pObjs, pObj, h ) + { + Vec_IntPush( p->vObj2Id, pObj->Id ); + pObj->Id = Vec_IntSize(p->vObj2Id) - 1; + } + return p; +} + +/**Fnction************************************************************* + + Synopsis [Prints stats of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbl_ManPrintStats( Bbl_Man_t * p ) +{ + Bbl_Obj_t * pObj; + Bbl_Fnc_t * pFnc; + int h, nFuncs = 0, nNodes = 0, nObjs = 0; + Bbl_ManForEachObj_int( p->pObjs, pObj, h ) + nObjs++, nNodes += Bbl_ObjIsNode(pObj); + Bbl_ManForEachFnc_int( p->pFncs, pFnc, h ) + nFuncs++; + printf( "Total objects = %7d. Total nodes = %7d. Unique functions = %7d.\n", nObjs, nNodes, nFuncs ); + printf( "Name manager = %5.2f Mb\n", 1.0*Vec_StrSize(p->pName)/(1 << 20) ); + printf( "Objs manager = %5.2f Mb\n", 1.0*Vec_StrSize(p->pObjs)/(1 << 20) ); + printf( "Fncs manager = %5.2f Mb\n", 1.0*Vec_StrSize(p->pFncs)/(1 << 20) ); +} + +/**Fnction************************************************************* + + Synopsis [Deletes the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbl_ManStop( Bbl_Man_t * p ) +{ + if ( p->vId2Obj ) Vec_IntFree( p->vId2Obj ); + if ( p->vObj2Id ) Vec_IntFree( p->vObj2Id ); + if ( p->vFaninNums ) Vec_IntFree( p->vFaninNums ); + if ( p->pFileData ) + { + BBLIF_FREE( p->pFileData ); + p->pName->pArray = NULL; + p->pObjs->pArray = NULL; + p->pFncs->pArray = NULL; + } + if ( p->pEnts ) + Vec_StrFree( p->pEnts ); + Vec_StrFree( p->pName ); + Vec_StrFree( p->pObjs ); + Vec_StrFree( p->pFncs ); + BBLIF_FREE( p ); +} + +/**Fnction************************************************************* + + Synopsis [Creates manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bbl_Man_t * Bbl_ManStart( char * pName ) +{ + Bbl_Man_t * p; + int nLength; + p = BBLIF_ALLOC( Bbl_Man_t, 1 ); + memset( p, 0, sizeof(Bbl_Man_t) ); + nLength = pName? 4 * ((strlen(pName) + 1) / 4 + 1) : 0; + p->pName = Vec_StrAlloc( nLength ); + p->pName->nSize = p->pName->nCap; + if ( pName ) + strcpy( p->pName->pArray, pName ); + p->pObjs = Vec_StrAlloc( 1 << 16 ); + p->pFncs = Vec_StrAlloc( 1 << 16 ); + p->pEnts = Vec_StrAlloc( 1 << 16 ); p->pEnts->nSize = 1; + p->vId2Obj = Vec_IntStart( 1 << 10 ); + p->vFaninNums = Vec_IntStart( 1 << 10 ); + return p; +} + + + + +/**Function************************************************************* + + Synopsis [Performs selection sort on the array of cubes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbl_ManSortCubes( char ** pCubes, int nCubes, int nVars ) +{ + char * pTemp; + int i, j, best_i; + for ( i = 0; i < nCubes-1; i++ ) + { + best_i = i; + for (j = i+1; j < nCubes; j++) + if ( memcmp( pCubes[j], pCubes[best_i], nVars ) < 0 ) + best_i = j; + pTemp = pCubes[i]; pCubes[i] = pCubes[best_i]; pCubes[best_i] = pTemp; + } +} + +/**Function************************************************************* + + Synopsis [Sorts the cubes in the SOP to uniqify them to some extent.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Bbl_ManSortSop( char * pSop, int nVars ) +{ + char ** pCubes, * pSopNew; + int c, Length, nCubes; + Length = strlen(pSop); + assert( Length % (nVars + 3) == 0 ); + nCubes = Length / (nVars + 3); + if ( nCubes < 2 ) + { + pSopNew = BBLIF_ALLOC( char, Length + 1 ); + memcpy( pSopNew, pSop, Length + 1 ); + return pSopNew; + } + pCubes = BBLIF_ALLOC( char *, nCubes ); + for ( c = 0; c < nCubes; c++ ) + pCubes[c] = pSop + c * (nVars + 3); + if ( nCubes < 300 ) + Bbl_ManSortCubes( pCubes, nCubes, nVars ); + pSopNew = BBLIF_ALLOC( char, Length + 1 ); + for ( c = 0; c < nCubes; c++ ) + memcpy( pSopNew + c * (nVars + 3), pCubes[c], nVars + 3 ); + BBLIF_FREE( pCubes ); + pSopNew[nCubes * (nVars + 3)] = 0; + return pSopNew; +} + +/**Fnction************************************************************* + + Synopsis [Saves one entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bbl_ManCreateEntry( Bbl_Man_t * p, int iFunc, int iNext ) +{ + Bbl_Ent_t * pEnt; + pEnt = (Bbl_Ent_t *)Vec_StrFetch( p->pEnts, 2 * sizeof(int) ); + pEnt->iFunc = iFunc; + pEnt->iNext = iNext; + return (char *)pEnt - p->pEnts->pArray; +} + +/**Function************************************************************* + + Synopsis [Sorts the cubes in the SOP to uniqify them to some extent.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bbl_ManSopCheckUnique( Bbl_Man_t * p, char * pSop, int nVars, int nCubes, int iFunc ) +{ + Bbl_Fnc_t * pFnc; + Bbl_Ent_t * pEnt; + int h, Length = strlen(pSop) + 1; + int nWords = (Length / 4 + (Length % 4 > 0)); + if ( nVars > 16 ) nVars = 16; + if ( nCubes > 16 ) nCubes = 16; +// if ( nVars == 16 && nCubes == 16 ) +// return iFunc; + for ( h = p->SopMap[nVars][nCubes]; h; h = pEnt->iNext ) + { + pEnt = Bbl_VecEnt( p->pEnts, h ); + pFnc = Bbl_VecFnc( p->pFncs, pEnt->iFunc ); + assert( nVars == 16 || nCubes == 16 || pFnc->nWords == nWords ); + if ( pFnc->nWords == nWords && memcmp( pFnc->pWords, pSop, Length ) == 0 ) + return pEnt->iFunc; + } + p->SopMap[nVars][nCubes] = Bbl_ManCreateEntry( p, iFunc, p->SopMap[nVars][nCubes] ); + return iFunc; +} + +/**Fnction************************************************************* + + Synopsis [Saves one SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bbl_ManSaveSop( Bbl_Man_t * p, char * pSop, int nVars ) +{ + Bbl_Fnc_t * pFnc; + char * pSopNew; + int iFunc, Length = strlen(pSop) + 1; + int nWords = Length / 4 + (Length % 4 > 0); + // reorder cubes to semi-canicize SOPs + pSopNew = Bbl_ManSortSop( pSop, nVars ); + // get the candidate location + iFunc = Bbl_ManSopCheckUnique( p, pSopNew, nVars, Length / (nVars + 3), Vec_StrSize(p->pFncs) ); +// iFunc = Vec_StrSize(p->pFncs); + if ( iFunc == Vec_StrSize(p->pFncs) ) + { // store this SOP + pFnc = (Bbl_Fnc_t *)Vec_StrFetch( p->pFncs, sizeof(Bbl_Fnc_t) + nWords * sizeof(int) ); + pFnc->pWords[nWords-1] = 0; + pFnc->nWords = nWords; + strcpy( (char *)pFnc->pWords, pSopNew ); + assert( iFunc == (char *)pFnc - p->pFncs->pArray ); + } + BBLIF_FREE( pSopNew ); + return iFunc; +} + +/**Fnction************************************************************* + + Synopsis [Adds one object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbl_ManCreateObject( Bbl_Man_t * p, Bbl_Type_t Type, int ObjId, int nFanins, char * pSop ) +{ + Bbl_Obj_t * pObj; + if ( Type == BBL_OBJ_CI && nFanins != 0 ) + { + printf( "Attempting to create a combinational input with %d fanins (should be 0).\n", nFanins ); + return; + } + if ( Type == BBL_OBJ_CO && nFanins != 1 ) + { + printf( "Attempting to create a combinational output with %d fanins (should be 1).\n", nFanins ); + return; + } + pObj = (Bbl_Obj_t *)Vec_StrFetch( p->pObjs, sizeof(Bbl_Obj_t) + nFanins * sizeof(int) ); + memset( pObj, 0, sizeof(Bbl_Obj_t) ); + Vec_IntSetEntry( p->vId2Obj, ObjId, (char *)pObj - p->pObjs->pArray ); + Vec_IntSetEntry( p->vFaninNums, ObjId, 0 ); + pObj->fCi = (Type == BBL_OBJ_CI); + pObj->fCo = (Type == BBL_OBJ_CO); + pObj->Id = ObjId; + pObj->Fnc = pSop? Bbl_ManSaveSop(p, pSop, nFanins) : -1; + pObj->nFanins = nFanins; +} + +/**Fnction************************************************************* + + Synopsis [Creates fanin/fanout relationship between two objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbl_ManAddFanin( Bbl_Man_t * p, int ObjId, int FaninId ) +{ + Bbl_Obj_t * pObj, * pFanin; + int iFanin; + pObj = Bbl_ManObj( p, ObjId ); + if ( Bbl_ObjIsCi(pObj) ) + { + printf( "Bbl_ManAddFanin(): Cannot add fanin of the combinational input (Id = %d).\n", ObjId ); + return; + } + pFanin = Bbl_ManObj( p, FaninId ); + if ( Bbl_ObjIsCo(pFanin) ) + { + printf( "Bbl_ManAddFanin(): Cannot add fanout of the combinational output (Id = %d).\n", FaninId ); + return; + } + iFanin = Vec_IntEntry( p->vFaninNums, ObjId ); + if ( iFanin >= (int)pObj->nFanins ) + { + printf( "Bbl_ManAddFanin(): Trying to add more fanins to object (Id = %d) than declared (%d).\n", ObjId, pObj->nFanins ); + return; + } + assert( iFanin < (int)pObj->nFanins ); + Vec_IntWriteEntry( p->vFaninNums, ObjId, iFanin+1 ); + pObj->pFanins[iFanin] = (char *)pObj - (char *)pFanin; +} + + +/**Fnction************************************************************* + + Synopsis [Returns 1 if the manager was created correctly.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bbl_ManCheck( Bbl_Man_t * p ) +{ + Bbl_Obj_t * pObj; + int h, RetValue = 1; + Bbl_ManForEachObj_int( p->pObjs, pObj, h ) + { + if ( Bbl_ObjIsNode(pObj) && pObj->Fnc == -1 ) + RetValue = 0, printf( "Bbl_ManCheck(): Node %d does not have function specified.\n", pObj->Id ); + if ( Bbl_ObjIsCi(pObj) && pObj->Fnc != -1 ) + RetValue = 0, printf( "Bbl_ManCheck(): CI with %d has function specified.\n", pObj->Id ); + if ( Bbl_ObjIsCo(pObj) && pObj->Fnc != -1 ) + RetValue = 0, printf( "Bbl_ManCheck(): CO with %d has function specified.\n", pObj->Id ); + if ( Vec_IntEntry(p->vFaninNums, pObj->Id) != (int)pObj->nFanins ) + RetValue = 0, printf( "Bbl_ManCheck(): Object %d has less fanins (%d) than declared (%d).\n", + pObj->Id, Vec_IntEntry(p->vFaninNums, pObj->Id), pObj->nFanins ); + } + return RetValue; +} + + +/**Fnction************************************************************* + + Synopsis [Misc APIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bbl_ObjIsInput( Bbl_Obj_t * p ) { return Bbl_ObjIsCi(p); } +int Bbl_ObjIsOutput( Bbl_Obj_t * p ) { return Bbl_ObjIsCo(p); } +int Bbl_ObjIsLut( Bbl_Obj_t * p ) { return Bbl_ObjIsNode(p); } +int Bbl_ObjId( Bbl_Obj_t * p ) { return p->Id; } +int Bbl_ObjIdOriginal( Bbl_Man_t * pMan, Bbl_Obj_t * p ) { assert(0); return Vec_IntEntry(pMan->vObj2Id, p->Id); } +int Bbl_ObjFaninNumber( Bbl_Obj_t * p ) { return Bbl_ObjFaninNum(p); } +char * Bbl_ObjSop( Bbl_Man_t * pMan, Bbl_Obj_t * p ) { return Bbl_ManSop(pMan, p->Fnc); } +int Bbl_ObjIsMarked( Bbl_Obj_t * p ) { return p->fMark; } +void Bbl_ObjMark( Bbl_Obj_t * p ) { p->fMark = 1; } +int Bbl_ObjFncHandle( Bbl_Obj_t * p ) { return p->Fnc; } + +/**Fnction************************************************************* + + Synopsis [Returns the name of the design.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Bbl_ManName( Bbl_Man_t * p ) +{ + return p->pName->pArray; +} + +/**Fnction************************************************************* + + Synopsis [Returns the maximum handle of the SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bbl_ManFncSize( Bbl_Man_t * p ) +{ + return p->pFncs->nSize; +} + +/**Fnction************************************************************* + + Synopsis [Returns the first object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bbl_Obj_t * Bbl_ManObjFirst( Bbl_Man_t * p ) +{ + return Bbl_VecObj( p->pObjs, 0 ); +} + +/**Fnction************************************************************* + + Synopsis [Returns the next object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bbl_Obj_t * Bbl_ManObjNext( Bbl_Man_t * p, Bbl_Obj_t * pObj ) +{ + char * pNext = (char *)pObj + Bbl_ObjSize(pObj); + char * pEdge = p->pObjs->pArray + p->pObjs->nSize; + return (Bbl_Obj_t *)(pNext < pEdge ? pNext : NULL); +} + +/**Fnction************************************************************* + + Synopsis [Returns the first fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bbl_Obj_t * Bbl_ObjFaninFirst( Bbl_Obj_t * p ) +{ + return Bbl_ObjFaninNum(p) ? Bbl_ObjFanin( p, 0 ) : NULL; +} + +/**Fnction************************************************************* + + Synopsis [Returns the next fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bbl_Obj_t * Bbl_ObjFaninNext( Bbl_Obj_t * p, Bbl_Obj_t * pPrev ) +{ + Bbl_Obj_t * pFanin; + int i; + Bbl_ObjForEachFanin_int( p, pFanin, i ) + if ( pFanin == pPrev ) + break; + return i < Bbl_ObjFaninNum(p) - 1 ? Bbl_ObjFanin( p, i+1 ) : NULL; +} + +/**Fnction************************************************************* + + Synopsis [Drives text BLIF file for debugging.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbl_ManDumpBlif( Bbl_Man_t * p, char * pFileName ) +{ + FILE * pFile; + Bbl_Obj_t * pObj, * pFanin; + pFile = fopen( pFileName, "w" ); + fprintf( pFile, "# Test file written by Bbl_ManDumpBlif() in ABC.\n" ); + fprintf( pFile, ".model %s\n", Bbl_ManName(p) ); + // write objects + Bbl_ManForEachObj( p, pObj ) + { + if ( Bbl_ObjIsInput(pObj) ) + fprintf( pFile, ".inputs %d\n", Bbl_ObjId(pObj) ); + else if ( Bbl_ObjIsOutput(pObj) ) + fprintf( pFile, ".outputs %d\n", Bbl_ObjId(pObj) ); + else if ( Bbl_ObjIsLut(pObj) ) + { + fprintf( pFile, ".names" ); + Bbl_ObjForEachFanin( pObj, pFanin ) + fprintf( pFile, " %d", Bbl_ObjId(pFanin) ); + fprintf( pFile, " %d\n", Bbl_ObjId(pObj) ); + fprintf( pFile, "%s", Bbl_ObjSop(p, pObj) ); + } + else assert( 0 ); + } + // write output drivers + Bbl_ManForEachObj( p, pObj ) + { + if ( !Bbl_ObjIsOutput(pObj) ) + continue; + fprintf( pFile, ".names" ); + Bbl_ObjForEachFanin( pObj, pFanin ) + fprintf( pFile, " %d", Bbl_ObjId(pFanin) ); + fprintf( pFile, " %d\n", Bbl_ObjId(pObj) ); + fprintf( pFile, "1 1\n" ); + } + fprintf( pFile, ".end\n" ); + fclose( pFile ); +} + +/**Fnction************************************************************* + + Synopsis [Converting truth table into an SOP.] + + Description [The truth table is given as a bit-string pTruth + composed of 2^nVars bits. The result is an SOP derived by + collecting minterms appearing in the truth table. The SOP is + represented as a C-string, as documented in file "bblif.h". + It is recommended to limit the use of this procedure to Boolean + functions up to 6 inputs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Bbl_ManTruthToSop( unsigned * pTruth, int nVars ) +{ + char * pResult, * pTemp; + int nMints, nOnes, b, v; + assert( nVars >= 0 && nVars <= 16 ); + nMints = (1 << nVars); + // count the number of ones + nOnes = 0; + for ( b = 0; b < nMints; b++ ) + nOnes += ((pTruth[b>>5] >> (b&31)) & 1); + // handle constants + if ( nOnes == 0 || nOnes == nMints ) + { + pResult = pTemp = BBLIF_ALLOC( char, nVars + 4 ); + for ( v = 0; v < nVars; v++ ) + *pTemp++ = '-'; + *pTemp++ = ' '; + *pTemp++ = nOnes? '1' : '0'; + *pTemp++ = '\n'; + *pTemp++ = 0; + assert( pTemp - pResult == nVars + 4 ); + return pResult; + } + pResult = pTemp = BBLIF_ALLOC( char, nOnes * (nVars + 3) + 1 ); + for ( b = 0; b < nMints; b++ ) + { + if ( ((pTruth[b>>5] >> (b&31)) & 1) == 0 ) + continue; + for ( v = 0; v < nVars; v++ ) + *pTemp++ = ((b >> v) & 1)? '1' : '0'; + *pTemp++ = ' '; + *pTemp++ = '1'; + *pTemp++ = '\n'; + } + *pTemp++ = 0; + assert( pTemp - pResult == nOnes * (nVars + 3) + 1 ); + return pResult; +} + +/**Function************************************************************* + + Synopsis [Allocates the array of truth tables for the given number of vars.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Bbl_ManSopToTruthElem( int nVars, unsigned ** pVars ) +{ + unsigned Masks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; + int i, k, nWords; + nWords = (nVars <= 5 ? 1 : (1 << (nVars - 5))); + for ( i = 0; i < nVars; i++ ) + { + if ( i < 5 ) + { + for ( k = 0; k < nWords; k++ ) + pVars[i][k] = Masks[i]; + } + else + { + for ( k = 0; k < nWords; k++ ) + if ( k & (1 << (i-5)) ) + pVars[i][k] = ~(unsigned)0; + else + pVars[i][k] = 0; + } + } +} + +/**Fnction************************************************************* + + Synopsis [Converting SOP into a truth table.] + + Description [The SOP is represented as a C-string, as documented in + file "bblif.h". The truth table is returned as a bit-string composed + of 2^nVars bits. For functions of less than 6 variables, the full + machine word is returned. (The truth table looks as if the function + had 5 variables.) The use of this procedure should be limited to + Boolean functions with no more than 16 inputs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Bbl_ManSopToTruth( char * pSop, int nVars ) +{ + unsigned * pTruth, * pCube, * pVars[16]; + int nWords = nVars <= 5 ? 1 : (1 << (nVars - 5)); + int v, c, w, nCubes, fCompl = 0; + if ( pSop == NULL ) + return NULL; + if ( strlen(pSop) % (nVars + 3) != 0 ) + { + printf( "Bbl_ManSopToTruth(): SOP is represented incorrectly.\n" ); + return NULL; + } + // create storage for TTs of the result, elementary variables and the temp cube + pTruth = BBLIF_ALLOC( unsigned, nWords ); + pVars[0] = BBLIF_ALLOC( unsigned, nWords * (nVars+1) ); + for ( v = 1; v < nVars; v++ ) + pVars[v] = pVars[v-1] + nWords; + pCube = pVars[v-1] + nWords; + Bbl_ManSopToTruthElem( nVars, pVars ); + // iterate through the cubes + memset( pTruth, 0, sizeof(unsigned) * nWords ); + nCubes = strlen(pSop) / (nVars + 3); + for ( c = 0; c < nCubes; c++ ) + { + fCompl = (pSop[nVars+1] == '0'); + memset( pCube, 0xff, sizeof(unsigned) * nWords ); + // iterate through the literals of the cube + for ( v = 0; v < nVars; v++ ) + if ( pSop[v] == '1' ) + for ( w = 0; w < nWords; w++ ) + pCube[w] &= pVars[v][w]; + else if ( pSop[v] == '0' ) + for ( w = 0; w < nWords; w++ ) + pCube[w] &= ~pVars[v][w]; + // add cube to storage + for ( w = 0; w < nWords; w++ ) + pTruth[w] |= pCube[w]; + // go to the next cube + pSop += (nVars + 3); + } + BBLIF_FREE( pVars[0] ); + if ( fCompl ) + for ( w = 0; w < nWords; w++ ) + pTruth[w] = ~pTruth[w]; + return pTruth; +} + + +/**Fnction************************************************************* + + Synopsis [Checks the truth table computation.] + + Description [We construct the logic network for the half-adder represnted + using the BLIF file below] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbl_ManTestTruth( char * pSop, int nVars ) +{ + unsigned * pTruth; + char * pSopNew; + pTruth = Bbl_ManSopToTruth( pSop, nVars ); + pSopNew = Bbl_ManTruthToSop( pTruth, nVars ); + printf( "Old SOP:\n%s\n", pSop ); + printf( "New SOP:\n%s\n", pSopNew ); + BBLIF_FREE( pSopNew ); + BBLIF_FREE( pTruth ); +} + +/**Fnction************************************************************* + + Synopsis [This demo shows using the internal to construct a half-adder.] + + Description [We construct the logic network for the half-adder represnted + using the BLIF file below] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbl_ManSimpleDemo() +{ +/* + # There are contents of a BLIF file representing a half-adder: + .model hadder + .inputs a // ID = 1 + .inputs b // ID = 2 + .inputs cin // ID = 3 + .outputs s // ID = 4 + .outputs cout // ID = 5 + .names a b cin s_driver // ID = 6 + 100 1 + 010 1 + 001 1 + 111 1 + .names a b cin cout_driver // ID = 7 + -11 1 + 1-1 1 + 11- 1 + .names s_driver s + 1 1 + .names cout_driver cout + 1 1 + .end +*/ + Bbl_Man_t * p; + // start the data manager + p = Bbl_ManStart( "hadder" ); + // create CIs + Bbl_ManCreateObject( p, BBL_OBJ_CI, 1, 0, NULL ); // a + Bbl_ManCreateObject( p, BBL_OBJ_CI, 2, 0, NULL ); // b + Bbl_ManCreateObject( p, BBL_OBJ_CI, 3, 0, NULL ); // cin + // create COs + Bbl_ManCreateObject( p, BBL_OBJ_CO, 4, 1, NULL ); // s + Bbl_ManCreateObject( p, BBL_OBJ_CO, 5, 1, NULL ); // cout + // create internal nodes + Bbl_ManCreateObject( p, BBL_OBJ_NODE, 6, 3, "100 1\n010 1\n001 1\n111 1\n" ); // s_driver + Bbl_ManCreateObject( p, BBL_OBJ_NODE, 7, 3, "-11 1\n1-1 1\n11- 1\n" ); // cout_driver + // add fanins of node 6 + Bbl_ManAddFanin( p, 6, 1 ); // s_driver <- a + Bbl_ManAddFanin( p, 6, 2 ); // s_driver <- b + Bbl_ManAddFanin( p, 6, 3 ); // s_driver <- cin + // add fanins of node 7 + Bbl_ManAddFanin( p, 7, 1 ); // cout_driver <- a + Bbl_ManAddFanin( p, 7, 2 ); // cout_driver <- b + Bbl_ManAddFanin( p, 7, 3 ); // cout_driver <- cin + // add fanins of COs + Bbl_ManAddFanin( p, 4, 6 ); // s <- s_driver + Bbl_ManAddFanin( p, 5, 7 ); // cout <- cout_driver + // sanity check + Bbl_ManCheck( p ); + // write BLIF file as a sanity check + Bbl_ManDumpBlif( p, "hadder.blif" ); + // write binary BLIF file + Bbl_ManDumpBinaryBlif( p, "hadder.bblif" ); + // remove the manager + Bbl_ManStop( p ); + + +// Bbl_ManTestTruth( "100 1\n010 1\n001 1\n111 1\n", 3 ); +// Bbl_ManTestTruth( "-11 0\n1-1 0\n11- 0\n", 3 ); +// Bbl_ManTestTruth( "--- 1\n", 3 ); +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/misc/bbl/bblif.h b/src/misc/bbl/bblif.h new file mode 100644 index 00000000..b4859370 --- /dev/null +++ b/src/misc/bbl/bblif.h @@ -0,0 +1,285 @@ +/**CFile**************************************************************** + + FileName [bblif.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Binary BLIF representation for logic networks.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 28, 2009.] + + Revision [$Id: bblif.h,v 1.00 2009/02/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__bbl__bblif_h +#define ABC__aig__bbl__bblif_h + + +/* + This file (taken together with "bblif.c") implements a stand-alone + interface between ABC and an application that uses ABC. + + The interface is designed to pass a combinational logic network + from the calling application to ABC using a binary BLIF format (BBLIF) + and return the network after synthesis/mapping/verification in ABC + back to the caller. + + The interface can do the following: + (1) accept a combinational logic network via a set of APIs + (2) write the logic network into a binary BLIF file readable by ABC + (3) read a binary BLIF file with a mapped network produced by ABC + (4) return the mapped network to the caller through a set of APIs + + It should be noted that the BBLIF interface can be used to pass + the network from the calling application into ABC without writing it + into a file. In this case, ABC should be compiled as a library and + linked to the calling application. The BBLIF manager can be given + directly to the procedure Bbl_ManToAbc() to convert it into an AIG. + Similarly, the resulting mapped network can be converted into + BBLIF manager and passed back after the call to Bbl_ManFromAbc(). + + Here these steps are described in more detail: + + (1) The BBLIF manager is allocated by calling Bbl_ManStart() and + deallocated by calling Bbl_ManStop(). + + The combinational network is composed of three types of objects: + (a) combinational inputs (CIs), (b) combinational outputs (COs), + (c) internal logic nodes represented using Sum-of-Products (SOPs) + similar to the way logic nodes are represented in SIS. Sequential + elements (flops) are currently not supported. A CI has no fanins. + A CO has exactly one fanin and no fanouts. Internal nodes can + have any number of fanins and fanouts. Only an internal node can + have a logic function. + + Before constructing the BBLIF manager, each object should be + assigned a unique non-negative (0-based) integer ID. The sequence + of ID numbers may have gaps in it (for example, 0, 1, 2, 5, 6, etc) + but care should be taken that the ID numbers do not grow too large + because internally they are used to index the objects. So if + the largest given ID has value N, an array of 4*N bytes will be + allocated internally by the BBLIF manager. Obviously if N = 1M, + the array will use 4Mb, but if N = 100M, it will use 0.4Gb. + + This object ID (called also "the original ID of the object") is + given to Bbl_ManCreateObject(), which construct the BBLIF objects + and to the procedure Bbl_ManAddFanin(), which creates fanin/fanout + relations between two objects. The exact number of fanins of an + object should be declared when calling Bbl_ManCreateObject(). + Later on, each node should be assigned as many fanins using + Bbl_ManAddFanin(). The order/number of fanins corresponds to the + order/number of variables in the SOP of the logic function of the + node. The declared and actual number of fanins should be the same. + otherwise the interface will not function correctly. This is checked + by the procedure Bbl_ManCheck(), which should be called when + constructing all objects and their fanins is finished. + + The SOP representation of the logic function should be given to + every internal node. It is given as a C-string, showing the SOP + as it would appear in a BLIF or PLA file. Each cube is composed + of characters '0', '1', and '-', and ended by a seqence of three + characters: space ' ', followed by '0' or '1' (depending on whether + on- or off-set is used), followed by the new line character '\n'. + For example, a two-input OR has the following SOP representation: + "1- 1\n-1 1\n", or equivalently, "00 0\n". The SOP for a constant + function with no fanins is represented as " 0\n" (constant 0) and + " 1\n" (constant 1). SOP for a constant node with some fanins + may also be represented. For example, constant 0 node with three + fanins will have SOP representation as follows: "--- 0\n". + + The objects can be added to the BBLIF manager in any order, but + by the time the fanin/fanout connections are created, corresponding + objects should be already created. + + The number of objects is limited by 2^31. The number of fanins + of one object is restricted to 2^28. The SOP representation can + have arbitrary many products (cubes), as long as memory is enough + to represent them in the C-string form, as described above. + + (2) To write the manager into a file, call procedure Bbl_ManDumpBinaryBlif(). + It is recommended to use files with extension ".bblif" because it + will allow ABC to call the approapriate reader in command "read". + + (3) To read the network from file, call procedure Bbl_ManReadBinaryBlif(). + + (4) It is assumed that ABC will return the network after mapping. + This network will arrive in a BBLIF file, from which the BBLIF + manager is created by the call to Bbl_ManReadBinaryBlif(). The + following APIs are useful to extract the mapped network from the manager: + + Iterator Bbl_ManForEachObj() iterates through the pointers to the + BBLIF objects, which are guaranteed to be in a topological order. + + For each object, the following APIs can be used: + Bbl_ObjIsInput() returns 1 if the object is a CI + Bbl_ObjIsOutput() returns 1 if the object is a CO + Bbl_ObjIsLut() returns 1 if the object is a logic node (lookup table) + Bbl_ObjFaninNumber() returns the number of fanins of the node + Bbl_ObjSop() returns the SOP representation of the node, as described above. + + A special attention should be given to the representation of object IDs + after mapping. Recall that when the outgoing BBLIF network is constructed, + the IDs of objects are assigned by the calling application and given to + the BBLIF manager when procedure Bbl_ManCreateObject() is called. + We refer to these object IDs as "original IDs of the objects". + + When the network has been given to ABC, mapped, and returned to the + calling application in the incoming BBLIF file, only CIs and COs are + guaranteed to preserve their "original IDs". Other objects may be created + during synthesis/mapping. The original IDs of these objects are set to -1. + + The following two APIs are used to return the IDs of objects after mapping: + Bbl_ObjId() returns the new ID (useful to construct network after mapping) + Bbl_ObjIdOriginal() returns the original ID (or -1 if this is a new object). + + !!!***!!! + Note: The original ID currently cannot be returned by Bbl_ObjIdOriginal(). + It is recommended to use the work-around described below. + !!!***!!! + + The original ID is useful to map CIs/COs after mapping into CIs/COs before + mapping. However, the order of CIs/COs after mapping in the incoming network + is the same as the order of their creation by the calling application + in the outgoing network. This allows for a workaround that does not have + the need for the original IDs. We can simply iterate through the objects + after mapping, and create CIs and COs in the order of their appearance, + and this order is guaranteed to be the same as the order of their + construction by the calling application. + + It is also worth noting that currently the internal node names are not + preserved by ABC during synthesis. This may change in the future. and then + some of the internal nodes will preserve their IDs, which may allow the + calling application to reconstruct the names of some of the nodes after + synthesis/mapping in ABC using their original IDs whenever available. + + Finally, iterator Bbl_ObjForEachFanin() can be used to iterate through + the fanins of each mapped object. For CIs, there will be no fanins. + For COs, there will be exactly one fanin. For the internal nodes (LUTs) + the number of fanins is the number of inputs of these nodes. + + A demo of using this interface is included at the bottom of file "bblif.c" in + procedure Bbl_ManSimpleDemo(). Additional examples can be found in the files + "abc\src\base\io\ioReadBblif.c" and "abc\src\base\io\ioWriteBblif.c". These + files illustrate how an ABC network is created from the BBLIF data manager + and how the data manager is created from the ABC network. + + Note that only the files "bblif.h" and "bblif.c" are needed for interfacing + the user's application with ABC, while other files should not be compiled + as part of the application code. + + Finally, a warning regarding endianness. The interface may not work + if the BBLIF file is produced on a machine whose engianness is different + from the machine, which is reading this file. +*/ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +#ifdef _WIN32 +#define inline __inline +#endif + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +// object types +typedef enum { + BBL_OBJ_NONE, // 0: non-existent object + BBL_OBJ_CI, // 1: primary input + BBL_OBJ_CO, // 2: primary output + BBL_OBJ_NODE, // 3: buffer node + BBL_OBJ_VOID // 4: unused object +} Bbl_Type_t; + +// data manager +typedef struct Bbl_Man_t_ Bbl_Man_t; + +// data object +typedef struct Bbl_Obj_t_ Bbl_Obj_t; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// (1) creating the data manager in the application code +extern Bbl_Man_t * Bbl_ManStart( char * pName ); +extern void Bbl_ManCreateObject( Bbl_Man_t * p, Bbl_Type_t Type, int ObjId, int nFanins, char * pSop ); +extern void Bbl_ManAddFanin( Bbl_Man_t * p, int ObjId, int FaninId ); +extern int Bbl_ManCheck( Bbl_Man_t * p ); +extern void Bbl_ManPrintStats( Bbl_Man_t * p ); +extern void Bbl_ManStop( Bbl_Man_t * p ); + +// (2) writing the data manager into file +extern void Bbl_ManDumpBinaryBlif( Bbl_Man_t * p, char * pFileName ); + +// (3) reading the data manager from file +extern Bbl_Man_t * Bbl_ManReadBinaryBlif( char * pFileName ); + +// (4) returning the mapped network after reading the data manaager from file +extern char * Bbl_ManName( Bbl_Man_t * p ); +extern int Bbl_ObjIsInput( Bbl_Obj_t * p ); +extern int Bbl_ObjIsOutput( Bbl_Obj_t * p ); +extern int Bbl_ObjIsLut( Bbl_Obj_t * p ); +extern int Bbl_ObjId( Bbl_Obj_t * p ); +extern int Bbl_ObjIdOriginal( Bbl_Man_t * pMan, Bbl_Obj_t * p ); +extern int Bbl_ObjFaninNumber( Bbl_Obj_t * p ); +extern char * Bbl_ObjSop( Bbl_Man_t * pMan, Bbl_Obj_t * p ); + +// for the use in iterators only +extern Bbl_Obj_t * Bbl_ManObjFirst( Bbl_Man_t * p ); +extern Bbl_Obj_t * Bbl_ManObjNext( Bbl_Man_t * p, Bbl_Obj_t * pObj ); +extern Bbl_Obj_t * Bbl_ObjFaninFirst( Bbl_Obj_t * p ); +extern Bbl_Obj_t * Bbl_ObjFaninNext( Bbl_Obj_t * p, Bbl_Obj_t * pPrev ); + +// iterator through the objects +#define Bbl_ManForEachObj( p, pObj ) \ + for ( pObj = Bbl_ManObjFirst(p); pObj; pObj = Bbl_ManObjNext(p, pObj) ) +// iterator through the fanins fo the an object +#define Bbl_ObjForEachFanin( pObj, pFanin ) \ + for ( pFanin = Bbl_ObjFaninFirst(pObj); pFanin; pFanin = Bbl_ObjFaninNext(pObj, pFanin) ) + +// these additional procedures are provided to transform truth tables into SOPs, and vice versa +extern char * Bbl_ManTruthToSop( unsigned * pTruth, int nVars ); +extern unsigned * Bbl_ManSopToTruth( char * pSop, int nVars ); + +// write text BLIF file for debugging +extern void Bbl_ManDumpBlif( Bbl_Man_t * p, char * pFileName ); + +// a simple demo procedure +extern void Bbl_ManSimpleDemo(); + + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/misc/bbl/module.make b/src/misc/bbl/module.make new file mode 100644 index 00000000..187e570b --- /dev/null +++ b/src/misc/bbl/module.make @@ -0,0 +1 @@ +SRC += src/misc/bbl/bblif.c diff --git a/src/misc/bzlib/bzlib.h b/src/misc/bzlib/bzlib.h index 68a6cd01..30487828 100644 --- a/src/misc/bzlib/bzlib.h +++ b/src/misc/bzlib/bzlib.h @@ -24,8 +24,8 @@ #endif #endif -#ifndef _BZLIB_H -#define _BZLIB_H +#ifndef ABC__misc__bzlib__bzlib_h +#define ABC__misc__bzlib__bzlib_h #define BZ_RUN 0 #define BZ_FLUSH 1 @@ -96,7 +96,7 @@ typedef #endif #include -#include "abc_global.h" +#include "src/misc/util/abc_global.h" ABC_NAMESPACE_HEADER_START diff --git a/src/misc/bzlib/bzlib_private.h b/src/misc/bzlib/bzlib_private.h index 072f0486..229ed386 100644 --- a/src/misc/bzlib/bzlib_private.h +++ b/src/misc/bzlib/bzlib_private.h @@ -19,8 +19,8 @@ ------------------------------------------------------------------ */ -#ifndef _BZLIB_PRIVATE_H -#define _BZLIB_PRIVATE_H +#ifndef ABC__misc__bzlib__bzlib_private_h +#define ABC__misc__bzlib__bzlib_private_h #include diff --git a/src/misc/espresso/espresso.h b/src/misc/espresso/espresso.h index 27d1c124..8b54fab5 100644 --- a/src/misc/espresso/espresso.h +++ b/src/misc/espresso/espresso.h @@ -18,7 +18,7 @@ #include "util_hack.h" // added -#define ptime() util_cpu_time() +#define ABC__misc__espresso__espresso_h #define print_time(t) util_print_time(t) #ifdef IBM_WATC @@ -55,7 +55,7 @@ /* Define host machine characteristics of "unsigned int" */ -#ifndef BPI +#ifndef ABC__misc__espresso__espresso_h #define BPI diff --git a/src/misc/espresso/main.c b/src/misc/espresso/main.c index 157ef5a0..76c5fb79 100644 --- a/src/misc/espresso/main.c +++ b/src/misc/espresso/main.c @@ -14,7 +14,7 @@ */ #include "espresso.h" -#include "main.h" +#include "base/main/main.h" ABC_NAMESPACE_IMPL_START /* table definitions for options */ diff --git a/src/misc/espresso/mincov_int.h b/src/misc/espresso/mincov_int.h index e81850f2..4b61be17 100644 --- a/src/misc/espresso/mincov_int.h +++ b/src/misc/espresso/mincov_int.h @@ -52,4 +52,4 @@ extern solution_t *sm_mincov(); extern int gimpel_reduce(); -#define WEIGHT(weight, col) (weight == NIL(int) ? 1 : weight[col]) +#define ABC__misc__espresso__mincov_int_h diff --git a/src/misc/espresso/sparse.h b/src/misc/espresso/sparse.h index 9a15fc65..dda0a7ed 100644 --- a/src/misc/espresso/sparse.h +++ b/src/misc/espresso/sparse.h @@ -7,8 +7,8 @@ * $Date$ * */ -#ifndef SPARSE_H -#define SPARSE_H +#ifndef ABC__misc__espresso__sparse_h +#define ABC__misc__espresso__sparse_h ABC_NAMESPACE_HEADER_START diff --git a/src/misc/espresso/sparse_int.h b/src/misc/espresso/sparse_int.h index 49b2509a..c567afde 100644 --- a/src/misc/espresso/sparse_int.h +++ b/src/misc/espresso/sparse_int.h @@ -30,7 +30,7 @@ * 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) \ +#define ABC__misc__espresso__sparse_int_h if (last == 0) { \ e->value = newval; \ first = e; \ diff --git a/src/misc/espresso/util_old.h b/src/misc/espresso/util_old.h index 32be6ffa..d60790d3 100644 --- a/src/misc/espresso/util_old.h +++ b/src/misc/espresso/util_old.h @@ -7,8 +7,8 @@ * $Date: 1993/06/07 21:04:07 $ * */ -#ifndef UTIL_H -#define UTIL_H +#ifndef ABC__misc__espresso__util_old_h +#define ABC__misc__espresso__util_old_h #if defined(_IBMR2) #ifndef _POSIX_SOURCE diff --git a/src/misc/ext/ext.h b/src/misc/ext/ext.h index 8db5a056..86601e52 100644 --- a/src/misc/ext/ext.h +++ b/src/misc/ext/ext.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __EXT_H__ -#define __EXT_H__ +#ifndef ABC__misc__ext__ext_h +#define ABC__misc__ext__ext_h #define EXT_ABC_FRAME #define EXT_ABC_INIT(pAbc) diff --git a/src/misc/extra/extra.h b/src/misc/extra/extra.h index 693c25bd..0bef042c 100644 --- a/src/misc/extra/extra.h +++ b/src/misc/extra/extra.h @@ -26,8 +26,8 @@ ***********************************************************************/ -#ifndef __EXTRA_H__ -#define __EXTRA_H__ +#ifndef ABC__misc__extra__extra_h +#define ABC__misc__extra__extra_h #ifdef _WIN32 @@ -44,10 +44,7 @@ #include #include -#include "st.h" -#include "cuddInt.h" - - +#include "src/misc/st/st.h" ABC_NAMESPACE_HEADER_START @@ -76,239 +73,10 @@ typedef unsigned char uint8; typedef unsigned short uint16; typedef unsigned int uint32; -/* constants of the manager */ -#define b0 Cudd_Not((dd)->one) -#define b1 (dd)->one -#define z0 (dd)->zero -#define z1 (dd)->one -#define a0 (dd)->zero -#define a1 (dd)->one - -// hash key macros -#define hashKey1(a,TSIZE) \ -((ABC_PTRUINT_T)(a) % TSIZE) - -#define hashKey2(a,b,TSIZE) \ -(((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b) * DD_P1) % TSIZE) - -#define hashKey3(a,b,c,TSIZE) \ -(((((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b)) * DD_P1 + (ABC_PTRUINT_T)(c)) * DD_P2 ) % TSIZE) - -#define hashKey4(a,b,c,d,TSIZE) \ -((((((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b)) * DD_P1 + (ABC_PTRUINT_T)(c)) * DD_P2 + \ - (ABC_PTRUINT_T)(d)) * DD_P3) % TSIZE) - -#define hashKey5(a,b,c,d,e,TSIZE) \ -(((((((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b)) * DD_P1 + (ABC_PTRUINT_T)(c)) * DD_P2 + \ - (ABC_PTRUINT_T)(d)) * DD_P3 + (ABC_PTRUINT_T)(e)) * DD_P1) % TSIZE) - /*===========================================================================*/ /* 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 ); - -/*=== extraBddImage.c ================================================================*/ - -typedef struct Extra_ImageTree_t_ Extra_ImageTree_t; -extern Extra_ImageTree_t * Extra_bddImageStart( - DdManager * dd, DdNode * bCare, - int nParts, DdNode ** pbParts, - int nVars, DdNode ** pbVars, int fVerbose ); -extern DdNode * Extra_bddImageCompute( Extra_ImageTree_t * pTree, DdNode * bCare ); -extern void Extra_bddImageTreeDelete( Extra_ImageTree_t * pTree ); -extern DdNode * Extra_bddImageRead( Extra_ImageTree_t * pTree ); - -typedef struct Extra_ImageTree2_t_ Extra_ImageTree2_t; -extern Extra_ImageTree2_t * Extra_bddImageStart2( - DdManager * dd, DdNode * bCare, - int nParts, DdNode ** pbParts, - int nVars, DdNode ** pbVars, int fVerbose ); -extern DdNode * Extra_bddImageCompute2( Extra_ImageTree2_t * pTree, DdNode * bCare ); -extern void Extra_bddImageTreeDelete2( Extra_ImageTree2_t * pTree ); -extern DdNode * Extra_bddImageRead2( Extra_ImageTree2_t * pTree ); - -/*=== extraBddMisc.c ========================================================*/ - -extern DdNode * Extra_TransferPermute( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute ); -extern DdNode * Extra_TransferLevelByLevel( DdManager * ddSource, DdManager * ddDestination, DdNode * f ); -extern DdNode * Extra_bddRemapUp( DdManager * dd, DdNode * bF ); -extern DdNode * Extra_bddMove( DdManager * dd, DdNode * bF, int nVars ); -extern DdNode * extraBddMove( DdManager * dd, DdNode * bF, DdNode * bFlag ); -extern void Extra_StopManager( DdManager * dd ); -extern void Extra_bddPrint( DdManager * dd, DdNode * F ); -extern void Extra_bddPrintSupport( DdManager * dd, DdNode * F ); -extern void extraDecomposeCover( DdManager* dd, DdNode* zC, DdNode** zC0, DdNode** zC1, DdNode** zC2 ); -extern int Extra_bddSuppSize( DdManager * dd, DdNode * bSupp ); -extern int Extra_bddSuppContainVar( DdManager * dd, DdNode * bS, DdNode * bVar ); -extern int Extra_bddSuppOverlapping( DdManager * dd, DdNode * S1, DdNode * S2 ); -extern int Extra_bddSuppDifferentVars( DdManager * dd, DdNode * S1, DdNode * S2, int DiffMax ); -extern int Extra_bddSuppCheckContainment( DdManager * dd, DdNode * bL, DdNode * bH, DdNode ** bLarge, DdNode ** bSmall ); -extern int * Extra_SupportArray( DdManager * dd, DdNode * F, int * support ); -extern int * Extra_VectorSupportArray( DdManager * dd, DdNode ** F, int n, int * support ); -extern DdNode * Extra_bddFindOneCube( DdManager * dd, DdNode * bF ); -extern DdNode * Extra_bddGetOneCube( DdManager * dd, DdNode * bFunc ); -extern DdNode * Extra_bddComputeRangeCube( DdManager * dd, int iStart, int iStop ); -extern DdNode * Extra_bddBitsToCube( DdManager * dd, int Code, int CodeWidth, DdNode ** pbVars, int fMsbFirst ); -extern DdNode * Extra_bddSupportNegativeCube( DdManager * dd, DdNode * f ); -extern int Extra_bddIsVar( DdNode * bFunc ); -extern DdNode * Extra_bddCreateAnd( DdManager * dd, int nVars ); -extern DdNode * Extra_bddCreateOr( DdManager * dd, int nVars ); -extern DdNode * Extra_bddCreateExor( DdManager * dd, int nVars ); -extern DdNode * Extra_zddPrimes( DdManager * dd, DdNode * F ); -extern void Extra_bddPermuteArray( DdManager * dd, DdNode ** bNodesIn, DdNode ** bNodesOut, int nNodes, int *permut ); -extern DdNode * Extra_bddComputeCube( DdManager * dd, DdNode ** bXVars, int nVars ); -extern DdNode * Extra_bddChangePolarity( DdManager * dd, DdNode * bFunc, DdNode * bVars ); -extern DdNode * extraBddChangePolarity( DdManager * dd, DdNode * bFunc, DdNode * bVars ); -extern int Extra_bddVarIsInCube( DdNode * bCube, int iVar ); -extern DdNode * Extra_bddAndPermute( DdManager * ddF, DdNode * bF, DdManager * ddG, DdNode * bG, int * pPermute ); - -#ifndef ABC_PRB -#define ABC_PRB(dd,f) printf("%s = ", #f); Extra_bddPrint(dd,f); printf("\n") -#endif - -/*=== extraBddKmap.c ================================================================*/ - -/* displays the Karnaugh Map of a function */ -extern void Extra_PrintKMap( FILE * pFile, DdManager * dd, DdNode * OnSet, DdNode * OffSet, int nVars, DdNode ** XVars, int fSuppType, char ** pVarNames ); -/* displays the Karnaugh Map of a relation */ -extern void Extra_PrintKMapRelation( FILE * pFile, DdManager * dd, DdNode * OnSet, DdNode * OffSet, int nXVars, int nYVars, DdNode ** XVars, DdNode ** YVars ); - -/*=== extraBddSymm.c =================================================================*/ - -typedef struct Extra_SymmInfo_t_ Extra_SymmInfo_t; -struct Extra_SymmInfo_t_ { - int nVars; // the number of variables in the support - int nVarsMax; // the number of variables in the DD manager - int nSymms; // the number of pair-wise symmetries - int nNodes; // the number of nodes in a ZDD (if applicable) - int * pVars; // the list of all variables present in the support - char ** pSymms; // the symmetry information -}; - -/* computes the classical symmetry information for the function - recursive */ -extern Extra_SymmInfo_t * Extra_SymmPairsCompute( DdManager * dd, DdNode * bFunc ); -/* computes the classical symmetry information for the function - using naive approach */ -extern Extra_SymmInfo_t * Extra_SymmPairsComputeNaive( DdManager * dd, DdNode * bFunc ); -extern int Extra_bddCheckVarsSymmetricNaive( DdManager * dd, DdNode * bF, int iVar1, int iVar2 ); - -/* allocates the data structure */ -extern Extra_SymmInfo_t * Extra_SymmPairsAllocate( int nVars ); -/* deallocates the data structure */ -extern void Extra_SymmPairsDissolve( Extra_SymmInfo_t * ); -/* print the contents the data structure */ -extern void Extra_SymmPairsPrint( Extra_SymmInfo_t * ); -/* converts the ZDD into the Extra_SymmInfo_t structure */ -extern Extra_SymmInfo_t * Extra_SymmPairsCreateFromZdd( DdManager * dd, DdNode * zPairs, DdNode * bVars ); - -/* computes the classical symmetry information as a ZDD */ -extern DdNode * Extra_zddSymmPairsCompute( DdManager * dd, DdNode * bF, DdNode * bVars ); -extern DdNode * extraZddSymmPairsCompute( DdManager * dd, DdNode * bF, DdNode * bVars ); -/* returns a singleton-set ZDD containing all variables that are symmetric with the given one */ -extern DdNode * Extra_zddGetSymmetricVars( DdManager * dd, DdNode * bF, DdNode * bG, DdNode * bVars ); -extern DdNode * extraZddGetSymmetricVars( DdManager * dd, DdNode * bF, DdNode * bG, DdNode * bVars ); -/* converts a set of variables into a set of singleton subsets */ -extern DdNode * Extra_zddGetSingletons( DdManager * dd, DdNode * bVars ); -extern DdNode * extraZddGetSingletons( DdManager * dd, DdNode * bVars ); -/* filters the set of variables using the support of the function */ -extern DdNode * Extra_bddReduceVarSet( DdManager * dd, DdNode * bVars, DdNode * bF ); -extern DdNode * extraBddReduceVarSet( DdManager * dd, DdNode * bVars, DdNode * bF ); - -/* checks the possibility that the two vars are symmetric */ -extern int Extra_bddCheckVarsSymmetric( DdManager * dd, DdNode * bF, int iVar1, int iVar2 ); -extern DdNode * extraBddCheckVarsSymmetric( DdManager * dd, DdNode * bF, DdNode * bVars ); - -/* build the set of all tuples of K variables out of N from the BDD cube */ -extern DdNode * Extra_zddTuplesFromBdd( DdManager * dd, int K, DdNode * bVarsN ); -extern DdNode * extraZddTuplesFromBdd( DdManager * dd, DdNode * bVarsK, DdNode * bVarsN ); -/* selects one subset from a ZDD representing the set of subsets */ -extern DdNode * Extra_zddSelectOneSubset( DdManager * dd, DdNode * zS ); -extern DdNode * extraZddSelectOneSubset( DdManager * dd, DdNode * zS ); - -/*=== extraBddUnate.c =================================================================*/ - -extern DdNode * Extra_bddAndTime( DdManager * dd, DdNode * f, DdNode * g, int TimeOut ); -extern DdNode * Extra_bddAndAbstractTime( DdManager * manager, DdNode * f, DdNode * g, DdNode * cube, int TimeOut ); -extern DdNode * Extra_TransferPermuteTime( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute, int TimeOut ); - -/*=== 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; @@ -391,9 +159,7 @@ extern int Extra_MmStepReadMemUsage( Extra_MmStep_t * p ); /*=== extraUtilMisc.c ========================================================*/ /* finds the smallest integer larger or equal than the logarithm */ -extern int Extra_Base2Log( unsigned Num ); extern int Extra_Base2LogDouble( double Num ); -extern int Extra_Base10Log( unsigned Num ); /* returns the power of two as a double */ extern double Extra_Power2( int Num ); extern int Extra_Power3( int Num ); @@ -430,8 +196,6 @@ extern unsigned ** Extra_TruthPerm53(); extern unsigned ** Extra_TruthPerm54(); /* bubble sort for small number of entries */ extern void Extra_BubbleSort( int Order[], int Costs[], int nSize, int fIncreasing ); -/* for independence from CUDD */ -extern unsigned int Cudd_PrimeCopy( unsigned int p ); /*=== extraUtilCanon.c ========================================================*/ @@ -451,10 +215,6 @@ static inline void Extra_ProgressBarUpdate( ProgressBar * p, int nItemsCur, char /*=== 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_Float2Int( float Val ) { union { int x; float y; } v; v.y = Val; return v.x; } -static inline float Extra_Int2Float( int Num ) { union { int x; float y; } v; v.x = Num; return v.y; } 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)); } diff --git a/src/misc/extra/extraBdd.h b/src/misc/extra/extraBdd.h new file mode 100644 index 00000000..25df14bb --- /dev/null +++ b/src/misc/extra/extraBdd.h @@ -0,0 +1,316 @@ +/**CFile**************************************************************** + + FileName [extraBdd.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [extra] + + Synopsis [Various reusable software utilities.] + + Description [This library contains a number of operators and + traversal routines developed to extend the functionality of + CUDD v.2.3.x, by Fabio Somenzi (http://vlsi.colorado.edu/~fabio/) + To compile your code with the library, #include "extra.h" + in your source files and link your project to CUDD and this + library. Use the library at your own risk and with caution. + Note that debugging of some operators still continues.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: extraBdd.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__misc__extra__extra_bdd_h +#define ABC__misc__extra__extra_bdd_h + + +#ifdef _WIN32 +#define inline __inline // compatible with MS VS 6.0 +#endif + +/*---------------------------------------------------------------------------*/ +/* Nested includes */ +/*---------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include + +#include "src/misc/st/st.h" +#include "src/bdd/cudd/cuddInt.h" +#include "src/misc/extra/extra.h" + + +ABC_NAMESPACE_HEADER_START + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/* constants of the manager */ +#define b0 Cudd_Not((dd)->one) +#define b1 (dd)->one +#define z0 (dd)->zero +#define z1 (dd)->one +#define a0 (dd)->zero +#define a1 (dd)->one + +// hash key macros +#define hashKey1(a,TSIZE) \ +((ABC_PTRUINT_T)(a) % TSIZE) + +#define hashKey2(a,b,TSIZE) \ +(((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b) * DD_P1) % TSIZE) + +#define hashKey3(a,b,c,TSIZE) \ +(((((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b)) * DD_P1 + (ABC_PTRUINT_T)(c)) * DD_P2 ) % TSIZE) + +#define hashKey4(a,b,c,d,TSIZE) \ +((((((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b)) * DD_P1 + (ABC_PTRUINT_T)(c)) * DD_P2 + \ + (ABC_PTRUINT_T)(d)) * DD_P3) % TSIZE) + +#define hashKey5(a,b,c,d,e,TSIZE) \ +(((((((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b)) * DD_P1 + (ABC_PTRUINT_T)(c)) * DD_P2 + \ + (ABC_PTRUINT_T)(d)) * DD_P3 + (ABC_PTRUINT_T)(e)) * DD_P1) % TSIZE) + +/*===========================================================================*/ +/* 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 ); + +/*=== extraBddImage.c ================================================================*/ + +typedef struct Extra_ImageTree_t_ Extra_ImageTree_t; +extern Extra_ImageTree_t * Extra_bddImageStart( + DdManager * dd, DdNode * bCare, + int nParts, DdNode ** pbParts, + int nVars, DdNode ** pbVars, int fVerbose ); +extern DdNode * Extra_bddImageCompute( Extra_ImageTree_t * pTree, DdNode * bCare ); +extern void Extra_bddImageTreeDelete( Extra_ImageTree_t * pTree ); +extern DdNode * Extra_bddImageRead( Extra_ImageTree_t * pTree ); + +typedef struct Extra_ImageTree2_t_ Extra_ImageTree2_t; +extern Extra_ImageTree2_t * Extra_bddImageStart2( + DdManager * dd, DdNode * bCare, + int nParts, DdNode ** pbParts, + int nVars, DdNode ** pbVars, int fVerbose ); +extern DdNode * Extra_bddImageCompute2( Extra_ImageTree2_t * pTree, DdNode * bCare ); +extern void Extra_bddImageTreeDelete2( Extra_ImageTree2_t * pTree ); +extern DdNode * Extra_bddImageRead2( Extra_ImageTree2_t * pTree ); + +/*=== extraBddMisc.c ========================================================*/ + +extern DdNode * Extra_TransferPermute( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute ); +extern DdNode * Extra_TransferLevelByLevel( DdManager * ddSource, DdManager * ddDestination, DdNode * f ); +extern DdNode * Extra_bddRemapUp( DdManager * dd, DdNode * bF ); +extern DdNode * Extra_bddMove( DdManager * dd, DdNode * bF, int nVars ); +extern DdNode * extraBddMove( DdManager * dd, DdNode * bF, DdNode * bFlag ); +extern void Extra_StopManager( DdManager * dd ); +extern void Extra_bddPrint( DdManager * dd, DdNode * F ); +extern void Extra_bddPrintSupport( DdManager * dd, DdNode * F ); +extern void extraDecomposeCover( DdManager* dd, DdNode* zC, DdNode** zC0, DdNode** zC1, DdNode** zC2 ); +extern int Extra_bddSuppSize( DdManager * dd, DdNode * bSupp ); +extern int Extra_bddSuppContainVar( DdManager * dd, DdNode * bS, DdNode * bVar ); +extern int Extra_bddSuppOverlapping( DdManager * dd, DdNode * S1, DdNode * S2 ); +extern int Extra_bddSuppDifferentVars( DdManager * dd, DdNode * S1, DdNode * S2, int DiffMax ); +extern int Extra_bddSuppCheckContainment( DdManager * dd, DdNode * bL, DdNode * bH, DdNode ** bLarge, DdNode ** bSmall ); +extern int * Extra_SupportArray( DdManager * dd, DdNode * F, int * support ); +extern int * Extra_VectorSupportArray( DdManager * dd, DdNode ** F, int n, int * support ); +extern DdNode * Extra_bddFindOneCube( DdManager * dd, DdNode * bF ); +extern DdNode * Extra_bddGetOneCube( DdManager * dd, DdNode * bFunc ); +extern DdNode * Extra_bddComputeRangeCube( DdManager * dd, int iStart, int iStop ); +extern DdNode * Extra_bddBitsToCube( DdManager * dd, int Code, int CodeWidth, DdNode ** pbVars, int fMsbFirst ); +extern DdNode * Extra_bddSupportNegativeCube( DdManager * dd, DdNode * f ); +extern int Extra_bddIsVar( DdNode * bFunc ); +extern DdNode * Extra_bddCreateAnd( DdManager * dd, int nVars ); +extern DdNode * Extra_bddCreateOr( DdManager * dd, int nVars ); +extern DdNode * Extra_bddCreateExor( DdManager * dd, int nVars ); +extern DdNode * Extra_zddPrimes( DdManager * dd, DdNode * F ); +extern void Extra_bddPermuteArray( DdManager * dd, DdNode ** bNodesIn, DdNode ** bNodesOut, int nNodes, int *permut ); +extern DdNode * Extra_bddComputeCube( DdManager * dd, DdNode ** bXVars, int nVars ); +extern DdNode * Extra_bddChangePolarity( DdManager * dd, DdNode * bFunc, DdNode * bVars ); +extern DdNode * extraBddChangePolarity( DdManager * dd, DdNode * bFunc, DdNode * bVars ); +extern int Extra_bddVarIsInCube( DdNode * bCube, int iVar ); +extern DdNode * Extra_bddAndPermute( DdManager * ddF, DdNode * bF, DdManager * ddG, DdNode * bG, int * pPermute ); + +#ifndef ABC_PRB +#define ABC_PRB(dd,f) printf("%s = ", #f); Extra_bddPrint(dd,f); printf("\n") +#endif + +/*=== extraBddKmap.c ================================================================*/ + +/* displays the Karnaugh Map of a function */ +extern void Extra_PrintKMap( FILE * pFile, DdManager * dd, DdNode * OnSet, DdNode * OffSet, int nVars, DdNode ** XVars, int fSuppType, char ** pVarNames ); +/* displays the Karnaugh Map of a relation */ +extern void Extra_PrintKMapRelation( FILE * pFile, DdManager * dd, DdNode * OnSet, DdNode * OffSet, int nXVars, int nYVars, DdNode ** XVars, DdNode ** YVars ); + +/*=== extraBddSymm.c =================================================================*/ + +typedef struct Extra_SymmInfo_t_ Extra_SymmInfo_t; +struct Extra_SymmInfo_t_ { + int nVars; // the number of variables in the support + int nVarsMax; // the number of variables in the DD manager + int nSymms; // the number of pair-wise symmetries + int nNodes; // the number of nodes in a ZDD (if applicable) + int * pVars; // the list of all variables present in the support + char ** pSymms; // the symmetry information +}; + +/* computes the classical symmetry information for the function - recursive */ +extern Extra_SymmInfo_t * Extra_SymmPairsCompute( DdManager * dd, DdNode * bFunc ); +/* computes the classical symmetry information for the function - using naive approach */ +extern Extra_SymmInfo_t * Extra_SymmPairsComputeNaive( DdManager * dd, DdNode * bFunc ); +extern int Extra_bddCheckVarsSymmetricNaive( DdManager * dd, DdNode * bF, int iVar1, int iVar2 ); + +/* allocates the data structure */ +extern Extra_SymmInfo_t * Extra_SymmPairsAllocate( int nVars ); +/* deallocates the data structure */ +extern void Extra_SymmPairsDissolve( Extra_SymmInfo_t * ); +/* print the contents the data structure */ +extern void Extra_SymmPairsPrint( Extra_SymmInfo_t * ); +/* converts the ZDD into the Extra_SymmInfo_t structure */ +extern Extra_SymmInfo_t * Extra_SymmPairsCreateFromZdd( DdManager * dd, DdNode * zPairs, DdNode * bVars ); + +/* computes the classical symmetry information as a ZDD */ +extern DdNode * Extra_zddSymmPairsCompute( DdManager * dd, DdNode * bF, DdNode * bVars ); +extern DdNode * extraZddSymmPairsCompute( DdManager * dd, DdNode * bF, DdNode * bVars ); +/* returns a singleton-set ZDD containing all variables that are symmetric with the given one */ +extern DdNode * Extra_zddGetSymmetricVars( DdManager * dd, DdNode * bF, DdNode * bG, DdNode * bVars ); +extern DdNode * extraZddGetSymmetricVars( DdManager * dd, DdNode * bF, DdNode * bG, DdNode * bVars ); +/* converts a set of variables into a set of singleton subsets */ +extern DdNode * Extra_zddGetSingletons( DdManager * dd, DdNode * bVars ); +extern DdNode * extraZddGetSingletons( DdManager * dd, DdNode * bVars ); +/* filters the set of variables using the support of the function */ +extern DdNode * Extra_bddReduceVarSet( DdManager * dd, DdNode * bVars, DdNode * bF ); +extern DdNode * extraBddReduceVarSet( DdManager * dd, DdNode * bVars, DdNode * bF ); + +/* checks the possibility that the two vars are symmetric */ +extern int Extra_bddCheckVarsSymmetric( DdManager * dd, DdNode * bF, int iVar1, int iVar2 ); +extern DdNode * extraBddCheckVarsSymmetric( DdManager * dd, DdNode * bF, DdNode * bVars ); + +/* build the set of all tuples of K variables out of N from the BDD cube */ +extern DdNode * Extra_zddTuplesFromBdd( DdManager * dd, int K, DdNode * bVarsN ); +extern DdNode * extraZddTuplesFromBdd( DdManager * dd, DdNode * bVarsK, DdNode * bVarsN ); +/* selects one subset from a ZDD representing the set of subsets */ +extern DdNode * Extra_zddSelectOneSubset( DdManager * dd, DdNode * zS ); +extern DdNode * extraZddSelectOneSubset( DdManager * dd, DdNode * zS ); + +/*=== extraBddUnate.c =================================================================*/ + +extern DdNode * Extra_bddAndTime( DdManager * dd, DdNode * f, DdNode * g, int TimeOut ); +extern DdNode * Extra_bddAndAbstractTime( DdManager * manager, DdNode * f, DdNode * g, DdNode * cube, int TimeOut ); +extern DdNode * Extra_TransferPermuteTime( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute, int TimeOut ); + +/*=== 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 ); + +/**AutomaticEnd***************************************************************/ + + + +ABC_NAMESPACE_HEADER_END + + + +#endif /* __EXTRA_H__ */ diff --git a/src/misc/extra/extraBddAuto.c b/src/misc/extra/extraBddAuto.c index 3b0e2aa0..5fb38aec 100644 --- a/src/misc/extra/extraBddAuto.c +++ b/src/misc/extra/extraBddAuto.c @@ -16,7 +16,7 @@ ***********************************************************************/ -#include "extra.h" +#include "extraBdd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/misc/extra/extraBddCas.c b/src/misc/extra/extraBddCas.c index 14de2d2b..0416a0d2 100644 --- a/src/misc/extra/extraBddCas.c +++ b/src/misc/extra/extraBddCas.c @@ -16,7 +16,7 @@ ***********************************************************************/ -#include "extra.h" +#include "extraBdd.h" ABC_NAMESPACE_IMPL_START @@ -146,7 +146,7 @@ Extra_bddEncodingBinary( DdNode * bResult; DdNode * bCube, * bTemp, * bProd; - assert( nVars >= Extra_Base2Log(nFuncs) ); + assert( nVars >= Abc_Base2Log(nFuncs) ); bResult = b0; Cudd_Ref( bResult ); for ( i = 0; i < nFuncs; i++ ) diff --git a/src/misc/extra/extraBddImage.c b/src/misc/extra/extraBddImage.c index 38c18f63..46afb4f2 100644 --- a/src/misc/extra/extraBddImage.c +++ b/src/misc/extra/extraBddImage.c @@ -16,7 +16,7 @@ ***********************************************************************/ -#include "extra.h" +#include "extraBdd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/misc/extra/extraBddKmap.c b/src/misc/extra/extraBddKmap.c index aa8e3764..23bf2224 100644 --- a/src/misc/extra/extraBddKmap.c +++ b/src/misc/extra/extraBddKmap.c @@ -20,7 +20,7 @@ /// Version 1.0. Started - August 20, 2000 /// /// Version 2.0. Added to EXTRA - July 17, 2001 /// -#include "extra.h" +#include "extraBdd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/misc/extra/extraBddMisc.c b/src/misc/extra/extraBddMisc.c index 3af9c81e..4512572d 100644 --- a/src/misc/extra/extraBddMisc.c +++ b/src/misc/extra/extraBddMisc.c @@ -18,7 +18,7 @@ ***********************************************************************/ -#include "extra.h" +#include "extraBdd.h" ABC_NAMESPACE_IMPL_START @@ -1917,7 +1917,7 @@ DdNode * extraBddAndPermute( DdHashTable * table, DdManager * ddF, DdNode * bF, // find the topmost variable in F and G using var order of F LevF = cuddI( ddF, Cudd_Regular(bF)->index ); LevG = cuddI( ddF, pPermute ? pPermute[Cudd_Regular(bG)->index] : Cudd_Regular(bG)->index ); - Lev = ABC_MIN( LevF, LevG ); + Lev = Abc_MinInt( LevF, LevG ); assert( Lev < ddF->size ); bVar = ddF->vars[ddF->invperm[Lev]]; diff --git a/src/misc/extra/extraBddSymm.c b/src/misc/extra/extraBddSymm.c index 0adcbd2a..9dd2c8e5 100644 --- a/src/misc/extra/extraBddSymm.c +++ b/src/misc/extra/extraBddSymm.c @@ -19,7 +19,7 @@ ***********************************************************************/ -#include "extra.h" +#include "extraBdd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/misc/extra/extraBddTime.c b/src/misc/extra/extraBddTime.c index b861d51a..853f8a64 100644 --- a/src/misc/extra/extraBddTime.c +++ b/src/misc/extra/extraBddTime.c @@ -16,7 +16,7 @@ ***********************************************************************/ -#include "extra.h" +#include "extraBdd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/misc/extra/extraBddUnate.c b/src/misc/extra/extraBddUnate.c index 3aa18e51..9ebdd4e5 100644 --- a/src/misc/extra/extraBddUnate.c +++ b/src/misc/extra/extraBddUnate.c @@ -20,7 +20,7 @@ ***********************************************************************/ -#include "extra.h" +#include "extraBdd.h" ABC_NAMESPACE_IMPL_START diff --git a/src/misc/extra/extraUtilFile.c b/src/misc/extra/extraUtilFile.c index a8542da4..b38befd6 100644 --- a/src/misc/extra/extraUtilFile.c +++ b/src/misc/extra/extraUtilFile.c @@ -580,7 +580,7 @@ void Extra_FileSort( char * pFileName, char * pFileNameOut ) Begin = i + 1; } // sort the lines - qsort( pLines, nLines, sizeof(char *), Extra_StringCompare ); + qsort( pLines, nLines, sizeof(char *), (int(*)(const void *,const void *))Extra_StringCompare ); // write a new file pFile = fopen( pFileNameOut, "wb" ); for ( i = 0; i < nLines; i++ ) diff --git a/src/misc/extra/extraUtilMisc.c b/src/misc/extra/extraUtilMisc.c index e4c5acd5..b910f209 100644 --- a/src/misc/extra/extraUtilMisc.c +++ b/src/misc/extra/extraUtilMisc.c @@ -18,6 +18,8 @@ ***********************************************************************/ +#include + #include "extra.h" ABC_NAMESPACE_IMPL_START @@ -58,27 +60,6 @@ static void Extra_Permutations_rec( char ** pRes, int nFact, int n, char Array[] /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Finds the smallest integer larger of equal than the logarithm.] - - Description [Returns [Log2(Num)].] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_Base2Log( unsigned Num ) -{ - int Res; - if ( Num == 0 ) return 0; - if ( Num == 1 ) return 1; - for ( Res = 0, Num--; Num; Num >>= 1, Res++ ); - return Res; -} /* end of Extra_Base2Log */ - /**Function******************************************************************** Synopsis [Finds the smallest integer larger of equal than the logarithm.] @@ -103,26 +84,6 @@ int Extra_Base2LogDouble( double Num ) return ResInt+1; } -/**Function******************************************************************** - - Synopsis [Finds the smallest integer larger of equal than the logarithm.] - - Description [Returns [Log10(Num)].] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_Base10Log( unsigned Num ) -{ - int Res; - if ( Num == 0 ) return 0; - if ( Num == 1 ) return 1; - for ( Res = 0, Num--; Num; Num /= 10, Res++ ); - return Res; -} /* end of Extra_Base2Log */ - /**Function******************************************************************** Synopsis [Returns the power of two as a double.] @@ -2118,41 +2079,6 @@ void Extra_BubbleSort( int Order[], int Costs[], int nSize, int fIncreasing ) } } -/**Function************************************************************* - - Synopsis [Returns the smallest prime larger than the number.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned int Cudd_PrimeCopy( unsigned int p) -{ - int i,pn; - - p--; - do { - p++; - if (p&1) { - pn = 1; - i = 3; - while ((unsigned) (i * i) <= p) { - if (p % i == 0) { - pn = 0; - break; - } - i += 2; - } - } else { - pn = 0; - } - } while (!pn); - return(p); - -} /* end of Cudd_Prime */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ diff --git a/src/misc/extra/extraUtilProgress.c b/src/misc/extra/extraUtilProgress.c index e7add47f..ab0f5849 100644 --- a/src/misc/extra/extraUtilProgress.c +++ b/src/misc/extra/extraUtilProgress.c @@ -20,7 +20,7 @@ #include #include "extra.h" -#include "main.h" +#include "src/base/main/main.h" ABC_NAMESPACE_IMPL_START diff --git a/src/misc/extra/extraUtilReader.c b/src/misc/extra/extraUtilReader.c index bcf3da37..41e02a27 100644 --- a/src/misc/extra/extraUtilReader.c +++ b/src/misc/extra/extraUtilReader.c @@ -20,7 +20,7 @@ #include #include "extra.h" -#include "vec.h" +#include "src/misc/vec/vec.h" ABC_NAMESPACE_IMPL_START diff --git a/src/misc/hash/hash.h b/src/misc/hash/hash.h index 9b5b25d6..6e6c637c 100644 --- a/src/misc/hash/hash.h +++ b/src/misc/hash/hash.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __HASH_H__ -#define __HASH_H__ +#ifndef ABC__misc__hash__hash_h +#define ABC__misc__hash__hash_h #ifdef _WIN32 @@ -29,7 +29,7 @@ /// INCLUDES /// //////////////////////////////////////////////////////////////////////// -#include "abc_global.h" +#include "src/misc/util/abc_global.h" #include "hashInt.h" #include "hashFlt.h" @@ -55,7 +55,7 @@ ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// int Hash_DefaultHashFunc(int key, int nBins) { - return ABC_ABS( ( (key+11)*(key)*7+3 ) % nBins ); + return Abc_AbsInt( ( (key+11)*(key)*7+3 ) % nBins ); } //////////////////////////////////////////////////////////////////////// diff --git a/src/misc/hash/hashFlt.h b/src/misc/hash/hashFlt.h index 74e8503d..c5776b46 100644 --- a/src/misc/hash/hashFlt.h +++ b/src/misc/hash/hashFlt.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __HASH_FLT_H__ -#define __HASH_FLT_H__ +#ifndef ABC__misc__hash__hashFlt_h +#define ABC__misc__hash__hashFlt_h //////////////////////////////////////////////////////////////////////// @@ -27,7 +27,7 @@ //////////////////////////////////////////////////////////////////////// #include -#include "extra.h" +#include "src/misc/extra/extra.h" ABC_NAMESPACE_HEADER_START diff --git a/src/misc/hash/hashGen.h b/src/misc/hash/hashGen.h index e26a3c84..eaeef6fd 100644 --- a/src/misc/hash/hashGen.h +++ b/src/misc/hash/hashGen.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __HASH_GEN_H__ -#define __HASH_GEN_H__ +#ifndef ABC__misc__hash__hashGen_h +#define ABC__misc__hash__hashGen_h //////////////////////////////////////////////////////////////////////// @@ -27,7 +27,7 @@ //////////////////////////////////////////////////////////////////////// #include -#include "extra.h" +#include "misc/extra/extra.h" ABC_NAMESPACE_HEADER_START diff --git a/src/misc/hash/hashInt.h b/src/misc/hash/hashInt.h index 23947946..81a338fc 100644 --- a/src/misc/hash/hashInt.h +++ b/src/misc/hash/hashInt.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __HASH_INT_H__ -#define __HASH_INT_H__ +#ifndef ABC__misc__hash__hashInt_h +#define ABC__misc__hash__hashInt_h //////////////////////////////////////////////////////////////////////// @@ -27,7 +27,7 @@ //////////////////////////////////////////////////////////////////////// #include -#include "extra.h" +#include "src/misc/extra/extra.h" ABC_NAMESPACE_HEADER_START diff --git a/src/misc/hash/hashPtr.h b/src/misc/hash/hashPtr.h index a10fb548..72e2f394 100644 --- a/src/misc/hash/hashPtr.h +++ b/src/misc/hash/hashPtr.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __HASH_PTR_H__ -#define __HASH_PTR_H__ +#ifndef ABC__misc__hash__hashPtr_h +#define ABC__misc__hash__hashPtr_h //////////////////////////////////////////////////////////////////////// @@ -27,7 +27,7 @@ //////////////////////////////////////////////////////////////////////// #include -#include "extra.h" +#include "src/misc/extra/extra.h" ABC_NAMESPACE_HEADER_START diff --git a/src/misc/mem/mem.c b/src/misc/mem/mem.c new file mode 100644 index 00000000..23d8d7ec --- /dev/null +++ b/src/misc/mem/mem.c @@ -0,0 +1,605 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 + 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 +}; + +//////////////////////////////////////////////////////////////////////// +/// 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 = ABC_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 = ABC_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++ ) + ABC_FREE( p->pChunks[i] ); + ABC_FREE( p->pChunks ); + ABC_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 = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); + } + p->pEntriesFree = ABC_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++ ) + ABC_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 = ABC_ALLOC( Mem_Flex_t, 1 ); + memset( p, 0, sizeof(Mem_Flex_t) ); + + p->nEntriesUsed = 0; + p->pCurrent = NULL; + p->pEnd = NULL; + + p->nChunkSize = (1 << 12); + p->nChunksAlloc = 64; + p->nChunks = 0; + p->pChunks = ABC_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++ ) + ABC_FREE( p->pChunks[i] ); + ABC_FREE( p->pChunks ); + ABC_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 = ABC_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 = ABC_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++ ) + ABC_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 ABC_FREE()ed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mem_Step_t * Mem_StepStart( int nSteps ) +{ + Mem_Step_t * p; + int i, k; + p = ABC_ALLOC( Mem_Step_t, 1 ); + memset( p, 0, sizeof(Mem_Step_t) ); + p->nMems = nSteps; + // start the fixed memory managers + p->pMems = ABC_ALLOC( Mem_Fixed_t *, p->nMems ); + for ( i = 0; i < p->nMems; i++ ) + p->pMems[i] = Mem_FixedStart( (8<nMapSize = (4<nMems); + p->pMap = ABC_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++ ) + ABC_FREE( p->pLargeChunks[i] ); + ABC_FREE( p->pLargeChunks ); + } + ABC_FREE( p->pMems ); + ABC_FREE( p->pMap ); + ABC_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 ); +// return ABC_ALLOC( char, nBytes ); + if ( p->nLargeChunks == p->nLargeChunksAlloc ) + { + if ( p->nLargeChunksAlloc == 0 ) + p->nLargeChunksAlloc = 32; + p->nLargeChunksAlloc *= 2; + p->pLargeChunks = (void **)ABC_REALLOC( char *, p->pLargeChunks, p->nLargeChunksAlloc ); + } + p->pLargeChunks[ p->nLargeChunks++ ] = ABC_ALLOC( char, nBytes ); + return (char *)p->pLargeChunks[ p->nLargeChunks - 1 ]; + } + 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 ) + { +// ABC_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 /// +//////////////////////////////////////////////////////////////////////// +ABC_NAMESPACE_IMPL_END + diff --git a/src/misc/mem/mem.h b/src/misc/mem/mem.h new file mode 100644 index 00000000..0f04c160 --- /dev/null +++ b/src/misc/mem/mem.h @@ -0,0 +1,75 @@ +/**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 ABC__aig__mem__mem_h +#define ABC__aig__mem__mem_h + +#include "src/misc/util/abc_global.h" + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/misc/mem/module.make b/src/misc/mem/module.make new file mode 100644 index 00000000..53d76603 --- /dev/null +++ b/src/misc/mem/module.make @@ -0,0 +1 @@ +SRC += src/misc/mem/mem.c diff --git a/src/misc/mvc/mvc.h b/src/misc/mvc/mvc.h index 93229470..94b9acd9 100644 --- a/src/misc/mvc/mvc.h +++ b/src/misc/mvc/mvc.h @@ -16,8 +16,8 @@ ***********************************************************************/ -#ifndef __MVC_H__ -#define __MVC_H__ +#ifndef ABC__misc__mvc__mvc_h +#define ABC__misc__mvc__mvc_h //////////////////////////////////////////////////////////////////////// @@ -25,8 +25,7 @@ //////////////////////////////////////////////////////////////////////// #include -#include "extra.h" -#include "extra.h" +#include "src/misc/extra/extra.h" ABC_NAMESPACE_HEADER_START diff --git a/src/misc/nm/nm.h b/src/misc/nm/nm.h index 015b4ef4..2fa46d73 100644 --- a/src/misc/nm/nm.h +++ b/src/misc/nm/nm.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __NM_H__ -#define __NM_H__ +#ifndef ABC__misc__nm__nm_h +#define ABC__misc__nm__nm_h /* diff --git a/src/misc/nm/nmApi.c b/src/misc/nm/nmApi.c index e6bfb069..ab334032 100644 --- a/src/misc/nm/nmApi.c +++ b/src/misc/nm/nmApi.c @@ -52,7 +52,7 @@ Nm_Man_t * Nm_ManCreate( int nSize ) 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->nBins = Abc_PrimeCudd(nSize); p->pBinsI2N = ABC_ALLOC( Nm_Entry_t *, p->nBins ); p->pBinsN2I = ABC_ALLOC( Nm_Entry_t *, p->nBins ); memset( p->pBinsI2N, 0, sizeof(Nm_Entry_t *) * p->nBins ); diff --git a/src/misc/nm/nmInt.h b/src/misc/nm/nmInt.h index 0978c6b6..4463b276 100644 --- a/src/misc/nm/nmInt.h +++ b/src/misc/nm/nmInt.h @@ -18,16 +18,16 @@ ***********************************************************************/ -#ifndef __NM_INT_H__ -#define __NM_INT_H__ +#ifndef ABC__misc__nm__nmInt_h +#define ABC__misc__nm__nmInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// -#include "extra.h" -#include "vec.h" +#include "src/misc/extra/extra.h" +#include "src/misc/vec/vec.h" #include "nm.h" //////////////////////////////////////////////////////////////////////// @@ -78,7 +78,6 @@ 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 ); diff --git a/src/misc/nm/nmTable.c b/src/misc/nm/nmTable.c index 29c751a6..4c2b7a0a 100644 --- a/src/misc/nm/nmTable.c +++ b/src/misc/nm/nmTable.c @@ -260,7 +260,7 @@ void Nm_ManResize( Nm_Man_t * p ) clk = clock(); // get the new table size - nBinsNew = Cudd_PrimeCopy( p->nGrowthFactor * p->nBins ); + nBinsNew = Abc_PrimeCudd( p->nGrowthFactor * p->nBins ); // allocate a new array pBinsNewI2N = ABC_ALLOC( Nm_Entry_t *, nBinsNew ); pBinsNewN2I = ABC_ALLOC( Nm_Entry_t *, nBinsNew ); @@ -299,41 +299,6 @@ clk = clock(); } -/**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 cadddb0b..2e2edc53 100644 --- a/src/misc/st/st.c +++ b/src/misc/st/st.c @@ -9,6 +9,7 @@ */ #include #include +#include #include "st.h" @@ -16,7 +17,7 @@ ABC_NAMESPACE_IMPL_START #define ST_NUMCMP(x,y) ((x) != (y)) -#define ST_NUMHASH(x,size) (ABC_ABS((long)x)%(size)) +#define ST_NUMHASH(x,size) (Abc_AbsInt((long)x)%(size)) //#define ST_PTRHASH(x,size) ((int)((ABC_PTRUINT_T)(x)>>2)%size) // 64-bit bug fix 9/17/2007 #define ST_PTRHASH(x,size) ((int)(((ABC_PTRUINT_T)(x)>>2)%size)) #define EQUAL(func, x, y) \ diff --git a/src/misc/st/st.h b/src/misc/st/st.h index d16fc4b6..50a8440e 100644 --- a/src/misc/st/st.h +++ b/src/misc/st/st.h @@ -11,10 +11,11 @@ /* /projects/hsis/CVS/utilities/st/st.h,v 1.1 1993/07/29 01:00:21 serdar Exp */ -#ifndef ST_INCLUDED +#ifndef ABC__misc__st__st_h +#define ABC__misc__st__st_h #define ST_INCLUDED -#include "abc_global.h" +#include "src/misc/util/abc_global.h" ABC_NAMESPACE_HEADER_START diff --git a/src/misc/st/stmm.c b/src/misc/st/stmm.c index 1305d5b0..dc883a67 100644 --- a/src/misc/st/stmm.c +++ b/src/misc/st/stmm.c @@ -8,14 +8,14 @@ * */ #include -#include "extra.h" +#include "src/misc/extra/extra.h" #include "stmm.h" ABC_NAMESPACE_IMPL_START #define STMM_NUMCMP(x,y) ((x) != (y)) -#define STMM_NUMHASH(x,size) (ABC_ABS((long)x)%(size)) +#define STMM_NUMHASH(x,size) (Abc_AbsInt((long)x)%(size)) //#define STMM_PTRHASH(x,size) ((int)((ABC_PTRUINT_T)(x)>>2)%size) // 64-bit bug fix 9/17/2007 #define STMM_PTRHASH(x,size) ((int)(((ABC_PTRUINT_T)(x)>>2)%size)) #define EQUAL(func, x, y) \ diff --git a/src/misc/st/stmm.h b/src/misc/st/stmm.h index eee90073..1853ce36 100644 --- a/src/misc/st/stmm.h +++ b/src/misc/st/stmm.h @@ -11,10 +11,10 @@ /* /projects/hsis/CVS/utilities/st/st.h,v 1.1 1993/07/29 01:00:21 serdar Exp */ -#ifndef STMM_INCLUDED -#define STMM_INCLUDED +#ifndef ABC__misc__st__stmm_h +#define ABC__misc__st__stmm_h -#include "abc_global.h" +#include "src/misc/util/abc_global.h" ABC_NAMESPACE_HEADER_START diff --git a/src/misc/tim/module.make b/src/misc/tim/module.make new file mode 100644 index 00000000..62a3ede5 --- /dev/null +++ b/src/misc/tim/module.make @@ -0,0 +1 @@ +SRC += src/misc/tim/tim.c diff --git a/src/misc/tim/tim.c b/src/misc/tim/tim.c new file mode 100644 index 00000000..fe5f214d --- /dev/null +++ b/src/misc/tim/tim.c @@ -0,0 +1,996 @@ +/**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 "src/misc/vec/vec.h" +#include "src/misc/mem/mem.h" +#include "tim.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 fUseTravId; // enables the use of traversal ID + int nCis; // the number of PIs + int nCos; // the number of POs + Tim_Obj_t * pCis; // timing info for the PIs + Tim_Obj_t * pCos; // 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_ManCi( Tim_Man_t * p, int i ) { assert( i < p->nCis ); return p->pCis + i; } +static inline Tim_Obj_t * Tim_ManCo( Tim_Man_t * p, int i ) { assert( i < p->nCos ); return p->pCos + i; } +static inline Tim_Box_t * Tim_ManBox( Tim_Man_t * p, int i ) { return (Tim_Box_t *)Vec_PtrEntry(p->vBoxes, i); } + +static inline Tim_Box_t * Tim_ManCiBox( Tim_Man_t * p, int i ) { return Tim_ManCi(p,i)->iObj2Box < 0 ? NULL : (Tim_Box_t *)Vec_PtrEntry( p->vBoxes, Tim_ManCi(p,i)->iObj2Box ); } +static inline Tim_Box_t * Tim_ManCoBox( Tim_Man_t * p, int i ) { return Tim_ManCo(p,i)->iObj2Box < 0 ? NULL : (Tim_Box_t *)Vec_PtrEntry( p->vBoxes, Tim_ManCo(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->pCos + 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->pCis + 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_ManForEachCi( p, pObj, i ) \ + for ( i = 0; (i < (p)->nCis) && ((pObj) = (p)->pCis + i); i++ ) \ + if ( pObj->iObj2Box >= 0 ) {} else +#define Tim_ManForEachCo( p, pObj, i ) \ + for ( i = 0; (i < (p)->nCos) && ((pObj) = (p)->pCos + i); i++ ) \ + if ( pObj->iObj2Box >= 0 ) {} else +#define Tim_ManForEachBox( p, pBox, i ) \ + Vec_PtrForEachEntry( Tim_Box_t *, p->vBoxes, pBox, i ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the timing manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Tim_Man_t * Tim_ManStart( int nCis, int nCos ) +{ + Tim_Man_t * p; + int i; + p = ABC_ALLOC( Tim_Man_t, 1 ); + memset( p, 0, sizeof(Tim_Man_t) ); + p->pMemObj = Mem_FlexStart(); + p->vBoxes = Vec_PtrAlloc( 100 ); + p->nCis = nCis; + p->nCos = nCos; + p->pCis = ABC_ALLOC( Tim_Obj_t, nCis ); + memset( p->pCis, 0, sizeof(Tim_Obj_t) * nCis ); + p->pCos = ABC_ALLOC( Tim_Obj_t, nCos ); + memset( p->pCos, 0, sizeof(Tim_Obj_t) * nCos ); + for ( i = 0; i < nCis; i++ ) + { + p->pCis[i].Id = i; + p->pCis[i].iObj2Box = p->pCis[i].iObj2Num = -1; + p->pCis[i].timeReq = TIM_ETERNITY; + p->pCis[i].timeArr = 0.0; + p->pCis[i].TravId = 0; + } + for ( i = 0; i < nCos; i++ ) + { + p->pCos[i].Id = i; + p->pCos[i].iObj2Box = p->pCos[i].iObj2Num = -1; + p->pCos[i].timeReq = TIM_ETERNITY; + p->pCos[i].timeArr = 0.0; + p->pCos[i].TravId = 0; + } + p->fUseTravId = 1; + return p; +} + +/**Function************************************************************* + + Synopsis [Duplicates the timing manager.] + + Description [Derives discrete-delay-model timing manager. + Useful for AIG optimization with approximate timing information.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Tim_Man_t * Tim_ManDup( Tim_Man_t * p, int fDiscrete ) +{ + Tim_Man_t * pNew; + Tim_Box_t * pBox; + float * pDelayTableNew; + int i, k; + pNew = Tim_ManStart( p->nCis, p->nCos ); + memcpy( pNew->pCis, p->pCis, sizeof(Tim_Obj_t) * p->nCis ); + memcpy( pNew->pCos, p->pCos, sizeof(Tim_Obj_t) * p->nCos ); + for ( k = 0; k < p->nCis; k++ ) + pNew->pCis[k].TravId = 0; + for ( k = 0; k < p->nCos; k++ ) + pNew->pCos[k].TravId = 0; + if ( fDiscrete ) + { + for ( k = 0; k < p->nCis; k++ ) + pNew->pCis[k].timeArr = 0.0; // modify here + // modify the required times + } + pNew->vDelayTables = Vec_PtrAlloc( 100 ); + Tim_ManForEachBox( p, pBox, i ) + { +//printf( "%d %d\n", pBox->nInputs, pBox->nOutputs ); + pDelayTableNew = ABC_ALLOC( float, pBox->nInputs * pBox->nOutputs ); + Vec_PtrPush( pNew->vDelayTables, pDelayTableNew ); + if ( fDiscrete ) + { + for ( k = 0; k < pBox->nInputs * pBox->nOutputs; k++ ) + pDelayTableNew[k] = 1.0; // modify here + +///// begin part of improved CIN/COUT propagation + for ( k = 0; k < pBox->nInputs; k++ ) // fill in the first row + pDelayTableNew[k] = 0.5; + for ( k = 0; k < pBox->nOutputs; k++ ) // fill in the first column + pDelayTableNew[k*pBox->nInputs] = 0.5; + pDelayTableNew[0] = 0.0; // fill in the first entry +///// end part of improved CIN/COUT propagation + + /// change +// pDelayTableNew[0] = 0.0; + /// change + } + else + memcpy( pDelayTableNew, pBox->pDelayTable, sizeof(float) * pBox->nInputs * pBox->nOutputs ); + Tim_ManCreateBoxFirst( pNew, pBox->Inouts[0], pBox->nInputs, + pBox->Inouts[pBox->nInputs], pBox->nOutputs, pDelayTableNew ); + } + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the timing manager.] + + Description [Derives unit-delay-model timing manager. + Useful for levelizing the network.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Tim_Man_t * Tim_ManDupUnit( Tim_Man_t * p ) +{ + Tim_Man_t * pNew; + Tim_Box_t * pBox; + float * pDelayTableNew; + int i, k; + pNew = Tim_ManStart( p->nCis, p->nCos ); + memcpy( pNew->pCis, p->pCis, sizeof(Tim_Obj_t) * p->nCis ); + memcpy( pNew->pCos, p->pCos, sizeof(Tim_Obj_t) * p->nCos ); + for ( k = 0; k < p->nCis; k++ ) + { + pNew->pCis[k].TravId = 0; + pNew->pCis[k].timeArr = 0.0; + } + for ( k = 0; k < p->nCos; k++ ) + pNew->pCos[k].TravId = 0; + pNew->vDelayTables = Vec_PtrAlloc( 100 ); + Tim_ManForEachBox( p, pBox, i ) + { + pDelayTableNew = ABC_ALLOC( float, pBox->nInputs * pBox->nOutputs ); + Vec_PtrPush( pNew->vDelayTables, pDelayTableNew ); + for ( k = 0; k < pBox->nInputs * pBox->nOutputs; k++ ) + pDelayTableNew[k] = 1.0; + Tim_ManCreateBoxFirst( pNew, pBox->Inouts[0], pBox->nInputs, + pBox->Inouts[pBox->nInputs], pBox->nOutputs, pDelayTableNew ); + } + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the timing manager.] + + Description [Derives the approximate timing manager with realistic delays + but without white-boxes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Tim_Man_t * Tim_ManDupApprox( Tim_Man_t * p ) +{ + Tim_Man_t * pNew; + int k; + pNew = Tim_ManStart( p->nCis, p->nCos ); + for ( k = 0; k < p->nCis; k++ ) + if ( p->pCis[k].iObj2Box == -1 ) + pNew->pCis[k].timeArr = p->pCis[k].timeArr; + else + pNew->pCis[k].timeArr = p->pCis[k].timeReq; + for ( k = 0; k < p->nCos; k++ ) + pNew->pCos[k].timeReq = p->pCos[k].timeReq; + return pNew; +} + +/**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( float *, p->vDelayTables, pTable, i ) + ABC_FREE( pTable ); + Vec_PtrFree( p->vDelayTables ); + } + Vec_PtrFree( p->vBoxes ); + Mem_FlexStop( p->pMemObj, 0 ); + ABC_FREE( p->pCis ); + ABC_FREE( p->pCos ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Stops the timing manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Tim_ManStopP( Tim_Man_t ** p ) +{ + if ( *p == NULL ) + return; + Tim_ManStop( *p ); + *p = NULL; +} + +/**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_ManForEachCi( p, pObj, i ) + printf( "pi%5d : arr = %5.3f req = %5.3f\n", i, pObj->timeArr, pObj->timeReq ); + Tim_ManForEachCo( 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 [Disables the use of the traversal ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Tim_ManTravIdDisable( Tim_Man_t * p ) +{ + p->fUseTravId = 0; +} + +/**Function************************************************************* + + Synopsis [Enables the use of the traversal ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Tim_ManTravIdEnable( Tim_Man_t * p ) +{ + p->fUseTravId = 1; +} + +/**Function************************************************************* + + Synopsis [Label box inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Tim_ManSetCurrentTravIdBoxInputs( Tim_Man_t * p, int iBox ) +{ + Tim_Box_t * pBox; + Tim_Obj_t * pObj; + int i; + pBox = Tim_ManBox( p, iBox ); + Tim_ManBoxForEachInput( p, pBox, pObj, i ) + pObj->TravId = p->nTravIds; +} + +/**Function************************************************************* + + Synopsis [Label box outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Tim_ManSetCurrentTravIdBoxOutputs( Tim_Man_t * p, int iBox ) +{ + Tim_Box_t * pBox; + Tim_Obj_t * pObj; + int i; + pBox = Tim_ManBox( p, iBox ); + Tim_ManBoxForEachOutput( p, pBox, pObj, i ) + pObj->TravId = p->nTravIds; +} + +/**Function************************************************************* + + Synopsis [Label box inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Tim_ManSetPreviousTravIdBoxInputs( Tim_Man_t * p, int iBox ) +{ + Tim_Box_t * pBox; + Tim_Obj_t * pObj; + int i; + pBox = Tim_ManBox( p, iBox ); + Tim_ManBoxForEachInput( p, pBox, pObj, i ) + pObj->TravId = p->nTravIds - 1; +} + +/**Function************************************************************* + + Synopsis [Label box outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Tim_ManSetPreviousTravIdBoxOutputs( Tim_Man_t * p, int iBox ) +{ + Tim_Box_t * pBox; + Tim_Obj_t * pObj; + int i; + pBox = Tim_ManBox( p, iBox ); + Tim_ManBoxForEachOutput( p, pBox, pObj, i ) + pObj->TravId = p->nTravIds - 1; +} + +/**Function************************************************************* + + Synopsis [Updates required time of the PO.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Tim_ManIsCiTravIdCurrent( Tim_Man_t * p, int iCi ) +{ + assert( iCi < p->nCis ); + assert( p->fUseTravId ); + return p->pCis[iCi].TravId == p->nTravIds; +} + +/**Function************************************************************* + + Synopsis [Updates required time of the PO.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Tim_ManIsCoTravIdCurrent( Tim_Man_t * p, int iCo ) +{ + assert( iCo < p->nCos ); + assert( p->fUseTravId ); + return p->pCos[iCo].TravId == p->nTravIds; +} + +/**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->nCos ); + pBox->Inouts[i] = pIns[i]; + p->pCos[pIns[i]].iObj2Box = pBox->iBox; + p->pCos[pIns[i]].iObj2Num = i; + } + for ( i = 0; i < nOuts; i++ ) + { + assert( pOuts[i] < p->nCis ); + pBox->Inouts[nIns+i] = pOuts[i]; + p->pCis[pOuts[i]].iObj2Box = pBox->iBox; + p->pCis[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->nCos ); + pBox->Inouts[i] = firstIn+i; + p->pCos[firstIn+i].iObj2Box = pBox->iBox; + p->pCos[firstIn+i].iObj2Num = i; + } + for ( i = 0; i < nOuts; i++ ) + { + assert( firstOut+i < p->nCis ); + pBox->Inouts[nIns+i] = firstOut+i; + p->pCis[firstOut+i].iObj2Box = pBox->iBox; + p->pCis[firstOut+i].iObj2Num = i; + } +// if ( pBox->iBox < 50 ) +// printf( "%4d %4d %4d %4d \n", firstIn, nIns, firstOut, nOuts ); +} + + + +/**Function************************************************************* + + Synopsis [Increments the trav ID of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Tim_ManIncrementTravId( Tim_Man_t * p ) +{ + int i; + if ( p->nTravIds >= (1<<30)-1 ) + { + p->nTravIds = 0; + for ( i = 0; i < p->nCis; i++ ) + p->pCis[i].TravId = 0; + for ( i = 0; i < p->nCos; i++ ) + p->pCos[i].TravId = 0; + } + assert( p->nTravIds < (1<<30)-1 ); + p->nTravIds++; +} + +/**Function************************************************************* + + Synopsis [Initializes arrival time of the PI.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Tim_ManInitCiArrival( Tim_Man_t * p, int iCi, float Delay ) +{ + assert( iCi < p->nCis ); + p->pCis[iCi].timeArr = Delay; +} + +/**Function************************************************************* + + Synopsis [Initializes required time of the PO.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Tim_ManInitCoRequired( Tim_Man_t * p, int iCo, float Delay ) +{ + assert( iCo < p->nCos ); + p->pCos[iCo].timeReq = Delay; +} + +/**Function************************************************************* + + Synopsis [Updates required time of the PO.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Tim_ManSetCoArrival( Tim_Man_t * p, int iCo, float Delay ) +{ + assert( iCo < p->nCos ); + assert( !p->fUseTravId || p->pCos[iCo].TravId != p->nTravIds ); + p->pCos[iCo].timeArr = Delay; + p->pCos[iCo].TravId = p->nTravIds; +} + +/**Function************************************************************* + + Synopsis [Updates arrival time of the PI.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Tim_ManSetCiRequired( Tim_Man_t * p, int iCi, float Delay ) +{ + assert( iCi < p->nCis ); + assert( !p->fUseTravId || p->pCis[iCi].TravId != p->nTravIds ); + p->pCis[iCi].timeReq = Delay; + p->pCis[iCi].TravId = p->nTravIds; +} + +/**Function************************************************************* + + Synopsis [Updates required time of the PO.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Tim_ManSetCoRequired( Tim_Man_t * p, int iCo, float Delay ) +{ + assert( iCo < p->nCos ); + assert( !p->fUseTravId || p->pCos[iCo].TravId != p->nTravIds ); + p->pCos[iCo].timeReq = Delay; + p->pCos[iCo].TravId = p->nTravIds; +} + +/**Function************************************************************* + + Synopsis [Sets the correct required times for all POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Tim_ManSetCiArrivalAll( Tim_Man_t * p, float Delay ) +{ + Tim_Obj_t * pObj; + int i; + Tim_ManForEachCi( p, pObj, i ) + Tim_ManInitCiArrival( p, i, Delay ); +} + +/**Function************************************************************* + + Synopsis [Sets the correct required times for all POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Tim_ManSetCoRequiredAll( Tim_Man_t * p, float Delay ) +{ + Tim_Obj_t * pObj; + int i; + Tim_ManForEachCo( p, pObj, i ) + { + Tim_ManSetCoRequired( p, i, Delay ); +//printf( "%d ", i ); + } +} + + +/**Function************************************************************* + + Synopsis [Returns PI arrival time.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Tim_ManGetCiArrival( Tim_Man_t * p, int iCi ) +{ + Tim_Box_t * pBox; + Tim_Obj_t * pObjThis, * pObj, * pObjRes; + float * pDelays, DelayBest; + int i, k; + // consider the already processed PI + pObjThis = Tim_ManCi( p, iCi ); + if ( p->fUseTravId && pObjThis->TravId == p->nTravIds ) + return pObjThis->timeArr; + pObjThis->TravId = p->nTravIds; + // consider the main PI + pBox = Tim_ManCiBox( p, iCi ); + if ( pBox == NULL ) + return pObjThis->timeArr; + // update box timing + pBox->TravId = p->nTravIds; + // get the arrival times of the inputs of the box (POs) + if ( p->fUseTravId ) + Tim_ManBoxForEachInput( p, pBox, pObj, i ) + if ( pObj->TravId != p->nTravIds ) + printf( "Tim_ManGetCiArrival(): Input 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 = -TIM_ETERNITY; + Tim_ManBoxForEachInput( p, pBox, pObj, k ) + DelayBest = Abc_MaxInt( 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_ManGetCoRequired( Tim_Man_t * p, int iCo ) +{ + Tim_Box_t * pBox; + Tim_Obj_t * pObjThis, * pObj, * pObjRes; + float * pDelays, DelayBest; + int i, k; + // consider the already processed PO + pObjThis = Tim_ManCo( p, iCo ); + if ( p->fUseTravId && pObjThis->TravId == p->nTravIds ) + return pObjThis->timeReq; + pObjThis->TravId = p->nTravIds; + // consider the main PO + pBox = Tim_ManCoBox( p, iCo ); + if ( pBox == NULL ) + return pObjThis->timeReq; + // update box timing + pBox->TravId = p->nTravIds; + // get the required times of the outputs of the box (PIs) + if ( p->fUseTravId ) + Tim_ManBoxForEachOutput( p, pBox, pObj, i ) + if ( pObj->TravId != p->nTravIds ) + printf( "Tim_ManGetCoRequired(): Output required times of the box are not up to date!\n" ); + // compute the required times for each input of the box (POs) + Tim_ManBoxForEachInput( p, pBox, pObjRes, i ) + { + DelayBest = TIM_ETERNITY; + Tim_ManBoxForEachOutput( p, pBox, pObj, k ) + { + pDelays = pBox->pDelayTable + k * pBox->nInputs; + DelayBest = Abc_MinInt( DelayBest, pObj->timeReq - pDelays[i] ); + } + pObjRes->timeReq = DelayBest; + pObjRes->TravId = p->nTravIds; + } + return pObjThis->timeReq; +} + +/**Function************************************************************* + + Synopsis [Returns the box number for the given input.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Tim_ManBoxForCi( Tim_Man_t * p, int iCi ) +{ + if ( iCi >= p->nCis ) + return -1; + return p->pCis[iCi].iObj2Box; +} + +/**Function************************************************************* + + Synopsis [Returns the box number for the given output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Tim_ManBoxForCo( Tim_Man_t * p, int iCo ) +{ + if ( iCo >= p->nCos ) + return -1; + return p->pCos[iCo].iObj2Box; +} + +/**Function************************************************************* + + Synopsis [Returns the first input of the box.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Tim_ManBoxInputFirst( Tim_Man_t * p, int iBox ) +{ + Tim_Box_t * pBox = (Tim_Box_t *)Vec_PtrEntry( p->vBoxes, iBox ); + return pBox->Inouts[0]; +} + +/**Function************************************************************* + + Synopsis [Returns the first input of the box.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Tim_ManBoxOutputFirst( Tim_Man_t * p, int iBox ) +{ + Tim_Box_t * pBox = (Tim_Box_t *)Vec_PtrEntry( p->vBoxes, iBox ); + return pBox->Inouts[pBox->nInputs]; +} + +/**Function************************************************************* + + Synopsis [Returns the first input of the box.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Tim_ManBoxInputNum( Tim_Man_t * p, int iBox ) +{ + Tim_Box_t * pBox = (Tim_Box_t *)Vec_PtrEntry( p->vBoxes, iBox ); + return pBox->nInputs; +} + +/**Function************************************************************* + + Synopsis [Returns the first input of the box.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Tim_ManBoxOutputNum( Tim_Man_t * p, int iBox ) +{ + Tim_Box_t * pBox = (Tim_Box_t *)Vec_PtrEntry( p->vBoxes, iBox ); + return pBox->nOutputs; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Tim_ManChangeForAdders( Tim_Man_t * p ) +{ + Tim_Box_t * pBox; + int i; + Tim_ManForEachBox( p, pBox, i ) + pBox->pDelayTable[0] = 0.0; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/misc/tim/tim.h b/src/misc/tim/tim.h new file mode 100644 index 00000000..d921bcc5 --- /dev/null +++ b/src/misc/tim/tim.h @@ -0,0 +1,110 @@ +/**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 ABC__aig__tim__tim_h +#define ABC__aig__tim__tim_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Tim_Man_t_ Tim_Man_t; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define TIM_ETERNITY 10000 + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// SEQUENTIAL ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== time.c ===========================================================*/ +extern Tim_Man_t * Tim_ManStart( int nCis, int nCos ); +extern Tim_Man_t * Tim_ManDup( Tim_Man_t * p, int fDiscrete ); +extern Tim_Man_t * Tim_ManDupUnit( Tim_Man_t * p ); +extern Tim_Man_t * Tim_ManDupApprox( Tim_Man_t * p ); +extern void Tim_ManStop( Tim_Man_t * p ); +extern void Tim_ManStopP( Tim_Man_t ** p ); +extern void Tim_ManPrint( Tim_Man_t * p ); +extern void Tim_ManTravIdDisable( Tim_Man_t * p ); +extern void Tim_ManTravIdEnable( Tim_Man_t * p ); +extern void Tim_ManSetCurrentTravIdBoxInputs( Tim_Man_t * p, int iBox ); +extern void Tim_ManSetCurrentTravIdBoxOutputs( Tim_Man_t * p, int iBox ); +extern void Tim_ManSetPreviousTravIdBoxInputs( Tim_Man_t * p, int iBox ); +extern void Tim_ManSetPreviousTravIdBoxOutputs( Tim_Man_t * p, int iBox ); +extern int Tim_ManIsCiTravIdCurrent( Tim_Man_t * p, int iCi ); +extern int Tim_ManIsCoTravIdCurrent( Tim_Man_t * p, int iCo ); +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_ManInitCiArrival( Tim_Man_t * p, int iCi, float Delay ); +extern void Tim_ManInitCoRequired( Tim_Man_t * p, int iCo, float Delay ); +extern void Tim_ManSetCoArrival( Tim_Man_t * p, int iCo, float Delay ); +extern void Tim_ManSetCiRequired( Tim_Man_t * p, int iCi, float Delay ); +extern void Tim_ManSetCoRequired( Tim_Man_t * p, int iCo, float Delay ); +extern void Tim_ManSetCiArrivalAll( Tim_Man_t * p, float Delay ); +extern void Tim_ManSetCoRequiredAll( Tim_Man_t * p, float Delay ); +extern float Tim_ManGetCiArrival( Tim_Man_t * p, int iCi ); +extern float Tim_ManGetCoRequired( Tim_Man_t * p, int iCo ); +extern int Tim_ManBoxForCi( Tim_Man_t * p, int iCo ); +extern int Tim_ManBoxForCo( Tim_Man_t * p, int iCi ); +extern int Tim_ManBoxInputFirst( Tim_Man_t * p, int iBox ); +extern int Tim_ManBoxOutputFirst( Tim_Man_t * p, int iBox ); +extern int Tim_ManBoxInputNum( Tim_Man_t * p, int iBox ); +extern int Tim_ManBoxOutputNum( Tim_Man_t * p, int iBox ); +extern void Tim_ManChangeForAdders( Tim_Man_t * p ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/misc/util/abc_global.h b/src/misc/util/abc_global.h index 61aa9327..83c86f28 100644 --- a/src/misc/util/abc_global.h +++ b/src/misc/util/abc_global.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __ABC_GLOBAL_H__ -#define __ABC_GLOBAL_H__ +#ifndef ABC__misc__util__abc_global_h +#define ABC__misc__util__abc_global_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// @@ -200,11 +200,7 @@ typedef ABC_UINT64_T word; /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// - -#define ABC_ABS(a) ((a) < 0 ? -(a) : (a)) -#define ABC_MAX(a,b) ((a) > (b) ? (a) : (b)) -#define ABC_MIN(a,b) ((a) < (b) ? (a) : (b)) -#define ABC_INFINITY (100000000) +#define ABC_INFINITY (100000000) #define ABC_PRT(a,t) (printf("%s = ", (a)), printf("%7.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC))) #define ABC_PRTr(a,t) (printf("%s = ", (a)), printf("%7.2f sec\r", (float)(t)/(float)(CLOCKS_PER_SEC))) @@ -236,17 +232,37 @@ ABC_NAMESPACE_HEADER_START ((type *) Util_MemRecAlloc(malloc(sizeof(type) * (num))))) #endif -static inline int Abc_AbsInt( int a ) { return a < 0 ? -a : a; } -static inline int Abc_MaxInt( int a, int b ) { return a > b ? a : b; } -static inline int Abc_MinInt( int a, int b ) { return a < b ? a : b; } -static inline word Abc_MaxWord( word a, word b ) { return a > b ? a : b; } -static inline word Abc_MinWord( word a, word b ) { return a < b ? a : b; } -static inline float Abc_AbsFloat( float a ) { return a < 0 ? -a : a; } -static inline float Abc_MaxFloat( float a, float b ) { return a > b ? a : b; } -static inline float Abc_MinFloat( float a, float b ) { return a < b ? a : b; } -static inline double Abc_AbsDouble( double a ) { return a < 0 ? -a : a; } -static inline double Abc_MaxDouble( double a, double b ) { return a > b ? a : b; } -static inline double Abc_MinDouble( double a, double b ) { return a < b ? a : b; } +static inline int Abc_AbsInt( int a ) { return a < 0 ? -a : a; } +static inline int Abc_MaxInt( int a, int b ) { return a > b ? a : b; } +static inline int Abc_MinInt( int a, int b ) { return a < b ? a : b; } +static inline word Abc_MaxWord( word a, word b ) { return a > b ? a : b; } +static inline word Abc_MinWord( word a, word b ) { return a < b ? a : b; } +static inline float Abc_AbsFloat( float a ) { return a < 0 ? -a : a; } +static inline float Abc_MaxFloat( float a, float b ) { return a > b ? a : b; } +static inline float Abc_MinFloat( float a, float b ) { return a < b ? a : b; } +static inline double Abc_AbsDouble( double a ) { return a < 0 ? -a : a; } +static inline double Abc_MaxDouble( double a, double b ) { return a > b ? a : b; } +static inline double Abc_MinDouble( double a, double b ) { return a < b ? a : b; } + +static inline int Abc_Float2Int( float Val ) { union { int x; float y; } v; v.y = Val; return v.x; } +static inline float Abc_Int2Float( int Num ) { union { int x; float y; } v; v.x = Num; return v.y; } +static inline int Abc_Base2Log( unsigned n ) { int r; if ( n < 2 ) return n; for ( r = 0, n--; n; n >>= 1, r++ ); return r; } +static inline int Abc_Base10Log( unsigned n ) { int r; if ( n < 2 ) return n; for ( r = 0, n--; n; n /= 10, r++ ); return r; } +static inline int Abc_Base16Log( unsigned n ) { int r; if ( n < 2 ) return n; for ( r = 0, n--; n; n /= 16, r++ ); return r; } +static inline char * Abc_UtilStrsav( char * s ) { return s ? strcpy(ABC_ALLOC(char, strlen(s)+1), s) : NULL; } +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_InfoMask( int nVar ) { return (~(unsigned)0) >> (32-nVar); } + +static inline int Abc_Var2Lit( int Var, int fCompl ) { return Var + Var + fCompl; } +static inline int Abc_Lit2Var( int Lit ) { return Lit >> 1; } +static inline int Abc_LitIsCompl( int Lit ) { return Lit & 1; } +static inline int Abc_LitNot( int Lit ) { return Lit ^ 1; } +static inline int Abc_LitNotCond( int Lit, int c ) { return Lit ^ (int)(c > 0); } +static inline int Abc_LitRegular( int Lit ) { return Lit & ~01; } enum Abc_VerbLevel { diff --git a/src/misc/util/utilCex.c b/src/misc/util/utilCex.c index 37205543..80d8e141 100644 --- a/src/misc/util/utilCex.c +++ b/src/misc/util/utilCex.c @@ -32,10 +32,6 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static inline int Abc_BitWordNum( int nBits ) { return (nBits>>5) + ((nBits&31) > 0); } -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)); } - //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// diff --git a/src/misc/util/utilCex.h b/src/misc/util/utilCex.h index 556f2268..b45cd27b 100644 --- a/src/misc/util/utilCex.h +++ b/src/misc/util/utilCex.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __UTIL_CEX_H__ -#define __UTIL_CEX_H__ +#ifndef ABC__misc__util__utilCex_h +#define ABC__misc__util__utilCex_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// diff --git a/src/misc/util/utilMem.h b/src/misc/util/utilMem.h index 1f8432c1..af5873c0 100644 --- a/src/misc/util/utilMem.h +++ b/src/misc/util/utilMem.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __UTIL_INT_H__ -#define __UTIL_INT_H__ +#ifndef ABC__misc__util__utilMem_h +#define ABC__misc__util__utilMem_h //////////////////////////////////////////////////////////////////////// diff --git a/src/misc/util/utilNam.c b/src/misc/util/utilNam.c index 79565186..c6399818 100644 --- a/src/misc/util/utilNam.c +++ b/src/misc/util/utilNam.c @@ -25,7 +25,7 @@ #include #include "abc_global.h" -#include "vec.h" +#include "src/misc/vec/vec.h" #include "utilNam.h" ABC_NAMESPACE_IMPL_START @@ -304,7 +304,7 @@ void Abc_NamStrHashResize( Abc_Nam_t * p ) char * pThis; int * piPlace, * pBinsOld, iHandleOld, i;//, clk = clock(); assert( p->pBins != NULL ); -// Abc_Print( 1, "Resizing names manager hash table from %6d to %6d. ", p->nBins, Gia_PrimeCudd( 3 * p->nBins ) ); +// Abc_Print( 1, "Resizing names manager hash table from %6d to %6d. ", p->nBins, Abc_PrimeCudd( 3 * p->nBins ) ); // replace the table pBinsOld = p->pBins; p->nBins = Abc_PrimeCudd( 3 * p->nBins ); diff --git a/src/misc/util/utilNam.h b/src/misc/util/utilNam.h index ae2c099c..fd29e537 100644 --- a/src/misc/util/utilNam.h +++ b/src/misc/util/utilNam.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __UTIL_NAM_H__ -#define __UTIL_NAM_H__ +#ifndef ABC__misc__util__utilNam_h +#define ABC__misc__util__utilNam_h //////////////////////////////////////////////////////////////////////// diff --git a/src/misc/util/utilSignal.c b/src/misc/util/utilSignal.c index 2886f69b..af0948bd 100644 --- a/src/misc/util/utilSignal.c +++ b/src/misc/util/utilSignal.c @@ -20,6 +20,8 @@ #include #include +#include + #include "abc_global.h" #include "utilSignal.h" diff --git a/src/misc/util/utilSignal.h b/src/misc/util/utilSignal.h index 0ac87290..b29def80 100644 --- a/src/misc/util/utilSignal.h +++ b/src/misc/util/utilSignal.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __UTIL_SIGNAL_H__ -#define __UTIL_SIGNAL_H__ +#ifndef ABC__misc__util__utilSignal_h +#define ABC__misc__util__utilSignal_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// diff --git a/src/misc/util/util_hack.h b/src/misc/util/util_hack.h index 1a734f03..9c702bfe 100644 --- a/src/misc/util/util_hack.h +++ b/src/misc/util/util_hack.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __UTIL_HACK_H__ -#define __UTIL_HACK_H__ +#ifndef ABC__misc__util__util_hack_h +#define ABC__misc__util__util_hack_h #include #include diff --git a/src/misc/vec/vec.h b/src/misc/vec/vec.h index da5fc866..c02cafeb 100644 --- a/src/misc/vec/vec.h +++ b/src/misc/vec/vec.h @@ -18,15 +18,15 @@ ***********************************************************************/ -#ifndef __VEC_H__ -#define __VEC_H__ +#ifndef ABC__misc__vec__vec_h +#define ABC__misc__vec__vec_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// -#include "abc_global.h" +#include "src/misc/util/abc_global.h" #include "vecInt.h" #include "vecFlt.h" diff --git a/src/misc/vec/vecAtt.h b/src/misc/vec/vecAtt.h index 60b2d17a..63dd4779 100644 --- a/src/misc/vec/vecAtt.h +++ b/src/misc/vec/vecAtt.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __VEC_ATT_H__ -#define __VEC_ATT_H__ +#ifndef ABC__misc__vec__vecAtt_h +#define ABC__misc__vec__vecAtt_h //////////////////////////////////////////////////////////////////////// diff --git a/src/misc/vec/vecBit.h b/src/misc/vec/vecBit.h index 802486d9..7f0d7409 100644 --- a/src/misc/vec/vecBit.h +++ b/src/misc/vec/vecBit.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __VEC_BIT_H__ -#define __VEC_BIT_H__ +#ifndef ABC__misc__vec__vecBit_h +#define ABC__misc__vec__vecBit_h //////////////////////////////////////////////////////////////////////// diff --git a/src/misc/vec/vecFlt.h b/src/misc/vec/vecFlt.h index 8273b033..0ad6da27 100644 --- a/src/misc/vec/vecFlt.h +++ b/src/misc/vec/vecFlt.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __VEC_FLT_H__ -#define __VEC_FLT_H__ +#ifndef ABC__misc__vec__vecFlt_h +#define ABC__misc__vec__vecFlt_h //////////////////////////////////////////////////////////////////////// diff --git a/src/misc/vec/vecInt.h b/src/misc/vec/vecInt.h index 0d0c24a8..0d18f973 100644 --- a/src/misc/vec/vecInt.h +++ b/src/misc/vec/vecInt.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __VEC_INT_H__ -#define __VEC_INT_H__ +#ifndef ABC__misc__vec__vecInt_h +#define ABC__misc__vec__vecInt_h //////////////////////////////////////////////////////////////////////// diff --git a/src/misc/vec/vecPtr.h b/src/misc/vec/vecPtr.h index fe4b00b2..afad09d1 100644 --- a/src/misc/vec/vecPtr.h +++ b/src/misc/vec/vecPtr.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __VEC_PTR_H__ -#define __VEC_PTR_H__ +#ifndef ABC__misc__vec__vecPtr_h +#define ABC__misc__vec__vecPtr_h //////////////////////////////////////////////////////////////////////// diff --git a/src/misc/vec/vecStr.h b/src/misc/vec/vecStr.h index c92760f2..cec3e7e1 100644 --- a/src/misc/vec/vecStr.h +++ b/src/misc/vec/vecStr.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __VEC_STR_H__ -#define __VEC_STR_H__ +#ifndef ABC__misc__vec__vecStr_h +#define ABC__misc__vec__vecStr_h //////////////////////////////////////////////////////////////////////// diff --git a/src/misc/vec/vecVec.h b/src/misc/vec/vecVec.h index 91713291..f72bd93c 100644 --- a/src/misc/vec/vecVec.h +++ b/src/misc/vec/vecVec.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __VEC_VEC_H__ -#define __VEC_VEC_H__ +#ifndef ABC__misc__vec__vecVec_h +#define ABC__misc__vec__vecVec_h //////////////////////////////////////////////////////////////////////// diff --git a/src/misc/vec/vecWrd.h b/src/misc/vec/vecWrd.h index 94449262..ab8e8306 100644 --- a/src/misc/vec/vecWrd.h +++ b/src/misc/vec/vecWrd.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __VEC_WRD_H__ -#define __VEC_WRD_H__ +#ifndef ABC__misc__vec__vecWrd_h +#define ABC__misc__vec__vecWrd_h //////////////////////////////////////////////////////////////////////// diff --git a/src/misc/zlib/adler32.c b/src/misc/zlib/adler32.c index 7783d96c..10208ab4 100644 --- a/src/misc/zlib/adler32.c +++ b/src/misc/zlib/adler32.c @@ -8,7 +8,7 @@ #include #include #include -#include "abc_global.h" +#include "src/misc/util/abc_global.h" #include "zutil.h" diff --git a/src/misc/zlib/crc32.c b/src/misc/zlib/crc32.c index 749480ef..6c33b549 100644 --- a/src/misc/zlib/crc32.c +++ b/src/misc/zlib/crc32.c @@ -29,7 +29,7 @@ #include #include #include -#include "abc_global.h" +#include "src/misc/util/abc_global.h" #include "zutil.h" /* for STDC and FAR definitions */ diff --git a/src/misc/zlib/deflate.c b/src/misc/zlib/deflate.c index ceeeed06..e47050bd 100644 --- a/src/misc/zlib/deflate.c +++ b/src/misc/zlib/deflate.c @@ -52,7 +52,7 @@ #include #include #include -#include "abc_global.h" +#include "src/misc/util/abc_global.h" #include "deflate.h" diff --git a/src/misc/zlib/gzclose.c b/src/misc/zlib/gzclose.c index 07d6e0d9..6cd8dc3d 100644 --- a/src/misc/zlib/gzclose.c +++ b/src/misc/zlib/gzclose.c @@ -6,7 +6,7 @@ #include #include #include -#include "abc_global.h" +#include "src/misc/util/abc_global.h" #include "gzguts.h" diff --git a/src/misc/zlib/gzguts.h b/src/misc/zlib/gzguts.h index 7334b92e..f95db6c2 100644 --- a/src/misc/zlib/gzguts.h +++ b/src/misc/zlib/gzguts.h @@ -61,7 +61,7 @@ #endif #include -#include "abc_global.h" +#include "src/misc/util/abc_global.h" ABC_NAMESPACE_HEADER_START diff --git a/src/misc/zlib/gzlib.c b/src/misc/zlib/gzlib.c index 1d88baa4..4d6fdfd0 100644 --- a/src/misc/zlib/gzlib.c +++ b/src/misc/zlib/gzlib.c @@ -6,7 +6,7 @@ #include #include #include -#include "abc_global.h" +#include "src/misc/util/abc_global.h" #include "gzguts.h" diff --git a/src/misc/zlib/gzread.c b/src/misc/zlib/gzread.c index 7abe5d9c..6a4d13b6 100644 --- a/src/misc/zlib/gzread.c +++ b/src/misc/zlib/gzread.c @@ -6,7 +6,7 @@ #include #include #include -#include "abc_global.h" +#include "src/misc/util/abc_global.h" #include "gzguts.h" diff --git a/src/misc/zlib/gzwrite.c b/src/misc/zlib/gzwrite.c index bf96602c..f7482615 100644 --- a/src/misc/zlib/gzwrite.c +++ b/src/misc/zlib/gzwrite.c @@ -6,7 +6,7 @@ #include #include #include -#include "abc_global.h" +#include "src/misc/util/abc_global.h" #include "gzguts.h" diff --git a/src/misc/zlib/infback.c b/src/misc/zlib/infback.c index 882b2492..7163f99d 100644 --- a/src/misc/zlib/infback.c +++ b/src/misc/zlib/infback.c @@ -13,7 +13,7 @@ #include #include #include -#include "abc_global.h" +#include "src/misc/util/abc_global.h" #include "zutil.h" #include "inftrees.h" diff --git a/src/misc/zlib/inffast.c b/src/misc/zlib/inffast.c index 22bc98d1..fbdf94d0 100644 --- a/src/misc/zlib/inffast.c +++ b/src/misc/zlib/inffast.c @@ -6,7 +6,7 @@ #include #include #include -#include "abc_global.h" +#include "src/misc/util/abc_global.h" #include "zutil.h" #include "inftrees.h" diff --git a/src/misc/zlib/inflate.c b/src/misc/zlib/inflate.c index c68c13f5..04feb237 100644 --- a/src/misc/zlib/inflate.c +++ b/src/misc/zlib/inflate.c @@ -83,7 +83,7 @@ #include #include #include -#include "abc_global.h" +#include "src/misc/util/abc_global.h" #include "zutil.h" #include "inftrees.h" diff --git a/src/misc/zlib/inftrees.c b/src/misc/zlib/inftrees.c index ad631f85..a73e58a8 100644 --- a/src/misc/zlib/inftrees.c +++ b/src/misc/zlib/inftrees.c @@ -6,7 +6,7 @@ #include #include #include -#include "abc_global.h" +#include "src/misc/util/abc_global.h" #include "zutil.h" #include "inftrees.h" diff --git a/src/misc/zlib/trees.c b/src/misc/zlib/trees.c index e107ba04..a7365594 100644 --- a/src/misc/zlib/trees.c +++ b/src/misc/zlib/trees.c @@ -37,7 +37,7 @@ #include #include #include -#include "abc_global.h" +#include "src/misc/util/abc_global.h" #include "deflate.h" diff --git a/src/misc/zlib/uncompr.c b/src/misc/zlib/uncompr.c index e195ec3e..cf021273 100644 --- a/src/misc/zlib/uncompr.c +++ b/src/misc/zlib/uncompr.c @@ -8,7 +8,7 @@ #include #include #include -#include "abc_global.h" +#include "src/misc/util/abc_global.h" #define ZLIB_INTERNAL #include "zlib.h" diff --git a/src/misc/zlib/zlib.h b/src/misc/zlib/zlib.h index 58ff1d15..94825b55 100644 --- a/src/misc/zlib/zlib.h +++ b/src/misc/zlib/zlib.h @@ -32,7 +32,10 @@ #define ZLIB_H #include -#include "abc_global.h" +#include +#include + +#include "src/misc/util/abc_global.h" #include "zconf.h" diff --git a/src/misc/zlib/zutil.c b/src/misc/zlib/zutil.c index 17a906d8..b74b21ea 100644 --- a/src/misc/zlib/zutil.c +++ b/src/misc/zlib/zutil.c @@ -8,7 +8,7 @@ #include #include #include -#include "abc_global.h" +#include "src/misc/util/abc_global.h" #include "zutil.h" diff --git a/src/opt/cgt/cgt.h b/src/opt/cgt/cgt.h new file mode 100644 index 00000000..73edbfc3 --- /dev/null +++ b/src/opt/cgt/cgt.h @@ -0,0 +1,86 @@ +/**CFile**************************************************************** + + FileName [cgt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Clock gating package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cgt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__cgt__cgt_h +#define ABC__aig__cgt__cgt_h + + +/* + The algorithm implemented in this package is based on the paper: + A. Hurst. "Automatic synthesis of clock gating logic with controlled + netlist perturbation", DAC 2008. +*/ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Cgt_Par_t_ Cgt_Par_t; +struct Cgt_Par_t_ +{ + int nLevelMax; // the max number of levels to look for clock-gates + int nCandMax; // the max number of candidates at each node + int nOdcMax; // the max number of ODC levels to consider + int nConfMax; // the max number of conflicts at a node + int nVarsMin; // the min number of variables to recycle the SAT solver + int nFlopsMin; // the min number of flops needed to recycle the SAT solver + int fAreaOnly; // derive clock gating to minimize area + int fVerbose; // verbosity flag + int fVeryVerbose; // verbosity flag +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== cgtCore.c ==========================================================*/ +extern void Cgt_SetDefaultParams( Cgt_Par_t * p ); +extern Vec_Vec_t * Cgt_ClockGatingCandidates( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars ); +extern Aig_Man_t * Cgt_ClockGating( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/opt/cgt/cgtAig.c b/src/opt/cgt/cgtAig.c new file mode 100644 index 00000000..757ebb85 --- /dev/null +++ b/src/opt/cgt/cgtAig.c @@ -0,0 +1,601 @@ +/**CFile**************************************************************** + + FileName [cgtAig.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Clock gating package.] + + Synopsis [Creates AIG to compute clock-gating.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cgtAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cgtInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes transitive fanout cone of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cgt_ManDetectCandidates_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nLevelMax, Vec_Ptr_t * vCands ) +{ + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + return; + Aig_ObjSetTravIdCurrent(pAig, pObj); + if ( Aig_ObjIsNode(pObj) ) + { + Cgt_ManDetectCandidates_rec( pAig, Aig_ObjFanin0(pObj), nLevelMax, vCands ); + Cgt_ManDetectCandidates_rec( pAig, Aig_ObjFanin1(pObj), nLevelMax, vCands ); + } + if ( Aig_ObjLevel(pObj) <= nLevelMax ) + Vec_PtrPush( vCands, pObj ); +} + +/**Function************************************************************* + + Synopsis [Computes transitive fanout cone of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cgt_ManDetectCandidates( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nLevelMax, Vec_Ptr_t * vCands ) +{ + Vec_PtrClear( vCands ); + if ( !Aig_ObjIsNode(pObj) ) + return; + Aig_ManIncrementTravId( pAig ); + Cgt_ManDetectCandidates_rec( pAig, pObj, nLevelMax, vCands ); +} + +/**Function************************************************************* + + Synopsis [Computes transitive fanout cone of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cgt_ManDetectFanout_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nOdcMax, Vec_Ptr_t * vFanout ) +{ + Aig_Obj_t * pFanout; + int f, iFanout; + if ( Aig_ObjIsPo(pObj) || Aig_ObjLevel(pObj) > nOdcMax ) + return; + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + return; + Aig_ObjSetTravIdCurrent(pAig, pObj); + Vec_PtrPush( vFanout, pObj ); + Aig_ObjForEachFanout( pAig, pObj, pFanout, iFanout, f ) + Cgt_ManDetectFanout_rec( pAig, pFanout, nOdcMax, vFanout ); +} + +/**Function************************************************************* + + Synopsis [Computes transitive fanout cone of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cgt_ManDetectFanout( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nOdcMax, Vec_Ptr_t * vFanout ) +{ + Aig_Obj_t * pFanout; + int i, k, f, iFanout; + // collect visited nodes + Vec_PtrClear( vFanout ); + Aig_ManIncrementTravId( pAig ); + Cgt_ManDetectFanout_rec( pAig, pObj, nOdcMax, vFanout ); + // remove those nodes whose fanout is included + k = 0; + Vec_PtrForEachEntry( Aig_Obj_t *, vFanout, pObj, i ) + { + // go through the fanouts of this node + Aig_ObjForEachFanout( pAig, pObj, pFanout, iFanout, f ) + if ( !Aig_ObjIsTravIdCurrent(pAig, pFanout) ) + break; + if ( f == Aig_ObjRefs(pObj) ) // all fanouts are included + continue; + Vec_PtrWriteEntry( vFanout, k++, pObj ); + } + Vec_PtrShrink( vFanout, k ); + Vec_PtrSort( vFanout, (int (*)(void))Aig_ObjCompareIdIncrease ); + assert( Vec_PtrSize(vFanout) > 0 ); +} + +/**Function************************************************************* + + Synopsis [Computes visited nodes in the topological order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cgt_ManCollectVisited_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vVisited ) +{ + if ( Aig_ObjIsPi(pObj) ) + return; + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + return; + Aig_ObjSetTravIdCurrent(pAig, pObj); + assert( Aig_ObjIsNode(pObj) ); + Cgt_ManCollectVisited_rec( pAig, Aig_ObjFanin0(pObj), vVisited ); + Cgt_ManCollectVisited_rec( pAig, Aig_ObjFanin1(pObj), vVisited ); + Vec_PtrPush( vVisited, pObj ); +} + +/**Function************************************************************* + + Synopsis [Computes visited nodes in the topological order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cgt_ManCollectVisited( Aig_Man_t * pAig, Vec_Ptr_t * vFanout, Vec_Ptr_t * vVisited ) +{ + Aig_Obj_t * pObj; + int i; + Vec_PtrClear( vVisited ); + Aig_ManIncrementTravId( pAig ); + Vec_PtrForEachEntry( Aig_Obj_t *, vFanout, pObj, i ) + Cgt_ManCollectVisited_rec( pAig, pObj, vVisited ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Aig_Obj_t * Aig_ObjChild0CopyVec( Vec_Ptr_t * vCopy, Aig_Obj_t * pObj ) +{ return Aig_NotCond((Aig_Obj_t *)Vec_PtrEntry(vCopy, Aig_ObjFaninId0(pObj)), Aig_ObjFaninC0(pObj)); } +static inline Aig_Obj_t * Aig_ObjChild1CopyVec( Vec_Ptr_t * vCopy, Aig_Obj_t * pObj ) +{ return Aig_NotCond((Aig_Obj_t *)Vec_PtrEntry(vCopy, Aig_ObjFaninId1(pObj)), Aig_ObjFaninC1(pObj)); } + +/**Function************************************************************* + + Synopsis [Derives miter for clock-gating.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Cgt_ManConstructCareCondition( Cgt_Man_t * p, Aig_Man_t * pNew, Aig_Obj_t * pObjLo, Vec_Ptr_t * vCopy0, Vec_Ptr_t * vCopy1 ) +{ + Aig_Obj_t * pMiter, * pObj, * pTemp; + int i; + assert( Aig_ObjIsPi(pObjLo) ); + // detect nodes and their cone + Cgt_ManDetectFanout( p->pAig, pObjLo, p->pPars->nOdcMax, p->vFanout ); + Cgt_ManCollectVisited( p->pAig, p->vFanout, p->vVisited ); + // add new variables if the observability condition depends on PI variables + Vec_PtrForEachEntry( Aig_Obj_t *, p->vVisited, pObj, i ) + { + assert( Aig_ObjIsNode(pObj) ); + if ( Saig_ObjIsPi(p->pAig, Aig_ObjFanin0(pObj)) && Vec_PtrEntry(vCopy0, Aig_ObjFaninId0(pObj)) == NULL ) + { + pTemp = Aig_ObjCreatePi( pNew ); + Vec_PtrWriteEntry( vCopy0, Aig_ObjFaninId0(pObj), pTemp ); + Vec_PtrWriteEntry( vCopy1, Aig_ObjFaninId0(pObj), pTemp ); + } + if ( Saig_ObjIsPi(p->pAig, Aig_ObjFanin1(pObj)) && Vec_PtrEntry(vCopy0, Aig_ObjFaninId1(pObj)) == NULL ) + { + pTemp = Aig_ObjCreatePi( pNew ); + Vec_PtrWriteEntry( vCopy0, Aig_ObjFaninId1(pObj), pTemp ); + Vec_PtrWriteEntry( vCopy1, Aig_ObjFaninId1(pObj), pTemp ); + } + } + // construct AIGs for the nodes + Vec_PtrForEachEntry( Aig_Obj_t *, p->vVisited, pObj, i ) + { + pTemp = Aig_And( pNew, Aig_ObjChild0CopyVec(vCopy0, pObj), Aig_ObjChild1CopyVec(vCopy0, pObj) ); + Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObj), pTemp ); + pTemp = Aig_And( pNew, Aig_ObjChild0CopyVec(vCopy1, pObj), Aig_ObjChild1CopyVec(vCopy1, pObj) ); + Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObj), pTemp ); + } + // construct the care miter + pMiter = Aig_ManConst0( pNew ); + Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanout, pObj, i ) + { + pTemp = Aig_Exor( pNew, (Aig_Obj_t *)Vec_PtrEntry(vCopy0, Aig_ObjId(pObj)), (Aig_Obj_t *)Vec_PtrEntry(vCopy1, Aig_ObjId(pObj)) ); + pMiter = Aig_Or( pNew, pMiter, pTemp ); + } + return pMiter; +} + +/**Function************************************************************* + + Synopsis [Derives AIG for clock-gating.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Cgt_ManDeriveAigForGating( Cgt_Man_t * p ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pCare, * pMiter; + Vec_Ptr_t * vCopy0, * vCopy1; + int i; + assert( Aig_ManRegNum(p->pAig) ); + pNew = Aig_ManStart( Aig_ManObjNumMax(p->pAig) ); + pNew->pName = Abc_UtilStrsav( "CG_miter" ); + // build the first frame + Aig_ManConst1(p->pAig)->pData = Aig_ManConst1(pNew); + Aig_ManForEachPi( p->pAig, pObj, i ) + pObj->pData = Aig_ObjCreatePi( pNew ); + Aig_ManForEachNode( p->pAig, pObj, i ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); +// Saig_ManForEachPo( p->pAig, pObj, i ) +// pObj->pData = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); + if ( p->pPars->nOdcMax > 0 ) + { + // create storage for observability conditions + vCopy0 = Vec_PtrStart( Aig_ManObjNumMax(p->pAig) ); + vCopy1 = Vec_PtrStart( Aig_ManObjNumMax(p->pAig) ); + // initialize register outputs + Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) + { + Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) ); + Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) ); + } + // compute observability condition for each latch output + Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) + { + // set the constants + Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObjLo), Aig_ManConst0(pNew) ); + Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObjLo), Aig_ManConst1(pNew) ); + // compute condition + pCare = Cgt_ManConstructCareCondition( p, pNew, pObjLo, vCopy0, vCopy1 ); + // restore the values + Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) ); + Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) ); + // compute the miter + pMiter = Aig_Exor( pNew, (Aig_Obj_t *)pObjLo->pData, Aig_ObjChild0Copy(pObjLi) ); + pMiter = Aig_And( pNew, pMiter, pCare ); + pObjLi->pData = Aig_ObjCreatePo( pNew, pMiter ); + } + Vec_PtrFree( vCopy0 ); + Vec_PtrFree( vCopy1 ); + } + else + { + // construct clock-gating miters for each register input + Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) + { + pMiter = Aig_Exor( pNew, (Aig_Obj_t *)pObjLo->pData, Aig_ObjChild0Copy(pObjLi) ); + pObjLi->pData = Aig_ObjCreatePo( pNew, pMiter ); + } + } + Aig_ManCleanup( pNew ); + Aig_ManSetPioNumbers( pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Adds relevant constraints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Cgt_ManConstructCare_rec( Aig_Man_t * pCare, Aig_Obj_t * pObj, Aig_Man_t * pNew ) +{ + Aig_Obj_t * pObj0, * pObj1; + if ( Aig_ObjIsTravIdCurrent( pCare, pObj ) ) + return (Aig_Obj_t *)pObj->pData; + Aig_ObjSetTravIdCurrent( pCare, pObj ); + if ( Aig_ObjIsPi(pObj) ) + return (Aig_Obj_t *)(pObj->pData = NULL); + pObj0 = Cgt_ManConstructCare_rec( pCare, Aig_ObjFanin0(pObj), pNew ); + if ( pObj0 == NULL ) + return (Aig_Obj_t *)(pObj->pData = NULL); + pObj1 = Cgt_ManConstructCare_rec( pCare, Aig_ObjFanin1(pObj), pNew ); + if ( pObj1 == NULL ) + return (Aig_Obj_t *)(pObj->pData = NULL); + pObj0 = Aig_NotCond( pObj0, Aig_ObjFaninC0(pObj) ); + pObj1 = Aig_NotCond( pObj1, Aig_ObjFaninC1(pObj) ); + return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, pObj0, pObj1 )); +} + +/**Function************************************************************* + + Synopsis [Builds constraints belonging to the given partition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cgt_ManConstructCare( Aig_Man_t * pNew, Aig_Man_t * pCare, Vec_Vec_t * vSuppsInv, Vec_Ptr_t * vLeaves ) +{ + Vec_Int_t * vOuts; + Aig_Obj_t * pLeaf, * pPi, * pPo, * pObjAig; + int i, k, iOut; + // go through the PIs of the partition + // label the corresponding PIs of the care set + Aig_ManIncrementTravId( pCare ); + Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pLeaf, i ) + { + pPi = Aig_ManPi( pCare, Aig_ObjPioNum(pLeaf) ); + Aig_ObjSetTravIdCurrent( pCare, pPi ); + pPi->pData = pLeaf->pData; + } + // construct the constraints + Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pLeaf, i ) + { + vOuts = Vec_VecEntryInt( vSuppsInv, Aig_ObjPioNum(pLeaf) ); + Vec_IntForEachEntry( vOuts, iOut, k ) + { + pPo = Aig_ManPo( pCare, iOut ); + if ( Aig_ObjIsTravIdCurrent( pCare, pPo ) ) + continue; + Aig_ObjSetTravIdCurrent( pCare, pPo ); + if ( Aig_ObjFanin0(pPo) == Aig_ManConst1(pCare) ) + continue; + pObjAig = Cgt_ManConstructCare_rec( pCare, Aig_ObjFanin0(pPo), pNew ); + if ( pObjAig == NULL ) + continue; + pObjAig = Aig_NotCond( pObjAig, Aig_ObjFaninC0(pPo) ); + Aig_ObjCreatePo( pNew, pObjAig ); + } + } +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG recursively.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Cgt_ManDupPartition_rec( Aig_Man_t * pNew, Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vLeaves ) +{ + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + return (Aig_Obj_t *)pObj->pData; + Aig_ObjSetTravIdCurrent(pAig, pObj); + if ( Aig_ObjIsPi(pObj) ) + { + pObj->pData = Aig_ObjCreatePi( pNew ); + Vec_PtrPush( vLeaves, pObj ); + return (Aig_Obj_t *)pObj->pData; + } + Cgt_ManDupPartition_rec( pNew, pAig, Aig_ObjFanin0(pObj), vLeaves ); + Cgt_ManDupPartition_rec( pNew, pAig, Aig_ObjFanin1(pObj), vLeaves ); + return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) )); +} + +/**Function************************************************************* + + Synopsis [Duplicates register outputs starting from the given one.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Cgt_ManDupPartition( Aig_Man_t * pFrame, int nVarsMin, int nFlopsMin, int iStart, Aig_Man_t * pCare, Vec_Vec_t * vSuppsInv, int * pnOutputs ) +{ + Vec_Ptr_t * vRoots, * vLeaves, * vPos; + Aig_Man_t * pNew; + Aig_Obj_t * pObj; + int i; + assert( Aig_ManRegNum(pFrame) == 0 ); + vRoots = Vec_PtrAlloc( 100 ); + vLeaves = Vec_PtrAlloc( 100 ); + vPos = Vec_PtrAlloc( 100 ); + pNew = Aig_ManStart( nVarsMin ); + pNew->pName = Abc_UtilStrsav( "partition" ); + Aig_ManIncrementTravId( pFrame ); + Aig_ManConst1(pFrame)->pData = Aig_ManConst1(pNew); + Aig_ObjSetTravIdCurrent( pFrame, Aig_ManConst1(pFrame) ); + for ( i = iStart; i < iStart + nFlopsMin && i < Aig_ManPoNum(pFrame); i++ ) + { + pObj = Aig_ManPo( pFrame, i ); + Cgt_ManDupPartition_rec( pNew, pFrame, Aig_ObjFanin0(pObj), vLeaves ); + Vec_PtrPush( vRoots, Aig_ObjChild0Copy(pObj) ); + Vec_PtrPush( vPos, pObj ); + } + for ( ; Aig_ManObjNum(pNew) < nVarsMin && i < Aig_ManPoNum(pFrame); i++ ) + { + pObj = Aig_ManPo( pFrame, i ); + Cgt_ManDupPartition_rec( pNew, pFrame, Aig_ObjFanin0(pObj), vLeaves ); + Vec_PtrPush( vRoots, Aig_ObjChild0Copy(pObj) ); + Vec_PtrPush( vPos, pObj ); + } + assert( nFlopsMin >= Vec_PtrSize(vRoots) || Vec_PtrSize(vRoots) >= nFlopsMin ); + // create constaints + if ( pCare ) + Cgt_ManConstructCare( pNew, pCare, vSuppsInv, vLeaves ); + // create POs + Vec_PtrForEachEntry( Aig_Obj_t *, vPos, pObj, i ) + pObj->pData = (Aig_Obj_t *)Aig_ObjCreatePo( pNew, (Aig_Obj_t *)Vec_PtrEntry(vRoots, i) ); + if ( pnOutputs != NULL ) + *pnOutputs = Vec_PtrSize( vPos ); + Vec_PtrFree( vRoots ); + Vec_PtrFree( vLeaves ); + Vec_PtrFree( vPos ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Implements one clock-gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Cgt_ManBuildClockGate( Aig_Man_t * pNew, Vec_Ptr_t * vGates ) +{ + Aig_Obj_t * pGate, * pTotal; + int i; + assert( Vec_PtrSize(vGates) > 0 ); + pTotal = Aig_ManConst0(pNew); + Vec_PtrForEachEntry( Aig_Obj_t *, vGates, pGate, i ) + { + if ( Aig_Regular(pGate)->pNext ) + pGate = Aig_NotCond( Aig_Regular(pGate)->pNext, Aig_IsComplement(pGate) ); + else + pGate = Aig_NotCond( (Aig_Obj_t *)Aig_Regular(pGate)->pData, Aig_IsComplement(pGate) ); + pTotal = Aig_Or( pNew, pTotal, pGate ); + } + return pTotal; +} + +/**Function************************************************************* + + Synopsis [Derives AIG after clock-gating.] + + Description [The array contains, for each flop, its gate if present.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Cgt_ManDeriveGatedAig( Aig_Man_t * pAig, Vec_Vec_t * vGates, int fReduce, int * pnUsedNodes ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo, * pGateNew; + Vec_Ptr_t * vOne; + int i, k; + Aig_ManCleanNext( pAig ); + // label nodes + Vec_VecForEachEntry( Aig_Obj_t *, vGates, pObj, i, k ) + { + if ( Aig_IsComplement(pObj) ) + Aig_Regular(pObj)->fMarkB = 1; + else + Aig_Regular(pObj)->fMarkA = 1; + } + // construct AIG + assert( Aig_ManRegNum(pAig) ); + pNew = Aig_ManStart( Aig_ManObjNumMax(pAig) ); + pNew->pName = Abc_UtilStrsav( pAig->pName ); + pNew->pSpec = Abc_UtilStrsav( pAig->pSpec ); + Aig_ManConst1(pAig)->pData = Aig_ManConst1(pNew); + Aig_ManForEachPi( pAig, pObj, i ) + pObj->pData = Aig_ObjCreatePi( pNew ); + if ( fReduce ) + { + Aig_ManForEachNode( pAig, pObj, i ) + { + assert( !(pObj->fMarkA && pObj->fMarkB) ); + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + if ( pObj->fMarkA ) + { + pObj->pNext = (Aig_Obj_t *)pObj->pData; + pObj->pData = Aig_ManConst0(pNew); + } + else if ( pObj->fMarkB ) + { + pObj->pNext = (Aig_Obj_t *)pObj->pData; + pObj->pData = Aig_ManConst1(pNew); + } + } + } + else + { + Aig_ManForEachNode( pAig, pObj, i ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + } + if ( pnUsedNodes != NULL ) + *pnUsedNodes = Aig_ManNodeNum(pNew); + Saig_ManForEachPo( pAig, pObj, i ) + pObj->pData = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); + Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) + { + vOne = Vec_VecEntry( vGates, i ); + if ( Vec_PtrSize(vOne) == 0 ) + pObjNew = Aig_ObjChild0Copy(pObjLi); + else + { +// pGateNew = Aig_NotCond( Aig_Regular(pGate)->pData, Aig_IsComplement(pGate) ); + pGateNew = Cgt_ManBuildClockGate( pNew, vOne ); + pObjNew = Aig_Mux( pNew, pGateNew, (Aig_Obj_t *)pObjLo->pData, Aig_ObjChild0Copy(pObjLi) ); + } + pObjLi->pData = Aig_ObjCreatePo( pNew, pObjNew ); + } + Aig_ManCleanup( pNew ); + Aig_ManSetRegNum( pNew, Aig_ManRegNum(pAig) ); + // unlabel nodes + Aig_ManCleanMarkAB( pAig ); + Aig_ManCleanNext( pAig ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/cgt/cgtCore.c b/src/opt/cgt/cgtCore.c new file mode 100644 index 00000000..958080c9 --- /dev/null +++ b/src/opt/cgt/cgtCore.c @@ -0,0 +1,321 @@ +/**CFile**************************************************************** + + FileName [cgtCore.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Clock gating package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cgtCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cgtInt.h" +#include "src/misc/bar/bar.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [This procedure sets default parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cgt_SetDefaultParams( Cgt_Par_t * p ) +{ + memset( p, 0, sizeof(Cgt_Par_t) ); + p->nLevelMax = 25; // the max number of levels to look for clock-gates + p->nCandMax = 1000; // the max number of candidates at each node + p->nOdcMax = 0; // the max number of ODC levels to consider + p->nConfMax = 10; // the max number of conflicts at a node + p->nVarsMin = 1000; // the min number of vars to recycle the SAT solver + p->nFlopsMin = 5; // the min number of flops to recycle the SAT solver + p->fAreaOnly = 0; // derive clock-gating to minimize area + p->fVerbose = 1; // verbosity flag +} + +/**Function************************************************************* + + Synopsis [Returns 1 if simulation does not filter out this candidate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cgt_SimulationFilter( Cgt_Man_t * p, Aig_Obj_t * pCandPart, Aig_Obj_t * pMiterPart ) +{ + unsigned * pInfoCand, * pInfoMiter; + int w, nWords = Abc_BitWordNum( p->nPatts ); + pInfoCand = (unsigned *)Vec_PtrEntry( p->vPatts, Aig_ObjId(Aig_Regular(pCandPart)) ); + pInfoMiter = (unsigned *)Vec_PtrEntry( p->vPatts, Aig_ObjId(pMiterPart) ); + // C => !M -- true is the same as C & M -- false + if ( !Aig_IsComplement(pCandPart) ) + { + for ( w = 0; w < nWords; w++ ) + if ( pInfoCand[w] & pInfoMiter[w] ) + return 0; + } + else + { + for ( w = 0; w < nWords; w++ ) + if ( ~pInfoCand[w] & pInfoMiter[w] ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Saves one simulation pattern.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cgt_SimulationRecord( Cgt_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachObj( p->pPart, pObj, i ) + if ( sat_solver_var_value( p->pSat, p->pCnf->pVarNums[i] ) ) + Abc_InfoSetBit( (unsigned *)Vec_PtrEntry(p->vPatts, i), p->nPatts ); + p->nPatts++; + if ( p->nPatts == 32 * p->nPattWords ) + { + Vec_PtrReallocSimInfo( p->vPatts ); + Vec_PtrCleanSimInfo( p->vPatts, p->nPattWords, 2 * p->nPattWords ); + p->nPattWords *= 2; + } +} + +/**Function************************************************************* + + Synopsis [Performs clock-gating for the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cgt_ClockGatingRangeCheck( Cgt_Man_t * p, int iStart, int nOutputs ) +{ + Vec_Ptr_t * vNodes = p->vFanout; + Aig_Obj_t * pMiter, * pCand, * pMiterFrame, * pCandFrame, * pMiterPart, * pCandPart; + int i, k, RetValue, nCalls; + assert( Vec_VecSize(p->vGatesAll) == Aig_ManPoNum(p->pFrame) ); + // go through all the registers inputs of this range + for ( i = iStart; i < iStart + nOutputs; i++ ) + { + nCalls = p->nCalls; + pMiter = Saig_ManLi( p->pAig, i ); + Cgt_ManDetectCandidates( p->pAig, Aig_ObjFanin0(pMiter), p->pPars->nLevelMax, vNodes ); + // go through the candidates of this PO + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pCand, k ) + { + // get the corresponding nodes from the frames + pCandFrame = (Aig_Obj_t *)pCand->pData; + pMiterFrame = (Aig_Obj_t *)pMiter->pData; + // get the corresponding nodes from the part + pCandPart = (Aig_Obj_t *)pCandFrame->pData; + pMiterPart = (Aig_Obj_t *)pMiterFrame->pData; + // try direct polarity + if ( Cgt_SimulationFilter( p, pCandPart, pMiterPart ) ) + { + RetValue = Cgt_CheckImplication( p, pCandPart, pMiterPart ); + if ( RetValue == 1 ) + { + Vec_VecPush( p->vGatesAll, i, pCand ); + continue; + } + if ( RetValue == 0 ) + Cgt_SimulationRecord( p ); + } + else + p->nCallsFiltered++; + // try reverse polarity + if ( Cgt_SimulationFilter( p, Aig_Not(pCandPart), pMiterPart ) ) + { + RetValue = Cgt_CheckImplication( p, Aig_Not(pCandPart), pMiterPart ); + if ( RetValue == 1 ) + { + Vec_VecPush( p->vGatesAll, i, Aig_Not(pCand) ); + continue; + } + if ( RetValue == 0 ) + Cgt_SimulationRecord( p ); + } + else + p->nCallsFiltered++; + } + + if ( p->pPars->fVerbose ) + { +// printf( "Flop %3d : Cand = %4d. Gate = %4d. SAT calls = %3d.\n", +// i, Vec_PtrSize(vNodes), Vec_PtrSize(Vec_VecEntry(p->vGatesAll, i)), p->nCalls-nCalls ); + } + + } +} + +/**Function************************************************************* + + Synopsis [Performs clock-gating for the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cgt_ClockGatingRange( Cgt_Man_t * p, int iStart ) +{ + int nOutputs, iStop, clk, clkTotal = clock(); + int nCallsUnsat = p->nCallsUnsat; + int nCallsSat = p->nCallsSat; + int nCallsUndec = p->nCallsUndec; + int nCallsFiltered = p->nCallsFiltered; +clk = clock(); + p->pPart = Cgt_ManDupPartition( p->pFrame, p->pPars->nVarsMin, p->pPars->nFlopsMin, iStart, p->pCare, p->vSuppsInv, &nOutputs ); + p->pCnf = Cnf_DeriveSimple( p->pPart, nOutputs ); + p->pSat = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, 1, 0 ); + sat_solver_compress( p->pSat ); + p->vPatts = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p->pPart), p->nPattWords ); + Vec_PtrCleanSimInfo( p->vPatts, 0, p->nPattWords ); +p->timePrepare += clock() - clk; + Cgt_ClockGatingRangeCheck( p, iStart, nOutputs ); + iStop = iStart + nOutputs; + if ( p->pPars->fVeryVerbose ) + { + printf( "%5d : D =%4d. C =%5d. Var =%6d. Pr =%5d. Cex =%5d. F =%4d. Saved =%6d. ", + iStart, iStop-iStart, Aig_ManPoNum(p->pPart)-nOutputs, p->pSat->size, + p->nCallsUnsat-nCallsUnsat, + p->nCallsSat -nCallsSat, + p->nCallsUndec-nCallsUndec, + p->nCallsFiltered-nCallsFiltered ); + ABC_PRT( "Time", clock() - clkTotal ); + } + Cgt_ManClean( p ); + p->nRecycles++; + return iStop; +} + +/**Function************************************************************* + + Synopsis [Performs clock-gating for the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Vec_t * Cgt_ClockGatingCandidates( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars ) +{ + Bar_Progress_t * pProgress = NULL; + Cgt_Par_t Pars; + Cgt_Man_t * p; + Vec_Vec_t * vGatesAll; + int iStart, clk = clock(), clkTotal = clock(); + // reset random numbers + Aig_ManRandom( 1 ); + if ( pPars == NULL ) + Cgt_SetDefaultParams( pPars = &Pars ); + p = Cgt_ManCreate( pAig, pCare, pPars ); + p->pFrame = Cgt_ManDeriveAigForGating( p ); +p->timeAig += clock() - clk; + assert( Aig_ManPoNum(p->pFrame) == Saig_ManRegNum(p->pAig) ); + pProgress = Bar_ProgressStart( stdout, Aig_ManPoNum(p->pFrame) ); + for ( iStart = 0; iStart < Aig_ManPoNum(p->pFrame); ) + { + Bar_ProgressUpdate( pProgress, iStart, NULL ); + iStart = Cgt_ClockGatingRange( p, iStart ); + } + Bar_ProgressStop( pProgress ); + vGatesAll = p->vGatesAll; + p->vGatesAll = NULL; +p->timeTotal = clock() - clkTotal; + Cgt_ManStop( p ); + return vGatesAll; +} + +/**Function************************************************************* + + Synopsis [Performs clock-gating for the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Cgt_ClockGating( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars ) +{ + Aig_Man_t * pGated; + Vec_Vec_t * vGatesAll; + Vec_Vec_t * vGates; + int nNodesUsed, clk = clock(); + vGatesAll = Cgt_ClockGatingCandidates( pAig, pCare, pPars ); + if ( pPars->fAreaOnly ) + vGates = Cgt_ManDecideArea( pAig, vGatesAll, pPars->nOdcMax, pPars->fVerbose ); + else + vGates = Cgt_ManDecideSimple( pAig, vGatesAll, pPars->nOdcMax, pPars->fVerbose ); + if ( pPars->fVerbose ) + { +// printf( "Before CG: " ); +// Aig_ManPrintStats( pAig ); + } + pGated = Cgt_ManDeriveGatedAig( pAig, vGates, pPars->fAreaOnly, &nNodesUsed ); + if ( pPars->fVerbose ) + { +// printf( "After CG: " ); +// Aig_ManPrintStats( pGated ); + printf( "Nodes: Before CG = %6d. After CG = %6d. (%6.2f %%). Total after CG = %6d.\n", + Aig_ManNodeNum(pAig), nNodesUsed, + 100.0*nNodesUsed/Aig_ManNodeNum(pAig), + Aig_ManNodeNum(pGated) ); + } + Vec_VecFree( vGates ); + Vec_VecFree( vGatesAll ); + return pGated; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/cgt/cgtDecide.c b/src/opt/cgt/cgtDecide.c new file mode 100644 index 00000000..293bde85 --- /dev/null +++ b/src/opt/cgt/cgtDecide.c @@ -0,0 +1,301 @@ +/**CFile**************************************************************** + + FileName [cgtMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Clock gating package.] + + Synopsis [Decide what gate to use for what flop.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cgtMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cgtInt.h" +#include "src/proof/ssw/sswInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern int Ssw_SmlCheckXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo, Aig_Obj_t * pCand ); +extern int Ssw_SmlCountXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo, Aig_Obj_t * pCand ); +extern int Ssw_SmlCountEqual( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo ); +extern int Ssw_SmlNodeCountOnesReal( Ssw_Sml_t * p, Aig_Obj_t * pObj ); +extern int Ssw_SmlNodeCountOnesRealVec( Ssw_Sml_t * p, Vec_Ptr_t * vObjs ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Collects POs in the transitive fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cgt_ManCollectFanoutPos_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vFanout ) +{ + Aig_Obj_t * pFanout; + int f, iFanout; + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + return; + Aig_ObjSetTravIdCurrent(pAig, pObj); + if ( Aig_ObjIsPo(pObj) ) + { + Vec_PtrPush( vFanout, pObj ); + return; + } + Aig_ObjForEachFanout( pAig, pObj, pFanout, iFanout, f ) + Cgt_ManCollectFanoutPos_rec( pAig, pFanout, vFanout ); +} + +/**Function************************************************************* + + Synopsis [Collects POs in the transitive fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cgt_ManCollectFanoutPos( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vFanout ) +{ + Vec_PtrClear( vFanout ); + Aig_ManIncrementTravId( pAig ); + Cgt_ManCollectFanoutPos_rec( pAig, pObj, vFanout ); +} + +/**Function************************************************************* + + Synopsis [Checks if all PO fanouts can be gated by this node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cgt_ManCheckGateComplete( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, Aig_Obj_t * pGate, Vec_Ptr_t * vFanout ) +{ + Vec_Ptr_t * vGates; + Aig_Obj_t * pObj; + int i; + Vec_PtrForEachEntry( Aig_Obj_t *, vFanout, pObj, i ) + { + if ( Saig_ObjIsPo(pAig, pObj) ) + return 0; + vGates = Vec_VecEntry( vGatesAll, Aig_ObjPioNum(pObj) - Saig_ManPoNum(pAig) ); + if ( Vec_PtrFind( vGates, pGate ) == -1 ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes the set of complete clock gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Cgt_ManCompleteGates( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose ) +{ + Vec_Ptr_t * vFanout, * vGatesFull; + Aig_Obj_t * pGate, * pGateR; + int i, k; + vFanout = Vec_PtrAlloc( 100 ); + vGatesFull = Vec_PtrAlloc( 100 ); + Vec_VecForEachEntry( Aig_Obj_t *, vGatesAll, pGate, i, k ) + { + pGateR = Aig_Regular(pGate); + if ( pGateR->fMarkA ) + continue; + pGateR->fMarkA = 1; + Cgt_ManCollectFanoutPos( pAig, pGateR, vFanout ); + if ( Cgt_ManCheckGateComplete( pAig, vGatesAll, pGate, vFanout ) ) + Vec_PtrPush( vGatesFull, pGate ); + } + Vec_PtrFree( vFanout ); + Vec_VecForEachEntry( Aig_Obj_t *, vGatesAll, pGate, i, k ) + Aig_Regular(pGate)->fMarkA = 0; + return vGatesFull; +} + +/**Function************************************************************* + + Synopsis [Calculates coverage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Cgt_ManComputeCoverage( Aig_Man_t * pAig, Vec_Vec_t * vGates ) +{ + int nFrames = 32; + int nWords = 1; + Ssw_Sml_t * pSml; + Vec_Ptr_t * vOne; + int i, nTransTotal = 0, nTransSaved = 0; + pSml = Ssw_SmlSimulateSeq( pAig, 0, nFrames, nWords ); + Vec_VecForEachLevel( vGates, vOne, i ) + { + nTransSaved += Ssw_SmlNodeCountOnesRealVec( pSml, vOne ); + nTransTotal += 32 * nFrames * nWords; + } + Ssw_SmlStop( pSml ); + return (float)100.0*nTransSaved/nTransTotal; +} + +/**Function************************************************************* + + Synopsis [Chooses what clock-gate to use for this register.] + + Description [Currently uses the naive approach: For each register, + choose the clock gate, which covers most of the transitions.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Vec_t * Cgt_ManDecideSimple( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose ) +{ + int nFrames = 32; + int nWords = 1; + Ssw_Sml_t * pSml; + Vec_Vec_t * vGates; + Vec_Ptr_t * vCands; + Aig_Obj_t * pObjLi, * pObjLo, * pCand, * pCandBest; + int i, k, nHitsCur, nHitsMax, Counter = 0, clk = clock(); + int nTransTotal = 0, nTransSaved = 0; + vGates = Vec_VecStart( Saig_ManRegNum(pAig) ); + pSml = Ssw_SmlSimulateSeq( pAig, 0, nFrames, nWords ); + Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) + { + nHitsMax = 0; + pCandBest = NULL; + vCands = Vec_VecEntry( vGatesAll, i ); + Vec_PtrForEachEntry( Aig_Obj_t *, vCands, pCand, k ) + { + // check if this is indeed a clock-gate + if ( nOdcMax == 0 && !Ssw_SmlCheckXorImplication( pSml, pObjLi, pObjLo, pCand ) ) + printf( "Clock gate candidate is invalid!\n" ); + // find its characteristic number + nHitsCur = Ssw_SmlNodeCountOnesReal( pSml, pCand ); + if ( nHitsMax < nHitsCur ) + { + nHitsMax = nHitsCur; + pCandBest = pCand; + } + } + if ( pCandBest != NULL ) + { + Vec_VecPush( vGates, i, pCandBest ); + Counter++; + nTransSaved += nHitsMax; + } + nTransTotal += 32 * nFrames * nWords; + } + Ssw_SmlStop( pSml ); + if ( fVerbose ) + { + printf( "Gating signals = %6d. Gated flops = %6d. (Total flops = %6d.)\n", + Vec_VecSizeSize(vGatesAll), Counter, Saig_ManRegNum(pAig) ); +// printf( "Gated transitions = %5.2f %%. (%5.2f %%.) ", +// 100.0*nTransSaved/nTransTotal, Cgt_ManComputeCoverage(pAig, vGates) ); + printf( "Gated transitions = %5.2f %%. ", Cgt_ManComputeCoverage(pAig, vGates) ); + ABC_PRT( "Time", clock() - clk ); + } +/* + { + Vec_Ptr_t * vCompletes; + vCompletes = Cgt_ManCompleteGates( pAig, vGatesAll, nOdcMax, fVerbose ); + printf( "Complete gates = %d. \n", Vec_PtrSize(vCompletes) ); + Vec_PtrFree( vCompletes ); + } +*/ + return vGates; +} + +/**Function************************************************************* + + Synopsis [Computes the set of complete clock gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Vec_t * Cgt_ManDecideArea( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose ) +{ + Vec_Vec_t * vGates; + Vec_Ptr_t * vCompletes, * vOne; + Aig_Obj_t * pGate; + int i, k, Counter = 0, clk = clock(); + // derive and label complete gates + vCompletes = Cgt_ManCompleteGates( pAig, vGatesAll, nOdcMax, fVerbose ); + // label complete gates + Vec_PtrForEachEntry( Aig_Obj_t *, vCompletes, pGate, i ) + Aig_Regular(pGate)->fMarkA = 1; + // select only complete gates + vGates = Vec_VecStart( Saig_ManRegNum(pAig) ); + Vec_VecForEachEntry( Aig_Obj_t *, vGatesAll, pGate, i, k ) + if ( Aig_Regular(pGate)->fMarkA ) + Vec_VecPush( vGates, i, pGate ); + // unlabel complete gates + Vec_PtrForEachEntry( Aig_Obj_t *, vCompletes, pGate, i ) + Aig_Regular(pGate)->fMarkA = 0; + // count the number of gated flops + Vec_VecForEachLevel( vGates, vOne, i ) + { + Counter += (int)(Vec_PtrSize(vOne) > 0); +// printf( "%d ", Vec_PtrSize(vOne) ); + } +// printf( "\n" ); + if ( fVerbose ) + { + printf( "Gating signals = %6d. Gated flops = %6d. (Total flops = %6d.)\n", + Vec_VecSizeSize(vGatesAll), Counter, Saig_ManRegNum(pAig) ); + printf( "Complete gates = %6d. Gated transitions = %5.2f %%. ", + Vec_PtrSize(vCompletes), Cgt_ManComputeCoverage(pAig, vGates) ); + ABC_PRT( "Time", clock() - clk ); + } + Vec_PtrFree( vCompletes ); + return vGates; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/cgt/cgtInt.h b/src/opt/cgt/cgtInt.h new file mode 100644 index 00000000..1fdbf35f --- /dev/null +++ b/src/opt/cgt/cgtInt.h @@ -0,0 +1,122 @@ +/**CFile**************************************************************** + + FileName [cgtInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Clock gating package.] + + Synopsis [Internal declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cgtInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__cgt__cgtInt_h +#define ABC__aig__cgt__cgtInt_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "src/aig/saig/saig.h" +#include "src/sat/bsat/satSolver.h" +#include "src/sat/cnf/cnf.h" +#include "cgt.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Cgt_Man_t_ Cgt_Man_t; +struct Cgt_Man_t_ +{ + // user's data + Cgt_Par_t * pPars; // user's parameters + Aig_Man_t * pAig; // user's AIG manager + // user's constraints + Aig_Man_t * pCare; // constraint cones + Vec_Vec_t * vSuppsInv; // inverse support of the constraints + // result of clock-gating + Vec_Vec_t * vGatesAll; // the computed clock-gates + Vec_Ptr_t * vGates; // the selected clock-gates + // internal data + Aig_Man_t * pFrame; // clock gate AIG manager + Vec_Ptr_t * vFanout; // temporary storage for fanouts + Vec_Ptr_t * vVisited; // temporary storage for visited nodes + // SAT solving + Aig_Man_t * pPart; // partition + Cnf_Dat_t * pCnf; // CNF of the partition + sat_solver * pSat; // SAT solver + Vec_Ptr_t * vPatts; // simulation patterns + int nPatts; // the number of patterns accumulated + int nPattWords; // the number of pattern words + // statistics + int nRecycles; // recycles + int nCalls; // total calls + int nCallsSat; // satisfiable calls + int nCallsUnsat; // unsatisfiable calls + int nCallsUndec; // undecided calls + int nCallsFiltered; // filtered out calls + int timeAig; // constructing AIG + int timePrepare; // partitioning and SAT solving + int timeSat; // total runtime + int timeSatSat; // satisfiable runtime + int timeSatUnsat; // unsatisfiable runtime + int timeSatUndec; // undecided runtime + int timeDecision; // making decision about what gates to use + int timeOther; // other runtime + int timeTotal; // total runtime +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== cgtAig.c ==========================================================*/ +extern void Cgt_ManDetectCandidates( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nLevelMax, Vec_Ptr_t * vCands ); +extern Aig_Man_t * Cgt_ManDeriveAigForGating( Cgt_Man_t * p ); +extern Aig_Man_t * Cgt_ManDupPartition( Aig_Man_t * pAig, int nVarsMin, int nFlopsMin, int iStart, Aig_Man_t * pCare, Vec_Vec_t * vSuppsInv, int * pnOutputs ); +extern Aig_Man_t * Cgt_ManDeriveGatedAig( Aig_Man_t * pAig, Vec_Vec_t * vGates, int fReduce, int * pnUsedNodes ); +/*=== cgtDecide.c ==========================================================*/ +extern Vec_Vec_t * Cgt_ManDecideSimple( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose ); +extern Vec_Vec_t * Cgt_ManDecideArea( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose ); +/*=== cgtMan.c ==========================================================*/ +extern Cgt_Man_t * Cgt_ManCreate( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars ); +extern void Cgt_ManClean( Cgt_Man_t * p ); +extern void Cgt_ManStop( Cgt_Man_t * p ); +/*=== cgtSat.c ==========================================================*/ +extern int Cgt_CheckImplication( Cgt_Man_t * p, Aig_Obj_t * pGate, Aig_Obj_t * pFlop ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/opt/cgt/cgtMan.c b/src/opt/cgt/cgtMan.c new file mode 100644 index 00000000..7744226d --- /dev/null +++ b/src/opt/cgt/cgtMan.c @@ -0,0 +1,179 @@ +/**CFile**************************************************************** + + FileName [cgtMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Clock gating package.] + + Synopsis [Manipulation of clock gating manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cgtMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cgtInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cgt_Man_t * Cgt_ManCreate( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars ) +{ + Cgt_Man_t * p; + // prepare the sequential AIG + assert( Saig_ManRegNum(pAig) > 0 ); + Aig_ManFanoutStart( pAig ); + Aig_ManSetPioNumbers( pAig ); + // create interpolation manager + p = ABC_ALLOC( Cgt_Man_t, 1 ); + memset( p, 0, sizeof(Cgt_Man_t) ); + p->pPars = pPars; + p->pAig = pAig; + p->vGatesAll = Vec_VecStart( Saig_ManRegNum(pAig) ); + p->vFanout = Vec_PtrAlloc( 1000 ); + p->vVisited = Vec_PtrAlloc( 1000 ); + p->nPattWords = 16; + if ( pCare == NULL ) + return p; + // check out the constraints + if ( Aig_ManPiNum(pCare) != Aig_ManPiNum(pAig) ) + { + printf( "The PI count of care (%d) and AIG (%d) differ. Careset is not used.\n", + Aig_ManPiNum(pCare), Aig_ManPiNum(pAig) ); + return p; + } + p->pCare = pCare; + p->vSuppsInv = (Vec_Vec_t *)Aig_ManSupportsInverse( p->pCare ); + return p; +} + +/**Function************************************************************* + + Synopsis [Creates the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cgt_ManClean( Cgt_Man_t * p ) +{ + if ( p->pPart ) + { + Aig_ManStop( p->pPart ); + p->pPart = NULL; + } + if ( p->pCnf ) + { + Cnf_DataFree( p->pCnf ); + p->pCnf = NULL; + } + if ( p->pSat ) + { + sat_solver_delete( p->pSat ); + p->pSat = NULL; + } + if ( p->vPatts ) + { + Vec_PtrFree( p->vPatts ); + p->vPatts = NULL; + } +} + + +/**Function************************************************************* + + Synopsis [Prints stats of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cgt_ManPrintStats( Cgt_Man_t * p ) +{ + printf( "Params: LevMax = %d. CandMax = %d. OdcMax = %d. ConfMax = %d. VarMin = %d. FlopMin = %d.\n", + p->pPars->nLevelMax, p->pPars->nCandMax, p->pPars->nOdcMax, + p->pPars->nConfMax, p->pPars->nVarsMin, p->pPars->nFlopsMin ); + printf( "SAT : Calls = %d. Unsat = %d. Sat = %d. Fails = %d. Recycles = %d. ", + p->nCalls, p->nCallsUnsat, p->nCallsSat, p->nCallsUndec, p->nRecycles ); + ABC_PRT( "Time", p->timeTotal ); +/* + p->timeOther = p->timeTotal-p->timeAig-p->timePrepare-p->timeSat-p->timeDecision; + ABC_PRTP( "AIG ", p->timeAig, p->timeTotal ); + ABC_PRTP( "Prepare ", p->timePrepare, p->timeTotal ); + ABC_PRTP( "SAT solving", p->timeSat, p->timeTotal ); + ABC_PRTP( " unsat ", p->timeSatUnsat, p->timeTotal ); + ABC_PRTP( " sat ", p->timeSatSat, p->timeTotal ); + ABC_PRTP( " undecided", p->timeSatUndec, p->timeTotal ); + ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); + ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); +*/ +} + +/**Function************************************************************* + + Synopsis [Frees the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cgt_ManStop( Cgt_Man_t * p ) +{ + if ( p->pPars->fVerbose ) + Cgt_ManPrintStats( p ); + if ( p->pFrame ) + Aig_ManStop( p->pFrame ); + Cgt_ManClean( p ); + Vec_PtrFree( p->vFanout ); + Vec_PtrFree( p->vVisited ); + if ( p->vGates ) + Vec_PtrFree( p->vGates ); + if ( p->vGatesAll ) + Vec_VecFree( p->vGatesAll ); + if ( p->vSuppsInv ) + Vec_VecFree( p->vSuppsInv ); + ABC_FREE( p ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/cgt/cgtSat.c b/src/opt/cgt/cgtSat.c new file mode 100644 index 00000000..0a2a1daa --- /dev/null +++ b/src/opt/cgt/cgtSat.c @@ -0,0 +1,97 @@ +/**CFile**************************************************************** + + FileName [cgtSat.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Clock gating package.] + + Synopsis [Checking implications using SAT.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cgtSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cgtInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +/**Function************************************************************* + + Synopsis [Runs equivalence test for the two nodes.] + + Description [Both nodes should be regular and different from each other.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cgt_CheckImplication( Cgt_Man_t * p, Aig_Obj_t * pGate, Aig_Obj_t * pMiter ) +{ + int nBTLimit = p->pPars->nConfMax; + int pLits[2], RetValue, clk; + p->nCalls++; + + // sanity checks + assert( p->pSat && p->pCnf ); + assert( !Aig_IsComplement(pMiter) ); + assert( Aig_Regular(pGate) != pMiter ); + + // solve under assumptions + // G => !M -- true G & M -- false + pLits[0] = toLitCond( p->pCnf->pVarNums[Aig_Regular(pGate)->Id], Aig_IsComplement(pGate) ); + pLits[1] = toLitCond( p->pCnf->pVarNums[pMiter->Id], 0 ); + +clk = clock(); + RetValue = sat_solver_solve( p->pSat, pLits, pLits + 2, (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); +p->timeSat += clock() - clk; + if ( RetValue == 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 ); + sat_solver_compress( p->pSat ); + p->nCallsUnsat++; + return 1; + } + else if ( RetValue == l_True ) + { +p->timeSatSat += clock() - clk; + p->nCallsSat++; + return 0; + } + else // if ( RetValue1 == l_Undef ) + { +p->timeSatUndec += clock() - clk; + p->nCallsUndec++; + return -1; + } + return -2; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/cgt/module.make b/src/opt/cgt/module.make new file mode 100644 index 00000000..68494e68 --- /dev/null +++ b/src/opt/cgt/module.make @@ -0,0 +1,5 @@ +SRC += src/opt/cgt/cgtAig.c \ + src/opt/cgt/cgtCore.c \ + src/opt/cgt/cgtDecide.c \ + src/opt/cgt/cgtMan.c \ + src/opt/cgt/cgtSat.c diff --git a/src/opt/csw/csw.h b/src/opt/csw/csw.h new file mode 100644 index 00000000..f590ec62 --- /dev/null +++ b/src/opt/csw/csw.h @@ -0,0 +1,69 @@ +/**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 ABC__aig__csw__csw_h +#define ABC__aig__csw__csw_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/opt/csw/cswCore.c b/src/opt/csw/cswCore.c new file mode 100644 index 00000000..e1bdca00 --- /dev/null +++ b/src/opt/csw/cswCore.c @@ -0,0 +1,99 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/csw/cswCut.c b/src/opt/csw/cswCut.c new file mode 100644 index 00000000..bb6677c2 --- /dev/null +++ b/src/opt/csw/cswCut.c @@ -0,0 +1,607 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/csw/cswInt.h b/src/opt/csw/cswInt.h new file mode 100644 index 00000000..e6c10b36 --- /dev/null +++ b/src/opt/csw/cswInt.h @@ -0,0 +1,161 @@ +/**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 ABC__aig__csw__cswInt_h +#define ABC__aig__csw__cswInt_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + +#include "src/aig/aig/aig.h" +#include "src/opt/dar/dar.h" +#include "src/bool/kit/kit.h" +#include "csw.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/opt/csw/cswMan.c b/src/opt/csw/cswMan.c new file mode 100644 index 00000000..5df69492 --- /dev/null +++ b/src/opt/csw/cswMan.c @@ -0,0 +1,130 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 = ABC_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 = ABC_ALLOC( int, Aig_ManObjNumMax(pMan) ); + p->pEquiv = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pMan) ); + p->pCuts = ABC_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 = Abc_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 = Abc_PrimeCudd( Aig_ManNodeNum(pMan) * p->nCutsMax / 2 ); + p->pTable = ABC_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] = ABC_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 ); + ABC_PRTP( "Cuts ", p->timeCuts, p->timeTotal ); + ABC_PRTP( "Hashing ", p->timeHash, p->timeTotal ); + ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); + ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); + } + ABC_FREE( p->puTemp[0] ); + Aig_MmFixedStop( p->pMemCuts, 0 ); + ABC_FREE( p->pnRefs ); + ABC_FREE( p->pEquiv ); + ABC_FREE( p->pCuts ); + ABC_FREE( p->pTable ); + ABC_FREE( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/csw/cswTable.c b/src/opt/csw/cswTable.c new file mode 100644 index 00000000..9bab0a01 --- /dev/null +++ b/src/opt/csw/cswTable.c @@ -0,0 +1,166 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/csw/csw_.c b/src/opt/csw/csw_.c new file mode 100644 index 00000000..c12607d3 --- /dev/null +++ b/src/opt/csw/csw_.c @@ -0,0 +1,53 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/csw/module.make b/src/opt/csw/module.make new file mode 100644 index 00000000..501f92aa --- /dev/null +++ b/src/opt/csw/module.make @@ -0,0 +1,4 @@ +SRC += src/opt/csw/cswCore.c \ + src/opt/csw/cswCut.c \ + src/opt/csw/cswMan.c \ + src/opt/csw/cswTable.c diff --git a/src/opt/cut/abcCut.c b/src/opt/cut/abcCut.c index 3b80fe8d..0b57b844 100644 --- a/src/opt/cut/abcCut.c +++ b/src/opt/cut/abcCut.c @@ -18,7 +18,7 @@ ***********************************************************************/ -#include "abc.h" +#include "base/abc/abc.h" #include "cut.h" ABC_NAMESPACE_IMPL_START diff --git a/src/opt/cut/cut.h b/src/opt/cut/cut.h index 2ba3e341..cd87e5a0 100644 --- a/src/opt/cut/cut.h +++ b/src/opt/cut/cut.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __CUT_H__ -#define __CUT_H__ +#ifndef ABC__opt__cut__cut_h +#define ABC__opt__cut__cut_h //////////////////////////////////////////////////////////////////////// diff --git a/src/opt/cut/cutInt.h b/src/opt/cut/cutInt.h index 4705c019..39606b00 100644 --- a/src/opt/cut/cutInt.h +++ b/src/opt/cut/cutInt.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __CUT_INT_H__ -#define __CUT_INT_H__ +#ifndef ABC__opt__cut__cutInt_h +#define ABC__opt__cut__cutInt_h //////////////////////////////////////////////////////////////////////// @@ -27,8 +27,8 @@ //////////////////////////////////////////////////////////////////////// #include -#include "extra.h" -#include "vec.h" +#include "src/misc/extra/extra.h" +#include "src/misc/vec/vec.h" #include "cut.h" #include "cutList.h" diff --git a/src/opt/cut/cutList.h b/src/opt/cut/cutList.h index 0f0ccedf..3da27134 100644 --- a/src/opt/cut/cutList.h +++ b/src/opt/cut/cutList.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __CUT_LIST_H__ -#define __CUT_LIST_H__ +#ifndef ABC__opt__cut__cutList_h +#define ABC__opt__cut__cutList_h ABC_NAMESPACE_HEADER_START diff --git a/src/opt/cut/cutPre22.c b/src/opt/cut/cutPre22.c index fdb9bd8c..d51d9056 100644 --- a/src/opt/cut/cutPre22.c +++ b/src/opt/cut/cutPre22.c @@ -192,7 +192,7 @@ void Cut_CellLoad() // 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->nVars = Abc_Base2Log(Length*4); pCell->nUsed = 1; // Extra_TruthCopy( pCell->uTruth, pTruth, nVars ); Extra_ReadHexadecimal( pCell->uTruth, pString, pCell->nVars ); diff --git a/src/opt/dar/dar.h b/src/opt/dar/dar.h new file mode 100644 index 00000000..5c2c9bcc --- /dev/null +++ b/src/opt/dar/dar.h @@ -0,0 +1,116 @@ +/**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 ABC__aig__dar__dar_h +#define ABC__aig__dar__dar_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 fPower; // enables power-aware rewriting + int fRecycle; // enables cut recycling + 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(); +extern void Dar_LibPrepare( int nSubgraphs ); +extern int Dar_LibReturnClass( unsigned uTruth ); +/*=== darBalance.c ========================================================*/ +extern Aig_Man_t * Dar_ManBalance( Aig_Man_t * p, int fUpdateLevel ); +extern Aig_Man_t * Dar_ManBalanceXor( Aig_Man_t * pAig, int fExor, int fUpdateLevel, int fVerbose ); +extern void Dar_BalancePrintStats( Aig_Man_t * p ); +/*=== 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 fPower, int fVerbose ); +extern Aig_Man_t * Dar_ManCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fFanout, int fPower, int fVerbose ); +extern Aig_Man_t * Dar_ManChoice( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fConstruct, int nConfMax, int nLevelMax, int fVerbose ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/opt/dar/darBalance.c b/src/opt/dar/darBalance.c new file mode 100644 index 00000000..56ec51fa --- /dev/null +++ b/src/opt/dar/darBalance.c @@ -0,0 +1,645 @@ +/**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" +#include "src/misc/tim/tim.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//#define USE_LUTSIZE_BALANCE + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**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 ) + { + if ( Aig_ObjIsExor(pRoot) ) + { + assert( !Aig_IsComplement(pObj) ); + // check if the node occurs in the same polarity + Vec_PtrRemove( vSuper, pObj ); + Aig_Regular(pObj)->fMarkB = 0; +//printf( " Duplicated EXOR input!!! " ); + return 1; + } + else + { + // 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_PtrSize(vSuper) > 10000) ) + { + 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( RetValue != 0 || vNodes->nSize > 1 ); + // unmark the visited nodes + Vec_PtrForEachEntry( Aig_Obj_t *, 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 [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 = (Aig_Obj_t *)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 = (Aig_Obj_t *)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 = (Aig_Obj_t *)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 = (Aig_Obj_t *)Vec_PtrEntry( vSuper, RightBound + 1 ); + pObj2 = (Aig_Obj_t *)Vec_PtrEntry( vSuper, RightBound ); + if ( Aig_Regular(pObj1) == p->pConst1 || Aig_Regular(pObj2) == p->pConst1 || Aig_Regular(pObj1) == Aig_Regular(pObj2) ) + return; + // find the first node that can be shared + for ( i = RightBound; i >= LeftBound; i-- ) + { + pObj3 = (Aig_Obj_t *)Vec_PtrEntry( vSuper, i ); + if ( Aig_Regular(pObj3) == p->pConst1 ) + { + Vec_PtrWriteEntry( vSuper, i, pObj2 ); + Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); + return; + } + if ( Aig_Regular(pObj1) == Aig_Regular(pObj3) ) + { + if ( pObj3 == pObj2 ) + return; + 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 = Aig_ManRandom(0) % (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 [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; + Diff = Aig_ObjId(Aig_Regular(*pp1)) - Aig_ObjId(Aig_Regular(*pp2)); + if ( Diff > 0 ) + return -1; + if ( Diff < 0 ) + return 1; + return 0; +} + +/**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 = (Aig_Obj_t *)vStore->pArray[i ]; + pObj2 = (Aig_Obj_t *)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; + } +} + +/**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, (int (*)(void))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 = (Aig_Obj_t *)Vec_PtrPop(vSuper); + pObj2 = (Aig_Obj_t *)Vec_PtrPop(vSuper); + Dar_BalancePushUniqueOrderByLevel( vSuper, Aig_Oper(p, pObj1, pObj2, Type) ); + } + return (Aig_Obj_t *)Vec_PtrEntry(vSuper, 0); +} + + +/**Function************************************************************* + + Synopsis [Returns affective support size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_BaseSize( Aig_Man_t * p, Aig_Obj_t * pObj, int nLutSize ) +{ + int nBaseSize; + pObj = Aig_Regular(pObj); + if ( Aig_ObjIsConst1(pObj) ) + return 0; + if ( Aig_ObjLevel(pObj) >= nLutSize ) + return 1; + nBaseSize = Aig_SupportSize( p, pObj ); + if ( nBaseSize >= nLutSize ) + return 1; + return nBaseSize; +} + +/**Function************************************************************* + + Synopsis [Builds implication supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Dar_BalanceBuildSuperTop( Aig_Man_t * p, Vec_Ptr_t * vSuper, Aig_Type_t Type, int fUpdateLevel, int nLutSize ) +{ + Vec_Ptr_t * vSubset; + Aig_Obj_t * pObj; + int i, nBaseSizeAll, nBaseSize; + assert( vSuper->nSize > 1 ); + // sort the new nodes by level in the decreasing order + Vec_PtrSort( vSuper, (int (*)(void))Aig_NodeCompareLevelsDecrease ); + // add one LUT at a time + while ( Vec_PtrSize(vSuper) > 1 ) + { + // isolate the group of nodes with nLutSize inputs + nBaseSizeAll = 0; + vSubset = Vec_PtrAlloc( nLutSize ); + Vec_PtrForEachEntryReverse( Aig_Obj_t *, vSuper, pObj, i ) + { + nBaseSize = Aig_BaseSize( p, pObj, nLutSize ); + if ( nBaseSizeAll + nBaseSize > nLutSize && Vec_PtrSize(vSubset) > 1 ) + break; + nBaseSizeAll += nBaseSize; + Vec_PtrPush( vSubset, pObj ); + } + // remove them from vSuper + Vec_PtrShrink( vSuper, Vec_PtrSize(vSuper) - Vec_PtrSize(vSubset) ); + // create the new supergate + pObj = Dar_BalanceBuildSuper( p, vSubset, Type, fUpdateLevel ); + Vec_PtrFree( vSubset ); + // add the new output + Dar_BalancePushUniqueOrderByLevel( vSuper, pObj ); + } + return (Aig_Obj_t *)Vec_PtrEntry(vSuper, 0); +} + +/**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 (Aig_Obj_t *)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 (Aig_Obj_t *)(pObjOld->pData = Aig_ManConst0(pNew)); + if ( vSuper->nSize == 1 ) + return (Aig_Obj_t *)Vec_PtrEntry(vSuper, 0); + if ( Vec_PtrSize(vSuper) < 2 ) + printf( "Dar_Balance_rec: Internal error!\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((Aig_Obj_t *)vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel ); + vSuper->pArray[i] = Aig_NotCond( pObjNew, Aig_IsComplement((Aig_Obj_t *)vSuper->pArray[i]) ); + } + // build the supergate +#ifdef USE_LUTSIZE_BALANCE + pObjNew = Dar_BalanceBuildSuperTop( pNew, vSuper, Aig_ObjType(pObjOld), fUpdateLevel, 6 ); +#else + pObjNew = Dar_BalanceBuildSuper( pNew, vSuper, Aig_ObjType(pObjOld), fUpdateLevel ); +#endif + // make sure the balanced node is not assigned +// assert( pObjOld->Level >= Aig_Regular(pObjNew)->Level ); + assert( pObjOld->pData == NULL ); + if ( pNew->pManHaig != NULL ) + { + Aig_Obj_t * pObjNewR = Aig_Regular(pObjNew); +// printf( "Balancing HAIG node %d equivalent to HAIG node %d (over = %d).\n", +// pObjNewR->pHaig->Id, pObjOld->pHaig->Id, pObjNewR->pHaig->pHaig != NULL ); + assert( pObjNewR->pHaig != NULL ); + assert( !Aig_IsComplement(pObjNewR->pHaig) ); + assert( pNew->pManHaig->vEquPairs != NULL ); + Vec_IntPush( pNew->pManHaig->vEquPairs, pObjNewR->pHaig->Id ); + Vec_IntPush( pNew->pManHaig->vEquPairs, pObjOld->pHaig->Id ); + } + else + Aig_Regular(pObjNew)->pHaig = pObjOld->pHaig; + return (Aig_Obj_t *)(pObjOld->pData = pObjNew); +} + +/**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; + assert( Aig_ManVerifyTopoOrder(p) ); + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nAsserts = p->nAsserts; + pNew->nConstrs = p->nConstrs; + if ( p->vFlopNums ) + pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); + // pass the HAIG manager + if ( p->pManHaig != NULL ) + { + pNew->pManHaig = p->pManHaig; p->pManHaig = NULL; + Aig_ManConst1(pNew)->pHaig = Aig_ManConst1(pNew->pManHaig); + } + // map the PI nodes + Aig_ManCleanData( p ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + vStore = Vec_VecAlloc( 50 ); + if ( p->pManTime != NULL ) + { + float arrTime; + Tim_ManIncrementTravId( (Tim_Man_t *)p->pManTime ); + Aig_ManSetPioNumbers( p ); + Aig_ManForEachObj( p, pObj, i ) + { + if ( Aig_ObjIsNode(pObj) || Aig_ObjIsConst1(pObj) ) + continue; + if ( Aig_ObjIsPi(pObj) ) + { + // copy the PI + pObjNew = Aig_ObjCreatePi(pNew); + pObj->pData = pObjNew; + pObjNew->pHaig = pObj->pHaig; + // set the arrival time of the new PI + arrTime = Tim_ManGetCiArrival( (Tim_Man_t *)p->pManTime, Aig_ObjPioNum(pObj) ); + pObjNew->Level = (int)arrTime; + } + else if ( Aig_ObjIsPo(pObj) ) + { + // perform balancing + 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) ); + // save arrival time of the output + arrTime = (float)Aig_Regular(pObjNew)->Level; + Tim_ManSetCoArrival( (Tim_Man_t *)p->pManTime, Aig_ObjPioNum(pObj), arrTime ); + // create PO + pObjNew = Aig_ObjCreatePo( pNew, pObjNew ); + pObjNew->pHaig = pObj->pHaig; + } + else + assert( 0 ); + } + Aig_ManCleanPioNumbers( p ); + pNew->pManTime = Tim_ManDup( (Tim_Man_t *)p->pManTime, 0 ); + } + else + { + Aig_ManForEachPi( p, pObj, i ) + { + pObjNew = Aig_ObjCreatePi(pNew); + pObjNew->Level = pObj->Level; + pObj->pData = pObjNew; + pObjNew->pHaig = pObj->pHaig; + } + 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) ); + pObjNew = Aig_ObjCreatePo( pNew, pObjNew ); + pObjNew->pHaig = pObj->pHaig; + } + } + Vec_VecFree( vStore ); + // remove dangling nodes + Aig_ManCleanup( pNew ); + Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); + // check the resulting AIG + if ( !Aig_ManCheck(pNew) ) + printf( "Dar_ManBalance(): The check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Reproduces script "compress2".] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Dar_ManBalanceXor( Aig_Man_t * pAig, int fExor, int fUpdateLevel, int fVerbose ) +{ + Aig_Man_t * pAigXor, * pRes; + if ( fExor ) + { + pAigXor = Aig_ManDupExor( pAig ); + if ( fVerbose ) + Dar_BalancePrintStats( pAigXor ); + pRes = Dar_ManBalance( pAigXor, fUpdateLevel ); + Aig_ManStop( pAigXor ); + } + else + { + pRes = Dar_ManBalance( pAig, fUpdateLevel ); + } + return pRes; +} + +/**Function************************************************************* + + Synopsis [Inserts a new node in the order by levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_BalancePrintStats( Aig_Man_t * p ) +{ + Vec_Ptr_t * vSuper; + Aig_Obj_t * pObj, * pTemp; + int i, k; + if ( Aig_ManExorNum(p) == 0 ) + { + printf( "There is no EXOR gates.\n" ); + return; + } + Aig_ManForEachExor( p, pObj, i ) + { + Aig_ObjFanin0(pObj)->fMarkA = 1; + Aig_ObjFanin1(pObj)->fMarkA = 1; + assert( !Aig_ObjFaninC0(pObj) ); + assert( !Aig_ObjFaninC1(pObj) ); + } + vSuper = Vec_PtrAlloc( 1000 ); + Aig_ManForEachExor( p, pObj, i ) + { + if ( pObj->fMarkA && pObj->nRefs == 1 ) + continue; + Vec_PtrClear( vSuper ); + Dar_BalanceCone_rec( pObj, pObj, vSuper ); + Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pTemp, k ) + pTemp->fMarkB = 0; + if ( Vec_PtrSize(vSuper) < 3 ) + continue; + printf( " %d(", Vec_PtrSize(vSuper) ); + Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pTemp, k ) + printf( " %d", pTemp->Level ); + printf( " )" ); + } + Vec_PtrFree( vSuper ); + Aig_ManForEachObj( p, pObj, i ) + pObj->fMarkA = 0; + printf( "\n" ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/dar/darCore.c b/src/opt/dar/darCore.c new file mode 100644 index 00000000..6ca3082d --- /dev/null +++ b/src/opt/dar/darCore.c @@ -0,0 +1,344 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// 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] ) + +//////////////////////////////////////////////////////////////////////// +/// 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->fPower = 0; + pPars->fRecycle = 1; + pPars->fVerbose = 0; + pPars->fVeryVerbose = 0; +} + +#define MAX_VAL 10 + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dar_ManRewrite( Aig_Man_t * pAig, Dar_RwrPar_t * pPars ) +{ + extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ); + 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, Counter = 0; + int nMffcSize, nMffcGains[MAX_VAL+1][MAX_VAL+1] = {{0}}; + // prepare the library + Dar_LibPrepare( pPars->nSubgMax ); + // create rewriting manager + p = Dar_ManStart( pAig, pPars ); + if ( pPars->fPower ) + pAig->vProbs = Saig_ManComputeSwitchProbs( pAig, 48, 16, 1 ); + // 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 ) +// if ( p->pPars->fUseZeros && i > nNodesOld ) + break; + if ( pPars->fRecycle && ++Counter % 50000 == 0 && Aig_DagSize(pObj) < Vec_PtrSize(p->vCutNodes)/100 ) + { +// printf( "Counter = %7d. Node = %7d. Dag = %5d. Vec = %5d.\n", +// Counter, i, Aig_DagSize(pObj), Vec_PtrSize(p->vCutNodes) ); +// fflush( stdout ); + Dar_ManCutsRestart( p, pObj ); + } + + // 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_ObjSetCuts( pObj, NULL ); + 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, p->pPars->fUpdateLevel ); + continue; + } + + // evaluate the cuts + p->GainBest = -1; + nMffcSize = -1; + Required = pAig->vLevelR? Aig_ObjRequiredLevel(pAig, pObj) : ABC_INFINITY; + Dar_ObjForEachCut( pObj, pCut, k ) + { + int nLeavesOld = pCut->nLeaves; + if ( pCut->nLeaves == 3 ) + pCut->pLeaves[pCut->nLeaves++] = 0; + Dar_LibEval( p, pObj, pCut, Required, &nMffcSize ); + pCut->nLeaves = nLeavesOld; + } + // check the best gain + if ( !(p->GainBest > 0 || (p->GainBest == 0 && p->pPars->fUseZeros)) ) + { +// Aig_ObjOrderAdvance( pAig ); + continue; + } +// nMffcGains[p->GainBest < MAX_VAL ? p->GainBest : MAX_VAL][nMffcSize < MAX_VAL ? nMffcSize : MAX_VAL]++; + // 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, 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 ); +/* + printf( "Distribution of gain (row) by MFFC size (column) %s 0-costs:\n", p->pPars->fUseZeros? "with":"without" ); + for ( k = 0; k <= MAX_VAL; k++ ) + printf( "<%4d> ", k ); + printf( "\n" ); + for ( i = 0; i <= MAX_VAL; i++ ) + { + for ( k = 0; k <= MAX_VAL; k++ ) + printf( "%6d ", nMffcGains[i][k] ); + printf( "\n" ); + } +*/ + +p->timeTotal = clock() - clkStart; +p->timeOther = p->timeTotal - p->timeCuts - p->timeEval; + +// Bar_ProgressStop( pProgress ); + 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 ); + } + if ( pAig->vProbs ) + { + Vec_IntFree( pAig->vProbs ); + pAig->vProbs = NULL; + } + // 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 ); + Aig_MmFixedRestart( p->pMemCuts ); + Dar_ObjPrepareCuts( p, Aig_ManConst1(p->pAig) ); + Aig_ManForEachPi( pAig, pObj, i ) + Dar_ObjPrepareCuts( p, pObj ); + // 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 ", + (int)sizeof(Dar_Cut_t), (int)4, 1.0*Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20) ); + ABC_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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/dar/darCut.c b/src/opt/dar/darCut.c new file mode 100644 index 00000000..b272b388 --- /dev/null +++ b/src/opt/dar/darCut.c @@ -0,0 +1,752 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 ); + memset( pCutSet, 0, p->pPars->nCutsMax * sizeof(Dar_Cut_t) ); + Dar_ObjSetCuts( pObj, pCutSet ); + Dar_ObjForEachCutAll( pObj, pCut, i ) + pCut->fUsed = 0; + Vec_PtrPush( p->vCutNodes, pObj ); + // 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 ); + if ( p->nCutMemUsed < Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20) ) + p->nCutMemUsed = Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20); + return pCutSet; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_ManCutsRestart( Dar_Man_t * p, Aig_Obj_t * pRoot ) +{ + Aig_Obj_t * pObj; + int i; + Dar_ObjSetCuts( Aig_ManConst1(p->pAig), NULL ); + Vec_PtrForEachEntry( Aig_Obj_t *, p->vCutNodes, pObj, i ) + if ( !Aig_ObjIsNone(pObj) ) + Dar_ObjSetCuts( pObj, NULL ); + Vec_PtrClear( p->vCutNodes ); + Aig_MmFixedRestart( p->pMemCuts ); + Dar_ObjPrepareCuts( p, Aig_ManConst1(p->pAig) ); +} + +/**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_ObjIsPi(pObj) ) + return Dar_ObjPrepareCuts( p, 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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/dar/darData.c b/src/opt/dar/darData.c new file mode 100644 index 00000000..8257f4bb --- /dev/null +++ b/src/opt/dar/darData.c @@ -0,0 +1,11294 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// 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 "src/base/abc/abc.h" + +ABC_NAMESPACE_IMPL_START + + +/**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 = ABC_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 = ABC_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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/dar/darInt.h b/src/opt/dar/darInt.h new file mode 100644 index 00000000..08af70df --- /dev/null +++ b/src/opt/dar/darInt.h @@ -0,0 +1,171 @@ +/**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 ABC__aig__dar__darInt_h +#define ABC__aig__dar__darInt_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + +//#include "bar.h" +#include "src/misc/vec/vec.h" +#include "src/aig/aig/aig.h" +#include "dar.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 + Vec_Ptr_t * vCutNodes; // the nodes with cuts allocated + // 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 (Dar_Cut_t *)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_ManCutsRestart( Dar_Man_t * p, Aig_Obj_t * pRoot ); +extern void Dar_ManCutsFree( Dar_Man_t * p ); +extern Dar_Cut_t * Dar_ObjPrepareCuts( Dar_Man_t * p, Aig_Obj_t * pObj ); +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_LibReturnCanonicals( unsigned * pCanons ); +extern void Dar_LibEval( Dar_Man_t * p, Aig_Obj_t * pRoot, Dar_Cut_t * pCut, int Required, int * pnMffcSize ); +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 ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/opt/dar/darLib.c b/src/opt/dar/darLib.c new file mode 100644 index 00000000..2d047404 --- /dev/null +++ b/src/opt/dar/darLib.c @@ -0,0 +1,1339 @@ +/**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" +#include "src/aig/gia/gia.h" +#include "dar.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 +{ + union { + Aig_Obj_t * pFunc; // the corresponding AIG node if it exists + int iGunc; }; // 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 + float dProb; // probability of the node being 1 + 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 = ABC_ALLOC( Dar_Lib_t, 1 ); + memset( p, 0, sizeof(Dar_Lib_t) ); + // allocate objects + p->nObjs = nObjs; + p->pObjs = ABC_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]; + } +// ABC_PRT( "Library start", clock() - clk ); + return p; +} + +/**Function************************************************************* + + Synopsis [Frees the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_LibFree( Dar_Lib_t * p ) +{ + ABC_FREE( p->pObjs ); + ABC_FREE( p->pDatas ); + ABC_FREE( p->pNodesMem ); + ABC_FREE( p->pNodes0Mem ); + ABC_FREE( p->pSubgrMem ); + ABC_FREE( p->pSubgr0Mem ); + ABC_FREE( p->pPriosMem ); + ABC_FREE( p->pPlaceMem ); + ABC_FREE( p->pScoreMem ); + ABC_FREE( p->pPerms4 ); + ABC_FREE( p->puCanons ); + ABC_FREE( p->pPhases ); + ABC_FREE( p->pPerms ); + ABC_FREE( p->pMap ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Returns canonical truth tables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dar_LibReturnClass( unsigned uTruth ) +{ + return s_DarLib->pMap[uTruth & 0xffff]; +} + + +/**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 = ABC_ALLOC( int, Vec_IntSize(vOuts) ); + p->pSubgr0Mem = ABC_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 = ABC_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 = ABC_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 = ABC_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 = ABC_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 = ABC_ALLOC( int, p->nNodesTotal ); + p->pNodes0Mem = ABC_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; + ABC_FREE( p->pDatas ); + // allocate datas + p->nDatas = nDatas; + p->pDatas = ABC_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] = Abc_MinInt( 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 = Abc_MaxInt( 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 ); +// ABC_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; + // copy the propability of node being one + if ( p->pPars->fPower ) + { + float Prob = Abc_Int2Float( Vec_IntEntry( p->pAig->vProbs, Aig_ObjId(Aig_Regular(pFanin)) ) ); + s_DarLib->pDatas[i].dProb = Aig_IsComplement(pFanin)? 1.0-Prob : Prob; + } + } + 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, float * pPower ) +{ + 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_NodeMffcLabel( p, pRoot, pPower ); + // 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, Aig_Obj_t * pRoot ) +{ + 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 + Abc_MaxInt(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 ); + if ( Aig_Regular(pFanin0) == pRoot || Aig_Regular(pFanin1) == pRoot ) + continue; + 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, Aig_Regular(pData->pFunc)); + // assign the probability + if ( p->pPars->fPower ) + { + float Prob = Abc_Int2Float( Vec_IntEntry( p->pAig->vProbs, Aig_ObjId(Aig_Regular(pData->pFunc)) ) ); + pData->dProb = Aig_IsComplement(pData->pFunc)? 1.0-Prob : Prob; + } + } + } +} + +/**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, float * pPower ) +{ + Dar_LibDat_t * pData; + float Power0, Power1; + int Area; + if ( pPower ) + *pPower = (float)0.0; + pData = s_DarLib->pDatas + pObj->Num; + if ( pData->TravId == Out ) + return 0; + pData->TravId = Out; + if ( pObj->fTerm ) + { + if ( pPower ) + *pPower = pData->dProb; + return 0; + } + assert( pObj->Num > 3 ); + if ( pData->Level > Required ) + return 0xff; + if ( pData->pFunc && !pData->fMffc ) + { + if ( pPower ) + *pPower = pData->dProb; + return 0; + } + // 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, pPower? &Power0 : NULL ); + if ( Area > nNodesSaved ) + return 0xff; + Area += Dar_LibEval_rec( Dar_LibObj(s_DarLib, pObj->Fan1), Out, nNodesSaved, Required+1, pPower? &Power1 : NULL ); + if ( Area > nNodesSaved ) + return 0xff; + if ( pPower ) + { + Dar_LibDat_t * pData0 = s_DarLib->pDatas + Dar_LibObj(s_DarLib, pObj->Fan0)->Num; + Dar_LibDat_t * pData1 = s_DarLib->pDatas + Dar_LibObj(s_DarLib, pObj->Fan1)->Num; + pData->dProb = (pObj->fCompl0? 1.0 - pData0->dProb : pData0->dProb)* + (pObj->fCompl1? 1.0 - pData1->dProb : pData1->dProb); + *pPower = Power0 + 2.0 * pData0->dProb * (1.0 - pData0->dProb) + + Power1 + 2.0 * pData1->dProb * (1.0 - pData1->dProb); + } + 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 * pnMffcSize ) +{ + int fTraining = 0; + float PowerSaved, PowerAdded; + 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, p->pPars->fPower? &PowerSaved : NULL ); + // evaluate the cut + Class = s_DarLib->pMap[pCut->uTruth]; + Dar_LibEvalAssignNums( p, Class, pRoot ); + // 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, p->pPars->fPower? &PowerAdded : NULL ); + nNodesGained = nNodesSaved - nNodesAdded; + if ( p->pPars->fPower && PowerSaved < PowerAdded ) + continue; + 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 ); + *pnMffcSize = nNodesSaved; + } +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 = (Aig_Obj_t *)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) ); +} + + + + + + +/**Function************************************************************* + + Synopsis [Matches the cut with its canonical form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dar2_LibCutMatch( Gia_Man_t * p, Vec_Int_t * vCutLits, unsigned uTruth ) +{ + unsigned uPhase; + char * pPerm; + int i; + assert( Vec_IntSize(vCutLits) == 4 ); + // get the fanin permutation + uPhase = s_DarLib->pPhases[uTruth]; + pPerm = s_DarLib->pPerms4[ (int)s_DarLib->pPerms[uTruth] ]; + // collect fanins with the corresponding permutation/phase + for ( i = 0; i < Vec_IntSize(vCutLits); i++ ) + { +// pFanin = Gia_ManObj( p, pCut->pLeaves[ (int)pPerm[i] ] ); +// pFanin = Gia_ManObj( p, Vec_IntEntry( vCutLits, (int)pPerm[i] ) ); +// pFanin = Gia_ObjFromLit( p, Vec_IntEntry( vCutLits, (int)pPerm[i] ) ); + s_DarLib->pDatas[i].iGunc = Abc_LitNotCond( Vec_IntEntry(vCutLits, (int)pPerm[i]), ((uPhase >> i) & 1) ); + s_DarLib->pDatas[i].Level = Gia_ObjLevel( p, Gia_Regular(Gia_ObjFromLit(p, s_DarLib->pDatas[i].iGunc)) ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Assigns numbers to the nodes of one class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar2_LibEvalAssignNums( Gia_Man_t * p, int Class ) +{ + Dar_LibObj_t * pObj; + Dar_LibDat_t * pData, * pData0, * pData1; + int iFanin0, iFanin1, i, iLit; + 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->iGunc = -1; + 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 + Abc_MaxInt(pData0->Level, pData1->Level); + if ( pData0->iGunc == -1 || pData1->iGunc == -1 ) + continue; + iFanin0 = Abc_LitNotCond( pData0->iGunc, pObj->fCompl0 ); + iFanin1 = Abc_LitNotCond( pData1->iGunc, pObj->fCompl1 ); + // compute the resulting literal + if ( iFanin0 == 0 || iFanin1 == 0 || iFanin0 == Abc_LitNot(iFanin1) ) + iLit = 0; + else if ( iFanin0 == 1 || iFanin0 == iFanin1 ) + iLit = iFanin1; + else if ( iFanin1 == 1 ) + iLit = iFanin0; + else + { + iLit = Gia_ManHashLookup( p, Gia_ObjFromLit(p, iFanin0), Gia_ObjFromLit(p, iFanin1) ); + if ( iLit == 0 ) + iLit = -1; + } + pData->iGunc = iLit; + if ( pData->iGunc >= 0 ) + { + // update the level to be more accurate + pData->Level = Gia_ObjLevel( p, Gia_Regular(Gia_ObjFromLit(p, pData->iGunc)) ); + // mark the node if it is part of MFFC +// pData->fMffc = Gia_ObjIsTravIdCurrentArray(p, Gia_Regular(pData->pGunc)); + } + } +} + +/**Function************************************************************* + + Synopsis [Evaluates one cut.] + + Description [Returns the best gain.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dar2_LibEval_rec( Dar_LibObj_t * pObj, int Out ) +{ + Dar_LibDat_t * pData; + int Area; + pData = s_DarLib->pDatas + pObj->Num; + if ( pData->TravId == Out ) + return 0; + pData->TravId = Out; + if ( pObj->fTerm ) + return 0; + assert( pObj->Num > 3 ); + if ( pData->iGunc >= 0 )//&& !pData->fMffc ) + return 0; + // this is a new node - get a bound on the area of its branches +// nNodesSaved--; + Area = Dar2_LibEval_rec( Dar_LibObj(s_DarLib, pObj->Fan0), Out ); +// if ( Area > nNodesSaved ) +// return 0xff; + Area += Dar2_LibEval_rec( Dar_LibObj(s_DarLib, pObj->Fan1), Out ); +// if ( Area > nNodesSaved ) +// return 0xff; + return Area + 1; +} + +/**Function************************************************************* + + Synopsis [Evaluates one cut.] + + Description [Returns the best gain.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dar2_LibEval( Gia_Man_t * p, Vec_Int_t * vCutLits, unsigned uTruth, int fKeepLevel, Vec_Int_t * vLeavesBest2 ) +{ + int p_OutBest = -1; + int p_OutNumBest = -1; + int p_LevelBest = 1000000; + int p_GainBest = -1000000; + int p_ClassBest = -1; + int fTraining = 0; + Dar_LibObj_t * pObj; + int Out, k, Class, nNodesSaved, nNodesAdded, nNodesGained, clk; + clk = clock(); + assert( Vec_IntSize(vCutLits) == 4 ); + assert( (uTruth >> 16) == 0 ); + // check if the cut exits and assigns leaves and their levels + if ( !Dar2_LibCutMatch(p, vCutLits, uTruth) ) + return -1; + // mark MFFC of the node +// nNodesSaved = Dar2_LibCutMarkMffc( p->pAig, pRoot, pCut->nLeaves, p->pPars->fPower? &PowerSaved : NULL ); + nNodesSaved = 0; + // evaluate the cut + Class = s_DarLib->pMap[uTruth]; + Dar2_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]); +// nNodesAdded = Dar2_LibEval_rec( pObj, Out, nNodesSaved - !p->pPars->fUseZeros, Required, p->pPars->fPower? &PowerAdded : NULL ); + nNodesAdded = Dar2_LibEval_rec( pObj, Out ); + nNodesGained = nNodesSaved - nNodesAdded; + if ( fKeepLevel ) + { + if ( s_DarLib->pDatas[pObj->Num].Level > p_LevelBest || + (s_DarLib->pDatas[pObj->Num].Level == p_LevelBest && nNodesGained <= p_GainBest) ) + continue; + } + else + { + if ( nNodesGained < p_GainBest || + (nNodesGained == p_GainBest && s_DarLib->pDatas[pObj->Num].Level >= p_LevelBest) ) + continue; + } + // remember this possibility + Vec_IntClear( vLeavesBest2 ); + for ( k = 0; k < Vec_IntSize(vCutLits); k++ ) + Vec_IntPush( vLeavesBest2, s_DarLib->pDatas[k].iGunc ); + 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; + assert( p_OutBest != -1 ); + return p_OutBest; +} + +/**Function************************************************************* + + Synopsis [Clears the fields of the nodes used i this cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar2_LibBuildClear_rec( Dar_LibObj_t * pObj, int * pCounter ) +{ + if ( pObj->fTerm ) + return; + pObj->Num = (*pCounter)++; + s_DarLib->pDatas[ pObj->Num ].iGunc = -1; + Dar2_LibBuildClear_rec( Dar_LibObj(s_DarLib, pObj->Fan0), pCounter ); + Dar2_LibBuildClear_rec( Dar_LibObj(s_DarLib, pObj->Fan1), pCounter ); +} + +/**Function************************************************************* + + Synopsis [Reconstructs the best cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dar2_LibBuildBest_rec( Gia_Man_t * p, Dar_LibObj_t * pObj ) +{ + Gia_Obj_t * pNode; + Dar_LibDat_t * pData; + int iFanin0, iFanin1; + pData = s_DarLib->pDatas + pObj->Num; + if ( pData->iGunc >= 0 ) + return pData->iGunc; + iFanin0 = Dar2_LibBuildBest_rec( p, Dar_LibObj(s_DarLib, pObj->Fan0) ); + iFanin1 = Dar2_LibBuildBest_rec( p, Dar_LibObj(s_DarLib, pObj->Fan1) ); + iFanin0 = Abc_LitNotCond( iFanin0, pObj->fCompl0 ); + iFanin1 = Abc_LitNotCond( iFanin1, pObj->fCompl1 ); + pData->iGunc = Gia_ManHashAnd( p, iFanin0, iFanin1 ); + pNode = Gia_ManObj( p, Abc_Lit2Var(pData->iGunc) ); + if ( Gia_ObjIsAnd( pNode ) ) + Gia_ObjSetAndLevel( p, pNode ); + Gia_ObjSetPhase( pNode ); + return pData->iGunc; +} + +/**Function************************************************************* + + Synopsis [Reconstructs the best cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dar2_LibBuildBest( Gia_Man_t * p, Vec_Int_t * vLeavesBest2, int OutBest ) +{ + int i, iLeaf, Counter = 4; + assert( Vec_IntSize(vLeavesBest2) == 4 ); + Vec_IntForEachEntry( vLeavesBest2, iLeaf, i ) + s_DarLib->pDatas[i].iGunc = iLeaf; + Dar2_LibBuildClear_rec( Dar_LibObj(s_DarLib, OutBest), &Counter ); + return Dar2_LibBuildBest_rec( p, Dar_LibObj(s_DarLib, OutBest) ); +} + +/**Function************************************************************* + + Synopsis [Evaluate and build the new node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dar_LibEvalBuild( Gia_Man_t * p, Vec_Int_t * vCutLits, unsigned uTruth, int fKeepLevel, Vec_Int_t * vLeavesBest2 ) +{ + int OutBest = Dar2_LibEval( p, vCutLits, uTruth, fKeepLevel, vLeavesBest2 ); + return Dar2_LibBuildBest( p, vLeavesBest2, OutBest ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/dar/darMan.c b/src/opt/dar/darMan.c new file mode 100644 index 00000000..5a3e0687 --- /dev/null +++ b/src/opt/dar/darMan.c @@ -0,0 +1,174 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// 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; + Aig_ManCleanData( pAig ); + p = ABC_ALLOC( Dar_Man_t, 1 ); + memset( p, 0, sizeof(Dar_Man_t) ); + p->pPars = pPars; + p->pAig = pAig; + p->vCutNodes = Vec_PtrAlloc( 1000 ); + p->pMemCuts = Aig_MmFixedStart( p->pPars->nCutsMax * sizeof(Dar_Cut_t), 1024 ); + 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->vCutNodes ) + Vec_PtrFree( p->vCutNodes ); + if ( p->pMemCuts ) + Aig_MmFixedStop( p->pMemCuts, 0 ); + if ( p->vLeavesBest ) + Vec_PtrFree( p->vLeavesBest ); + ABC_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) ); + ABC_PRT( "Cuts ", p->timeCuts ); + ABC_PRT( "Eval ", p->timeEval ); + ABC_PRT( "Other ", p->timeOther ); + ABC_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 ); +// ABC_PRTP( "T", p->ClassTimes[i], p->timeEval ); + printf( "\n" ); + } + fflush( stdout ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +#if 0 + +ABC_NAMESPACE_IMPL_END + +#include "src/bool/kit/kit.h" + +ABC_NAMESPACE_IMPL_START + +void Dar_ManPrintScript() +{ + unsigned pCanons[222]; + int i; + Dar_LibReturnCanonicals( pCanons ); + for ( i = 1; i < 222; i++ ) + { + Kit_DsdNtk_t * pNtk; + pNtk = Kit_DsdDecompose( pCanons + i, 4 ); + printf( " \"" ); + Kit_DsdPrint( stdout, pNtk ); + printf( "\", /* %3d */\n", i ); + Kit_DsdNtkFree( pNtk ); + } +} +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/dar/darPrec.c b/src/opt/dar/darPrec.c new file mode 100644 index 00000000..4d164123 --- /dev/null +++ b/src/opt/dar/darPrec.c @@ -0,0 +1,394 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 = ABC_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 ABC_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 = ABC_ALLOC( int, nMints ); + pMintsP = ABC_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]); + } + + ABC_FREE( pMints ); + ABC_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 = ABC_CALLOC( unsigned short, nFuncs ); + uPhases = ABC_CALLOC( char, nFuncs ); + uPerms = ABC_CALLOC( char, nFuncs ); + uMap = ABC_CALLOC( 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; + uMap[uPerm] = uMap[uTruth]; + + uPerm = ~uPerm & 0xFFFF; + uCanons[uPerm] = uTruth; + uPhases[uPerm] = i | 16; + uPerms[uPerm] = k; + uMap[uPerm] = uMap[uTruth]; + } + 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; + uMap[uPerm] = uMap[uTruth]; + + uPerm = ~uPerm & 0xFFFF; + uCanons[uPerm] = uTruth; + uPhases[uPerm] = i | 16; + uPerms[uPerm] = k; + uMap[uPerm] = uMap[uTruth]; + } + else + assert( uCanons[uPerm] == uTruth ); + } + } + } + for ( uTruth = 1; uTruth < 0xffff; uTruth++ ) + assert( uMap[uTruth] != 0 ); + uPhases[(1<<16)-1] = 16; + assert( nClasses == 222 ); + ABC_FREE( pPerms4 ); + if ( puCanons ) + *puCanons = uCanons; + else + ABC_FREE( uCanons ); + if ( puPhases ) + *puPhases = uPhases; + else + ABC_FREE( uPhases ); + if ( puPerms ) + *puPerms = uPerms; + else + ABC_FREE( uPerms ); + if ( puMap ) + *puMap = uMap; + else + ABC_FREE( uMap ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/dar/darRefact.c b/src/opt/dar/darRefact.c new file mode 100644 index 00000000..60364358 --- /dev/null +++ b/src/opt/dar/darRefact.c @@ -0,0 +1,636 @@ +/**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 "src/bool/kit/kit.h" + +#include "src/bool/bdc/bdc.h" +#include "src/bool/bdc/bdcInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 + // bi-decomposition + Bdc_Par_t DecPars; // decomposition parameters + Bdc_Man_t * pManDec; // decomposition manager + // 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 = ABC_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( 1024, Kit_TruthWordNum(pPars->nLeafMax) ); + p->vMemory = Vec_IntAlloc( 1 << 16 ); + p->vCutNodes = Vec_PtrAlloc( 256 ); + p->vLeavesBest = Vec_PtrAlloc( pPars->nLeafMax ); + // alloc bi-decomposition manager + p->DecPars.nVarsMax = pPars->nLeafMax; + p->DecPars.fVerbose = pPars->fVerbose; + p->DecPars.fVeryVerbose = 0; +// p->pManDec = Bdc_ManAlloc( &p->DecPars ); + 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) ); + ABC_PRT( "Cuts ", p->timeCuts ); + ABC_PRT( "Eval ", p->timeEval ); + ABC_PRT( "Other ", p->timeOther ); + ABC_PRT( "TOTAL ", p->timeTotal ); +} + +/**Function************************************************************* + + Synopsis [Stops the rewriting manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_ManRefStop( Ref_Man_t * p ) +{ + if ( p->pManDec ) + Bdc_ManFree( p->pManDec ); + 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 ); + ABC_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((Aig_Obj_t *)pNode->pFunc)->Level; + assert( Aig_Regular((Aig_Obj_t *)pNode->pFunc)->Level < (1<<24)-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 = (Aig_Obj_t *)pNode0->pFunc; + pAnd1 = (Aig_Obj_t *)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 + Abc_MaxInt( 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( (Aig_Obj_t *)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( (Aig_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); + pAnd1 = Aig_NotCond( (Aig_Obj_t *)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( (Aig_Obj_t *)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 = Aig_NodeMffcSupp( p->pAig, pObj, 0, NULL ); + p->pGraphBest = Kit_GraphCreateConst0(); + Vec_PtrCopy( p->vLeavesBest, vCut ); + return p->GainBest; + } + if ( Kit_TruthIsConst1(pTruth, Vec_PtrSize(vCut)) ) + { + p->GainBest = Aig_NodeMffcSupp( p->pAig, pObj, 0, NULL ); + 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 ); +/* +{ + int RetValue; + RetValue = Bdc_ManDecompose( p->pManDec, pTruth, NULL, Vec_PtrSize(vCut), NULL, 1000 ); + printf( "Graph = %d. Bidec = %d.\n", Kit_GraphNodeNum(pGraphCur), RetValue ); +} +*/ + 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 ); +// Kit_TruthNot( pTruth, pTruth, Vec_PtrSize(vCut) ); + if ( RetValue > -1 ) + { + pGraphCur = Kit_SopFactor( p->vMemory, 1, Vec_PtrSize(vCut), p->vMemory ); +/* +{ + int RetValue; + RetValue = Bdc_ManDecompose( p->pManDec, pTruth, NULL, Vec_PtrSize(vCut), NULL, 1000 ); + printf( "Graph = %d. Bidec = %d.\n", Kit_GraphNodeNum(pGraphCur), RetValue ); +} +*/ + 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( Aig_Obj_t *, 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 = Abc_MaxInt( 0, Aig_ObjLevel(pObj) - 10 ); + nNodesSaved = Aig_NodeMffcSupp( 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_NodeMffcLabelCut( p->pAig, pObj, vCut ); + } + else if ( Vec_PtrSize(vCut) < p->pPars->nLeafMax - 2 && p->pPars->fExtend ) + { + if ( !Dar_ObjCutLevelAchieved(vCut, nLevelMin) ) + { + if ( Aig_NodeMffcExtendCut( pAig, pObj, vCut, vCut2 ) ) + { + nNodesSaved2 = Aig_NodeMffcLabelCut( 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) : ABC_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, 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 ); +/* + Aig_ManForEachObj( p->pAig, pObj, i ) + if ( Aig_ObjIsNode(pObj) && Aig_ObjRefs(pObj) == 0 ) + { + printf( "Unreferenced " ); + Aig_ObjPrintVerbose( pObj, 0 ); + printf( "\n" ); + } +*/ + // remove dangling nodes (they should not be here!) + Aig_ManCleanup( 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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/dar/darResub.c b/src/opt/dar/darResub.c new file mode 100644 index 00000000..44367207 --- /dev/null +++ b/src/opt/dar/darResub.c @@ -0,0 +1,53 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/dar/darScript.c b/src/opt/dar/darScript.c new file mode 100644 index 00000000..79d6dfc4 --- /dev/null +++ b/src/opt/dar/darScript.c @@ -0,0 +1,927 @@ +/**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 "src/proof/dch/dch.h" +#include "src/aig/gia/gia.h" +#include "src/aig/gia/giaAig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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_ManDupDfs( pAig ); + Dar_ManRewrite( pAig, pPars ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + return pAig; +} + +/**Function************************************************************* + + Synopsis [Reproduces script "rwsat".] + + 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; +//printf( "1" ); + pAig = Aig_ManDupDfs( pAig ); + if ( fVerbose ) printf( "Starting: " ), Aig_ManPrintStats( pAig ); + +//printf( "2" ); + // balance + if ( fBalance ) + { + pAig = Dar_ManBalance( pTemp = pAig, 0 ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); + } + +//Aig_ManDumpBlif( pAig, "inter.blif", NULL, NULL ); +//printf( "3" ); + // rewrite + Dar_ManRewrite( pAig, pParsRwr ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "Rewrite: " ), Aig_ManPrintStats( pAig ); + +//printf( "4" ); + // refactor + Dar_ManRefactor( pAig, pParsRef ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "Refactor: " ), Aig_ManPrintStats( pAig ); + +//printf( "5" ); + // balance + if ( fBalance ) + { + pAig = Dar_ManBalance( pTemp = pAig, 0 ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); + } + +//printf( "6" ); + // rewrite + Dar_ManRewrite( pAig, pParsRwr ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "Rewrite: " ), Aig_ManPrintStats( pAig ); + +//printf( "7" ); + return pAig; +} + +/**Function************************************************************* + + Synopsis [Performs one iteration of AIG rewriting.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_ManHaigPrintStats( Aig_Man_t * pAig ) +{ + Aig_Obj_t * pObj; + int Counter, i; + Counter = 0; + Aig_ManForEachNode( pAig, pObj, i ) + Counter += (pObj->pHaig != NULL); + printf( "Total nodes = %6d. Equiv nodes = %6d.\n", Aig_ManNodeNum(pAig), Counter ); +} + +/**Function************************************************************* + + Synopsis [Reproduces script "compress".] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, 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->fPower = fPower; + + pParsRwr->fVerbose = 0;//fVerbose; + pParsRef->fVerbose = 0;//fVerbose; + + pAig = Aig_ManDupDfs( pAig ); + if ( fVerbose ) printf( "Starting: " ), Aig_ManPrintStats( pAig ); +/* + // balance + if ( fBalance ) + { + pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); + } +*/ + // rewrite + Dar_ManRewrite( pAig, pParsRwr ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "Rewrite: " ), Aig_ManPrintStats( pAig ); + + // refactor + Dar_ManRefactor( pAig, pParsRef ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "Refactor: " ), Aig_ManPrintStats( pAig ); + + // balance + if ( fBalance ) + { + pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); + } + + pParsRwr->fUseZeros = 1; + pParsRef->fUseZeros = 1; + + // rewrite + Dar_ManRewrite( pAig, pParsRwr ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "RewriteZ: " ), 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 fFanout, int fPower, 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->fFanout = fFanout; + pParsRwr->fPower = fPower; + + pParsRwr->fVerbose = 0;//fVerbose; + pParsRef->fVerbose = 0;//fVerbose; + + pAig = Aig_ManDupDfs( pAig ); + if ( fVerbose ) printf( "Starting: " ), Aig_ManPrintStats( pAig ); +/* + // balance + if ( fBalance ) + { + pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); + } +*/ + // rewrite +// Dar_ManRewrite( pAig, pParsRwr ); + pParsRwr->fUpdateLevel = 0; // disable level update + Dar_ManRewrite( pAig, pParsRwr ); + pParsRwr->fUpdateLevel = fUpdateLevel; // reenable level update if needed + + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "Rewrite: " ), Aig_ManPrintStats( pAig ); + + // refactor + Dar_ManRefactor( pAig, pParsRef ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "Refactor: " ), Aig_ManPrintStats( pAig ); + + // balance +// if ( fBalance ) + { + pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); + } + + // rewrite + Dar_ManRewrite( pAig, pParsRwr ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "Rewrite: " ), Aig_ManPrintStats( pAig ); + + pParsRwr->fUseZeros = 1; + pParsRef->fUseZeros = 1; + + // rewrite + Dar_ManRewrite( pAig, pParsRwr ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "RewriteZ: " ), Aig_ManPrintStats( pAig ); + + // balance + if ( fBalance ) + { + pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); + } + + // refactor + Dar_ManRefactor( pAig, pParsRef ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "RefactorZ: " ), Aig_ManPrintStats( pAig ); + + // rewrite + Dar_ManRewrite( pAig, pParsRwr ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "RewriteZ: " ), Aig_ManPrintStats( pAig ); + + // balance + if ( fBalance ) + { + pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "Balance: " ), 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 fPower, 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; + Aig_Obj_t * pObj; + int i; + + vAigs = Vec_PtrAlloc( 3 ); + pAig = Aig_ManDupDfs(pAig); + Vec_PtrPush( vAigs, pAig ); + + Aig_ManForEachObj( pAig, pObj, i ) + pObj->pHaig = pObj; + + pAig = Dar_ManCompress(pAig, fBalance, fUpdateLevel, fPower, fVerbose); + Vec_PtrPush( vAigs, pAig ); +//Aig_ManPrintStats( pAig ); + + Aig_ManForEachObj( pAig, pObj, i ) + { + pObj->pNext = pObj->pHaig; + pObj->pHaig = pObj; + } + + pAig = Dar_ManCompress2(pAig, fBalance, fUpdateLevel, 1, fPower, fVerbose); + Vec_PtrPush( vAigs, pAig ); +//Aig_ManPrintStats( pAig ); + + pAig = (Aig_Man_t *)Vec_PtrEntry( vAigs, 1 ); + Aig_ManForEachObj( pAig, pObj, i ) + pObj->pHaig = pObj->pNext; + + return vAigs; +} + +/**Function************************************************************* + + Synopsis [Reproduces script "compress2".] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Dar_ManChoice( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fConstruct, int nConfMax, int nLevelMax, 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, 0, fVerbose ); + + // swap the first and last network + // this should lead to the primary choice being "better" because of synthesis + // (it is also important when constructing choices) + if ( !fConstruct ) + { + pMan = (Aig_Man_t *)Vec_PtrPop( vAigs ); + Vec_PtrPush( vAigs, Vec_PtrEntry(vAigs,0) ); + Vec_PtrWriteEntry( vAigs, 0, pMan ); + } + +if ( fVerbose ) +{ +ABC_PRT( "Synthesis time", clock() - clk ); +} +clk = clock(); + if ( fConstruct ) + pMan = Aig_ManChoiceConstructive( vAigs, fVerbose ); + else + pMan = Aig_ManChoicePartitioned( vAigs, 300, nConfMax, nLevelMax, fVerbose ); + Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pTemp, i ) + Aig_ManStop( pTemp ); + Vec_PtrFree( vAigs ); +if ( fVerbose ) +{ +ABC_PRT( "Choicing time ", clock() - clk ); +} + return pMan; +// return NULL; +} + + +/**Function************************************************************* + + Synopsis [Reproduces script "compress".] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Dar_NewCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, 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->fPower = fPower; + + pParsRwr->fVerbose = 0;//fVerbose; + pParsRef->fVerbose = 0;//fVerbose; + +// pAig = Aig_ManDupDfs( pAig ); + if ( fVerbose ) printf( "Starting: " ), Aig_ManPrintStats( pAig ); + + // rewrite + Dar_ManRewrite( pAig, pParsRwr ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "Rewrite: " ), Aig_ManPrintStats( pAig ); + + // refactor + Dar_ManRefactor( pAig, pParsRef ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "Refactor: " ), Aig_ManPrintStats( pAig ); + + // balance + if ( fBalance ) + { + pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); + } + + pParsRwr->fUseZeros = 1; + pParsRef->fUseZeros = 1; + + // rewrite + Dar_ManRewrite( pAig, pParsRwr ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "RewriteZ: " ), Aig_ManPrintStats( pAig ); + + return pAig; +} + +/**Function************************************************************* + + Synopsis [Reproduces script "compress2".] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Dar_NewCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fFanout, int fPower, int fLightSynth, 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->fFanout = fFanout; + pParsRwr->fPower = fPower; + + pParsRwr->fVerbose = 0;//fVerbose; + pParsRef->fVerbose = 0;//fVerbose; + +// pAig = Aig_ManDupDfs( pAig ); + if ( fVerbose ) printf( "Starting: " ), Aig_ManPrintStats( pAig ); + + // skip if lighter synthesis is requested + if ( !fLightSynth ) + { + // rewrite + //Dar_ManRewrite( pAig, pParsRwr ); +// pParsRwr->fUpdateLevel = 0; // disable level update // this change was requested in July and later disabled + Dar_ManRewrite( pAig, pParsRwr ); +// pParsRwr->fUpdateLevel = fUpdateLevel; // reenable level update if needed + + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "Rewrite: " ), Aig_ManPrintStats( pAig ); + + // refactor + Dar_ManRefactor( pAig, pParsRef ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "Refactor: " ), Aig_ManPrintStats( pAig ); + } + + // balance + pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); + + // skip if lighter synthesis is requested + if ( !fLightSynth ) + { + // rewrite + Dar_ManRewrite( pAig, pParsRwr ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "Rewrite: " ), Aig_ManPrintStats( pAig ); + } + + pParsRwr->fUseZeros = 1; + pParsRef->fUseZeros = 1; + + // rewrite + Dar_ManRewrite( pAig, pParsRwr ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "RewriteZ: " ), Aig_ManPrintStats( pAig ); + + // skip if lighter synthesis is requested + if ( !fLightSynth ) + { + // balance + if ( fBalance ) + { + pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); + } + } + + // refactor + Dar_ManRefactor( pAig, pParsRef ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "RefactorZ: " ), Aig_ManPrintStats( pAig ); + + // skip if lighter synthesis is requested + if ( !fLightSynth ) + { + // rewrite + Dar_ManRewrite( pAig, pParsRwr ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "RewriteZ: " ), Aig_ManPrintStats( pAig ); + } + + // balance + if ( fBalance ) + { + pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); + Aig_ManStop( pTemp ); + if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); + } + return pAig; +} + +/**Function************************************************************* + + Synopsis [Count the number of nodes with very high fanout count.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dar_NewChoiceSynthesisGuard( Aig_Man_t * pAig ) +{ + Aig_Obj_t * pObj; + int i, Count = 0; + Aig_ManForEachNode( pAig, pObj, i ) + if ( Aig_ObjRefs(pObj) > 1000 ) + Count += Aig_ObjRefs(pObj) / 1000; + return (int)(Count > 10); +} + +/**Function************************************************************* + + Synopsis [Reproduces script "compress2".] + + Description [Takes AIG manager, consumes it, and produces GIA manager.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Dar_NewChoiceSynthesis( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fLightSynth, 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 * vGias; + Gia_Man_t * pGia, * pTemp; + int i; + + if ( fUpdateLevel && Dar_NewChoiceSynthesisGuard(pAig) ) + { + if ( fVerbose ) + printf( "Warning: Due to high fanout count of some nodes, level updating is disabled.\n" ); + fUpdateLevel = 0; + } + + vGias = Vec_PtrAlloc( 3 ); + pGia = Gia_ManFromAig(pAig); + Vec_PtrPush( vGias, pGia ); + + pAig = Dar_NewCompress( pAig, fBalance, fUpdateLevel, fPower, fVerbose ); + pGia = Gia_ManFromAig(pAig); + Vec_PtrPush( vGias, pGia ); +//Aig_ManPrintStats( pAig ); + + pAig = Dar_NewCompress2( pAig, fBalance, fUpdateLevel, 1, fPower, fLightSynth, fVerbose ); + pGia = Gia_ManFromAig(pAig); + Vec_PtrPush( vGias, pGia ); +//Aig_ManPrintStats( pAig ); + + Aig_ManStop( pAig ); + + // swap around the first and the last + pTemp = (Gia_Man_t *)Vec_PtrPop( vGias ); + Vec_PtrPush( vGias, Vec_PtrEntry(vGias,0) ); + Vec_PtrWriteEntry( vGias, 0, pTemp ); + +// Aig_Man_t * pAig; +// int i; +// printf( "Choicing will be performed with %d AIGs:\n", Vec_PtrSize(p->vAigs) ); +// Vec_PtrForEachEntry( Aig_Man_t *, p->vAigs, pAig, i ) +// Aig_ManPrintStats( pAig ); + + // derive the miter + pGia = Gia_ManChoiceMiter( vGias ); + + // cleanup + Vec_PtrForEachEntry( Gia_Man_t *, vGias, pTemp, i ) + Gia_ManStop( pTemp ); + Vec_PtrFree( vGias ); + return pGia; +} + +/**Function************************************************************* + + Synopsis [Reproduces script "compress2".] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +/* +Aig_Man_t * Dar_ManChoiceNew( Aig_Man_t * pAig, Dch_Pars_t * pPars ) +{ + extern Aig_Man_t * Dch_ComputeChoices( Vec_Ptr_t * vAigs, Dch_Pars_t * pPars ); + extern Aig_Man_t * Cec_ComputeChoices( Vec_Ptr_t * vAigs, Dch_Pars_t * pPars ); + + int fVerbose = pPars->fVerbose; + int fConstruct = 0; + Aig_Man_t * pMan, * pTemp; + Vec_Ptr_t * vAigs; + int i, clk; + +clk = clock(); +// vAigs = Dar_ManChoiceSynthesisExt(); +// vAigs = Dar_ManChoiceSynthesis( pAig, 1, 1, pPars->fPower, fVerbose ); + vAigs = Dar_ManChoiceSynthesis( pAig, 1, 1, pPars->fPower, 0 ); + + // swap the first and last network + // this should lead to the primary choice being "better" because of synthesis + // (it is also important when constructing choices) + if ( !fConstruct ) + { + pMan = Vec_PtrPop( vAigs ); + Vec_PtrPush( vAigs, Vec_PtrEntry(vAigs,0) ); + Vec_PtrWriteEntry( vAigs, 0, pMan ); + } + +if ( fVerbose ) +{ +//ABC_PRT( "Synthesis time", clock() - clk ); +} + pPars->timeSynth = clock() - clk; + +clk = clock(); + // perform choice computation + if ( pPars->fUseGia ) + pMan = Cec_ComputeChoices( vAigs, pPars ); + else + pMan = Dch_ComputeChoices( vAigs, pPars ); + + // reconstruct the network + pMan = Aig_ManDupDfsGuided( pTemp = pMan, Vec_PtrEntry(vAigs,0) ); + Aig_ManStop( pTemp ); + // duplicate the timing manager + pTemp = Vec_PtrEntry( vAigs, 0 ); + if ( pTemp->pManTime ) + { + extern void * Tim_ManDup( void * p, int fDiscrete ); + pMan->pManTime = Tim_ManDup( pTemp->pManTime, 0 ); + } + // reset levels + Aig_ManChoiceLevel( pMan ); + ABC_FREE( pMan->pName ); + ABC_FREE( pMan->pSpec ); + pMan->pName = Abc_UtilStrsav( pTemp->pName ); + pMan->pSpec = Abc_UtilStrsav( pTemp->pSpec ); + + // cleanup + Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pTemp, i ) + Aig_ManStop( pTemp ); + Vec_PtrFree( vAigs ); + +if ( fVerbose ) +{ +//ABC_PRT( "Choicing time ", clock() - clk ); +} + return pMan; +// return NULL; +} +*/ + +/**Function************************************************************* + + Synopsis [Reproduces script "compress2".] + + Description [Consumes the input AIG to reduce memory usage.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Dar_ManChoiceNewAig( Aig_Man_t * pAig, Dch_Pars_t * pPars ) +{ +// extern Aig_Man_t * Dch_DeriveTotalAig( Vec_Ptr_t * vAigs ); + extern Aig_Man_t * Dch_ComputeChoices( Aig_Man_t * pAig, Dch_Pars_t * pPars ); + int fVerbose = pPars->fVerbose; + Aig_Man_t * pMan, * pTemp; + Vec_Ptr_t * vAigs; + Vec_Ptr_t * vPios; + void * pManTime; + char * pName, * pSpec; + int i, clk; + +clk = clock(); + vAigs = Dar_ManChoiceSynthesis( pAig, 1, 1, pPars->fPower, fVerbose ); +pPars->timeSynth = clock() - clk; + // swap the first and last network + // this should lead to the primary choice being "better" because of synthesis + // (it is also important when constructing choices) + pMan = (Aig_Man_t *)Vec_PtrPop( vAigs ); + Vec_PtrPush( vAigs, Vec_PtrEntry(vAigs,0) ); + Vec_PtrWriteEntry( vAigs, 0, pMan ); + + // derive the total AIG + pMan = Dch_DeriveTotalAig( vAigs ); + // cleanup + Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pTemp, i ) + Aig_ManStop( pTemp ); + Vec_PtrFree( vAigs ); + + // compute choices + pMan = Dch_ComputeChoices( pTemp = pMan, pPars ); + Aig_ManStop( pTemp ); + + // save useful things + pManTime = pAig->pManTime; pAig->pManTime = NULL; + pName = Abc_UtilStrsav( pAig->pName ); + pSpec = Abc_UtilStrsav( pAig->pSpec ); + + // create guidence + vPios = Aig_ManOrderPios( pMan, pAig ); + Aig_ManStop( pAig ); + + // reconstruct the network + pMan = Aig_ManDupDfsGuided( pTemp = pMan, vPios ); + Aig_ManStop( pTemp ); + Vec_PtrFree( vPios ); + + // reset levels + pMan->pManTime = pManTime; + Aig_ManChoiceLevel( pMan ); + + // copy names + ABC_FREE( pMan->pName ); + ABC_FREE( pMan->pSpec ); + pMan->pName = pName; + pMan->pSpec = pSpec; + return pMan; +} + +/**Function************************************************************* + + Synopsis [Reproduces script "compress2".] + + Description [Consumes the input AIG to reduce memory usage.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Dar_ManChoiceNew( Aig_Man_t * pAig, Dch_Pars_t * pPars ) +{ + extern Aig_Man_t * Cec_ComputeChoices( Gia_Man_t * pGia, Dch_Pars_t * pPars ); +// extern Aig_Man_t * Dch_DeriveTotalAig( Vec_Ptr_t * vAigs ); + extern Aig_Man_t * Dch_ComputeChoices( Aig_Man_t * pAig, Dch_Pars_t * pPars ); + int fVerbose = pPars->fVerbose; + Aig_Man_t * pMan, * pTemp; + Gia_Man_t * pGia; + Vec_Ptr_t * vPios; + void * pManTime; + char * pName, * pSpec; + int clk; + + // save useful things + pManTime = pAig->pManTime; pAig->pManTime = NULL; + pName = Abc_UtilStrsav( pAig->pName ); + pSpec = Abc_UtilStrsav( pAig->pSpec ); + + // perform synthesis +clk = clock(); + pGia = Dar_NewChoiceSynthesis( Aig_ManDupDfs(pAig), 1, 1, pPars->fPower, pPars->fLightSynth, pPars->fVerbose ); +pPars->timeSynth = clock() - clk; + + // perform choice computation + if ( pPars->fUseGia ) + pMan = Cec_ComputeChoices( pGia, pPars ); + else + { + pMan = Gia_ManToAigSkip( pGia, 3 ); + Gia_ManStop( pGia ); + pMan = Dch_ComputeChoices( pTemp = pMan, pPars ); + Aig_ManStop( pTemp ); + } + + // create guidence + vPios = Aig_ManOrderPios( pMan, pAig ); + Aig_ManStop( pAig ); + + // reconstruct the network + pMan = Aig_ManDupDfsGuided( pTemp = pMan, vPios ); + Aig_ManStop( pTemp ); + Vec_PtrFree( vPios ); + + // reset levels + pMan->pManTime = pManTime; + Aig_ManChoiceLevel( pMan ); + + // copy names + ABC_FREE( pMan->pName ); + ABC_FREE( pMan->pSpec ); + pMan->pName = pName; + pMan->pSpec = pSpec; + return pMan; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/dar/dar_.c b/src/opt/dar/dar_.c new file mode 100644 index 00000000..323abed2 --- /dev/null +++ b/src/opt/dar/dar_.c @@ -0,0 +1,53 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/dar/module.make b/src/opt/dar/module.make new file mode 100644 index 00000000..ef9ddbd5 --- /dev/null +++ b/src/opt/dar/module.make @@ -0,0 +1,10 @@ +SRC += src/opt/dar/darBalance.c \ + src/opt/dar/darCore.c \ + src/opt/dar/darCut.c \ + src/opt/dar/darData.c \ + src/opt/dar/darLib.c \ + src/opt/dar/darMan.c \ + src/opt/dar/darPrec.c \ + src/opt/dar/darRefact.c \ + src/opt/dar/darResub.c \ + src/opt/dar/darScript.c diff --git a/src/opt/dec/dec.h b/src/opt/dec/dec.h deleted file mode 100644 index 543fabf1..00000000 --- a/src/opt/dec/dec.h +++ /dev/null @@ -1,725 +0,0 @@ -/**CFile**************************************************************** - - FileName [dec.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [A simple decomposition tree/node data structure and its APIs.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: dec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __DEC_H__ -#define __DEC_H__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 - union { int iFunc; // the literal of the node (AIG) - void * pFunc; }; // the function of the node (BDD or AIG) - unsigned Level : 14; // the level of this node in the global AIG - // printing info - unsigned fNodeOr : 1; // marks the original OR node - unsigned fCompl0 : 1; // marks the original complemented edge - unsigned fCompl1 : 1; // marks the original complemented edge - // latch info - unsigned nLat0 : 5; // the number of latches on the first edge - unsigned nLat1 : 5; // the number of latches on the second edge - unsigned nLat2 : 5; // the number of latches on the output edge -}; - -typedef struct Dec_Graph_t_ Dec_Graph_t; -struct Dec_Graph_t_ -{ - int fConst; // marks the constant 1 graph - int nLeaves; // the number of leaves - int nSize; // the number of nodes (including the leaves) - int nCap; // the number of allocated nodes - Dec_Node_t * pNodes; // the array of leaves and internal nodes - Dec_Edge_t eRoot; // the pointer to the topmost node -}; - -typedef struct Dec_Man_t_ Dec_Man_t; -struct Dec_Man_t_ -{ - void * pMvcMem; // memory manager for MVC cover (used for factoring) - Vec_Int_t * vCubes; // storage for cubes - Vec_Int_t * vLits; // storage for literals - // precomputation information about 4-variable functions - unsigned short * puCanons; // canonical forms - char * pPhases; // canonical phases - char * pPerms; // canonical permutations - unsigned char * pMap; // mapping of functions into class numbers -}; - - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -// interator throught the leaves -#define Dec_GraphForEachLeaf( pGraph, pLeaf, i ) \ - for ( i = 0; (i < (pGraph)->nLeaves) && (((pLeaf) = Dec_GraphNode(pGraph, i)), 1); i++ ) -// interator throught the internal nodes -#define Dec_GraphForEachNode( pGraph, pAnd, i ) \ - for ( i = (pGraph)->nLeaves; (i < (pGraph)->nSize) && (((pAnd) = Dec_GraphNode(pGraph, i)), 1); i++ ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== decAbc.c ========================================================*/ -/*=== decFactor.c ========================================================*/ -extern Dec_Graph_t * Dec_Factor( char * pSop ); -/*=== decMan.c ========================================================*/ -extern Dec_Man_t * Dec_ManStart(); -extern void Dec_ManStop( Dec_Man_t * p ); -/*=== decPrint.c ========================================================*/ -extern void Dec_GraphPrint( FILE * pFile, Dec_Graph_t * pGraph, char * pNamesIn[], char * pNameOut ); -/*=== decUtil.c ========================================================*/ -extern unsigned Dec_GraphDeriveTruth( Dec_Graph_t * pGraph ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates an edge pointing to the node in the given polarity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Edge_t Dec_EdgeCreate( int Node, int fCompl ) -{ - Dec_Edge_t eEdge = { fCompl, Node }; - return eEdge; -} - -/**Function************************************************************* - - Synopsis [Converts the edge into unsigned integer.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned Dec_EdgeToInt( Dec_Edge_t eEdge ) -{ - return (eEdge.Node << 1) | eEdge.fCompl; -} - -/**Function************************************************************* - - Synopsis [Converts unsigned integer into the edge.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Edge_t Dec_IntToEdge( unsigned Edge ) -{ - return Dec_EdgeCreate( Edge >> 1, Edge & 1 ); -} - -/**Function************************************************************* - - Synopsis [Converts the edge into unsigned integer.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned Dec_EdgeToInt_( Dec_Edge_t m ) { union { Dec_Edge_t x; unsigned y; } v; v.x = m; return v.y; } -/* -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 m ) { union { Dec_Edge_t x; unsigned y; } v; v.y = m; return v.x; } -/* -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 = ABC_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 = ABC_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 = ABC_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 = ABC_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 ) -{ - ABC_FREE( pGraph->pNodes ); - ABC_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 = ABC_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; -} - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/opt/dec/decAbc.c b/src/opt/dec/decAbc.c deleted file mode 100644 index 24bfc9a8..00000000 --- a/src/opt/dec/decAbc.c +++ /dev/null @@ -1,358 +0,0 @@ -/**CFile**************************************************************** - - FileName [decAbc.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Interface between the decomposition package and ABC network.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: decAbc.c,v 1.1 2003/05/22 19:20:05 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "dec.h" -#include "ivy.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Transforms the decomposition graph into the AIG.] - - Description [AIG nodes for the fanins should be assigned to pNode->pFunc - of the leaves of the graph before calling this procedure.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Dec_GraphToNetwork( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph ) -{ - Abc_Obj_t * pAnd0, * pAnd1; - Dec_Node_t * pNode = NULL; // Suppress "might be used uninitialized" - 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( (Abc_Obj_t *)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( (Abc_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); - pAnd1 = Abc_ObjNotCond( (Abc_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); - pNode->pFunc = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, pAnd0, pAnd1 ); - } - // complement the result if necessary - return Abc_ObjNotCond( (Abc_Obj_t *)pNode->pFunc, Dec_GraphIsComplement(pGraph) ); -} - -/**Function************************************************************* - - Synopsis [Transforms the decomposition graph into the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Dec_SopToAig( Abc_Ntk_t * pNtk, char * pSop, Vec_Ptr_t * vFaninAigs ) -{ - Abc_Obj_t * pFunc; - Dec_Graph_t * pFForm; - Dec_Node_t * pNode; - int i; - pFForm = Dec_Factor( pSop ); - Dec_GraphForEachLeaf( pFForm, pNode, i ) - pNode->pFunc = Vec_PtrEntry( vFaninAigs, i ); - pFunc = Dec_GraphToNetwork( pNtk, pFForm ); - Dec_GraphFree( pFForm ); - return pFunc; -} - -/**Function************************************************************* - - Synopsis [Transforms the decomposition graph into the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Dec_GraphToAig( Abc_Ntk_t * pNtk, Dec_Graph_t * pFForm, Vec_Ptr_t * vFaninAigs ) -{ - Abc_Obj_t * pFunc; - Dec_Node_t * pNode; - int i; - Dec_GraphForEachLeaf( pFForm, pNode, i ) - pNode->pFunc = Vec_PtrEntry( vFaninAigs, i ); - pFunc = Dec_GraphToNetwork( pNtk, pFForm ); - return pFunc; -} - -/**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 = NULL; // Suppress "might be used uninitialized" - 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( (Abc_Obj_t *)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( (Abc_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); - pAnd1 = Abc_ObjNotCond( (Abc_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); -// pNode->pFunc = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, pAnd0, pAnd1 ); - pAnd = Abc_NtkCreateNode( pNtk ); - Abc_ObjAddFanin( pAnd, pAnd0 ); - Abc_ObjAddFanin( pAnd, pAnd1 ); - pNode->pFunc = pAnd; - } - // complement the result if necessary - return Abc_ObjNotCond( (Abc_Obj_t *)pNode->pFunc, Dec_GraphIsComplement(pGraph) ); -} - -/**Function************************************************************* - - Synopsis [Counts the number of new nodes added when using this graph.] - - Description [AIG nodes for the fanins should be assigned to pNode->pFunc - of the leaves of the graph before calling this procedure. - Returns -1 if the number of nodes and levels exceeded the given limit or - the number of levels exceeded the maximum allowed level.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dec_GraphToNetworkCount( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax ) -{ - Abc_Aig_t * pMan = (Abc_Aig_t *)pRoot->pNtk->pManFunc; - Dec_Node_t * pNode, * pNode0, * pNode1; - Abc_Obj_t * pAnd, * pAnd0, * pAnd1; - int i, Counter, LevelNew, LevelOld; - // check for constant function or a literal - if ( Dec_GraphIsConst(pGraph) || Dec_GraphIsVar(pGraph) ) - return 0; - // set the levels of the leaves - Dec_GraphForEachLeaf( pGraph, pNode, i ) - pNode->Level = Abc_ObjRegular((Abc_Obj_t *)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 = (Abc_Obj_t *)pNode0->pFunc; - pAnd1 = (Abc_Obj_t *)pNode1->pFunc; - if ( pAnd0 && pAnd1 ) - { - // if they are both present, find the resulting node - pAnd0 = Abc_ObjNotCond( pAnd0, pNode->eEdge0.fCompl ); - pAnd1 = Abc_ObjNotCond( pAnd1, pNode->eEdge1.fCompl ); - pAnd = Abc_AigAndLookup( pMan, pAnd0, pAnd1 ); - // return -1 if the node is the same as the original root - if ( Abc_ObjRegular(pAnd) == pRoot ) - return -1; - } - else - pAnd = NULL; - // count the number of added nodes - if ( pAnd == NULL || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pAnd)) ) - { - if ( ++Counter > NodeMax ) - return -1; - } - // count the number of new levels - LevelNew = 1 + ABC_MAX( pNode0->Level, pNode1->Level ); - if ( pAnd ) - { - if ( Abc_ObjRegular(pAnd) == Abc_AigConst1(pRoot->pNtk) ) - LevelNew = 0; - else if ( Abc_ObjRegular(pAnd) == Abc_ObjRegular(pAnd0) ) - LevelNew = (int)Abc_ObjRegular(pAnd0)->Level; - else if ( Abc_ObjRegular(pAnd) == Abc_ObjRegular(pAnd1) ) - LevelNew = (int)Abc_ObjRegular(pAnd1)->Level; - LevelOld = (int)Abc_ObjRegular(pAnd)->Level; -// assert( LevelNew == LevelOld ); - } - if ( LevelNew > LevelMax ) - return -1; - pNode->pFunc = pAnd; - pNode->Level = LevelNew; - } - return Counter; -} - - -/**Function************************************************************* - - Synopsis [Replaces MFFC of the node by the new factored form.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, 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 ); - // remove the old nodes - Abc_AigReplace( (Abc_Aig_t *)pNtk->pManFunc, pRoot, pRootNew, fUpdateLevel ); - // compare the gains - nNodesNew = Abc_NtkNodeNum(pNtk); - assert( nGain <= nNodesOld - nNodesNew ); -} - - -/**Function************************************************************* - - Synopsis [Transforms the decomposition graph into the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Dec_GraphToNetworkAig( Hop_Man_t * pMan, Dec_Graph_t * pGraph ) -{ - Dec_Node_t * pNode = NULL; // Suppress "might be used uninitialized" - 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( (Hop_Obj_t *)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( (Hop_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); - pAnd1 = Hop_NotCond( (Hop_Obj_t *)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( (Hop_Obj_t *)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 = NULL; // Suppress "might be used uninitialized" - 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( (Ivy_Obj_t *)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( (Ivy_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); - pAnd1 = Ivy_NotCond( (Ivy_Obj_t *)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( (Ivy_Obj_t *)pNode->pFunc, Dec_GraphIsComplement(pGraph) ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/opt/dec/decFactor.c b/src/opt/dec/decFactor.c deleted file mode 100644 index 8c414915..00000000 --- a/src/opt/dec/decFactor.c +++ /dev/null @@ -1,398 +0,0 @@ -/**CFile**************************************************************** - - FileName [ftFactor.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Procedures for algebraic factoring.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: ftFactor.c,v 1.3 2003/09/01 04:56:43 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "main.h" -#include "mvc.h" -#include "dec.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Dec_Edge_t Dec_Factor_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover ); -static Dec_Edge_t Dec_FactorLF_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cover_t * pSimple ); -static Dec_Edge_t Dec_FactorTrivial( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover ); -static Dec_Edge_t Dec_FactorTrivialCube( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cube_t * pCube, Vec_Int_t * vEdgeLits ); -static Dec_Edge_t Dec_FactorTrivialTree_rec( Dec_Graph_t * pFForm, Dec_Edge_t * peNodes, int nNodes, int fNodeOr ); -static int Dec_FactorVerify( char * pSop, Dec_Graph_t * pFForm ); -static Mvc_Cover_t * Dec_ConvertSopToMvc( char * pSop ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Factors the cover.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Dec_Factor( char * pSop ) -{ - Mvc_Cover_t * pCover; - Dec_Graph_t * pFForm; - Dec_Edge_t eRoot; - - // derive the cover from the SOP representation - pCover = Dec_ConvertSopToMvc( pSop ); - - // make sure the cover is CCS free (should be done before CST) - Mvc_CoverContain( pCover ); - // check for trivial functions - if ( Mvc_CoverIsEmpty(pCover) ) - { - Mvc_CoverFree( pCover ); - return Dec_GraphCreateConst0(); - } - if ( Mvc_CoverIsTautology(pCover) ) - { - Mvc_CoverFree( pCover ); - return Dec_GraphCreateConst1(); - } - - // perform CST - Mvc_CoverInverse( pCover ); // CST - // start the factored form - pFForm = Dec_GraphCreate( Abc_SopGetVarNum(pSop) ); - // factor the cover - eRoot = Dec_Factor_rec( pFForm, pCover ); - // finalize the factored form - Dec_GraphSetRoot( pFForm, eRoot ); - // complement the factored form if SOP is complemented - if ( Abc_SopIsComplement(pSop) ) - Dec_GraphComplement( pFForm ); - // verify the factored form -// if ( !Dec_FactorVerify( pSop, pFForm ) ) -// printf( "Verification has failed.\n" ); -// Mvc_CoverInverse( pCover ); // undo CST - Mvc_CoverFree( pCover ); - return pFForm; -} - -/**Function************************************************************* - - Synopsis [Internal recursive factoring procedure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Edge_t Dec_Factor_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover ) -{ - Mvc_Cover_t * pDiv, * pQuo, * pRem, * pCom; - Dec_Edge_t eNodeDiv, eNodeQuo, eNodeRem; - Dec_Edge_t eNodeAnd, eNode; - - // make sure the cover contains some cubes - assert( Mvc_CoverReadCubeNum(pCover) ); - - // get the divisor - pDiv = Mvc_CoverDivisor( pCover ); - if ( pDiv == NULL ) - return Dec_FactorTrivial( pFForm, pCover ); - - // divide the cover by the divisor - Mvc_CoverDivideInternal( pCover, pDiv, &pQuo, &pRem ); - assert( Mvc_CoverReadCubeNum(pQuo) ); - - Mvc_CoverFree( pDiv ); - Mvc_CoverFree( pRem ); - - // check the trivial case - if ( Mvc_CoverReadCubeNum(pQuo) == 1 ) - { - eNode = Dec_FactorLF_rec( pFForm, pCover, pQuo ); - Mvc_CoverFree( pQuo ); - return eNode; - } - - // make the quotient cube ABC_FREE - Mvc_CoverMakeCubeFree( pQuo ); - - // divide the cover by the quotient - Mvc_CoverDivideInternal( pCover, pQuo, &pDiv, &pRem ); - - // check the trivial case - if ( Mvc_CoverIsCubeFree( pDiv ) ) - { - eNodeDiv = Dec_Factor_rec( pFForm, pDiv ); - eNodeQuo = Dec_Factor_rec( pFForm, pQuo ); - Mvc_CoverFree( pDiv ); - Mvc_CoverFree( pQuo ); - eNodeAnd = Dec_GraphAddNodeAnd( pFForm, eNodeDiv, eNodeQuo ); - if ( Mvc_CoverReadCubeNum(pRem) == 0 ) - { - Mvc_CoverFree( pRem ); - return eNodeAnd; - } - else - { - eNodeRem = Dec_Factor_rec( pFForm, pRem ); - Mvc_CoverFree( pRem ); - return Dec_GraphAddNodeOr( pFForm, eNodeAnd, eNodeRem ); - } - } - - // get the common cube - pCom = Mvc_CoverCommonCubeCover( pDiv ); - Mvc_CoverFree( pDiv ); - Mvc_CoverFree( pQuo ); - Mvc_CoverFree( pRem ); - - // solve the simple problem - eNode = Dec_FactorLF_rec( pFForm, pCover, pCom ); - Mvc_CoverFree( pCom ); - return eNode; -} - - -/**Function************************************************************* - - Synopsis [Internal recursive factoring procedure for the leaf case.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Edge_t Dec_FactorLF_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cover_t * pSimple ) -{ - Dec_Man_t * pManDec = (Dec_Man_t *)Abc_FrameReadManDec(); - Vec_Int_t * vEdgeLits = pManDec->vLits; - Mvc_Cover_t * pDiv, * pQuo, * pRem; - Dec_Edge_t eNodeDiv, eNodeQuo, eNodeRem; - Dec_Edge_t eNodeAnd; - - // get the most often occurring literal - pDiv = Mvc_CoverBestLiteralCover( pCover, pSimple ); - // divide the cover by the literal - Mvc_CoverDivideByLiteral( pCover, pDiv, &pQuo, &pRem ); - // get the node pointer for the literal - eNodeDiv = Dec_FactorTrivialCube( pFForm, pDiv, Mvc_CoverReadCubeHead(pDiv), vEdgeLits ); - Mvc_CoverFree( pDiv ); - // factor the quotient and remainder - eNodeQuo = Dec_Factor_rec( pFForm, pQuo ); - Mvc_CoverFree( pQuo ); - eNodeAnd = Dec_GraphAddNodeAnd( pFForm, eNodeDiv, eNodeQuo ); - if ( Mvc_CoverReadCubeNum(pRem) == 0 ) - { - Mvc_CoverFree( pRem ); - return eNodeAnd; - } - else - { - eNodeRem = Dec_Factor_rec( pFForm, pRem ); - Mvc_CoverFree( pRem ); - return Dec_GraphAddNodeOr( pFForm, eNodeAnd, eNodeRem ); - } -} - - - -/**Function************************************************************* - - Synopsis [Factoring the cover, which has no algebraic divisors.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Edge_t Dec_FactorTrivial( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover ) -{ - Dec_Man_t * pManDec = (Dec_Man_t *)Abc_FrameReadManDec(); - Vec_Int_t * vEdgeCubes = pManDec->vCubes; - Vec_Int_t * vEdgeLits = pManDec->vLits; - Dec_Edge_t eNode; - Mvc_Cube_t * pCube; - // create the factored form for each cube - Vec_IntClear( vEdgeCubes ); - Mvc_CoverForEachCube( pCover, pCube ) - { - eNode = Dec_FactorTrivialCube( pFForm, pCover, pCube, vEdgeLits ); - Vec_IntPush( vEdgeCubes, Dec_EdgeToInt_(eNode) ); - } - // balance the factored forms - return Dec_FactorTrivialTree_rec( pFForm, (Dec_Edge_t *)vEdgeCubes->pArray, vEdgeCubes->nSize, 1 ); -} - -/**Function************************************************************* - - Synopsis [Factoring the cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Edge_t Dec_FactorTrivialCube( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cube_t * pCube, Vec_Int_t * vEdgeLits ) -{ - Dec_Edge_t eNode; - int iBit, Value; - // create the factored form for each literal - Vec_IntClear( vEdgeLits ); - Mvc_CubeForEachBit( pCover, pCube, iBit, Value ) - if ( Value ) - { - eNode = Dec_EdgeCreate( iBit/2, iBit%2 ); // CST - Vec_IntPush( vEdgeLits, Dec_EdgeToInt_(eNode) ); - } - // balance the factored forms - return Dec_FactorTrivialTree_rec( pFForm, (Dec_Edge_t *)vEdgeLits->pArray, vEdgeLits->nSize, 0 ); -} - -/**Function************************************************************* - - Synopsis [Create the well-balanced tree of nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Edge_t Dec_FactorTrivialTree_rec( Dec_Graph_t * pFForm, Dec_Edge_t * peNodes, int nNodes, int fNodeOr ) -{ - Dec_Edge_t eNode1, eNode2; - int nNodes1, nNodes2; - - if ( nNodes == 1 ) - return peNodes[0]; - - // split the nodes into two parts - nNodes1 = nNodes/2; - nNodes2 = nNodes - nNodes1; -// nNodes2 = nNodes/2; -// nNodes1 = nNodes - nNodes2; - - // recursively construct the tree for the parts - eNode1 = Dec_FactorTrivialTree_rec( pFForm, peNodes, nNodes1, fNodeOr ); - eNode2 = Dec_FactorTrivialTree_rec( pFForm, peNodes + nNodes1, nNodes2, fNodeOr ); - - if ( fNodeOr ) - return Dec_GraphAddNodeOr( pFForm, eNode1, eNode2 ); - else - return Dec_GraphAddNodeAnd( pFForm, eNode1, eNode2 ); -} - - - -/**Function************************************************************* - - Synopsis [Converts SOP into MVC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mvc_Cover_t * Dec_ConvertSopToMvc( char * pSop ) -{ - Dec_Man_t * pManDec = (Dec_Man_t *)Abc_FrameReadManDec(); - Mvc_Manager_t * pMem = (Mvc_Manager_t *)pManDec->pMvcMem; - Mvc_Cover_t * pMvc; - Mvc_Cube_t * pMvcCube; - char * pCube; - int nVars, Value, v; - - // start the cover - nVars = Abc_SopGetVarNum(pSop); - pMvc = Mvc_CoverAlloc( pMem, nVars * 2 ); - // check the logic function of the node - Abc_SopForEachCube( pSop, nVars, pCube ) - { - // create and add the cube - pMvcCube = Mvc_CubeAlloc( pMvc ); - Mvc_CoverAddCubeTail( pMvc, pMvcCube ); - // fill in the literals - Mvc_CubeBitFill( pMvcCube ); - Abc_CubeForEachVar( pCube, Value, v ) - { - if ( Value == '0' ) - Mvc_CubeBitRemove( pMvcCube, v * 2 + 1 ); - else if ( Value == '1' ) - Mvc_CubeBitRemove( pMvcCube, v * 2 ); - } - } - return pMvc; -} - -/**Function************************************************************* - - Synopsis [Verifies that the factoring is correct.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dec_FactorVerify( char * pSop, Dec_Graph_t * pFForm ) -{ - extern DdNode * Abc_ConvertSopToBdd( DdManager * dd, char * pSop, DdNode ** pbVars ); - extern DdNode * Dec_GraphDeriveBdd( DdManager * dd, Dec_Graph_t * pGraph ); - DdManager * dd = (DdManager *)Abc_FrameReadManDd(); - DdNode * bFunc1, * bFunc2; - int RetValue; - bFunc1 = Abc_ConvertSopToBdd( dd, pSop, NULL ); Cudd_Ref( bFunc1 ); - bFunc2 = Dec_GraphDeriveBdd( dd, pFForm ); Cudd_Ref( bFunc2 ); -//Extra_bddPrint( dd, bFunc1 ); printf("\n"); -//Extra_bddPrint( dd, bFunc2 ); printf("\n"); - RetValue = (bFunc1 == bFunc2); - if ( bFunc1 != bFunc2 ) - { - int s; - Extra_bddPrint( dd, bFunc1 ); printf("\n"); - Extra_bddPrint( dd, bFunc2 ); printf("\n"); - s = 0; - } - Cudd_RecursiveDeref( dd, bFunc1 ); - Cudd_RecursiveDeref( dd, bFunc2 ); - return RetValue; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/opt/dec/decMan.c b/src/opt/dec/decMan.c deleted file mode 100644 index 8b6fae65..00000000 --- a/src/opt/dec/decMan.c +++ /dev/null @@ -1,88 +0,0 @@ -/**CFile**************************************************************** - - FileName [decMan.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Decomposition manager.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: decMan.c,v 1.1 2003/05/22 19:20:05 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "mvc.h" -#include "dec.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Start the MVC manager used in the factoring package.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Man_t * Dec_ManStart() -{ - Dec_Man_t * p; -// int clk = clock(); - p = ABC_ALLOC( Dec_Man_t, 1 ); - p->pMvcMem = Mvc_ManagerStart(); - p->vCubes = Vec_IntAlloc( 8 ); - p->vLits = Vec_IntAlloc( 8 ); - // canonical forms, phases, perms - Extra_Truth4VarNPN( &p->puCanons, &p->pPhases, &p->pPerms, &p->pMap ); -//ABC_PRT( "NPN classes precomputation time", clock() - clk ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the MVC maanager used in the factoring package.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dec_ManStop( Dec_Man_t * p ) -{ - Mvc_ManagerFree( (Mvc_Manager_t *)p->pMvcMem ); - Vec_IntFree( p->vCubes ); - Vec_IntFree( p->vLits ); - ABC_FREE( p->puCanons ); - ABC_FREE( p->pPhases ); - ABC_FREE( p->pPerms ); - ABC_FREE( p->pMap ); - ABC_FREE( p ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/opt/dec/decPrint.c b/src/opt/dec/decPrint.c deleted file mode 100644 index 3cc0f811..00000000 --- a/src/opt/dec/decPrint.c +++ /dev/null @@ -1,289 +0,0 @@ -/**CFile**************************************************************** - - FileName [decPrint.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Procedures to print the decomposition graphs (factored forms).] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: decPrint.c,v 1.1 2003/05/22 19:20:05 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "dec.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Dec_GraphPrint_rec( FILE * pFile, Dec_Graph_t * pGraph, Dec_Node_t * pNode, int fCompl, char * pNamesIn[], int * pPos, int LitSizeMax ); -static int Dec_GraphPrintGetLeafName( FILE * pFile, int iLeaf, int fCompl, char * pNamesIn[] ); -static void Dec_GraphPrintUpdatePos( FILE * pFile, int * pPos, int LitSizeMax ); -static int Dec_GraphPrintOutputName( FILE * pFile, char * pNameOut, int fCompl ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Prints the decomposition graph.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dec_GraphPrint( FILE * pFile, Dec_Graph_t * pGraph, char * pNamesIn[], char * pNameOut ) -{ - Vec_Ptr_t * vNamesIn = NULL; - int LitSizeMax, LitSizeCur, Pos, i; - - // create the names if not given by the user - if ( pNamesIn == NULL ) - { - vNamesIn = Abc_NodeGetFakeNames( Dec_GraphLeaveNum(pGraph) ); - pNamesIn = (char **)vNamesIn->pArray; - } - if ( pNameOut == NULL ) - pNameOut = "F"; - - // get the size of the longest literal - LitSizeMax = 0; - for ( i = 0; i < Dec_GraphLeaveNum(pGraph); i++ ) - { - LitSizeCur = strlen(pNamesIn[i]); - if ( LitSizeMax < LitSizeCur ) - LitSizeMax = LitSizeCur; - } - if ( LitSizeMax > 50 ) - LitSizeMax = 20; - - // write the decomposition graph (factored form) - if ( Dec_GraphIsConst(pGraph) ) // constant - { - Pos = Dec_GraphPrintOutputName( pFile, pNameOut, 0 ); - fprintf( pFile, "Constant %d", !Dec_GraphIsComplement(pGraph) ); - } - else if ( Dec_GraphIsVar(pGraph) ) // literal - { - Pos = Dec_GraphPrintOutputName( pFile, pNameOut, 0 ); - Dec_GraphPrintGetLeafName( pFile, Dec_GraphVarInt(pGraph), Dec_GraphIsComplement(pGraph), pNamesIn ); - } - else - { - Pos = Dec_GraphPrintOutputName( pFile, pNameOut, Dec_GraphIsComplement(pGraph) ); - Dec_GraphPrint_rec( pFile, pGraph, Dec_GraphNodeLast(pGraph), 0, pNamesIn, &Pos, LitSizeMax ); - } - fprintf( pFile, "\n" ); - - if ( vNamesIn ) - Abc_NodeFreeNames( vNamesIn ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dec_GraphPrint2_rec( FILE * pFile, Dec_Graph_t * pGraph, Dec_Node_t * pNode, int fCompl, char * pNamesIn[], int * pPos, int LitSizeMax ) -{ - Dec_Node_t * pNode0, * pNode1; - pNode0 = Dec_GraphNode(pGraph, pNode->eEdge0.Node); - pNode1 = Dec_GraphNode(pGraph, pNode->eEdge1.Node); - if ( Dec_GraphNodeIsVar(pGraph, pNode) ) // FT_NODE_LEAF ) - { - (*pPos) += Dec_GraphPrintGetLeafName( pFile, Dec_GraphNodeInt(pGraph,pNode), fCompl, pNamesIn ); - return; - } - if ( !pNode->fNodeOr ) // FT_NODE_AND ) - { - if ( !pNode0->fNodeOr ) // != FT_NODE_OR ) - Dec_GraphPrint_rec( pFile, pGraph, pNode0, pNode->fCompl0, pNamesIn, pPos, LitSizeMax ); - else - { - fprintf( pFile, "(" ); - (*pPos)++; - Dec_GraphPrint_rec( pFile, pGraph, pNode0, pNode->fCompl0, pNamesIn, pPos, LitSizeMax ); - fprintf( pFile, ")" ); - (*pPos)++; - } - fprintf( pFile, " " ); - (*pPos)++; - - Dec_GraphPrintUpdatePos( pFile, pPos, LitSizeMax ); - - if ( !pNode1->fNodeOr ) // != FT_NODE_OR ) - Dec_GraphPrint_rec( pFile, pGraph, pNode1, pNode->fCompl1, pNamesIn, pPos, LitSizeMax ); - else - { - fprintf( pFile, "(" ); - (*pPos)++; - Dec_GraphPrint_rec( pFile, pGraph, pNode1, pNode->fCompl1, pNamesIn, pPos, LitSizeMax ); - fprintf( pFile, ")" ); - (*pPos)++; - } - return; - } - if ( pNode->fNodeOr ) // FT_NODE_OR ) - { - Dec_GraphPrint_rec( pFile, pGraph, pNode0, pNode->fCompl0, pNamesIn, pPos, LitSizeMax ); - fprintf( pFile, " + " ); - (*pPos) += 3; - - Dec_GraphPrintUpdatePos( pFile, pPos, LitSizeMax ); - - Dec_GraphPrint_rec( pFile, pGraph, pNode1, pNode->fCompl1, pNamesIn, pPos, LitSizeMax ); - return; - } - assert( 0 ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dec_GraphPrint_rec( FILE * pFile, Dec_Graph_t * pGraph, Dec_Node_t * pNode, int fCompl, char * pNamesIn[], int * pPos, int LitSizeMax ) -{ - Dec_Node_t * pNode0, * pNode1; - Dec_Node_t * pNode00, * pNode01, * pNode10, * pNode11; - pNode0 = Dec_GraphNode(pGraph, pNode->eEdge0.Node); - pNode1 = Dec_GraphNode(pGraph, pNode->eEdge1.Node); - if ( Dec_GraphNodeIsVar(pGraph, pNode) ) // FT_NODE_LEAF ) - { - (*pPos) += Dec_GraphPrintGetLeafName( pFile, Dec_GraphNodeInt(pGraph,pNode), fCompl, pNamesIn ); - return; - } - if ( !Dec_GraphNodeIsVar(pGraph, pNode0) && !Dec_GraphNodeIsVar(pGraph, pNode1) ) - { - pNode00 = Dec_GraphNode(pGraph, pNode0->eEdge0.Node); - pNode01 = Dec_GraphNode(pGraph, pNode0->eEdge1.Node); - pNode10 = Dec_GraphNode(pGraph, pNode1->eEdge0.Node); - pNode11 = Dec_GraphNode(pGraph, pNode1->eEdge1.Node); - if ( (pNode00 == pNode10 || pNode00 == pNode11) && (pNode01 == pNode10 || pNode01 == pNode11) ) - { - fprintf( pFile, "(" ); - (*pPos)++; - Dec_GraphPrint_rec( pFile, pGraph, pNode00, pNode00->fCompl0, pNamesIn, pPos, LitSizeMax ); - fprintf( pFile, " # " ); - (*pPos) += 3; - Dec_GraphPrint_rec( pFile, pGraph, pNode01, pNode01->fCompl1, pNamesIn, pPos, LitSizeMax ); - fprintf( pFile, ")" ); - (*pPos)++; - return; - } - } - if ( fCompl ) - { - fprintf( pFile, "(" ); - (*pPos)++; - Dec_GraphPrint_rec( pFile, pGraph, pNode0, !pNode->fCompl0, pNamesIn, pPos, LitSizeMax ); - fprintf( pFile, " + " ); - (*pPos) += 3; - Dec_GraphPrint_rec( pFile, pGraph, pNode1, !pNode->fCompl1, pNamesIn, pPos, LitSizeMax ); - fprintf( pFile, ")" ); - (*pPos)++; - } - else - { - fprintf( pFile, "(" ); - (*pPos)++; - Dec_GraphPrint_rec( pFile, pGraph, pNode0, pNode->fCompl0, pNamesIn, pPos, LitSizeMax ); - Dec_GraphPrint_rec( pFile, pGraph, pNode1, pNode->fCompl1, pNamesIn, pPos, LitSizeMax ); - fprintf( pFile, ")" ); - (*pPos)++; - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dec_GraphPrintGetLeafName( FILE * pFile, int iLeaf, int fCompl, char * pNamesIn[] ) -{ - static char Buffer[100]; - sprintf( Buffer, "%s%s", pNamesIn[iLeaf], fCompl? "\'" : "" ); - fprintf( pFile, "%s", Buffer ); - return strlen( Buffer ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dec_GraphPrintUpdatePos( FILE * pFile, int * pPos, int LitSizeMax ) -{ - int i; - if ( *pPos + LitSizeMax < 77 ) - return; - fprintf( pFile, "\n" ); - for ( i = 0; i < 10; i++ ) - fprintf( pFile, " " ); - *pPos = 10; -} - -/**Function************************************************************* - - Synopsis [Starts the printout for a decomposition graph.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dec_GraphPrintOutputName( FILE * pFile, char * pNameOut, int fCompl ) -{ - if ( pNameOut == NULL ) - return 0; - fprintf( pFile, "%6s%s = ", pNameOut, fCompl? "\'" : " " ); - return 10; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/opt/dec/decUtil.c b/src/opt/dec/decUtil.c deleted file mode 100644 index d2b5631e..00000000 --- a/src/opt/dec/decUtil.c +++ /dev/null @@ -1,141 +0,0 @@ -/**CFile**************************************************************** - - FileName [decUtil.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Decomposition unitilies.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: decUtil.c,v 1.1 2003/05/22 19:20:05 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "extra.h" -#include "dec.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Converts graph to BDD.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Dec_GraphDeriveBdd( DdManager * dd, Dec_Graph_t * pGraph ) -{ - DdNode * bFunc, * bFunc0, * bFunc1; - Dec_Node_t * pNode = NULL; // Suppress "might be used uninitialized" - int i; - - // sanity checks - assert( Dec_GraphLeaveNum(pGraph) >= 0 ); - assert( Dec_GraphLeaveNum(pGraph) <= pGraph->nSize ); - - // check for constant function - if ( Dec_GraphIsConst(pGraph) ) - return Cudd_NotCond( b1, Dec_GraphIsComplement(pGraph) ); - // check for a literal - if ( Dec_GraphIsVar(pGraph) ) - return Cudd_NotCond( Cudd_bddIthVar(dd, Dec_GraphVarInt(pGraph)), Dec_GraphIsComplement(pGraph) ); - - // assign the elementary variables - Dec_GraphForEachLeaf( pGraph, pNode, i ) - pNode->pFunc = Cudd_bddIthVar( dd, i ); - - // compute the function for each internal node - Dec_GraphForEachNode( pGraph, pNode, i ) - { - bFunc0 = Cudd_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); - bFunc1 = Cudd_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); - pNode->pFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( (DdNode *)pNode->pFunc ); - } - - // deref the intermediate results - bFunc = (DdNode *)pNode->pFunc; Cudd_Ref( bFunc ); - Dec_GraphForEachNode( pGraph, pNode, i ) - Cudd_RecursiveDeref( dd, (DdNode *)pNode->pFunc ); - Cudd_Deref( bFunc ); - - // complement the result if necessary - return Cudd_NotCond( bFunc, Dec_GraphIsComplement(pGraph) ); -} - -/**Function************************************************************* - - Synopsis [Derives the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Dec_GraphDeriveTruth( Dec_Graph_t * pGraph ) -{ - unsigned uTruths[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; - unsigned uTruth = 0; // Suppress "might be used uninitialized" - unsigned uTruth0, uTruth1; - Dec_Node_t * pNode; - int i; - - // sanity checks - assert( Dec_GraphLeaveNum(pGraph) >= 0 ); - assert( Dec_GraphLeaveNum(pGraph) <= pGraph->nSize ); - assert( Dec_GraphLeaveNum(pGraph) <= 5 ); - - // check for constant function - if ( Dec_GraphIsConst(pGraph) ) - return Dec_GraphIsComplement(pGraph)? 0 : ~((unsigned)0); - // check for a literal - if ( Dec_GraphIsVar(pGraph) ) - return Dec_GraphIsComplement(pGraph)? ~uTruths[Dec_GraphVarInt(pGraph)] : uTruths[Dec_GraphVarInt(pGraph)]; - - // assign the elementary variables - Dec_GraphForEachLeaf( pGraph, pNode, i ) - pNode->pFunc = (void *)(ABC_PTRUINT_T)uTruths[i]; - - // compute the function for each internal node - Dec_GraphForEachNode( pGraph, pNode, i ) - { - uTruth0 = (unsigned)(ABC_PTRUINT_T)Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc; - uTruth1 = (unsigned)(ABC_PTRUINT_T)Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc; - uTruth0 = pNode->eEdge0.fCompl? ~uTruth0 : uTruth0; - uTruth1 = pNode->eEdge1.fCompl? ~uTruth1 : uTruth1; - uTruth = uTruth0 & uTruth1; - pNode->pFunc = (void *)(ABC_PTRUINT_T)uTruth; - } - - // complement the result if necessary - return Dec_GraphIsComplement(pGraph)? ~uTruth : uTruth; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/opt/dec/module.make b/src/opt/dec/module.make deleted file mode 100644 index 1e0722d5..00000000 --- a/src/opt/dec/module.make +++ /dev/null @@ -1,5 +0,0 @@ -SRC += src/opt/dec/decAbc.c \ - src/opt/dec/decFactor.c \ - src/opt/dec/decMan.c \ - src/opt/dec/decPrint.c \ - src/opt/dec/decUtil.c diff --git a/src/opt/fret/fretFlow.c b/src/opt/fret/fretFlow.c deleted file mode 100644 index 498cb962..00000000 --- a/src/opt/fret/fretFlow.c +++ /dev/null @@ -1,702 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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) { - Vec_PtrForEachEntry( Abc_Obj_t *, 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 - assert(pManMR->vSinkDistHist); - memset(Vec_IntArray(pManMR->vSinkDistHist), 0, sizeof(int)*Vec_IntSize(pManMR->vSinkDistHist)); - - // seed queue : latches, PIOs, and blocks - Vec_PtrForEachEntry( Abc_Obj_t *, 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) { - Vec_PtrForEachEntry( Abc_Obj_t *, pNtk, pObj, i ) { - vTimeIn = FDATA(pObj)->vNodes; - if (vTimeIn) { - Vec_PtrFree(vTimeIn); - FDATA(pObj)->vNodes = 0; - } - } - } -#endif - - Vec_PtrForEachEntry( Abc_Obj_t *, 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; -} -ABC_NAMESPACE_IMPL_END - diff --git a/src/opt/fret/fretInit.c b/src/opt/fret/fretInit.c deleted file mode 100644 index ce9adefa..00000000 --- a/src/opt/fret/fretInit.c +++ /dev/null @@ -1,1334 +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 "ioAbc.h" -#include "fretime.h" -#include "mio.h" -#include "hop.h" - -ABC_NAMESPACE_IMPL_START - - -#undef DEBUG_PRINT_INIT_NTK - - -//////////////////////////////////////////////////////////////////////// -/// 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 ); - -static void Abc_FlowRetime_SimulateNode( Abc_Obj_t * pObj ); -static void Abc_FlowRetime_SimulateSop( Abc_Obj_t * pObj, char *pSop ); - -static void Abc_FlowRetime_SetInitToOrig( Abc_Obj_t *pInit, Abc_Obj_t *pOrig ); -static void Abc_FlowRetime_GetInitToOrig( Abc_Obj_t *pInit, Abc_Obj_t **pOrig, int *lag ); -static void Abc_FlowRetime_ClearInitToOrig( Abc_Obj_t *pInit ); - -extern void * Abc_FrameReadLibGen(); - -extern void Abc_NtkMarkCone_rec( Abc_Obj_t * pObj, int fForward ); - -//////////////////////////////////////////////////////////////////////// -/// 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 [] - -***********************************************************************/ -inline int -Abc_FlowRetime_ObjFirstNonLatchBox( Abc_Obj_t * pOrigObj, Abc_Obj_t ** pResult ) { - int lag = 0; - Abc_Ntk_t *pNtk; - *pResult = pOrigObj; - pNtk = Abc_ObjNtk( pOrigObj ); - - Abc_NtkIncrementTravId( pNtk ); - - while( Abc_ObjIsBo(*pResult) || Abc_ObjIsLatch(*pResult) || Abc_ObjIsBi(*pResult) ) { - assert(Abc_ObjFaninNum(*pResult)); - *pResult = Abc_ObjFanin0(*pResult); - - if (Abc_NodeIsTravIdCurrent(*pResult)) - return -1; - Abc_NodeSetTravIdCurrent(*pResult); - - if (Abc_ObjIsLatch(*pResult)) ++lag; - } - - return lag; -} - - -/**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 [Recursively evaluates HOP netlist.] - - Description [Exponential. There aren't enough flags on a HOP node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Abc_FlowRetime_EvalHop_rec( Hop_Man_t *pHop, Hop_Obj_t *pObj, int *f, int *dc ) { - int f1, dc1, f2, dc2; - Hop_Obj_t *pReg = Hop_Regular(pObj); - - // const 0 - if (Hop_ObjIsConst1(pReg)) { - *f = 1; - *f ^= (pReg == pObj ? 1 : 0); - *dc = 0; - return; - } - - // PI - if (Hop_ObjIsPi(pReg)) { - *f = pReg->fMarkA; - *f ^= (pReg == pObj ? 1 : 0); - *dc = pReg->fMarkB; - return; - } - - // PO - if (Hop_ObjIsPo(pReg)) { - assert( pReg == pObj ); - Abc_FlowRetime_EvalHop_rec(pHop, Hop_ObjChild0(pReg), f, dc); - return; - } - - // AND - if (Hop_ObjIsAnd(pReg)) { - Abc_FlowRetime_EvalHop_rec(pHop, Hop_ObjChild0(pReg), &f1, &dc1); - Abc_FlowRetime_EvalHop_rec(pHop, Hop_ObjChild1(pReg), &f2, &dc2); - - *dc = (dc1 & f2) | (dc2 & f1) | (dc1 & dc2); - *f = f1 & f2; - *f ^= (pReg == pObj ? 1 : 0); - return; - } - - assert(0); -} - - -/**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; - Hop_Man_t *pHop = pNtk->pManFunc; - - assert(!Abc_ObjIsLatch(pObj)); - assert(Abc_ObjRegular(pObj)); - - // (i) constant nodes - if (Abc_NtkIsStrash(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 logic network - else if ( Abc_NtkHasAig( pNtk ) && !Abc_NtkIsStrash( pNtk )) { - - assert(Abc_ObjIsNode(pObj)); - assert(pObj->pData); - assert(Abc_ObjFaninNum(pObj) <= Hop_ManPiNum(pHop) ); - - // set vals at inputs - Abc_ObjForEachFanin(pObj, pFanin, i) { - Hop_ManPi(pHop, i)->fMarkA = FTEST(pFanin, INIT_1)?1:0; - Hop_ManPi(pHop, i)->fMarkB = FTEST(pFanin, INIT_CARE)?1:0; - } - - Abc_FlowRetime_EvalHop_rec( pHop, pObj->pData, &rVar, &dcVar ); - - Abc_FlowRetime_SetInitValue(pObj, rVar, dcVar); - - // clear flags - Abc_ObjForEachFanin(pObj, pFanin, i) { - Hop_ManPi(pHop, i)->fMarkA = 0; - Hop_ManPi(pHop, i)->fMarkB = 0; - } - - return; - } - - // ------ strashed network - else if ( Abc_NtkIsStrash( pNtk )) { - - assert(Abc_ObjType(pObj) == ABC_OBJ_NODE); - 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_NtkIsStrash(pNtk)) { - pManMR->pInitNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); - } else 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 ); - - // DEBUG - // printf("setup : mapping latch %d to PI %d\n", pLatch->Id, pPi->Id); - - // has initial state requirement? - if (Abc_LatchIsInit0(pLatch)) { - 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 - - // 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 [Sets object copies in init ntk.] - - SeeAlso [] - -***********************************************************************/ -int Abc_FlowRetime_SolveBackwardInit( Abc_Ntk_t * pNtk ) { - int i; - Abc_Obj_t *pObj, *pInitObj; - Vec_Ptr_t *vDelete = Vec_PtrAlloc(0); - Abc_Ntk_t *pSatNtk; - int result; - - assert(pManMR->pInitNtk); - - // is the solution entirely DC's? - if (pManMR->fSolutionIsDc) { - 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 - Abc_NtkForEachObj( pManMR->pInitNtk, pObj, i ) { - assert(!Abc_ObjIsLatch(pObj)); - assert(!Abc_ObjIsBo(pObj)); - assert(!Abc_ObjIsBi(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); - -#if defined(DEBUG_PRINT_INIT_NTK) - Abc_NtkLevelReverse( pManMR->pInitNtk ); - Abc_NtkForEachObj( pManMR->pInitNtk, pObj, i ) - if (Abc_ObjLevel( pObj ) < 2) - Abc_ObjPrint(stdout, pObj); -#endif - - 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 ); - // convert AIGs to BDD - if (Abc_NtkHasAig(pManMR->pInitNtk)) - Abc_NtkAigToBdd( pManMR->pInitNtk ); - - pSatNtk = pManMR->pInitNtk; - - // solve - result = Abc_NtkMiterSat( pSatNtk, (sint64)500000, (sint64)50000000, 0, NULL, NULL ); - - if (!result) { - vprintf("SUCCESS\n"); - } else { - vprintf("FAILURE\n"); - 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 ); - - // DEBUG - // printf("solve : getting latch %d from PI %d\n", pObj->Id, pInitObj->Id); - } - - // 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 - - 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 *vPi = Vec_PtrAlloc(100); - Abc_Ntk_t *pInitNtk = pManMR-> pInitNtk; - Abc_Obj_t *pBuf; - 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)); - - // DEBUG - // printf("update : freeing PI %d\n", pInitObj->Id); - - // create a buffer instead - pBuf = Abc_NtkCreateNodeBuf( pInitNtk, NULL ); - Abc_FlowRetime_ClearInitToOrig( pBuf ); - - Abc_ObjBetterTransferFanout( pInitObj, pBuf, 0 ); - FDATA(pOrigObj)->pInitObj = pBuf; - pOrigObj->fMarkA = 1; - - Vec_PtrPush(vBo, pOrigObj); - Vec_PtrPush(vPi, pInitObj); - } - - // check that PIs are all free - Abc_NtkForEachPi( pInitNtk, pInitObj, i) { - assert( Abc_ObjFanoutNum( pInitObj ) == 0); - } - - // add PIs to to latches - Abc_NtkForEachLatch( pNtk, pOrigObj, i ) { - assert(Vec_PtrSize(vPi) > 0); - pInitObj = Vec_PtrPop(vPi); - - // DEBUG - // printf("update : mapping latch %d to PI %d\n", pOrigObj->Id, pInitObj->Id); - - pOrigObj->fMarkA = pOrigObj->fMarkB = 1; - FDATA(pOrigObj)->pInitObj = pInitObj; - Abc_ObjSetData(pOrigObj, pInitObj); - } - - // recursively build init network - Vec_PtrForEachEntry( Abc_Obj_t *, vBo, pOrigObj, i ) - Abc_FlowRetime_UpdateBackwardInit_rec( pOrigObj ); - - // clear flags - Abc_NtkForEachObj( pNtk, pOrigObj, i ) - pOrigObj->fMarkA = pOrigObj->fMarkB = 0; - - // deallocate - Vec_PtrFree( vBo ); - Vec_PtrFree( vPi ); -} - - -/**Function************************************************************* - - Synopsis [Creates a corresponding node in the init state network] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t *Abc_FlowRetime_CopyNodeToInitNtk( Abc_Obj_t *pOrigObj ) { - Abc_Ntk_t *pNtk = pManMR->pNtk; - Abc_Ntk_t *pInitNtk = pManMR->pInitNtk; - Abc_Obj_t *pInitObj; - void *pData; - int fCompl[2]; - - assert(pOrigObj); - - // what we do depends on the ntk types of original / init networks... - - // (0) convert BI/BO nodes to buffers - if (Abc_ObjIsBi( pOrigObj ) || Abc_ObjIsBo( pOrigObj ) ) { - pInitObj = Abc_NtkCreateNodeBuf( pInitNtk, NULL ); - Abc_FlowRetime_ClearInitToOrig( pInitObj ); - return pInitObj; - } - - // (i) strash node -> SOP node - if (Abc_NtkIsStrash( pNtk )) { - - if (Abc_AigNodeIsConst( pOrigObj )) { - return Abc_NtkCreateNodeConst1( pInitNtk ); - } - if (!Abc_ObjIsNode( pOrigObj )) { - assert(Abc_ObjFaninNum(pOrigObj) == 1); - pInitObj = Abc_NtkCreateNodeBuf( pInitNtk, NULL ); - Abc_FlowRetime_ClearInitToOrig( pInitObj ); - return pInitObj; - } - - assert( Abc_ObjIsNode(pOrigObj) ); - pInitObj = Abc_NtkCreateObj( pInitNtk, ABC_OBJ_NODE ); - - fCompl[0] = pOrigObj->fCompl0 ? 1 : 0; - fCompl[1] = pOrigObj->fCompl1 ? 1 : 0; - - pData = Abc_SopCreateAnd( (Extra_MmFlex_t *)pInitNtk->pManFunc, 2, fCompl ); - assert(pData); - pInitObj->pData = Abc_SopRegister( (Extra_MmFlex_t *)pInitNtk->pManFunc, pData ); - } - - // (ii) mapped node -> SOP node - else if (Abc_NtkHasMapping( pNtk )) { - if (!pOrigObj->pData) { - // assume terminal... - assert(Abc_ObjFaninNum(pOrigObj) == 1); - - pInitObj = Abc_NtkCreateNodeBuf( pInitNtk, NULL ); - Abc_FlowRetime_ClearInitToOrig( pInitObj ); - return pInitObj; - } - - pInitObj = Abc_NtkCreateObj( pInitNtk, Abc_ObjType(pOrigObj) ); - pData = Mio_GateReadSop(pOrigObj->pData); - assert( Abc_SopGetVarNum(pData) == Abc_ObjFaninNum(pOrigObj) ); - - pInitObj->pData = Abc_SopRegister( (Extra_MmFlex_t *)pInitNtk->pManFunc, pData ); - } - - // (iii) otherwise, duplicate obj - else { - pInitObj = Abc_NtkDupObj( pInitNtk, pOrigObj, 0 ); - - // copy phase - pInitObj->fPhase = pOrigObj->fPhase; - } - - assert(pInitObj); - return pInitObj; -} - -/**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 *pOrigFanin, *pInitFanin, *pInitObj; - int i; - - assert(pOrigObj); - - // should never reach primary IOs - assert(!Abc_ObjIsPi(pOrigObj)); - assert(!Abc_ObjIsPo(pOrigObj)); - - // skip bias nodes - if (FTEST(pOrigObj, BIAS_NODE)) - return NULL; - - // does an init node already exist? - if(!pOrigObj->fMarkA) { - - pInitObj = Abc_FlowRetime_CopyNodeToInitNtk( pOrigObj ); - - Abc_FlowRetime_SetInitToOrig( pInitObj, pOrigObj ); - FDATA(pOrigObj)->pInitObj = pInitObj; - - pOrigObj->fMarkA = 1; - } else { - pInitObj = FDATA(pOrigObj)->pInitObj; - } - assert(pInitObj); - - // have we already connected this object? - if (!pOrigObj->fMarkB) { - - // create and/or connect fanins - Abc_ObjForEachFanin( pOrigObj, pOrigFanin, i ) { - // should not reach BOs (i.e. the start of the next frame) - // the new latch bounday should lie before it - assert(!Abc_ObjIsBo( pOrigFanin )); - pInitFanin = Abc_FlowRetime_UpdateBackwardInit_rec( pOrigFanin ); - 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 [] - -***********************************************************************/ -int Abc_FlowRetime_PartialSat(Vec_Ptr_t *vNodes, int cut) { - Abc_Ntk_t *pPartNtk, *pInitNtk = pManMR->pInitNtk; - Abc_Obj_t *pObj, *pNext, *pPartObj, *pPartNext, *pPo; - int i, j, result; - - assert( Abc_NtkPoNum( pInitNtk ) == 1 ); - - pPartNtk = Abc_NtkAlloc( pInitNtk->ntkType, pInitNtk->ntkFunc, 0 ); - - // copy network - Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { - pObj->Level = i; - assert(!Abc_ObjIsPo( pObj )); - - if (i < cut && !pObj->fMarkA) { - pPartObj = Abc_NtkCreatePi( pPartNtk ); - Abc_ObjSetCopy( pObj, pPartObj ); - } else { - // copy node - pPartObj = Abc_NtkDupObj( pPartNtk, pObj, 0 ); - // copy complementation - pPartObj->fPhase = pObj->fPhase; - - // connect fanins - Abc_ObjForEachFanin( pObj, pNext, j ) { - pPartNext = Abc_ObjCopy( pNext ); - assert(pPartNext); - Abc_ObjAddFanin( pPartObj, pPartNext ); - } - } - - assert(pObj->pCopy == pPartObj); - } - - // create PO - pPo = Abc_NtkCreatePo( pPartNtk ); - pNext = Abc_ObjFanin0( Abc_NtkPo( pInitNtk, 0 ) ); - pPartNext = Abc_ObjCopy( pNext ); - assert( pPartNext ); - Abc_ObjAddFanin( pPo, pPartNext ); - - // check network -#if defined(DEBUG_CHECK) - Abc_NtkAddDummyPoNames(pPartNtk); - Abc_NtkAddDummyPiNames(pPartNtk); - Abc_NtkCheck( pPartNtk ); -#endif - - result = Abc_NtkMiterSat( pPartNtk, (sint64)500000, (sint64)50000000, 0, NULL, NULL ); - - Abc_NtkDelete( pPartNtk ); - - return !result; -} - - -/**Function************************************************************* - - Synopsis [Constrains backward retiming for initializability.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FlowRetime_ConstrainInit( ) { - Vec_Ptr_t *vNodes; - int low, high, mid; - int i, n, lag; - Abc_Obj_t *pObj = NULL, *pOrigObj; - InitConstraint_t *pConstraint = ALLOC( InitConstraint_t, 1 ); - - memset( pConstraint, 0, sizeof(InitConstraint_t) ); - - assert(pManMR->pInitNtk); - - vprintf("\tsearch for initial state conflict...\n"); - - vNodes = Abc_NtkDfs(pManMR->pInitNtk, 0); - n = Vec_PtrSize(vNodes); - // also add PIs to vNodes - Abc_NtkForEachPi(pManMR->pInitNtk, pObj, i) - Vec_PtrPush(vNodes, pObj); - Vec_PtrReorder(vNodes, n); - -#if defined(DEBUG_CHECK) - assert(!Abc_FlowRetime_PartialSat( vNodes, 0 )); -#endif - - // grow initialization constraint - do { - vprintf("\t\t"); - - // find element to add to set... - low = 0, high = Vec_PtrSize(vNodes); - while (low != high-1) { - mid = (low + high) >> 1; - - if (!Abc_FlowRetime_PartialSat( vNodes, mid )) { - low = mid; - vprintf("-"); - } else { - high = mid; - vprintf("*"); - } - fflush(stdout); - } - -#if defined(DEBUG_CHECK) - assert(Abc_FlowRetime_PartialSat( vNodes, high )); - assert(!Abc_FlowRetime_PartialSat( vNodes, low )); -#endif - - // mark its TFO - pObj = Vec_PtrEntry( vNodes, low ); - Abc_NtkMarkCone_rec( pObj, 1 ); - vprintf(" conflict term = %d ", low); - -#if 0 - printf("init ------\n"); - Abc_ObjPrint(stdout, pObj); - printf("\n"); - Abc_ObjPrintNeighborhood( pObj, 1 ); - printf("------\n"); -#endif - - // add node to constraint - Abc_FlowRetime_GetInitToOrig( pObj, &pOrigObj, &lag ); - assert(pOrigObj); - vprintf(" <=> %d/%d\n", Abc_ObjId(pOrigObj), lag); - -#if 0 - printf("orig ------\n"); - Abc_ObjPrint(stdout, pOrigObj); - printf("\n"); - Abc_ObjPrintNeighborhood( pOrigObj, 1 ); - printf("------\n"); -#endif - Vec_IntPush( &pConstraint->vNodes, Abc_ObjId(pOrigObj) ); - Vec_IntPush( &pConstraint->vLags, lag ); - - } while (Abc_FlowRetime_PartialSat( vNodes, Vec_PtrSize(vNodes) )); - - pConstraint->pBiasNode = NULL; - - // add constraint - Vec_PtrPush( pManMR->vInitConstraints, pConstraint ); - - // clear marks - Abc_NtkForEachObj( pManMR->pInitNtk, pObj, i) - pObj->fMarkA = 0; - - // free - Vec_PtrFree( vNodes ); -} - - -/**Function************************************************************* - - Synopsis [Removes nodes to bias against uninitializable cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FlowRetime_RemoveInitBias( ) { - // Abc_Ntk_t *pNtk = pManMR->pNtk; - Abc_Obj_t *pBiasNode; - InitConstraint_t *pConstraint; - int i; - - Vec_PtrForEachEntry( Abc_Obj_t *, pManMR->vInitConstraints, pConstraint, i ) { - pBiasNode = pConstraint->pBiasNode; - pConstraint->pBiasNode = NULL; - - if (pBiasNode) - Abc_NtkDeleteObj(pBiasNode); - } -} - - -/**Function************************************************************* - - Synopsis [Connects the bias node to one of the constraint vertices.] - - Description [ACK! - Currently this is dumb dumb hack. - What should we do with biases that belong on BOs? These - move through the circuit. - Currently, the bias gets marked on the fan-in of BO - and the bias gets implemented on every BO fan-out of a - node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Abc_FlowRetime_ConnectBiasNode(Abc_Obj_t *pBiasNode, Abc_Obj_t *pObj, int biasLag) { - Abc_Obj_t *pCur, *pNext; - int i; - int lag; - Vec_Ptr_t *vNodes = Vec_PtrAlloc(1); - Vec_Int_t *vLags = Vec_IntAlloc(1); - Abc_Ntk_t *pNtk = Abc_ObjNtk( pObj ); - - Vec_PtrPush( vNodes, pObj ); - Vec_IntPush( vLags, 0 ); - - Abc_NtkIncrementTravId( pNtk ); - - while (Vec_PtrSize( vNodes )) { - pCur = Vec_PtrPop( vNodes ); - lag = Vec_IntPop( vLags ); - - if (Abc_NodeIsTravIdCurrent( pCur )) continue; - Abc_NodeSetTravIdCurrent( pCur ); - - if (!Abc_ObjIsLatch(pCur) && - !Abc_ObjIsBo(pCur) && - Abc_FlowRetime_GetLag(pObj)+lag == biasLag ) { - - // printf("biasing : "); - // Abc_ObjPrint(stdout, pCur ); -#if 1 - FSET( pCur, BLOCK ); -#else - Abc_ObjAddFanin( pCur, pBiasNode ); -#endif - } - - Abc_ObjForEachFanout( pCur, pNext, i ) { - if (Abc_ObjIsBi(pNext) || - Abc_ObjIsLatch(pNext) || - Abc_ObjIsBo(pNext) || - Abc_ObjIsBo(pCur)) { - Vec_PtrPush( vNodes, pNext ); - Vec_IntPush( vLags, lag - Abc_ObjIsLatch(pNext) ? 1 : 0 ); - } - } - } - - Vec_PtrFree( vNodes ); - Vec_IntFree( vLags ); -} - -/**Function************************************************************* - - Synopsis [Adds nodes to bias against uninitializable cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FlowRetime_AddInitBias( ) { - Abc_Ntk_t *pNtk = pManMR->pNtk; - Abc_Obj_t *pBiasNode, *pObj; - InitConstraint_t *pConstraint; - int i, j, id; - const int nConstraints = Vec_PtrSize( pManMR->vInitConstraints ); - - pManMR->pDataArray = REALLOC( Flow_Data_t, pManMR->pDataArray, pManMR->nNodes + (nConstraints*(pManMR->iteration+1)) ); - memset(pManMR->pDataArray + pManMR->nNodes, 0, sizeof(Flow_Data_t)*(nConstraints*(pManMR->iteration+1))); - - vprintf("\t\tcreating %d bias structures\n", nConstraints); - - Vec_PtrForEachEntry( Abc_Obj_t *, pManMR->vInitConstraints, pConstraint, i ) { - if (pConstraint->pBiasNode) continue; - - // printf("\t\t\tbias %d...\n", i); - pBiasNode = Abc_NtkCreateBlackbox( pNtk ); - - Vec_IntForEachEntry( &pConstraint->vNodes, id, j ) { - pObj = Abc_NtkObj(pNtk, id); - Abc_FlowRetime_ConnectBiasNode(pBiasNode, pObj, Vec_IntEntry(&pConstraint->vLags, j)); - } - - // pConstraint->pBiasNode = pBiasNode; - } -} - - -/**Function************************************************************* - - Synopsis [Clears mapping from init node to original node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FlowRetime_ClearInitToOrig( Abc_Obj_t *pInit ) -{ - int id = Abc_ObjId( pInit ); - - // grow data structure if necessary - if (id >= pManMR->sizeInitToOrig) { - int oldSize = pManMR->sizeInitToOrig; - pManMR->sizeInitToOrig = 1.5*id + 10; - pManMR->pInitToOrig = realloc(pManMR->pInitToOrig, sizeof(NodeLag_t)*pManMR->sizeInitToOrig); - memset( &(pManMR->pInitToOrig[oldSize]), 0, sizeof(NodeLag_t)*(pManMR->sizeInitToOrig-oldSize) ); - } - assert( pManMR->pInitToOrig ); - - pManMR->pInitToOrig[id].id = -1; -} - - -/**Function************************************************************* - - Synopsis [Sets mapping from init node to original node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FlowRetime_SetInitToOrig( Abc_Obj_t *pInit, Abc_Obj_t *pOrig) -{ - int lag; - int id = Abc_ObjId( pInit ); - - // grow data structure if necessary - if (id >= pManMR->sizeInitToOrig) { - int oldSize = pManMR->sizeInitToOrig; - pManMR->sizeInitToOrig = 1.5*id + 10; - pManMR->pInitToOrig = realloc(pManMR->pInitToOrig, sizeof(NodeLag_t)*pManMR->sizeInitToOrig); - memset( &(pManMR->pInitToOrig[oldSize]), 0, sizeof(NodeLag_t)*(pManMR->sizeInitToOrig-oldSize) ); - } - assert( pManMR->pInitToOrig ); - - // ignore BI, BO, and latch nodes - if (Abc_ObjIsBo(pOrig) || Abc_ObjIsBi(pOrig) || Abc_ObjIsLatch(pOrig)) { - Abc_FlowRetime_ClearInitToOrig(pInit); - return; - } - - // move out of latch boxes - lag = Abc_FlowRetime_ObjFirstNonLatchBox(pOrig, &pOrig); - - pManMR->pInitToOrig[id].id = Abc_ObjId(pOrig); - pManMR->pInitToOrig[id].lag = Abc_FlowRetime_GetLag(pOrig) + lag; -} - - -/**Function************************************************************* - - Synopsis [Gets mapping from init node to original node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FlowRetime_GetInitToOrig( Abc_Obj_t *pInit, Abc_Obj_t **pOrig, int *lag ) { - - int id = Abc_ObjId( pInit ); - int origId; - - assert(id < pManMR->sizeInitToOrig); - - origId = pManMR->pInitToOrig[id].id; - - if (origId < 0) { - assert(Abc_ObjFaninNum(pInit)); - Abc_FlowRetime_GetInitToOrig( Abc_ObjFanin0(pInit), pOrig, lag); - return; - } - - *pOrig = Abc_NtkObj(pManMR->pNtk, origId); - *lag = pManMR->pInitToOrig[id].lag; -} -ABC_NAMESPACE_IMPL_END - diff --git a/src/opt/fret/fretMain.c b/src/opt/fret/fretMain.c deleted file mode 100644 index 141baff4..00000000 --- a/src/opt/fret/fretMain.c +++ /dev/null @@ -1,1385 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Abc_FlowRetime_AddDummyFanin( Abc_Obj_t * pObj ); - -static Abc_Ntk_t* 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 Abc_Ntk_t* Abc_FlowRetime_NtkDup( Abc_Ntk_t * pNtk ); - -static void Abc_FlowRetime_VerifyPathLatencies( Abc_Ntk_t * pNtk ); -static int Abc_FlowRetime_VerifyPathLatencies_rec( Abc_Obj_t * pObj, int markD ); - -static void Abc_FlowRetime_UpdateLags_forw_rec( Abc_Obj_t *pObj ); -static void Abc_FlowRetime_UpdateLags_back_rec( Abc_Obj_t *pObj ); - -extern void Abc_NtkMarkCone_rec( Abc_Obj_t * pObj, int fForward ); - -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 fGuaranteeInitState, int fBlockConst, - int fForwardOnly, int fBackwardOnly, int nMaxIters, - int maxDelay, int fFastButConservative ) { - - int i; - Abc_Obj_t *pObj, *pNext; - InitConstraint_t *pData; - - // create manager - pManMR = ALLOC( MinRegMan_t, 1 ); - - pManMR->pNtk = pNtk; - pManMR->fVerbose = fVerbose; - pManMR->fComputeInitState = fComputeInitState; - pManMR->fGuaranteeInitState = fGuaranteeInitState; - pManMR->fBlockConst = fBlockConst; - pManMR->fForwardOnly = fForwardOnly; - pManMR->fBackwardOnly = fBackwardOnly; - pManMR->nMaxIters = nMaxIters; - pManMR->maxDelay = maxDelay; - pManMR->fComputeInitState = fComputeInitState; - pManMR->fConservTimingOnly = fFastButConservative; - pManMR->vNodes = Vec_PtrAlloc(100); - pManMR->vInitConstraints = Vec_PtrAlloc(2); - pManMR->pInitNtk = NULL; - pManMR->pInitToOrig = NULL; - pManMR->sizeInitToOrig = 0; - - 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 (%d) must be > current max delay (%d)\n", maxDelay, 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 lag and Flow_Data structure - pManMR->vLags = Vec_IntStart(pManMR->nNodes); - memset(pManMR->vLags->pArray, 0, sizeof(int)*pManMR->nNodes); - - pManMR->pDataArray = ALLOC( Flow_Data_t, pManMR->nNodes ); - Abc_FlowRetime_ClearFlows( 1 ); - - // main loop! - pNtk = Abc_FlowRetime_MainLoop(); - - // cleanup node fields - Abc_NtkForEachObj( pNtk, pObj, i ) { - // 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->pInitToOrig) FREE( pManMR->pInitToOrig ); - if (pManMR->vNodes) Vec_PtrFree(pManMR->vNodes); - if (pManMR->vLags) Vec_IntFree(pManMR->vLags); - if (pManMR->vSinkDistHist) Vec_IntFree(pManMR->vSinkDistHist); - if (pManMR->maxDelay) Abc_FlowRetime_FreeTiming( pNtk ); - while( Vec_PtrSize( pManMR->vInitConstraints )) { - pData = Vec_PtrPop( pManMR->vInitConstraints ); - //assert( pData->pBiasNode ); - //Abc_NtkDeleteObj( pData->pBiasNode ); - FREE( pData->vNodes.pArray ); - FREE( pData ); - } - FREE( pManMR->vInitConstraints ); - - // restrash if necessary - if (Abc_NtkIsStrash(pNtk)) { - Abc_NtkReassignIds( pNtk ); - pNtk = Abc_FlowRetime_NtkSilentRestrash( 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 [] - -***********************************************************************/ -Abc_Ntk_t * -Abc_FlowRetime_MainLoop( ) { - Abc_Ntk_t *pNtk = pManMR->pNtk, *pNtkCopy = 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 ); - -#if defined (DEBUG_PRINT_LEVELS) - vprintf("\t\tlevels = %d\n", Abc_NtkLevel(pNtk)); -#endif - - Abc_FlowRetime_ClearFlows( 1 ); - - pManMR->iteration++; - } while( cut != last ); - - // intermediate cleanup (for strashed networks) - if (Abc_NtkIsStrash(pNtk)) { - Abc_NtkReassignIds( pNtk ); - pNtk = pManMR->pNtk = Abc_FlowRetime_NtkSilentRestrash( pNtk, 1 ); - } - - // print info about initial states - if (pManMR->fComputeInitState && pManMR->fVerbose) - Abc_FlowRetime_PrintInitStateInfo( pNtk ); - - // (ii) backward retiming loop - pManMR->fIsForward = 0; - - if (!pManMR->fForwardOnly) do { - // initializability loop - pManMR->iteration = 0; - - // copy/restore network - if (pManMR->fGuaranteeInitState) { - if ( pNtk != pNtkCopy ) - Abc_NtkDelete( pNtk ); - pNtk = pManMR->pNtk = Abc_FlowRetime_NtkDup( pNtkCopy ); - vprintf("\trestoring network. regs = %d\n", Abc_NtkLatchNum( pNtk )); - } - - 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_AddInitBias( ); - 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 ); - } - - Abc_FlowRetime_RemoveInitBias( ); - cut = Abc_FlowRetime_ImplementCut( pNtk ); - -#if defined(DEBUG_PRINT_LEVELS) - vprintf("\t\tlevels = %d\n", Abc_NtkLevelReverse(pNtk)); -#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) { - printf("WARNING: no equivalent init state. setting all initial states to don't-cares\n"); - Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_LatchSetInitDc( pObj ); - break; - } - Abc_FlowRetime_ConstrainInit( ); - } - - Abc_NtkDelete(pManMR->pInitNtk); - pManMR->pInitNtk = NULL; - } while(1); - -// assert(!pManMR->fComputeInitState || pManMR->pInitNtk); - if (pManMR->fComputeInitState) Abc_NtkDelete(pManMR->pInitNtk); - if (pManMR->fGuaranteeInitState) ; /* Abc_NtkDelete(pNtkCopy); note: original ntk deleted later */ - - return pNtk; -} - - -/**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_NtkIsStrash( 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){ - // --- forward retiming : block TFO of inputs - - // 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 { - // --- backward retiming : block TFI of outputs - - // 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 ); - // block constant nodes (if enabled) - if (pManMR->fBlockConst) { - Abc_NtkForEachObj( pNtk, pObj, i ) - if ((Abc_NtkIsStrash(pNtk) && Abc_AigNodeIsConst(pObj)) || - (!Abc_NtkIsStrash(pNtk) && Abc_NodeIsConst(pObj))) { - FSET(pObj, BLOCK); - } - } - } - - // 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, int fVerbose ) { - int i, j, flow = 0, last, srcDist = 0; - Abc_Obj_t *pObj, *pObj2; -// int clk = clock(); - - 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); - -// PRT( "time", clock() - clk ); - 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); - // APH: broken by bias nodes 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 if (Abc_ObjIsLatch(pBo)) { - } else { - Abc_ObjPrint(stdout, pBi); - Abc_ObjPrint(stdout, pBo); - assert(0); - } - } - - // 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; - if (FTEST(pObj, BIAS_NODE)) 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); - - } - // APH: broken by bias nodes 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_UpdateLags( ); - 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_NtkIsStrash(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 [] - -***********************************************************************/ -int -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( int 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; - } - } -} - - -/**Function************************************************************* - - Synopsis [Duplicates network.] - - Description [Duplicates any type of network. Preserves copy data.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static Abc_Ntk_t* Abc_FlowRetime_NtkDup( Abc_Ntk_t * pNtk ) { - Abc_Ntk_t *pNtkCopy; - Abc_Obj_t *pObj, *pObjCopy, *pNext, *pNextCopy; - int i, j; - - pNtkCopy = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); - pNtkCopy->pName = Extra_UtilStrsav(pNtk->pName); - pNtkCopy->pSpec = Extra_UtilStrsav(pNtk->pSpec); - - // copy each object - Abc_NtkForEachObj( pNtk, pObj, i) { - - if (Abc_NtkIsStrash( pNtk ) && Abc_AigNodeIsConst( pObj )) - pObjCopy = Abc_AigConst1( pNtkCopy ); - else - pObjCopy = Abc_NtkDupObj( pNtkCopy, pObj, 0 ); - - FDATA( pObj )->pCopy = pObjCopy; - FDATA( pObj )->mark = 0; - - // assert( pManMR->fIsForward || pObj->Id == pObjCopy->Id ); - - // copy complementation - pObjCopy->fCompl0 = pObj->fCompl0; - pObjCopy->fCompl1 = pObj->fCompl1; - pObjCopy->fPhase = pObj->fPhase; - } - - // connect fanin - Abc_NtkForEachObj( pNtk, pObj, i) { - pObjCopy = FDATA(pObj)->pCopy; - assert(pObjCopy); - Abc_ObjForEachFanin( pObj, pNext, j ) { - pNextCopy = FDATA(pNext)->pCopy; - assert(pNextCopy); - assert(pNext->Type == pNextCopy->Type); - - Abc_ObjAddFanin(pObjCopy, pNextCopy); - } - } - -#if defined(DEBUG_CHECK) || 1 - Abc_NtkForEachObj( pNtk, pObj, i) { - pObjCopy = FDATA(pObj)->pCopy; - assert( Abc_ObjFanoutNum( pObj ) == Abc_ObjFanoutNum( pObjCopy ) ); - assert( Abc_ObjFaninNum( pObj ) == Abc_ObjFaninNum( pObjCopy ) ); - } -#endif - - assert(Abc_NtkObjNum( pNtk ) == Abc_NtkObjNum( pNtkCopy ) ); - assert(Abc_NtkLatchNum( pNtk ) == Abc_NtkLatchNum( pNtkCopy ) ); - assert(Abc_NtkPoNum( pNtk ) == Abc_NtkPoNum( pNtkCopy ) ); - assert(Abc_NtkPiNum( pNtk ) == Abc_NtkPiNum( pNtkCopy ) ); - - return pNtkCopy; -} - - -/**Function************************************************************* - - Synopsis [Silent restrash.] - - Description [Same functionality as Abc_NtkRestrash but w/o warnings.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_FlowRetime_NtkSilentRestrash( Abc_Ntk_t * pNtk, int fCleanup ) -{ - Abc_Ntk_t * pNtkAig; - Abc_Obj_t * pObj; - int i, nNodes;//, RetValue; - assert( Abc_NtkIsStrash(pNtk) ); - // 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( (Abc_Aig_t *)pNtkAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); - // finalize the network - Abc_NtkFinalize( pNtk, pNtkAig ); - // perform cleanup if requested - if ( fCleanup ) - nNodes = Abc_AigCleanup((Abc_Aig_t *)pNtkAig->pManFunc); - // 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 [Updates lag values.] - - Description [Recursive. Forward retiming.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void -Abc_FlowRetime_UpdateLags_forw_rec( Abc_Obj_t *pObj ) { - Abc_Obj_t *pNext; - int i; - - assert(!Abc_ObjIsPi(pObj)); - assert(!Abc_ObjIsLatch(pObj)); - - if (Abc_ObjIsBo(pObj)) return; - if (Abc_NodeIsTravIdCurrent(pObj)) return; - - Abc_NodeSetTravIdCurrent(pObj); - - if (Abc_ObjIsNode(pObj)) { - Abc_FlowRetime_SetLag( pObj, -1+Abc_FlowRetime_GetLag(pObj) ); - } - - Abc_ObjForEachFanin( pObj, pNext, i ) { - Abc_FlowRetime_UpdateLags_forw_rec( pNext ); - } -} - - -/**Function************************************************************* - - Synopsis [Updates lag values.] - - Description [Recursive. Backward retiming.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void -Abc_FlowRetime_UpdateLags_back_rec( Abc_Obj_t *pObj ) { - Abc_Obj_t *pNext; - int i; - - assert(!Abc_ObjIsPo(pObj)); - assert(!Abc_ObjIsLatch(pObj)); - - if (Abc_ObjIsBo(pObj)) return; - if (Abc_NodeIsTravIdCurrent(pObj)) return; - - Abc_NodeSetTravIdCurrent(pObj); - - if (Abc_ObjIsNode(pObj)) { - Abc_FlowRetime_SetLag( pObj, 1+Abc_FlowRetime_GetLag(pObj) ); - } - - Abc_ObjForEachFanout( pObj, pNext, i ) { - Abc_FlowRetime_UpdateLags_back_rec( pNext ); - } -} - -/**Function************************************************************* - - Synopsis [Updates lag values.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void -Abc_FlowRetime_UpdateLags( ) { - Abc_Obj_t *pObj, *pNext; - int i, j; - - Abc_NtkIncrementTravId( pManMR->pNtk ); - - Abc_NtkForEachLatch( pManMR->pNtk, pObj, i ) - if (pManMR->fIsForward) { - Abc_ObjForEachFanin( pObj, pNext, j ) - Abc_FlowRetime_UpdateLags_forw_rec( pNext ); - } else { - Abc_ObjForEachFanout( pObj, pNext, j ) - Abc_FlowRetime_UpdateLags_back_rec( pNext ); - } -} - - -/**Function************************************************************* - - Synopsis [Gets lag value of a node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int -Abc_FlowRetime_GetLag( Abc_Obj_t *pObj ) { - assert( !Abc_ObjIsLatch(pObj) ); - assert( Abc_ObjId(pObj) < Vec_IntSize(pManMR->vLags) ); - - return Vec_IntEntry(pManMR->vLags, Abc_ObjId(pObj)); -} - -/**Function************************************************************* - - Synopsis [Sets lag value of a node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void -Abc_FlowRetime_SetLag( Abc_Obj_t *pObj, int lag ) { - assert( Abc_ObjIsNode(pObj) ); - assert( Abc_ObjId(pObj) < Vec_IntSize(pManMR->vLags) ); - - Vec_IntWriteEntry(pManMR->vLags, Abc_ObjId(pObj), lag); -} - - -static void Abc_ObjPrintNeighborhood_rec( Abc_Obj_t *pObj, Vec_Ptr_t *vNodes, int depth ) { - Abc_Obj_t *pObj2; - int i; - - if (pObj->fMarkC || depth < 0) return; - - pObj->fMarkC = 1; - Vec_PtrPush( vNodes, pObj ); - - Abc_ObjPrint( stdout, pObj ); - - Abc_ObjForEachFanout(pObj, pObj2, i) { - Abc_ObjPrintNeighborhood_rec( pObj2, vNodes, depth-1 ); - } - Abc_ObjForEachFanin(pObj, pObj2, i) { - Abc_ObjPrintNeighborhood_rec( pObj2, vNodes, depth-1 ); - } -} - -void Abc_ObjPrintNeighborhood( Abc_Obj_t *pObj, int depth ) { - Vec_Ptr_t *vNodes = Vec_PtrAlloc(100); - Abc_Obj_t *pObj2; - - Abc_ObjPrintNeighborhood_rec( pObj, vNodes, depth ); - - while(Vec_PtrSize(vNodes)) { - pObj2 = Vec_PtrPop(vNodes); - pObj2->fMarkC = 0; - } - - Vec_PtrFree(vNodes); -} -ABC_NAMESPACE_IMPL_END - diff --git a/src/opt/fret/fretTime.c b/src/opt/fret/fretTime.c deleted file mode 100644 index 47e90519..00000000 --- a/src/opt/fret/fretTime.c +++ /dev/null @@ -1,768 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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( Abc_Obj_t *,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( Abc_Obj_t *,vNodes, pObj, i) { - pObj->fMarkB = 1; - - Abc_ObjForEachFanin( pObj, pNext, j ) - if ( Abc_NodeIsTravIdCurrent(pNext) && !Abc_ObjIsLatch(pNext)) - assert(pNext->fMarkB); - } - Vec_PtrForEachEntryReverse( Abc_Obj_t *,vNodes, pObj, i) - pObj->fMarkB = 0; -#endif - - // ... propagate values - Vec_PtrForEachEntryReverse( Abc_Obj_t *,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( Abc_Obj_t *,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( Abc_Obj_t *,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( Abc_Obj_t *,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( Abc_Obj_t *,vNodes, pObj, i) { - pObj->fMarkB = 1; - - Abc_ObjForEachFanout( pObj, pNext, j ) - if ( Abc_NodeIsTravIdCurrent(pNext) && !Abc_ObjIsLatch(pNext)) - assert(pNext->fMarkB); - } - Vec_PtrForEachEntryReverse( Abc_Obj_t *,vNodes, pObj, i) - pObj->fMarkB = 0; -#endif - - // ... propagate values - Vec_PtrForEachEntryReverse( Abc_Obj_t *,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( Abc_Obj_t *,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( Abc_Obj_t *,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( Abc_Obj_t *, 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( Abc_Obj_t *, 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( Abc_Obj_t *, 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( Abc_Obj_t *, 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 [] - -***********************************************************************/ -int 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); -} - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/opt/fret/fretime.h b/src/opt/fret/fretime.h deleted file mode 100644 index 2d70d7e3..00000000 --- a/src/opt/fret/fretime.h +++ /dev/null @@ -1,205 +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" - -ABC_NAMESPACE_HEADER_START - - -// #define IGNORE_TIMING -// #define DEBUG_PRINT_FLOWS -// #define DEBUG_VISITED -// #define DEBUG_PREORDER -#define DEBUG_CHECK -// #define DEBUG_PRINT_LEVELS - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define MAX_DIST 30000 - -// flags in Flow_Data structure... -#define VISITED_E 0x001 -#define VISITED_R 0x002 -#define VISITED (VISITED_E | VISITED_R) -#define FLOW 0x004 -#define CROSS_BOUNDARY 0x008 -#define BLOCK 0x010 -#define INIT_0 0x020 -#define INIT_1 0x040 -#define INIT_CARE (INIT_0 | INIT_1) -#define CONSERVATIVE 0x080 -#define BLOCK_OR_CONS (BLOCK | CONSERVATIVE) -#define BIAS_NODE 0x100 - -typedef struct Flow_Data_t_ { - unsigned int mark : 16; - - union { - Abc_Obj_t *pred; - /* unsigned int var; */ - Abc_Obj_t *pInitObj; - Abc_Obj_t *pCopy; - 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 ) (pManMR->pDataArray+Abc_ObjId(x)) -#define FSET( x, y ) FDATA(x)->mark |= y -#define FUNSET( x, y ) FDATA(x)->mark &= ~y -#define FTEST( x, y ) (FDATA(x)->mark & y) -#define FTIMEEDGES( x ) &(pManMR->vTimeEdges[Abc_ObjId( x )]) - -typedef struct NodeLag_T_ { - int id; - int lag; -} NodeLag_t; - -typedef struct InitConstraint_t_ { - Abc_Obj_t *pBiasNode; - - Vec_Int_t vNodes; - Vec_Int_t vLags; - -} InitConstraint_t; - -typedef struct MinRegMan_t_ { - - // problem description: - int maxDelay; - int fComputeInitState, fGuaranteeInitState, fBlockConst; - int nNodes, nLatches; - int fForwardOnly, fBackwardOnly; - int fConservTimingOnly; - int nMaxIters; - int fVerbose; - Abc_Ntk_t *pNtk; - - int nPreRefine; - - // problem state - int fIsForward; - int fSinkDistTerminate; - int nExactConstraints, nConservConstraints; - int fSolutionIsDc; - int constraintMask; - int iteration, subIteration; - Vec_Int_t *vLags; - - // problem data - Vec_Int_t *vSinkDistHist; - Flow_Data_t *pDataArray; - Vec_Ptr_t *vTimeEdges; - Vec_Ptr_t *vExactNodes; - Vec_Ptr_t *vInitConstraints; - Abc_Ntk_t *pInitNtk; - Vec_Ptr_t *vNodes; // re-useable struct - - NodeLag_t *pInitToOrig; - int sizeInitToOrig; - -} MinRegMan_t ; - -extern MinRegMan_t *pManMR; - -#define vprintf if (pManMR->fVerbose) printf - -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; -} - -/*=== fretMain.c ==========================================================*/ - -Abc_Ntk_t * Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose, - int fComputeInitState, int fGuaranteeInitState, int fBlockConst, - 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, int fVerbose ); -int Abc_FlowRetime_IsAcrossCut( Abc_Obj_t *pCur, Abc_Obj_t *pNext ); -void Abc_FlowRetime_ClearFlows( int fClearAll ); - -int Abc_FlowRetime_GetLag( Abc_Obj_t *pObj ); -void Abc_FlowRetime_SetLag( Abc_Obj_t *pObj, int lag ); - -void Abc_FlowRetime_UpdateLags( ); - -void Abc_ObjPrintNeighborhood( Abc_Obj_t *pObj, int depth ); - -Abc_Ntk_t * Abc_FlowRetime_NtkSilentRestrash( Abc_Ntk_t * pNtk, int fCleanup ); - -/*=== 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( ); -void Abc_FlowRetime_AddInitBias( ); -void Abc_FlowRetime_RemoveInitBias( ); - -/*=== fretTime.c ==========================================================*/ - -void Abc_FlowRetime_InitTiming( Abc_Ntk_t *pNtk ); -void Abc_FlowRetime_FreeTiming( Abc_Ntk_t *pNtk ); - -int 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 ); - - - -ABC_NAMESPACE_HEADER_END - -#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/fsim/fsim.h b/src/opt/fsim/fsim.h new file mode 100644 index 00000000..5a17550b --- /dev/null +++ b/src/opt/fsim/fsim.h @@ -0,0 +1,101 @@ +/**CFile**************************************************************** + + FileName [fsim.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast sequential AIG simulator.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: fsim.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__fsim__fsim_h +#define ABC__aig__fsim__fsim_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Fsim_Man_t_ Fsim_Man_t; + +// simulation parameters +typedef struct Fsim_ParSim_t_ Fsim_ParSim_t; +struct Fsim_ParSim_t_ +{ + // user-controlled parameters + int nWords; // the number of machine words + int nIters; // the number of timeframes + int TimeLimit; // time limit in seconds + int fCheckMiter; // check if miter outputs are non-zero + int fVerbose; // enables verbose output + // internal parameters + int fCompressAig; // compresses internal data +}; + +// switching estimation parameters +typedef struct Fsim_ParSwitch_t_ Fsim_ParSwitch_t; +struct Fsim_ParSwitch_t_ +{ + // user-controlled parameters + int nWords; // the number of machine words + int nIters; // the number of timeframes + int nPref; // the number of first timeframes to skip + int nRandPiNum; // PI trans prob (0=1/2; 1=1/4; 2=1/8, etc) + int fProbOne; // collect probability of one + int fProbTrans; // collect probatility of switching + int fVerbose; // enables verbose output +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== fsimCore.c ==========================================================*/ +extern void Fsim_ManSetDefaultParamsSim( Fsim_ParSim_t * p ); +extern void Fsim_ManSetDefaultParamsSwitch( Fsim_ParSwitch_t * p ); +/*=== fsimSim.c ==========================================================*/ +extern int Fsim_ManSimulate( Aig_Man_t * pAig, Fsim_ParSim_t * pPars ); +/*=== fsimSwitch.c ==========================================================*/ +extern Vec_Int_t * Fsim_ManSwitchSimulate( Aig_Man_t * pAig, Fsim_ParSwitch_t * pPars ); +/*=== fsimTsim.c ==========================================================*/ +extern Vec_Ptr_t * Fsim_ManTerSimulate( Aig_Man_t * pAig, int fVerbose ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/opt/fsim/fsimCore.c b/src/opt/fsim/fsimCore.c new file mode 100644 index 00000000..9516f09e --- /dev/null +++ b/src/opt/fsim/fsimCore.c @@ -0,0 +1,88 @@ +/**CFile**************************************************************** + + FileName [fsimCore.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast sequential AIG simulator.] + + Synopsis [Core procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: fsimCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fsimInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [This procedure sets default parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fsim_ManSetDefaultParamsSim( Fsim_ParSim_t * p ) +{ + memset( p, 0, sizeof(Fsim_ParSim_t) ); + // user-controlled parameters + p->nWords = 8; // the number of machine words + p->nIters = 32; // the number of timeframes + p->TimeLimit = 60; // time limit in seconds + p->fCheckMiter = 0; // check if miter outputs are non-zero + p->fVerbose = 1; // enables verbose output + // internal parameters + p->fCompressAig = 0; // compresses internal data +} + +/**Function************************************************************* + + Synopsis [This procedure sets default parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fsim_ManSetDefaultParamsSwitch( Fsim_ParSwitch_t * p ) +{ + memset( p, 0, sizeof(Fsim_ParSwitch_t) ); + // user-controlled parameters + p->nWords = 1; // the number of machine words + p->nIters = 48; // the number of timeframes + p->nPref = 16; // the number of first timeframes to skip + p->nRandPiNum = 0; // PI trans prob (0=1/2; 1=1/4; 2=1/8, etc) + p->fProbOne = 1; // collect probability of one + p->fProbTrans = 1; // collect probatility of switching + p->fVerbose = 1; // enables verbose output +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/fsim/fsimFront.c b/src/opt/fsim/fsimFront.c new file mode 100644 index 00000000..6169543c --- /dev/null +++ b/src/opt/fsim/fsimFront.c @@ -0,0 +1,369 @@ +/**CFile**************************************************************** + + FileName [fsimFront.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast sequential AIG simulator.] + + Synopsis [Simulation frontier.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: fsimFront.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fsimInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManStoreNum( Fsim_Man_t * p, int Num ) +{ + unsigned x = (unsigned)Num; + assert( Num >= 0 ); + while ( x & ~0x7f ) + { + *p->pDataCur++ = (x & 0x7f) | 0x80; + x >>= 7; + } + *p->pDataCur++ = x; + assert( p->pDataCur - p->pDataAig < p->nDataAig ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Fsim_ManRestoreNum( Fsim_Man_t * p ) +{ + int ch, i, x = 0; + for ( i = 0; (ch = *p->pDataCur++) & 0x80; i++ ) + x |= (ch & 0x7f) << (7 * i); + assert( p->pDataCur - p->pDataAig < p->nDataAig ); + return x | (ch << (7 * i)); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManStoreObj( Fsim_Man_t * p, Fsim_Obj_t * pObj ) +{ + if ( p->pDataAig2 ) + { + *p->pDataCur2++ = pObj->iNode; + *p->pDataCur2++ = pObj->iFan0; + *p->pDataCur2++ = pObj->iFan1; + return; + } + if ( pObj->iFan0 && pObj->iFan1 ) // and + { + assert( pObj->iNode ); + assert( pObj->iNode >= p->iNodePrev ); + assert( (pObj->iNode << 1) > pObj->iFan0 ); + assert( pObj->iFan0 > pObj->iFan1 ); + Fsim_ManStoreNum( p, ((pObj->iNode - p->iNodePrev) << 2) | 3 ); + Fsim_ManStoreNum( p, (pObj->iNode << 1) - pObj->iFan0 ); + Fsim_ManStoreNum( p, pObj->iFan0 - pObj->iFan1 ); + p->iNodePrev = pObj->iNode; + } + else if ( !pObj->iFan0 && !pObj->iFan1 ) // ci + { + assert( pObj->iNode ); + assert( pObj->iNode >= p->iNodePrev ); + Fsim_ManStoreNum( p, ((pObj->iNode - p->iNodePrev) << 2) | 1 ); + p->iNodePrev = pObj->iNode; + } + else // if ( !pObj->iFan0 && pObj->iFan1 ) // co + { + assert( pObj->iNode == 0 ); + assert( pObj->iFan0 != 0 ); + assert( pObj->iFan1 == 0 ); + assert( ((p->iNodePrev << 1) | 1) >= pObj->iFan0 ); + Fsim_ManStoreNum( p, (((p->iNodePrev << 1) | 1) - pObj->iFan0) << 1 ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Fsim_ManRestoreObj( Fsim_Man_t * p, Fsim_Obj_t * pObj ) +{ + int iValue = Fsim_ManRestoreNum( p ); + if ( (iValue & 3) == 3 ) // and + { + pObj->iNode = (iValue >> 2) + p->iNodePrev; + pObj->iFan0 = (pObj->iNode << 1) - Fsim_ManRestoreNum( p ); + pObj->iFan1 = pObj->iFan0 - Fsim_ManRestoreNum( p ); + p->iNodePrev = pObj->iNode; + } + else if ( (iValue & 3) == 1 ) // ci + { + pObj->iNode = (iValue >> 2) + p->iNodePrev; + pObj->iFan0 = 0; + pObj->iFan1 = 0; + p->iNodePrev = pObj->iNode; + } + else // if ( (iValue & 1) == 0 ) // co + { + pObj->iNode = 0; + pObj->iFan0 = ((p->iNodePrev << 1) | 1) - (iValue >> 1); + pObj->iFan1 = 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Determine the frontier.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Fsim_ManFrontFindNext( Fsim_Man_t * p, char * pFront ) +{ + assert( p->iNumber < (1 << 30) - p->nFront ); + while ( 1 ) + { + if ( p->iNumber % p->nFront == 0 ) + p->iNumber++; + if ( pFront[p->iNumber % p->nFront] == 0 ) + { + pFront[p->iNumber % p->nFront] = 1; + return p->iNumber; + } + p->iNumber++; + } + return -1; +} + +/**Function************************************************************* + + Synopsis [Verifies the frontier.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fsim_ManVerifyFront( Fsim_Man_t * p ) +{ + Fsim_Obj_t * pObj; + int * pFans0, * pFans1; // representation of fanins + int * pFrontToId; // mapping of nodes into frontier variables + int i, iVar0, iVar1; + pFans0 = ABC_ALLOC( int, p->nObjs ); + pFans1 = ABC_ALLOC( int, p->nObjs ); + pFans0[0] = pFans1[0] = 0; + pFans0[1] = pFans1[1] = 0; + pFrontToId = ABC_CALLOC( int, p->nFront ); + if ( Aig_ObjRefs(Aig_ManConst1(p->pAig)) ) + pFrontToId[1] = 1; + Fsim_ManForEachObj( p, pObj, i ) + { + if ( pObj->iNode ) + pFrontToId[pObj->iNode % p->nFront] = i; + iVar0 = Fsim_Lit2Var(pObj->iFan0); + iVar1 = Fsim_Lit2Var(pObj->iFan1); + pFans0[i] = Fsim_Var2Lit(pFrontToId[iVar0 % p->nFront], Fsim_LitIsCompl(pObj->iFan0)); + pFans1[i] = Fsim_Var2Lit(pFrontToId[iVar1 % p->nFront], Fsim_LitIsCompl(pObj->iFan1)); + } + for ( i = 0; i < p->nObjs; i++ ) + { + assert( pFans0[i] == p->pFans0[i] ); + assert( pFans1[i] == p->pFans1[i] ); + } + ABC_FREE( pFrontToId ); + ABC_FREE( pFans0 ); + ABC_FREE( pFans1 ); +} + +/**Function************************************************************* + + Synopsis [Determine the frontier.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fsim_ManFront( Fsim_Man_t * p, int fCompressAig ) +{ + Fsim_Obj_t Obj, * pObj = &Obj; + char * pFront; // places used for the frontier + int * pIdToFront; // mapping of nodes into frontier places + int i, iVar0, iVar1, nCrossCut = 0, nCrossCutMax = 0; + // start the frontier + pFront = ABC_CALLOC( char, p->nFront ); + pIdToFront = ABC_ALLOC( int, p->nObjs ); + pIdToFront[0] = -1; + pIdToFront[1] = -1; + // add constant node + p->iNumber = 1; + if ( p->pRefs[1] ) + { + pIdToFront[1] = Fsim_ManFrontFindNext( p, pFront ); + nCrossCut = 1; + } + // allocate room for data + if ( fCompressAig ) + { + p->nDataAig = p->nObjs * 6; + p->pDataAig = ABC_ALLOC( unsigned char, p->nDataAig ); + p->pDataCur = p->pDataAig; + p->iNodePrev = 0; + } + else + { + p->pDataAig2 = ABC_ALLOC( int, 3 * p->nObjs ); + p->pDataCur2 = p->pDataAig2 + 6; + } + // iterate through the objects + for ( i = 2; i < p->nObjs; i++ ) + { + if ( p->pFans0[i] == 0 ) // ci + { + // store node + pIdToFront[i] = Fsim_ManFrontFindNext( p, pFront ); + pObj->iNode = pIdToFront[i]; + pObj->iFan0 = 0; + pObj->iFan1 = 0; + Fsim_ManStoreObj( p, pObj ); + // handle CIs without fanout + if ( p->pRefs[i] == 0 ) + { + pFront[pIdToFront[i] % p->nFront] = 0; + pIdToFront[i] = -1; + } + } + else if ( p->pFans1[i] == 0 ) // co + { + assert( p->pRefs[i] == 0 ); + // get the fanin + iVar0 = Fsim_Lit2Var(p->pFans0[i]); + assert( pIdToFront[iVar0] > 0 ); + // store node + pObj->iNode = 0; + pObj->iFan0 = Fsim_Var2Lit(pIdToFront[iVar0], Fsim_LitIsCompl(p->pFans0[i])); + pObj->iFan1 = 0; + Fsim_ManStoreObj( p, pObj ); + // deref the fanin + if ( --p->pRefs[iVar0] == 0 ) + { + pFront[pIdToFront[iVar0] % p->nFront] = 0; + pIdToFront[iVar0] = -1; + nCrossCut--; + } + } + else + { + // get the fanins + iVar0 = Fsim_Lit2Var(p->pFans0[i]); + assert( pIdToFront[iVar0] > 0 ); + iVar1 = Fsim_Lit2Var(p->pFans1[i]); + assert( pIdToFront[iVar1] > 0 ); + // store node + pIdToFront[i] = Fsim_ManFrontFindNext( p, pFront ); + pObj->iNode = pIdToFront[i]; + pObj->iFan0 = Fsim_Var2Lit(pIdToFront[iVar0], Fsim_LitIsCompl(p->pFans0[i])); + pObj->iFan1 = Fsim_Var2Lit(pIdToFront[iVar1], Fsim_LitIsCompl(p->pFans1[i])); + Fsim_ManStoreObj( p, pObj ); + // deref the fanins + if ( --p->pRefs[iVar0] == 0 ) + { + pFront[pIdToFront[iVar0] % p->nFront] = 0; + pIdToFront[iVar0] = -1; + nCrossCut--; + } + if ( --p->pRefs[iVar1] == 0 ) + { + pFront[pIdToFront[iVar1] % p->nFront] = 0; + pIdToFront[iVar1] = -1; + nCrossCut--; + } + // handle nodes without fanout (choice nodes) + if ( p->pRefs[i] == 0 ) + { + pFront[pIdToFront[i] % p->nFront] = 0; + pIdToFront[i] = -1; + } + } + if ( p->pRefs[i] ) + if ( nCrossCutMax < ++nCrossCut ) + nCrossCutMax = nCrossCut; + } + assert( p->pDataAig2 == NULL || p->pDataCur2 - p->pDataAig2 == (3 * p->nObjs) ); + assert( nCrossCut == 0 ); + assert( nCrossCutMax == p->nCrossCutMax ); + for ( i = 0; i < p->nFront; i++ ) + assert( pFront[i] == 0 ); + ABC_FREE( pFront ); + ABC_FREE( pIdToFront ); +// Fsim_ManVerifyFront( p ); + ABC_FREE( p->pFans0 ); + ABC_FREE( p->pFans1 ); + ABC_FREE( p->pRefs ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/fsim/fsimInt.h b/src/opt/fsim/fsimInt.h new file mode 100644 index 00000000..0a7493a0 --- /dev/null +++ b/src/opt/fsim/fsimInt.h @@ -0,0 +1,138 @@ +/**CFile**************************************************************** + + FileName [fsimInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast sequential AIG simulator.] + + Synopsis [Internal declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: fsimInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__fsim__fsimInt_h +#define ABC__aig__fsim__fsimInt_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "aig/saig/saig.h" +#include "fsim.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +// simulation object +typedef struct Fsim_Obj_t_ Fsim_Obj_t; +struct Fsim_Obj_t_ +{ + int iNode; // the node ID + int iFan0; // the first fanin + int iFan1; // the second fanin +}; + +// fast sequential simulation manager +struct Fsim_Man_t_ +{ + // parameters + Aig_Man_t * pAig; // the AIG to be used for simulation + int nWords; // the number of simulation words + // AIG representation + int nPis; // the number of primary inputs + int nPos; // the number of primary outputs + int nCis; // the number of combinational inputs + int nCos; // the number of combinational outputs + int nNodes; // the number of internal nodes + int nObjs; // nCis + nNodes + nCos + 2 + int * pFans0; // fanin0 for all objects + int * pFans1; // fanin1 for all objects + int * pRefs; // reference counter for each node + int * pRefsCopy; // reference counter for each node + Vec_Int_t * vCis2Ids; // mapping of CIs into their PI ids + Vec_Int_t * vLos; // register outputs + Vec_Int_t * vLis; // register inputs + // cross-cut representation + int nCrossCut; // temporary cross-cut variable + int nCrossCutMax; // maximum cross-cut variable + int nFront; // the size of frontier + // derived AIG representation + int nDataAig; // the length of allocated data + unsigned char * pDataAig; // AIG representation + unsigned char * pDataCur; // AIG representation (current position) + int iNodePrev; // previous extracted value + int iNumber; // the number of the last object + Fsim_Obj_t Obj; // current object + // temporary AIG representation + int * pDataAig2; // temporary representation + int * pDataCur2; // AIG representation (current position) + // simulation information + unsigned * pDataSim; // simulation data + unsigned * pDataSimCis; // simulation data for CIs + unsigned * pDataSimCos; // simulation data for COs + // other information + int * pData1; + int * pData2; +}; + +static inline unsigned * Fsim_SimData( Fsim_Man_t * p, int i ) { return p->pDataSim + i * p->nWords; } +static inline unsigned * Fsim_SimDataCi( Fsim_Man_t * p, int i ) { return p->pDataSimCis + i * p->nWords; } +static inline unsigned * Fsim_SimDataCo( Fsim_Man_t * p, int i ) { return p->pDataSimCos + i * p->nWords; } + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Fsim_Var2Lit( int Var, int fCompl ) { return Var + Var + fCompl; } +static inline int Fsim_Lit2Var( int Lit ) { return Lit >> 1; } +static inline int Fsim_LitIsCompl( int Lit ) { return Lit & 1; } +static inline int Fsim_LitNot( int Lit ) { return Lit ^ 1; } +static inline int Fsim_LitNotCond( int Lit, int c ) { return Lit ^ (int)(c > 0); } +static inline int Fsim_LitRegular( int Lit ) { return Lit & ~01; } + +#define Fsim_ManForEachObj( p, pObj, i )\ + for ( i = 2, p->pDataCur = p->pDataAig, p->iNodePrev = 0, pObj = &p->Obj;\ + i < p->nObjs && Fsim_ManRestoreObj( p, pObj ); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== fsimFront.c ========================================================*/ +extern void Fsim_ManFront( Fsim_Man_t * p, int fCompressAig ); +/*=== fsimMan.c ==========================================================*/ +extern Fsim_Man_t * Fsim_ManCreate( Aig_Man_t * pAig ); +extern void Fsim_ManDelete( Fsim_Man_t * p ); +extern void Fsim_ManTest( Aig_Man_t * pAig ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/opt/fsim/fsimMan.c b/src/opt/fsim/fsimMan.c new file mode 100644 index 00000000..ea0cab43 --- /dev/null +++ b/src/opt/fsim/fsimMan.c @@ -0,0 +1,212 @@ +/**CFile**************************************************************** + + FileName [fsimMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast sequential AIG simulator.] + + Synopsis [Simulation manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: fsimMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fsimInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates fast simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fsim_ManCreate_rec( Fsim_Man_t * p, Aig_Obj_t * pObj ) +{ + int iFan0, iFan1, iTemp; + assert( !Aig_IsComplement(pObj) ); + if ( pObj->iData ) + return pObj->iData; + assert( !Aig_ObjIsConst1(pObj) ); + if ( Aig_ObjIsNode(pObj) ) + { + iFan0 = Fsim_ManCreate_rec( p, Aig_ObjFanin0(pObj) ); + iFan1 = Fsim_ManCreate_rec( p, Aig_ObjFanin1(pObj) ); + assert( iFan0 != iFan1 ); + if ( --p->pRefs[iFan0] == 0 ) + p->nCrossCut--; + iFan0 = Fsim_Var2Lit( iFan0, Aig_ObjFaninC0(pObj) ); + if ( --p->pRefs[iFan1] == 0 ) + p->nCrossCut--; + iFan1 = Fsim_Var2Lit( iFan1, Aig_ObjFaninC1(pObj) ); + if ( p->pAig->pEquivs ) + Fsim_ManCreate_rec( p, Aig_ObjEquiv(p->pAig, pObj) ); + } + else if ( Aig_ObjIsPo(pObj) ) + { + assert( Aig_ObjRefs(pObj) == 0 ); + iFan0 = Fsim_ManCreate_rec( p, Aig_ObjFanin0(pObj) ); + if ( --p->pRefs[iFan0] == 0 ) + p->nCrossCut--; + iFan0 = Fsim_Var2Lit( iFan0, Aig_ObjFaninC0(pObj) ); + iFan1 = 0; + } + else + { + iFan0 = iFan1 = 0; + Vec_IntPush( p->vCis2Ids, Aig_ObjPioNum(pObj) ); + } + if ( iFan0 < iFan1 ) + iTemp = iFan0, iFan0 = iFan1, iFan1 = iTemp; + p->pFans0[p->nObjs] = iFan0; + p->pFans1[p->nObjs] = iFan1; + p->pRefs[p->nObjs] = Aig_ObjRefs(pObj); + if ( p->pRefs[p->nObjs] ) + if ( p->nCrossCutMax < ++p->nCrossCut ) + p->nCrossCutMax = p->nCrossCut; + return pObj->iData = p->nObjs++; +} + +/**Function************************************************************* + + Synopsis [Creates fast simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fsim_Man_t * Fsim_ManCreate( Aig_Man_t * pAig ) +{ + Fsim_Man_t * p; + Aig_Obj_t * pObj; + int i, nObjs; + Aig_ManCleanData( pAig ); + p = (Fsim_Man_t *)ABC_ALLOC( Fsim_Man_t, 1 ); + memset( p, 0, sizeof(Fsim_Man_t) ); + p->pAig = pAig; + p->nPis = Saig_ManPiNum(pAig); + p->nPos = Saig_ManPoNum(pAig); + p->nCis = Aig_ManPiNum(pAig); + p->nCos = Aig_ManPoNum(pAig); + p->nNodes = Aig_ManNodeNum(pAig); + nObjs = p->nCis + p->nCos + p->nNodes + 2; + p->pFans0 = ABC_ALLOC( int, nObjs ); + p->pFans1 = ABC_ALLOC( int, nObjs ); + p->pRefs = ABC_ALLOC( int, nObjs ); + p->vCis2Ids = Vec_IntAlloc( Aig_ManPiNum(pAig) ); + // add objects (0=unused; 1=const1) + p->pFans0[0] = p->pFans1[0] = 0; + p->pFans0[1] = p->pFans1[1] = 0; + p->pRefs[0] = 0; + p->nObjs = 2; + pObj = Aig_ManConst1( pAig ); + pObj->iData = 1; + p->pRefs[1] = Aig_ObjRefs(pObj); + if ( p->pRefs[1] ) + p->nCrossCut = 1; + Aig_ManForEachPi( pAig, pObj, i ) + if ( Aig_ObjRefs(pObj) == 0 ) + Fsim_ManCreate_rec( p, pObj ); + Aig_ManForEachPo( pAig, pObj, i ) + Fsim_ManCreate_rec( p, pObj ); + assert( Vec_IntSize(p->vCis2Ids) == Aig_ManPiNum(pAig) ); + assert( p->nObjs == nObjs ); + // check references + assert( p->nCrossCut == 0 ); + Aig_ManForEachObj( pAig, pObj, i ) + { + assert( p->pRefs[pObj->iData] == 0 ); + p->pRefs[pObj->iData] = Aig_ObjRefs(pObj); + } + // collect flop outputs + p->vLos = Vec_IntAlloc( Aig_ManRegNum(pAig) ); + Saig_ManForEachLo( pAig, pObj, i ) + Vec_IntPush( p->vLos, pObj->iData ); + // collect flop inputs + p->vLis = Vec_IntAlloc( Aig_ManRegNum(pAig) ); + Saig_ManForEachLi( pAig, pObj, i ) + Vec_IntPush( p->vLis, pObj->iData ); + // determine the frontier size + p->nFront = 1 + (int)(1.1 * p->nCrossCutMax); + return p; +} + +/**Function************************************************************* + + Synopsis [Deletes fast simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fsim_ManDelete( Fsim_Man_t * p ) +{ + Vec_IntFree( p->vCis2Ids ); + Vec_IntFree( p->vLos ); + Vec_IntFree( p->vLis ); + ABC_FREE( p->pDataAig2 ); + ABC_FREE( p->pDataAig ); + ABC_FREE( p->pFans0 ); + ABC_FREE( p->pFans1 ); + ABC_FREE( p->pRefs ); + ABC_FREE( p->pDataSim ); + ABC_FREE( p->pDataSimCis ); + ABC_FREE( p->pDataSimCos ); + ABC_FREE( p->pData1 ); + ABC_FREE( p->pData2 ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Testing procedure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fsim_ManTest( Aig_Man_t * pAig ) +{ + Fsim_Man_t * p; + p = Fsim_ManCreate( pAig ); + Fsim_ManFront( p, 0 ); + Fsim_ManDelete( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/fsim/fsimSim.c b/src/opt/fsim/fsimSim.c new file mode 100644 index 00000000..84844407 --- /dev/null +++ b/src/opt/fsim/fsimSim.c @@ -0,0 +1,567 @@ +/**CFile**************************************************************** + + FileName [fsimSim.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast sequential AIG simulator.] + + Synopsis [Simulation procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: fsimSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fsimInt.h" +#include "aig/ssw/ssw.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSimInfoRandom( Fsim_Man_t * p, unsigned * pInfo ) +{ + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = Aig_ManRandom( 0 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSimInfoZero( Fsim_Man_t * p, unsigned * pInfo ) +{ + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = 0; +} + +/**Function************************************************************* + + Synopsis [Returns index of the first pattern that failed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Fsim_ManSimInfoIsZero( Fsim_Man_t * p, unsigned * pInfo ) +{ + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + if ( pInfo[w] ) + return 32*(w-1) + Aig_WordFindFirstBit( pInfo[w] ); + return -1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSimInfoOne( Fsim_Man_t * p, unsigned * pInfo ) +{ + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = ~0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSimInfoCopy( Fsim_Man_t * p, unsigned * pInfo, unsigned * pInfo0 ) +{ + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSimulateCi( Fsim_Man_t * p, int iNode, int iCi ) +{ + unsigned * pInfo = Fsim_SimData( p, iNode % p->nFront ); + unsigned * pInfo0 = Fsim_SimDataCi( p, iCi ); + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSimulateCo( Fsim_Man_t * p, int iCo, int iFan0 ) +{ + unsigned * pInfo = Fsim_SimDataCo( p, iCo ); + unsigned * pInfo0 = Fsim_SimData( p, Fsim_Lit2Var(iFan0) % p->nFront ); + int w; + if ( Fsim_LitIsCompl(iFan0) ) + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = ~pInfo0[w]; + else //if ( !Fsim_LitIsCompl(iFan0) ) + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSimulateNode( Fsim_Man_t * p, int iNode, int iFan0, int iFan1 ) +{ + unsigned * pInfo = Fsim_SimData( p, iNode % p->nFront ); + unsigned * pInfo0 = Fsim_SimData( p, Fsim_Lit2Var(iFan0) % p->nFront ); + unsigned * pInfo1 = Fsim_SimData( p, Fsim_Lit2Var(iFan1) % p->nFront ); + int w; + if ( Fsim_LitIsCompl(iFan0) && Fsim_LitIsCompl(iFan1) ) + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = ~(pInfo0[w] | pInfo1[w]); + else if ( Fsim_LitIsCompl(iFan0) && !Fsim_LitIsCompl(iFan1) ) + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = ~pInfo0[w] & pInfo1[w]; + else if ( !Fsim_LitIsCompl(iFan0) && Fsim_LitIsCompl(iFan1) ) + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w] & ~pInfo1[w]; + else //if ( !Fsim_LitIsCompl(iFan0) && !Fsim_LitIsCompl(iFan1) ) + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w] & pInfo1[w]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSimInfoInit( Fsim_Man_t * p ) +{ + int iPioNum, i; + Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i ) + { + if ( iPioNum < p->nPis ) + Fsim_ManSimInfoRandom( p, Fsim_SimDataCi(p, i) ); + else + Fsim_ManSimInfoZero( p, Fsim_SimDataCi(p, i) ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSimInfoTransfer( Fsim_Man_t * p ) +{ + int iPioNum, i; + Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i ) + { + if ( iPioNum < p->nPis ) + Fsim_ManSimInfoRandom( p, Fsim_SimDataCi(p, i) ); + else + Fsim_ManSimInfoCopy( p, Fsim_SimDataCi(p, i), Fsim_SimDataCo(p, p->nPos+iPioNum-p->nPis) ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Fsim_ManRestoreNum( Fsim_Man_t * p ) +{ + int ch, i, x = 0; + for ( i = 0; (ch = *p->pDataCur++) & 0x80; i++ ) + x |= (ch & 0x7f) << (7 * i); + assert( p->pDataCur - p->pDataAig < p->nDataAig ); + return x | (ch << (7 * i)); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Fsim_ManRestoreObj( Fsim_Man_t * p, Fsim_Obj_t * pObj ) +{ + int iValue = Fsim_ManRestoreNum( p ); + if ( (iValue & 3) == 3 ) // and + { + pObj->iNode = (iValue >> 2) + p->iNodePrev; + pObj->iFan0 = (pObj->iNode << 1) - Fsim_ManRestoreNum( p ); + pObj->iFan1 = pObj->iFan0 - Fsim_ManRestoreNum( p ); + p->iNodePrev = pObj->iNode; + } + else if ( (iValue & 3) == 1 ) // ci + { + pObj->iNode = (iValue >> 2) + p->iNodePrev; + pObj->iFan0 = 0; + pObj->iFan1 = 0; + p->iNodePrev = pObj->iNode; + } + else // if ( (iValue & 1) == 0 ) // co + { + pObj->iNode = 0; + pObj->iFan0 = ((p->iNodePrev << 1) | 1) - (iValue >> 1); + pObj->iFan1 = 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSimulateRound2( Fsim_Man_t * p ) +{ + Fsim_Obj_t * pObj; + int i, iCis = 0, iCos = 0; + if ( Aig_ObjRefs(Aig_ManConst1(p->pAig)) ) + Fsim_ManSimInfoOne( p, Fsim_SimData(p, 1) ); + Fsim_ManForEachObj( p, pObj, i ) + { + if ( pObj->iFan0 == 0 ) + Fsim_ManSimulateCi( p, pObj->iNode, iCis++ ); + else if ( pObj->iFan1 == 0 ) + Fsim_ManSimulateCo( p, iCos++, pObj->iFan0 ); + else + Fsim_ManSimulateNode( p, pObj->iNode, pObj->iFan0, pObj->iFan1 ); + } + assert( iCis == p->nCis ); + assert( iCos == p->nCos ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSimulateRound( Fsim_Man_t * p ) +{ + int * pCur, * pEnd; + int iCis = 0, iCos = 0; + if ( p->pDataAig2 == NULL ) + { + Fsim_ManSimulateRound2( p ); + return; + } + if ( Aig_ObjRefs(Aig_ManConst1(p->pAig)) ) + Fsim_ManSimInfoOne( p, Fsim_SimData(p, 1) ); + pCur = p->pDataAig2 + 6; + pEnd = p->pDataAig2 + 3 * p->nObjs; + while ( pCur < pEnd ) + { + if ( pCur[1] == 0 ) + Fsim_ManSimulateCi( p, pCur[0], iCis++ ); + else if ( pCur[2] == 0 ) + Fsim_ManSimulateCo( p, iCos++, pCur[1] ); + else + Fsim_ManSimulateNode( p, pCur[0], pCur[1], pCur[2] ); + pCur += 3; + } + assert( iCis == p->nCis ); + assert( iCos == p->nCos ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fsim_ManSimulateRoundTest( Fsim_Man_t * p ) +{ + Fsim_Obj_t * pObj; + int i, clk = clock(); + Fsim_ManForEachObj( p, pObj, i ) + { + } +// ABC_PRT( "Unpacking time", p->pPars->nIters * (clock() - clk) ); +} + +/**Function************************************************************* + + Synopsis [Returns index of the PO and pattern that failed it.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Fsim_ManCheckPos( Fsim_Man_t * p, int * piPo, int * piPat ) +{ + int i, iPat; + for ( i = 0; i < p->nPos; i++ ) + { + iPat = Fsim_ManSimInfoIsZero( p, Fsim_SimDataCo(p, i) ); + if ( iPat >= 0 ) + { + *piPo = i; + *piPat = iPat; + return 1; + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Fsim_ManGenerateCounter( Aig_Man_t * pAig, int iFrame, int iOut, int nWords, int iPat, Vec_Int_t * vCis2Ids ) +{ + Abc_Cex_t * p; + unsigned * pData; + int f, i, w, iPioId, Counter; + p = Abc_CexAlloc( Aig_ManRegNum(pAig), Saig_ManPiNum(pAig), iFrame+1 ); + p->iFrame = iFrame; + p->iPo = iOut; + // fill in the binary data + Aig_ManRandom( 1 ); + Counter = p->nRegs; + pData = ABC_ALLOC( unsigned, nWords ); + for ( f = 0; f <= iFrame; f++, Counter += p->nPis ) + for ( i = 0; i < Aig_ManPiNum(pAig); i++ ) + { + iPioId = Vec_IntEntry( vCis2Ids, i ); + if ( iPioId >= p->nPis ) + continue; + for ( w = nWords-1; w >= 0; w-- ) + pData[w] = Aig_ManRandom( 0 ); + if ( Aig_InfoHasBit( pData, iPat ) ) + Aig_InfoSetBit( p->pData, Counter + iPioId ); + } + ABC_FREE( pData ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fsim_ManSimulate( Aig_Man_t * pAig, Fsim_ParSim_t * pPars ) +{ + Fsim_Man_t * p; + Sec_MtrStatus_t Status; + int i, iOut, iPat, clk, clkTotal = clock(), clk2, clk2Total = 0; + assert( Aig_ManRegNum(pAig) > 0 ); + if ( pPars->fCheckMiter ) + { + Status = Sec_MiterStatus( pAig ); + if ( Status.nSat > 0 ) + { + printf( "Miter is trivially satisfiable (output %d).\n", Status.iOut ); + return 1; + } + if ( Status.nUndec == 0 ) + { + printf( "Miter is trivially unsatisfiable.\n" ); + return 0; + } + } + // create manager + clk = clock(); + p = Fsim_ManCreate( pAig ); + p->nWords = pPars->nWords; + if ( pPars->fVerbose ) + { + printf( "Obj = %8d (%8d). Cut = %6d. Front = %6d. FrtMem = %7.2f Mb. ", + p->nObjs, p->nCis + p->nNodes, p->nCrossCutMax, p->nFront, + 4.0*p->nWords*(p->nFront)/(1<<20) ); + ABC_PRT( "Time", clock() - clk ); + } + // create simulation frontier + clk = clock(); + Fsim_ManFront( p, pPars->fCompressAig ); + if ( pPars->fVerbose ) + { + printf( "Max ID = %8d. Log max ID = %2d. AigMem = %7.2f Mb (%5.2f byte/obj). ", + p->iNumber, Aig_Base2Log(p->iNumber), + 1.0*(p->pDataCur-p->pDataAig)/(1<<20), + 1.0*(p->pDataCur-p->pDataAig)/p->nObjs ); + ABC_PRT( "Time", clock() - clk ); + } + // perform simulation + Aig_ManRandom( 1 ); + assert( p->pDataSim == NULL ); + p->pDataSim = ABC_ALLOC( unsigned, p->nWords * p->nFront ); + p->pDataSimCis = ABC_ALLOC( unsigned, p->nWords * p->nCis ); + p->pDataSimCos = ABC_ALLOC( unsigned, p->nWords * p->nCos ); + Fsim_ManSimInfoInit( p ); + for ( i = 0; i < pPars->nIters; i++ ) + { + Fsim_ManSimulateRound( p ); + if ( pPars->fVerbose ) + { + printf( "Frame %4d out of %4d and timeout %3d sec. ", i+1, pPars->nIters, pPars->TimeLimit ); + printf( "Time = %7.2f sec\r", (1.0*clock()-clkTotal)/CLOCKS_PER_SEC ); + } + if ( pPars->fCheckMiter && Fsim_ManCheckPos( p, &iOut, &iPat ) ) + { + assert( pAig->pSeqModel == NULL ); + pAig->pSeqModel = Fsim_ManGenerateCounter( pAig, i, iOut, p->nWords, iPat, p->vCis2Ids ); + if ( pPars->fVerbose ) + printf( "Miter is satisfiable after simulation (output %d).\n", iOut ); + break; + } + if ( (clock() - clkTotal)/CLOCKS_PER_SEC >= pPars->TimeLimit ) + break; + clk2 = clock(); + if ( i < pPars->nIters - 1 ) + Fsim_ManSimInfoTransfer( p ); + clk2Total += clock() - clk2; + } + if ( pAig->pSeqModel == NULL ) + printf( "No bug detected after %d frames with time limit %d seconds.\n", i+1, pPars->TimeLimit ); + if ( pPars->fVerbose ) + { + printf( "Maxcut = %8d. AigMem = %7.2f Mb. SimMem = %7.2f Mb. ", + p->nCrossCutMax, + p->pDataAig2? 12.0*p->nObjs/(1<<20) : 1.0*(p->pDataCur-p->pDataAig)/(1<<20), + 4.0*p->nWords*(p->nFront+p->nCis+p->nCos)/(1<<20) ); + ABC_PRT( "Sim time", clock() - clkTotal ); + +// ABC_PRT( "Additional time", clk2Total ); +// Fsim_ManSimulateRoundTest( p ); +// Fsim_ManSimulateRoundTest2( p ); + } + Fsim_ManDelete( p ); + return pAig->pSeqModel != NULL; + +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/fsim/fsimSwitch.c b/src/opt/fsim/fsimSwitch.c new file mode 100644 index 00000000..3eef2d4c --- /dev/null +++ b/src/opt/fsim/fsimSwitch.c @@ -0,0 +1,40 @@ +/**CFile**************************************************************** + + FileName [fsimSwitch.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast sequential AIG simulator.] + + Synopsis [Computing switching activity.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: fsimSwitch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fsimInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/fsim/fsimTsim.c b/src/opt/fsim/fsimTsim.c new file mode 100644 index 00000000..5ad78b33 --- /dev/null +++ b/src/opt/fsim/fsimTsim.c @@ -0,0 +1,415 @@ +/**CFile**************************************************************** + + FileName [fsimTsim.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast sequential AIG simulator.] + + Synopsis [Varius utilities.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: fsimTsim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fsimInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define FSIM_ZER 1 +#define FSIM_ONE 2 +#define FSIM_UND 3 + +static inline int Aig_XsimNotCond( int Value, int fCompl ) +{ + if ( Value == FSIM_UND ) + return FSIM_UND; + if ( Value == FSIM_ZER + fCompl ) + return FSIM_ZER; + return FSIM_ONE; +} +static inline int Aig_XsimAndCond( int Value0, int fCompl0, int Value1, int fCompl1 ) +{ + if ( Value0 == FSIM_UND || Value1 == FSIM_UND ) + return FSIM_UND; + if ( Value0 == FSIM_ZER + fCompl0 || Value1 == FSIM_ZER + fCompl1 ) + return FSIM_ZER; + return FSIM_ONE; +} + +static inline int Fsim_ManTerSimInfoGet( unsigned * pInfo, int i ) +{ + return 3 & (pInfo[i >> 4] >> ((i & 15) << 1)); +} +static inline void Fsim_ManTerSimInfoSet( unsigned * pInfo, int i, int Value ) +{ + assert( Value >= FSIM_ZER && Value <= FSIM_UND ); + Value ^= Fsim_ManTerSimInfoGet( pInfo, i ); + pInfo[i >> 4] ^= (Value << ((i & 15) << 1)); +} + +static inline unsigned * Fsim_ManTerStateNext( unsigned * pState, int nWords ) { return *((unsigned **)(pState + nWords)); } +static inline void Fsim_ManTerStateSetNext( unsigned * pState, int nWords, unsigned * pNext ) { *((unsigned **)(pState + nWords)) = pNext; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManTerSimulateCi( Fsim_Man_t * p, int iNode, int iCi ) +{ + Fsim_ManTerSimInfoSet( p->pDataSim, iNode, Fsim_ManTerSimInfoGet(p->pDataSimCis, iCi) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManTerSimulateCo( Fsim_Man_t * p, int iCo, int iFan0 ) +{ + int Value = Fsim_ManTerSimInfoGet( p->pDataSim, Fsim_Lit2Var(iFan0) ); + Fsim_ManTerSimInfoSet( p->pDataSimCos, iCo, Aig_XsimNotCond( Value, Fsim_LitIsCompl(iFan0) ) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManTerSimulateNode( Fsim_Man_t * p, int iNode, int iFan0, int iFan1 ) +{ + int Value0 = Fsim_ManTerSimInfoGet( p->pDataSim, Fsim_Lit2Var(iFan0) ); + int Value1 = Fsim_ManTerSimInfoGet( p->pDataSim, Fsim_Lit2Var(iFan1) ); + Fsim_ManTerSimInfoSet( p->pDataSim, iNode, Aig_XsimAndCond( Value0, Fsim_LitIsCompl(iFan0), Value1, Fsim_LitIsCompl(iFan1) ) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManTerSimInfoInit( Fsim_Man_t * p ) +{ + int iPioNum, i; + Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i ) + { + if ( iPioNum < p->nPis ) + Fsim_ManTerSimInfoSet( p->pDataSimCis, i, FSIM_UND ); + else + Fsim_ManTerSimInfoSet( p->pDataSimCis, i, FSIM_ZER ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManTerSimInfoTransfer( Fsim_Man_t * p ) +{ + int iPioNum, i; + Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i ) + { + if ( iPioNum < p->nPis ) + Fsim_ManTerSimInfoSet( p->pDataSimCis, i, FSIM_UND ); + else + Fsim_ManTerSimInfoSet( p->pDataSimCis, i, Fsim_ManTerSimInfoGet( p->pDataSimCos, p->nPos+iPioNum-p->nPis ) ); + } +} + + +/**Function************************************************************* + + Synopsis [Computes hash value of the node using its simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fsim_ManTerStateHash( 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 Fsim_ManTerStateLookup( unsigned * pState, int nWords, unsigned ** pBins, int nBins ) +{ + unsigned * pEntry; + int Hash; + Hash = Fsim_ManTerStateHash( pState, nWords, nBins ); + for ( pEntry = pBins[Hash]; pEntry; pEntry = Fsim_ManTerStateNext(pEntry, nWords) ) + if ( !memcmp( pEntry, pState, sizeof(unsigned) * nWords ) ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Inserts value into the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fsim_ManTerStateInsert( unsigned * pState, int nWords, unsigned ** pBins, int nBins ) +{ + int Hash = Fsim_ManTerStateHash( pState, nWords, nBins ); + assert( !Fsim_ManTerStateLookup( pState, nWords, pBins, nBins ) ); + Fsim_ManTerStateSetNext( pState, nWords, pBins[Hash] ); + pBins[Hash] = pState; +} + +/**Function************************************************************* + + Synopsis [Inserts value into the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Fsim_ManTerStateCreate( unsigned * pInfo, int nPis, int nCis, int nWords ) +{ + unsigned * pRes; + int i; + pRes = (unsigned *)ABC_CALLOC( char, sizeof(unsigned) * nWords + sizeof(unsigned *) ); + for ( i = nPis; i < nCis; i++ ) + Fsim_ManTerSimInfoSet( pRes, i-nPis, Fsim_ManTerSimInfoGet(pInfo, i) ); + return pRes; +} + +/**Function************************************************************* + + Synopsis [Inserts value into the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fsim_ManTerStatePrint( unsigned * pState, int nRegs ) +{ + int i, Value, nZeros = 0, nOnes = 0, nDcs = 0; + for ( i = 0; i < nRegs; 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 [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManTerSimulateRound( Fsim_Man_t * p ) +{ + int * pCur, * pEnd; + int iCis = 0, iCos = 0; + if ( Aig_ObjRefs(Aig_ManConst1(p->pAig)) ) + Fsim_ManTerSimInfoSet( p->pDataSimCis, 1, FSIM_ONE ); + pCur = p->pDataAig2 + 6; + pEnd = p->pDataAig2 + 3 * p->nObjs; + while ( pCur < pEnd ) + { + if ( pCur[1] == 0 ) + Fsim_ManTerSimulateCi( p, pCur[0], iCis++ ); + else if ( pCur[2] == 0 ) + Fsim_ManTerSimulateCo( p, iCos++, pCur[1] ); + else + Fsim_ManTerSimulateNode( p, pCur[0], pCur[1], pCur[2] ); + pCur += 3; + } + assert( iCis == p->nCis ); + assert( iCos == p->nCos ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Fsim_ManTerSimulate( Aig_Man_t * pAig, int fVerbose ) +{ + Fsim_Man_t * p; + Vec_Ptr_t * vStates; + unsigned ** pBins, * pState; + int i, nWords, nBins, clk, clkTotal = clock(); + assert( Aig_ManRegNum(pAig) > 0 ); + // create manager + clk = clock(); + p = Fsim_ManCreate( pAig ); + if ( fVerbose ) + { + printf( "Obj = %8d (%8d). Cut = %6d. Front = %6d. FrtMem = %7.2f Mb. ", + p->nObjs, p->nCis + p->nNodes, p->nCrossCutMax, p->nFront, + 4.0*Aig_BitWordNum(2 * p->nFront)/(1<<20) ); + ABC_PRT( "Time", clock() - clk ); + } + // create simulation frontier + clk = clock(); + Fsim_ManFront( p, 0 ); + if ( fVerbose ) + { + printf( "Max ID = %8d. Log max ID = %2d. AigMem = %7.2f Mb (%5.2f byte/obj). ", + p->iNumber, Aig_Base2Log(p->iNumber), + 1.0*(p->pDataCur-p->pDataAig)/(1<<20), + 1.0*(p->pDataCur-p->pDataAig)/p->nObjs ); + ABC_PRT( "Time", clock() - clk ); + } + // allocate storage for terminary states + nWords = Abc_BitWordNum( 2*Aig_ManRegNum(pAig) ); + vStates = Vec_PtrAlloc( 1000 ); + nBins = Abc_PrimeCudd( 500 ); + pBins = ABC_ALLOC( unsigned *, nBins ); + memset( pBins, 0, sizeof(unsigned *) * nBins ); + // perform simulation + assert( p->pDataSim == NULL ); + p->pDataSim = ABC_ALLOC( unsigned, Aig_BitWordNum(2 * p->nFront) * sizeof(unsigned) ); + p->pDataSimCis = ABC_ALLOC( unsigned, Aig_BitWordNum(2 * p->nCis) * sizeof(unsigned) ); + p->pDataSimCos = ABC_ALLOC( unsigned, Aig_BitWordNum(2 * p->nCos) * sizeof(unsigned) ); + Fsim_ManTerSimInfoInit( p ); + // hash the first state + pState = Fsim_ManTerStateCreate( p->pDataSimCis, p->nPis, p->nCis, nWords ); + Vec_PtrPush( vStates, pState ); + Fsim_ManTerStateInsert( pState, nWords, pBins, nBins ); + // perform simuluation till convergence + for ( i = 0; ; i++ ) + { + Fsim_ManTerSimulateRound( p ); + Fsim_ManTerSimInfoTransfer( p ); + // hash the first state + pState = Fsim_ManTerStateCreate( p->pDataSimCis, p->nPis, p->nCis, nWords ); + Vec_PtrPush( vStates, pState ); + if ( Fsim_ManTerStateLookup(pState, nWords, pBins, nBins) ) + break; + Fsim_ManTerStateInsert( pState, nWords, pBins, nBins ); + } + if ( fVerbose ) + { + printf( "Maxcut = %8d. AigMem = %7.2f Mb. SimMem = %7.2f Mb. ", + p->nCrossCutMax, + p->pDataAig2? 12.0*p->nObjs/(1<<20) : 1.0*(p->pDataCur-p->pDataAig)/(1<<20), + 4.0*(Aig_BitWordNum(2 * p->nFront)+Aig_BitWordNum(2 * p->nCis)+Aig_BitWordNum(2 * p->nCos))/(1<<20) ); + ABC_PRT( "Sim time", clock() - clkTotal ); + } + ABC_FREE( pBins ); + Fsim_ManDelete( p ); + return vStates; + +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/fsim/module.make b/src/opt/fsim/module.make new file mode 100644 index 00000000..c728e128 --- /dev/null +++ b/src/opt/fsim/module.make @@ -0,0 +1,6 @@ +SRC += src/opt/fsim/fsimCore.c \ + src/opt/fsim/fsimFront.c \ + src/opt/fsim/fsimMan.c \ + src/opt/fsim/fsimSim.c \ + src/opt/fsim/fsimSwitch.c \ + src/opt/fsim/fsimTsim.c diff --git a/src/opt/fxu/fxu.h b/src/opt/fxu/fxu.h index d42bf873..28856c28 100644 --- a/src/opt/fxu/fxu.h +++ b/src/opt/fxu/fxu.h @@ -16,15 +16,15 @@ ***********************************************************************/ -#ifndef __FXU_H__ -#define __FXU_H__ +#ifndef ABC__opt__fxu__fxu_h +#define ABC__opt__fxu__fxu_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// -#include "vec.h" +#include "src/misc/vec/vec.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// diff --git a/src/opt/fxu/fxuInt.h b/src/opt/fxu/fxuInt.h index 402b7cdd..1ca081c9 100644 --- a/src/opt/fxu/fxuInt.h +++ b/src/opt/fxu/fxuInt.h @@ -16,16 +16,15 @@ ***********************************************************************/ -#ifndef __FXU_INT_H__ -#define __FXU_INT_H__ +#ifndef ABC__opt__fxu__fxuInt_h +#define ABC__opt__fxu__fxuInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" ABC_NAMESPACE_HEADER_START diff --git a/src/opt/fxu/fxuMatrix.c b/src/opt/fxu/fxuMatrix.c index a53de0a3..d032f7cd 100644 --- a/src/opt/fxu/fxuMatrix.c +++ b/src/opt/fxu/fxuMatrix.c @@ -25,8 +25,6 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -extern unsigned int Cudd_Prime( unsigned int p ); - //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -47,7 +45,7 @@ Fxu_Matrix * Fxu_MatrixAllocate() Fxu_Matrix * p; p = ABC_ALLOC( Fxu_Matrix, 1 ); memset( p, 0, sizeof(Fxu_Matrix) ); - p->nTableSize = Cudd_Prime(10000); + p->nTableSize = Abc_PrimeCudd(10000); p->pTable = ABC_ALLOC( Fxu_ListDouble, p->nTableSize ); memset( p->pTable, 0, sizeof(Fxu_ListDouble) * p->nTableSize ); #ifndef USE_SYSTEM_MEMORY_MANAGEMENT diff --git a/src/opt/fxu/fxuReduce.c b/src/opt/fxu/fxuReduce.c index b0e3e4a7..6d76576a 100644 --- a/src/opt/fxu/fxuReduce.c +++ b/src/opt/fxu/fxuReduce.c @@ -16,7 +16,7 @@ ***********************************************************************/ -#include "abc.h" +#include "src/base/abc/abc.h" #include "fxuInt.h" #include "fxu.h" diff --git a/src/opt/fxu/fxuSingle.c b/src/opt/fxu/fxuSingle.c index b1cc2e63..e4fd0c5c 100644 --- a/src/opt/fxu/fxuSingle.c +++ b/src/opt/fxu/fxuSingle.c @@ -17,7 +17,7 @@ ***********************************************************************/ #include "fxuInt.h" -#include "vec.h" +#include "src/misc/vec/vec.h" ABC_NAMESPACE_IMPL_START diff --git a/src/opt/lpk/lpk.h b/src/opt/lpk/lpk.h index 498da845..ebc18907 100644 --- a/src/opt/lpk/lpk.h +++ b/src/opt/lpk/lpk.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __LPK_H__ -#define __LPK_H__ +#ifndef ABC__opt__lpk__lpk_h +#define ABC__opt__lpk__lpk_h //////////////////////////////////////////////////////////////////////// diff --git a/src/opt/lpk/lpkAbcDsd.c b/src/opt/lpk/lpkAbcDsd.c index 34785941..2a6ba980 100644 --- a/src/opt/lpk/lpkAbcDsd.c +++ b/src/opt/lpk/lpkAbcDsd.c @@ -73,8 +73,8 @@ int Lpk_FunComputeMinSuppSizeVar( Lpk_Fun_t * p, unsigned ** ppTruths, int nTrut 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 ); + nSuppMaxCur = Abc_MaxInt( nSuppMaxCur, nSuppSize0 ); + nSuppMaxCur = Abc_MaxInt( nSuppMaxCur, nSuppSize1 ); nSuppTotalCur += nSuppSize0 + nSuppSize1; } if ( VarBest == -1 || nSuppMaxMin > nSuppMaxCur || @@ -110,9 +110,9 @@ unsigned Lpk_ComputeBoundSets_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) ); + pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit) ); if ( pObj == NULL ) - return (1 << Kit_DsdLit2Var(iLit)); + return (1 << Abc_Lit2Var(iLit)); if ( pObj->Type == KIT_DSD_AND || pObj->Type == KIT_DSD_XOR ) { unsigned uSupps[16], Limit, s; @@ -171,7 +171,7 @@ Vec_Int_t * Lpk_ComputeBoundSets( Kit_DsdNtk_t * p, int nSizeMax ) return vSets; if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_VAR ) { - uSupport = ( 1 << Kit_DsdLit2Var(Kit_DsdNtkRoot(p)->pFans[0]) ); + uSupport = ( 1 << Abc_Lit2Var(Kit_DsdNtkRoot(p)->pFans[0]) ); if ( Kit_WordCountOnes(uSupport) <= nSizeMax ) Vec_IntPush( vSets, uSupport ); return vSets; diff --git a/src/opt/lpk/lpkAbcMux.c b/src/opt/lpk/lpkAbcMux.c index 4e9cc654..1e4b6e22 100644 --- a/src/opt/lpk/lpkAbcMux.c +++ b/src/opt/lpk/lpkAbcMux.c @@ -66,13 +66,13 @@ Lpk_Res_t * Lpk_MuxAnalize( Lpk_Man_t * pMan, Lpk_Fun_t * p ) // 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 ); + Delay0 = Abc_MaxInt( 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 ); + Delay1 = Abc_MaxInt( DelayA, DelayB + 1 ); // get the best delay - Delay = ABC_MIN( Delay0, Delay1 ); + Delay = Abc_MinInt( Delay0, Delay1 ); Area = 2; Polarity = (int)(Delay == Delay1); } @@ -80,7 +80,7 @@ Lpk_Res_t * Lpk_MuxAnalize( Lpk_Man_t * pMan, Lpk_Fun_t * p ) { 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 ); + Delay = Abc_MaxInt( DelayA, DelayB + 1 ); Area = 1 + Lpk_LutNumLuts( nSuppSize1, p->nLutK ); Polarity = 0; } @@ -88,7 +88,7 @@ Lpk_Res_t * Lpk_MuxAnalize( Lpk_Man_t * pMan, Lpk_Fun_t * p ) { 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 ); + Delay = Abc_MaxInt( DelayA, DelayB + 1 ); Area = 1 + Lpk_LutNumLuts( nSuppSize0, p->nLutK ); Polarity = 1; } @@ -96,7 +96,7 @@ Lpk_Res_t * Lpk_MuxAnalize( Lpk_Man_t * pMan, Lpk_Fun_t * p ) { 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 ); + Delay = Abc_MaxInt( DelayA, DelayB + 1 ); Area = 1 + Lpk_LutNumLuts( nSuppSize1+2, p->nLutK ); Polarity = 1; } @@ -104,7 +104,7 @@ Lpk_Res_t * Lpk_MuxAnalize( Lpk_Man_t * pMan, Lpk_Fun_t * p ) { 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 ); + Delay = Abc_MaxInt( DelayA, DelayB + 1 ); Area = 1 + Lpk_LutNumLuts( nSuppSize0+2, p->nLutK ); Polarity = 0; } @@ -113,13 +113,13 @@ Lpk_Res_t * Lpk_MuxAnalize( Lpk_Man_t * pMan, Lpk_Fun_t * p ) // 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 ); + Delay0 = Abc_MaxInt( 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 ); + Delay1 = Abc_MaxInt( DelayA, DelayB + 1 ); // get the best delay - Delay = ABC_MIN( Delay0, Delay1 ); + Delay = Abc_MinInt( Delay0, Delay1 ); if ( Delay == Delay0 ) Area = Lpk_LutNumLuts( nSuppSize0+2, p->nLutK ) + Lpk_LutNumLuts( nSuppSize1, p->nLutK ); else @@ -131,8 +131,8 @@ Lpk_Res_t * Lpk_MuxAnalize( Lpk_Man_t * pMan, Lpk_Fun_t * p ) 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 ); + nSuppSizeS = Abc_MinInt( nSuppSize0 + 2 *!Polarity, nSuppSize1 + 2 * Polarity ); + nSuppSizeL = Abc_MaxInt( nSuppSize0 + 2 *!Polarity, nSuppSize1 + 2 * Polarity ); if ( nSuppSizeL > (int)p->nVars ) continue; if ( pRes->Variable == -1 || pRes->AreaEst > Area || diff --git a/src/opt/lpk/lpkAbcUtil.c b/src/opt/lpk/lpkAbcUtil.c index b086d35f..b96614d2 100644 --- a/src/opt/lpk/lpkAbcUtil.c +++ b/src/opt/lpk/lpkAbcUtil.c @@ -217,7 +217,7 @@ int Lpk_SuppDelay( unsigned uSupp, char * pDelays ) int Delay, Var; Delay = 0; Lpk_SuppForEachVar( uSupp, Var ) - Delay = ABC_MAX( Delay, pDelays[Var] ); + Delay = Abc_MaxInt( Delay, pDelays[Var] ); return Delay + 1; } diff --git a/src/opt/lpk/lpkCore.c b/src/opt/lpk/lpkCore.c index a4c9471d..51f05b21 100644 --- a/src/opt/lpk/lpkCore.c +++ b/src/opt/lpk/lpkCore.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "lpkInt.h" -#include "cloud.h" -#include "main.h" +#include "src/bool/kit/cloud.h" +#include "src/base/main/main.h" ABC_NAMESPACE_IMPL_START @@ -140,7 +140,7 @@ int Lpk_ExploreCut( Lpk_Man_t * p, Lpk_Cut_t * pCut, Kit_DsdNtk_t * pNtk ) pRoot = Kit_DsdNtkRoot( pNtk ); if ( pRoot->Type == KIT_DSD_CONST1 ) { - if ( Kit_DsdLitIsCompl(pNtk->Root) ) + if ( Abc_LitIsCompl(pNtk->Root) ) pObjNew = Abc_NtkCreateNodeConst0( p->pNtk ); else pObjNew = Abc_NtkCreateNodeConst1( p->pNtk ); @@ -150,8 +150,8 @@ int Lpk_ExploreCut( Lpk_Man_t * p, Lpk_Cut_t * pCut, Kit_DsdNtk_t * pNtk ) } 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_NtkObj( p->pNtk, pCut->pLeaves[ Abc_Lit2Var(pRoot->pFans[0]) ] ); + if ( Abc_LitIsCompl(pNtk->Root) ^ Abc_LitIsCompl(pRoot->pFans[0]) ) pObjNew = Abc_NtkCreateNodeInv( p->pNtk, pObjNew ); Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels ); p->nGainTotal += pCut->nNodes - pCut->nNodesDup; diff --git a/src/opt/lpk/lpkCut.c b/src/opt/lpk/lpkCut.c index a07372e6..c4be0c35 100644 --- a/src/opt/lpk/lpkCut.c +++ b/src/opt/lpk/lpkCut.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "lpkInt.h" -#include "cloud.h" +#include "src/bool/kit/cloud.h" ABC_NAMESPACE_IMPL_START diff --git a/src/opt/lpk/lpkInt.h b/src/opt/lpk/lpkInt.h index 5cb8c1a2..61fa1624 100644 --- a/src/opt/lpk/lpkInt.h +++ b/src/opt/lpk/lpkInt.h @@ -18,17 +18,17 @@ ***********************************************************************/ -#ifndef __LPK_INT_H__ -#define __LPK_INT_H__ +#ifndef ABC__opt__lpk__lpkInt_h +#define ABC__opt__lpk__lpkInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// -#include "abc.h" -#include "kit.h" -#include "if.h" +#include "src/base/abc/abc.h" +#include "src/bool/kit/kit.h" +#include "src/map/if/if.h" #include "lpk.h" //////////////////////////////////////////////////////////////////////// diff --git a/src/opt/lpk/lpkMap.c b/src/opt/lpk/lpkMap.c index c6c6b233..28780bc1 100644 --- a/src/opt/lpk/lpkMap.c +++ b/src/opt/lpk/lpkMap.c @@ -116,20 +116,20 @@ If_Obj_t * Lpk_MapTree_rec( Lpk_Man_t * p, Kit_DsdNtk_t * pNtk, If_Obj_t ** ppLe assert( iLit >= 0 ); // consider the case of a gate - pObj = Kit_DsdNtkObj( pNtk, Kit_DsdLit2Var(iLit) ); + pObj = Kit_DsdNtkObj( pNtk, Abc_Lit2Var(iLit) ); if ( pObj == NULL ) { - pObjNew = ppLeaves[Kit_DsdLit2Var(iLit)]; - return If_NotCond( pObjNew, Kit_DsdLitIsCompl(iLit) ); + pObjNew = ppLeaves[Abc_Lit2Var(iLit)]; + return If_NotCond( pObjNew, Abc_LitIsCompl(iLit) ); } if ( pObj->Type == KIT_DSD_CONST1 ) { - return If_NotCond( If_ManConst1(p->pIfMan), Kit_DsdLitIsCompl(iLit) ); + return If_NotCond( If_ManConst1(p->pIfMan), Abc_LitIsCompl(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]) ); + pObjNew = ppLeaves[Abc_Lit2Var(pObj->pFans[0])]; + return If_NotCond( pObjNew, Abc_LitIsCompl(iLit) ^ Abc_LitIsCompl(pObj->pFans[0]) ); } if ( pObj->Type == KIT_DSD_AND ) { @@ -139,11 +139,11 @@ If_Obj_t * Lpk_MapTree_rec( Lpk_Man_t * p, Kit_DsdNtk_t * pNtk, If_Obj_t ** ppLe 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) ); + return If_NotCond( pObjNew, Abc_LitIsCompl(iLit) ); } if ( pObj->Type == KIT_DSD_XOR ) { - int fCompl = Kit_DsdLitIsCompl(iLit); + int fCompl = Abc_LitIsCompl(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 ); @@ -170,7 +170,7 @@ If_Obj_t * Lpk_MapTree_rec( Lpk_Man_t * p, Kit_DsdNtk_t * pNtk, If_Obj_t ** ppLe 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) ); + return If_NotCond( pObjNew, Abc_LitIsCompl(iLit) ); } */ /* @@ -178,7 +178,7 @@ If_Obj_t * Lpk_MapTree_rec( Lpk_Man_t * p, Kit_DsdNtk_t * pNtk, If_Obj_t ** ppLe { pObjNew2 = Lpk_MapTreeMux_rec( p, Kit_DsdObjTruth(pObj), pObj->nFans, pFansNew ); // if ( pObjNew2 ) -// return If_NotCond( pObjNew2, Kit_DsdLitIsCompl(iLit) ); +// return If_NotCond( pObjNew2, Abc_LitIsCompl(iLit) ); } */ @@ -187,7 +187,7 @@ If_Obj_t * Lpk_MapTree_rec( Lpk_Man_t * p, Kit_DsdNtk_t * pNtk, If_Obj_t ** ppLe { pObjNew2 = Lpk_MapSuppRedDec_rec( p, Kit_DsdObjTruth(pObj), pObj->nFans, pFansNew ); if ( pObjNew2 ) - return If_NotCond( pObjNew2, Kit_DsdLitIsCompl(iLit) ); + return If_NotCond( pObjNew2, Abc_LitIsCompl(iLit) ); } pObjNew = Lpk_MapPrime( p, Kit_DsdObjTruth(pObj), pObj->nFans, pFansNew ); @@ -198,7 +198,7 @@ If_Obj_t * Lpk_MapTree_rec( Lpk_Man_t * p, Kit_DsdNtk_t * pNtk, If_Obj_t ** ppLe If_ObjSetChoice( If_Regular(pObjNew), If_Regular(pObjNew2) ); If_ManCreateChoice( p->pIfMan, If_Regular(pObjNew) ); } - return If_NotCond( pObjNew, Kit_DsdLitIsCompl(iLit) ); + return If_NotCond( pObjNew, Abc_LitIsCompl(iLit) ); } //////////////////////////////////////////////////////////////////////// diff --git a/src/opt/lpk/lpkMulti.c b/src/opt/lpk/lpkMulti.c index cce154ee..d2bdcf45 100644 --- a/src/opt/lpk/lpkMulti.c +++ b/src/opt/lpk/lpkMulti.c @@ -57,7 +57,7 @@ void Lpk_CreateVarOrder( Kit_DsdNtk_t * pNtk, char pTable[][16] ) Kit_DsdObjForEachFanin( pNtk, pObj, iFaninLit, k ) { if ( Kit_DsdLitIsLeaf( pNtk, iFaninLit ) ) - Above[nAbove++] = Kit_DsdLit2Var(iFaninLit); + Above[nAbove++] = Abc_Lit2Var(iFaninLit); else uSuppFanins |= Kit_DsdLitSupport( pNtk, iFaninLit ); } @@ -190,7 +190,7 @@ int Lpk_FindHighest( Kit_DsdNtk_t ** ppNtks, int * piLits, int nSize, int * pPri uSupps[i] = Kit_DsdLitSupport( ppNtks[i], piLits[i] ); else { - pObj = Kit_DsdNtkObj( ppNtks[i], Kit_DsdLit2Var(piLits[i]) ); + pObj = Kit_DsdNtkObj( ppNtks[i], Abc_Lit2Var(piLits[i]) ); if ( pObj->Type == KIT_DSD_PRIME ) { pTriv[i] = 0; @@ -292,7 +292,7 @@ If_Obj_t * Lpk_MapTreeMulti_rec( Lpk_Man_t * p, Kit_DsdNtk_t ** ppNtks, int * pi if ( p->pPars->fVeryVerbose ) printf( "%d ", i ); assert( piLits[i] >= 0 ); - pObj = Kit_DsdNtkObj( ppNtks[i], Kit_DsdLit2Var(piLits[i]) ); + pObj = Kit_DsdNtkObj( ppNtks[i], Abc_Lit2Var(piLits[i]) ); if ( pObj == NULL ) piLitsNew[i] = -2; else if ( pObj->Type == KIT_DSD_PRIME ) @@ -464,9 +464,9 @@ If_Obj_t * Lpk_MapTreeMulti( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj // collect the roots pRoot = Kit_DsdNtkRoot(ppNtks[i]); if ( pRoot->Type == KIT_DSD_CONST1 ) - piLits[i] = Kit_DsdLitIsCompl(ppNtks[i]->Root)? -2: -1; + piLits[i] = Abc_LitIsCompl(ppNtks[i]->Root)? -2: -1; else if ( pRoot->Type == KIT_DSD_VAR ) - piLits[i] = Kit_DsdLitNotCond( pRoot->pFans[0], Kit_DsdLitIsCompl(ppNtks[i]->Root) ); + piLits[i] = Abc_LitNotCond( pRoot->pFans[0], Abc_LitIsCompl(ppNtks[i]->Root) ); else piLits[i] = ppNtks[i]->Root; } diff --git a/src/opt/lpk/lpkSets.c b/src/opt/lpk/lpkSets.c index 65b23ea9..980a49e3 100644 --- a/src/opt/lpk/lpkSets.c +++ b/src/opt/lpk/lpkSets.c @@ -58,9 +58,9 @@ 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) ); + pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit) ); if ( pObj == NULL ) - return (1 << Kit_DsdLit2Var(iLit)); + return (1 << Abc_Lit2Var(iLit)); if ( pObj->Type == KIT_DSD_AND || pObj->Type == KIT_DSD_XOR ) { unsigned uSupps[16], Limit, s; @@ -116,7 +116,7 @@ unsigned Lpk_ComputeSets( Kit_DsdNtk_t * p, Vec_Int_t * vSets ) return 0; if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_VAR ) { - uSupport = ( 1 << Kit_DsdLit2Var(Kit_DsdNtkRoot(p)->pFans[0]) ); + uSupport = ( 1 << Abc_Lit2Var(Kit_DsdNtkRoot(p)->pFans[0]) ); Vec_IntPush( vSets, uSupport ); return uSupport; } diff --git a/src/opt/mfs/mfs.h b/src/opt/mfs/mfs.h index 02fcc21b..9916b582 100644 --- a/src/opt/mfs/mfs.h +++ b/src/opt/mfs/mfs.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __MFS_H__ -#define __MFS_H__ +#ifndef ABC__opt__mfs__mfs_h +#define ABC__opt__mfs__mfs_h //////////////////////////////////////////////////////////////////////// diff --git a/src/opt/mfs/mfsGia.c b/src/opt/mfs/mfsGia.c index af6cc159..07c258ab 100644 --- a/src/opt/mfs/mfsGia.c +++ b/src/opt/mfs/mfsGia.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "mfsInt.h" -#include "giaAig.h" +#include "aig/gia/giaAig.h" ABC_NAMESPACE_IMPL_START diff --git a/src/opt/mfs/mfsInt.h b/src/opt/mfs/mfsInt.h index 650a154a..fe154093 100644 --- a/src/opt/mfs/mfsInt.h +++ b/src/opt/mfs/mfsInt.h @@ -18,23 +18,22 @@ ***********************************************************************/ -#ifndef __MFS_INT_H__ -#define __MFS_INT_H__ +#ifndef ABC__opt__mfs__mfsInt_h +#define ABC__opt__mfs__mfsInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" #include "mfs.h" -#include "aig.h" -#include "cnf.h" -#include "satSolver.h" -#include "satStore.h" -#include "bdc.h" -#include "gia.h" +#include "src/aig/aig/aig.h" +#include "src/sat/cnf/cnf.h" +#include "src/sat/bsat/satSolver.h" +#include "src/sat/bsat/satStore.h" +#include "src/bool/bdc/bdc.h" +#include "src/aig/gia/gia.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// diff --git a/src/opt/mfs/mfsInter.c b/src/opt/mfs/mfsInter.c index 0934513b..d18613c7 100644 --- a/src/opt/mfs/mfsInter.c +++ b/src/opt/mfs/mfsInter.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "mfsInt.h" -#include "kit.h" +#include "src/bool/kit/kit.h" ABC_NAMESPACE_IMPL_START diff --git a/src/opt/mfs/mfsMan.c b/src/opt/mfs/mfsMan.c index df331b43..caa82e68 100644 --- a/src/opt/mfs/mfsMan.c +++ b/src/opt/mfs/mfsMan.c @@ -52,7 +52,7 @@ Mfs_Man_t * Mfs_ManAlloc( Mfs_Par_t * pPars ) p->vProjVarsCnf = Vec_IntAlloc( 100 ); p->vProjVarsSat = Vec_IntAlloc( 100 ); p->vDivLits = Vec_IntAlloc( 100 ); - p->nDivWords = Aig_BitWordNum(p->pPars->nDivMax + MFS_FANIN_MAX); + p->nDivWords = Abc_BitWordNum(p->pPars->nDivMax + MFS_FANIN_MAX); p->vDivCexes = Vec_PtrAllocSimInfo( p->pPars->nDivMax+MFS_FANIN_MAX+1, p->nDivWords ); p->pMan = Int_ManAlloc(); p->vMem = Vec_IntAlloc( 0 ); diff --git a/src/opt/mfs/mfsResub.c b/src/opt/mfs/mfsResub.c index 40cb6198..45f75674 100644 --- a/src/opt/mfs/mfsResub.c +++ b/src/opt/mfs/mfsResub.c @@ -142,8 +142,8 @@ p->timeGia += clock() - clk; pData = (unsigned *)Vec_PtrEntry( p->vDivCexes, i ); if ( !sat_solver_var_value( p->pSat, iVar ) ) // remove 0s!!! { - assert( Aig_InfoHasBit(pData, p->nCexes) ); - Aig_InfoXorBit( pData, p->nCexes ); + assert( Abc_InfoHasBit(pData, p->nCexes) ); + Abc_InfoXorBit( pData, p->nCexes ); } } p->nCexes++; @@ -242,13 +242,13 @@ p->timeInt += clock() - clk; for ( i = 0; i < Vec_PtrSize(p->vDivs); i++ ) { pData = (unsigned *)Vec_PtrEntry( p->vDivCexes, i ); - printf( "%d", Aig_InfoHasBit(pData, p->nCexes-1) ); + printf( "%d", Abc_InfoHasBit(pData, p->nCexes-1) ); } printf( "\n" ); } // find the next divisor to try - nWords = Aig_BitWordNum(p->nCexes); + nWords = Abc_BitWordNum(p->nCexes); assert( nWords <= p->nDivWords ); for ( iVar = 0; iVar < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); iVar++ ) { @@ -387,13 +387,13 @@ p->timeInt += clock() - clk; for ( i = 0; i < Vec_PtrSize(p->vDivs); i++ ) { pData = (unsigned *)Vec_PtrEntry( p->vDivCexes, i ); - printf( "%d", Aig_InfoHasBit(pData, p->nCexes-1) ); + printf( "%d", Abc_InfoHasBit(pData, p->nCexes-1) ); } printf( "\n" ); } // find the next divisor to try - nWords = Aig_BitWordNum(p->nCexes); + nWords = Abc_BitWordNum(p->nCexes); assert( nWords <= p->nDivWords ); fBreak = 0; for ( iVar = 1; iVar < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); iVar++ ) diff --git a/src/opt/mfs/mfsSat.c b/src/opt/mfs/mfsSat.c index 37ee2b39..e5e9de1a 100644 --- a/src/opt/mfs/mfsSat.c +++ b/src/opt/mfs/mfsSat.c @@ -72,8 +72,8 @@ int Abc_NtkMfsSolveSat_iter( Mfs_Man_t * p ) Lits[b] = lit_neg( Lits[b] ); } } - assert( !Aig_InfoHasBit(p->uCare, Mint) ); - Aig_InfoSetBit( p->uCare, Mint ); + assert( !Abc_InfoHasBit(p->uCare, Mint) ); + Abc_InfoSetBit( p->uCare, Mint ); // add the blocking clause RetValue = sat_solver_addclause( p->pSat, Lits, Lits + Vec_IntSize(p->vProjVarsSat) ); if ( RetValue == 0 ) @@ -106,7 +106,7 @@ int Abc_NtkMfsSolveSat( Mfs_Man_t * p, Abc_Obj_t * pNode ) // prepare the truth table of care set p->nFanins = Vec_IntSize( p->vProjVarsSat ); - p->nWords = Aig_TruthWordNum( p->nFanins ); + p->nWords = Abc_TruthWordNum( p->nFanins ); memset( p->uCare, 0, sizeof(unsigned) * p->nWords ); // iterate through the SAT assignments diff --git a/src/opt/mfs/mfsStrash.c b/src/opt/mfs/mfsStrash.c index a5c7b987..922af3a8 100644 --- a/src/opt/mfs/mfsStrash.c +++ b/src/opt/mfs/mfsStrash.c @@ -367,7 +367,7 @@ Aig_Man_t * Abc_NtkAigForConstraints( Mfs_Man_t * p, Abc_Obj_t * pNode ) ABC_NAMESPACE_IMPL_END -#include "fra.h" +#include "src/proof/fra/fra.h" ABC_NAMESPACE_IMPL_START diff --git a/src/opt/nwk/module.make b/src/opt/nwk/module.make new file mode 100644 index 00000000..13812d68 --- /dev/null +++ b/src/opt/nwk/module.make @@ -0,0 +1,14 @@ +SRC += src/opt/nwk/nwkAig.c \ + src/opt/nwk/nwkCheck.c \ + src/opt/nwk/nwkBidec.c \ + src/opt/nwk/nwkDfs.c \ + src/opt/nwk/nwkFanio.c \ + src/opt/nwk/nwkFlow.c \ + src/opt/nwk/nwkMan.c \ + src/opt/nwk/nwkMap.c \ + src/opt/nwk/nwkMerge.c \ + src/opt/nwk/nwkObj.c \ + src/opt/nwk/nwkSpeedup.c \ + src/opt/nwk/nwkStrash.c \ + src/opt/nwk/nwkTiming.c \ + src/opt/nwk/nwkUtil.c diff --git a/src/opt/nwk/ntlnwk.h b/src/opt/nwk/ntlnwk.h new file mode 100644 index 00000000..5300e6f4 --- /dev/null +++ b/src/opt/nwk/ntlnwk.h @@ -0,0 +1,113 @@ +/**CFile**************************************************************** + + FileName [ntlnwk.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Netlist and network representation.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ntlnwk.h,v 1.3 2008/10/24 14:18:44 mjarvin Exp $] + +***********************************************************************/ + +#ifndef __NTLNWK_abc_opt_nwk_h +#define __NTLNWK_abc_opt_nwk_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Ntl_Man_t_ Ntl_Man_t; +typedef struct Nwk_Man_t_ Nwk_Man_t; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// INLINED FUNCTIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern ABC_DLL Ntl_Man_t * Ntl_ManReadBlif( char * pFileName, int fCheck ); +extern ABC_DLL void Ntl_ManWriteBlif( Ntl_Man_t * p, char * pFileName ); + +extern ABC_DLL Tim_Man_t * Ntl_ManReadTimeMan( Ntl_Man_t * p ); +extern ABC_DLL Ntl_Man_t * Ntl_ManDup( Ntl_Man_t * p ); +extern ABC_DLL void Ntl_ManFree( Ntl_Man_t * p ); +extern ABC_DLL int Ntl_ManIsComb( Ntl_Man_t * p ); +extern ABC_DLL void Ntl_ManPrintStats( Ntl_Man_t * p ); +extern ABC_DLL int Ntl_ManSweep( Ntl_Man_t * p, int fVerbose ); +extern ABC_DLL Ntl_Man_t * Ntl_ManInsertNtk( Ntl_Man_t * p, Nwk_Man_t * pNtk ); +extern ABC_DLL Ntl_Man_t * Ntl_ManInsertAig( Ntl_Man_t * p, Aig_Man_t * pAig ); +extern ABC_DLL Aig_Man_t * Ntl_ManExtract( Ntl_Man_t * p ); +extern ABC_DLL Aig_Man_t * Ntl_ManCollapse( Ntl_Man_t * p, int fSeq ); +extern ABC_DLL Aig_Man_t * Ntl_ManCollapseSeq( Ntl_Man_t * p, int nMinDomSize, int fVerbose ); +extern ABC_DLL Ntl_Man_t * Ntl_ManDupCollapseLuts( Ntl_Man_t * p ); +extern ABC_DLL Ntl_Man_t * Ntl_ManFraig( Ntl_Man_t * p, int nPartSize, int nConfLimit, int nLevelMax, int fUseCSat, int fVerbose ); +extern ABC_DLL void Ntl_ManPrepareCecMans( Ntl_Man_t * pMan1, Ntl_Man_t * pMan2, Aig_Man_t ** ppAig1, Aig_Man_t ** ppAig2 ); +extern ABC_DLL Vec_Ptr_t * Ntl_ManCollectCiNames( Ntl_Man_t * p ); +extern ABC_DLL Vec_Ptr_t * Ntl_ManCollectCoNames( Ntl_Man_t * p ); +extern ABC_DLL Ntl_Man_t * Ntl_ManScl( Ntl_Man_t * p, int fLatchConst, int fLatchEqual, int fVerbose ); +extern ABC_DLL Ntl_Man_t * Ntl_ManLcorr( Ntl_Man_t * p, int nConfMax, int fScorrGia, int fUseCSat, int fVerbose ); +extern ABC_DLL Ntl_Man_t * Ntl_ManSsw( Ntl_Man_t * p, Fra_Ssw_t * pPars ); +extern ABC_DLL Ntl_Man_t * Ntl_ManScorr( Ntl_Man_t * p, Ssw_Pars_t * pPars ); +extern ABC_DLL void Ntl_ManTransformInitValues( Ntl_Man_t * p ); + +extern ABC_DLL void Ntl_ManPrepareCec( char * pFileName1, char * pFileName2, Aig_Man_t ** ppMan1, Aig_Man_t ** ppMan2 ); +extern ABC_DLL Aig_Man_t * Ntl_ManPrepareSec( char * pFileName1, char * pFileName2 ); + +extern ABC_DLL Nwk_Man_t * Ntl_ManExtractNwk( Ntl_Man_t * p, Aig_Man_t * pAig, Tim_Man_t * pManTime ); +extern ABC_DLL Nwk_Man_t * Ntl_ManReadNwk( char * pFileName, Aig_Man_t * pAig, Tim_Man_t * pManTime ); +extern ABC_DLL void Nwk_ManPrintStats( Nwk_Man_t * p, If_Lib_t * pLutLib, int fSaveBest, int fDumpResult, int fPower, Ntl_Man_t * pNtl ); +extern ABC_DLL void Nwk_ManPrintStatsShort( Ntl_Man_t * p, Aig_Man_t * pAig, Nwk_Man_t * pNtk ); +extern ABC_DLL void Nwk_ManPrintFanioNew( Nwk_Man_t * p ); +extern ABC_DLL Nwk_Man_t * Nwk_MappingIf( Aig_Man_t * p, Tim_Man_t * pManTime, If_Par_t * pPars ); +extern ABC_DLL void Nwk_ManSetIfParsDefault( If_Par_t * pPars ); +extern ABC_DLL void Nwk_ManBidecResyn( Nwk_Man_t * p, int fVerbose ); +extern ABC_DLL Aig_Man_t * Nwk_ManSpeedup( Nwk_Man_t * p, int fUseLutLib, int Percentage, int Degree, int fVerbose, int fVeryVerbose ); +extern ABC_DLL Aig_Man_t * Nwk_ManStrash( Nwk_Man_t * p ); +extern ABC_DLL Vec_Int_t * Nwk_ManLutMerge( Nwk_Man_t * p, void * pPars ); +extern ABC_DLL int Nwk_ManCheck( Nwk_Man_t * p ); +extern ABC_DLL void Nwk_ManDumpBlif( Nwk_Man_t * p, char * pFileName, Vec_Ptr_t * vCiNames, Vec_Ptr_t * vCoNames ); +extern ABC_DLL void Nwk_ManFree( Nwk_Man_t * p ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/opt/nwk/nwk.h b/src/opt/nwk/nwk.h new file mode 100644 index 00000000..79c7bb1a --- /dev/null +++ b/src/opt/nwk/nwk.h @@ -0,0 +1,307 @@ +/**CFile**************************************************************** + + FileName [nwk.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Logic network representation.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: nwk.h,v 1.1 2008/05/14 22:13:09 wudenni Exp $] + +***********************************************************************/ + +#ifndef __NWK_abc_opt_nwk_h +#define __NWK_abc_opt_nwk_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "src/aig/aig/aig.h" +#include "src/aig/hop/hop.h" +#include "src/misc/tim/tim.h" +#include "src/map/if/if.h" +#include "src/bool/bdc/bdc.h" + +#include "src/proof/fra/fra.h" +#include "src/proof/ssw/ssw.h" +#include "ntlnwk.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_HEADER_START + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Nwk_Obj_t_ Nwk_Obj_t; + +// object types +typedef enum { + NWK_OBJ_NONE, // 0: non-existant object + NWK_OBJ_CI, // 1: combinational input + NWK_OBJ_CO, // 2: combinational output + NWK_OBJ_NODE, // 3: logic node + NWK_OBJ_LATCH, // 4: register + NWK_OBJ_VOID // 5: unused object +} Nwk_Type_t; + +struct Nwk_Man_t_ +{ + // models of this design + char * pName; // the name of this design + char * pSpec; // the name of input file + // node 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 * vObjs; // the objects in the topological order + int nObjs[NWK_OBJ_VOID]; // counter of objects of each type + int nFanioPlus; // the number of extra fanins/fanouts alloc by default + // functionality, timing, memory, etc + Hop_Man_t * pManHop; // the functionality representation + Tim_Man_t * pManTime; // the timing manager + If_Lib_t * pLutLib; // the LUT library + Aig_MmFlex_t * pMemObjs; // memory for objects + Vec_Ptr_t * vTemp; // array used for incremental updates + int nTravIds; // the counter of traversal IDs + int nRealloced; // the number of realloced nodes + // sequential information + int nLatches; // the total number of latches + int nTruePis; // the number of true primary inputs + int nTruePos; // the number of true primary outputs +}; + +struct Nwk_Obj_t_ +{ + Nwk_Man_t * pMan; // the manager + Hop_Obj_t * pFunc; // functionality + void * pCopy; // temporary pointer + union { + void * pNext; // temporary pointer + int iTemp; // temporary number + }; + // node information + unsigned Type : 3; // object type + unsigned fInvert : 1; // complemented attribute + unsigned MarkA : 1; // temporary mark + unsigned MarkB : 1; // temporary mark + unsigned MarkC : 1; // temporary mark + unsigned PioId : 25; // number of this node in the PI/PO list + int Id; // unique ID + int TravId; // traversal ID + // timing information + int Level; // the topological level + float tArrival; // the arrival time + float tRequired; // the required time + float tSlack; // the slack + // fanin/fanout representation + int nFanins; // the number of fanins + int nFanouts; // the number of fanouts + int nFanioAlloc; // the number of allocated fanins/fanouts + Nwk_Obj_t ** pFanio; // fanins/fanouts +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +/// INLINED FUNCTIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Nwk_ManCiNum( Nwk_Man_t * p ) { return p->nObjs[NWK_OBJ_CI]; } +static inline int Nwk_ManCoNum( Nwk_Man_t * p ) { return p->nObjs[NWK_OBJ_CO]; } +static inline int Nwk_ManNodeNum( Nwk_Man_t * p ) { return p->nObjs[NWK_OBJ_NODE]; } +static inline int Nwk_ManLatchNum( Nwk_Man_t * p ) { return p->nObjs[NWK_OBJ_LATCH]; } +static inline int Nwk_ManObjNumMax( Nwk_Man_t * p ) { return Vec_PtrSize(p->vObjs); } + +static inline Nwk_Obj_t * Nwk_ManCi( Nwk_Man_t * p, int i ) { return (Nwk_Obj_t *)Vec_PtrEntry( p->vCis, i ); } +static inline Nwk_Obj_t * Nwk_ManCo( Nwk_Man_t * p, int i ) { return (Nwk_Obj_t *)Vec_PtrEntry( p->vCos, i ); } +static inline Nwk_Obj_t * Nwk_ManObj( Nwk_Man_t * p, int i ) { return (Nwk_Obj_t *)Vec_PtrEntry( p->vObjs, i ); } + +static inline int Nwk_ObjId( Nwk_Obj_t * p ) { return p->Id; } +static inline int Nwk_ObjPioNum( Nwk_Obj_t * p ) { return p->PioId; } +static inline int Nwk_ObjFaninNum( Nwk_Obj_t * p ) { return p->nFanins; } +static inline int Nwk_ObjFanoutNum( Nwk_Obj_t * p ) { return p->nFanouts; } + +static inline Nwk_Obj_t * Nwk_ObjFanin0( Nwk_Obj_t * p ) { return p->pFanio[0]; } +static inline Nwk_Obj_t * Nwk_ObjFanout0( Nwk_Obj_t * p ) { return p->pFanio[p->nFanins]; } +static inline Nwk_Obj_t * Nwk_ObjFanin( Nwk_Obj_t * p, int i ) { return p->pFanio[i]; } +static inline Nwk_Obj_t * Nwk_ObjFanout( Nwk_Obj_t * p, int i ) { return p->pFanio[p->nFanins+1]; } + +static inline int Nwk_ObjIsNone( Nwk_Obj_t * p ) { return p->Type == NWK_OBJ_NONE; } +static inline int Nwk_ObjIsCi( Nwk_Obj_t * p ) { return p->Type == NWK_OBJ_CI; } +static inline int Nwk_ObjIsCo( Nwk_Obj_t * p ) { return p->Type == NWK_OBJ_CO; } +static inline int Nwk_ObjIsNode( Nwk_Obj_t * p ) { return p->Type == NWK_OBJ_NODE; } +static inline int Nwk_ObjIsLatch( Nwk_Obj_t * p ) { return p->Type == NWK_OBJ_LATCH; } +static inline int Nwk_ObjIsPi( Nwk_Obj_t * p ) { return Nwk_ObjIsCi(p) && (p->pMan->pManTime == NULL || Tim_ManBoxForCi(p->pMan->pManTime, p->PioId) == -1); } +static inline int Nwk_ObjIsPo( Nwk_Obj_t * p ) { return Nwk_ObjIsCo(p) && (p->pMan->pManTime == NULL || Tim_ManBoxForCo(p->pMan->pManTime, p->PioId) == -1); } +static inline int Nwk_ObjIsLi( Nwk_Obj_t * p ) { return p->pMan->nTruePos && Nwk_ObjIsCo(p) && (int)p->PioId >= p->pMan->nTruePos; } +static inline int Nwk_ObjIsLo( Nwk_Obj_t * p ) { return p->pMan->nTruePis && Nwk_ObjIsCi(p) && (int)p->PioId >= p->pMan->nTruePis; } + +static inline float Nwk_ObjArrival( Nwk_Obj_t * pObj ) { return pObj->tArrival; } +static inline float Nwk_ObjRequired( Nwk_Obj_t * pObj ) { return pObj->tRequired; } +static inline float Nwk_ObjSlack( Nwk_Obj_t * pObj ) { return pObj->tSlack; } +static inline void Nwk_ObjSetArrival( Nwk_Obj_t * pObj, float Time ) { pObj->tArrival = Time; } +static inline void Nwk_ObjSetRequired( Nwk_Obj_t * pObj, float Time ) { pObj->tRequired = Time; } +static inline void Nwk_ObjSetSlack( Nwk_Obj_t * pObj, float Time ) { pObj->tSlack = Time; } + +static inline int Nwk_ObjLevel( Nwk_Obj_t * pObj ) { return pObj->Level; } +static inline void Nwk_ObjSetLevel( Nwk_Obj_t * pObj, int Level ) { pObj->Level = Level; } + +static inline void Nwk_ObjSetTravId( Nwk_Obj_t * pObj, int TravId ) { pObj->TravId = TravId; } +static inline void Nwk_ObjSetTravIdCurrent( Nwk_Obj_t * pObj ) { pObj->TravId = pObj->pMan->nTravIds; } +static inline void Nwk_ObjSetTravIdPrevious( Nwk_Obj_t * pObj ) { pObj->TravId = pObj->pMan->nTravIds - 1; } +static inline int Nwk_ObjIsTravIdCurrent( Nwk_Obj_t * pObj ) { return pObj->TravId == pObj->pMan->nTravIds; } +static inline int Nwk_ObjIsTravIdPrevious( Nwk_Obj_t * pObj ) { return pObj->TravId == pObj->pMan->nTravIds - 1; } + +static inline int Nwk_ManTimeEqual( float f1, float f2, float Eps ) { return (f1 < f2 + Eps) && (f2 < f1 + Eps); } +static inline int Nwk_ManTimeLess( float f1, float f2, float Eps ) { return (f1 < f2 + Eps); } +static inline int Nwk_ManTimeMore( float f1, float f2, float Eps ) { return (f1 + Eps > f2); } + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +#define Nwk_ManForEachCi( p, pObj, i ) \ + Vec_PtrForEachEntry( Nwk_Obj_t *, p->vCis, pObj, i ) +#define Nwk_ManForEachCo( p, pObj, i ) \ + Vec_PtrForEachEntry( Nwk_Obj_t *, p->vCos, pObj, i ) +#define Nwk_ManForEachPi( p, pObj, i ) \ + Vec_PtrForEachEntry( Nwk_Obj_t *, p->vCis, pObj, i ) \ + if ( !Nwk_ObjIsPi(pObj) ) {} else +#define Nwk_ManForEachPo( p, pObj, i ) \ + Vec_PtrForEachEntry( Nwk_Obj_t *, p->vCos, pObj, i ) \ + if ( !Nwk_ObjIsPo(pObj) ) {} else +#define Nwk_ManForEachObj( p, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize(p->vObjs)) && (((pObj) = (Nwk_Obj_t *)Vec_PtrEntry(p->vObjs, i)), 1); i++ ) \ + if ( pObj == NULL ) {} else +#define Nwk_ManForEachNode( p, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize(p->vObjs)) && (((pObj) = (Nwk_Obj_t *)Vec_PtrEntry(p->vObjs, i)), 1); i++ ) \ + if ( (pObj) == NULL || !Nwk_ObjIsNode(pObj) ) {} else +#define Nwk_ManForEachLatch( p, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize(p->vObjs)) && (((pObj) = (Nwk_Obj_t *)Vec_PtrEntry(p->vObjs, i)), 1); i++ ) \ + if ( (pObj) == NULL || !Nwk_ObjIsLatch(pObj) ) {} else + +#define Nwk_ObjForEachFanin( pObj, pFanin, i ) \ + for ( i = 0; (i < (int)(pObj)->nFanins) && ((pFanin) = (pObj)->pFanio[i]); i++ ) +#define Nwk_ObjForEachFanout( pObj, pFanout, i ) \ + for ( i = 0; (i < (int)(pObj)->nFanouts) && ((pFanout) = (pObj)->pFanio[(pObj)->nFanins+i]); i++ ) + +// sequential iterators +#define Nwk_ManForEachPiSeq( p, pObj, i ) \ + Vec_PtrForEachEntryStop( Nwk_Obj_t *, p->vCis, pObj, i, (p)->nTruePis ) +#define Nwk_ManForEachPoSeq( p, pObj, i ) \ + Vec_PtrForEachEntryStop( Nwk_Obj_t *, p->vCos, pObj, i, (p)->nTruePos ) +#define Nwk_ManForEachLoSeq( p, pObj, i ) \ + for ( i = 0; (i < (p)->nLatches) && (((pObj) = (Nwk_Obj_t *)Vec_PtrEntry(p->vCis, i+(p)->nTruePis)), 1); i++ ) +#define Nwk_ManForEachLiSeq( p, pObj, i ) \ + for ( i = 0; (i < (p)->nLatches) && (((pObj) = (Nwk_Obj_t *)Vec_PtrEntry(p->vCos, i+(p)->nTruePos)), 1); i++ ) +#define Nwk_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) \ + for ( i = 0; (i < (p)->nLatches) && (((pObjLi) = Nwk_ManCo(p, i+(p)->nTruePos)), 1) \ + && (((pObjLo) = Nwk_ManCi(p, i+(p)->nTruePis)), 1); i++ ) + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== nwkAig.c ==========================================================*/ +extern ABC_DLL Vec_Ptr_t * Nwk_ManDeriveRetimingCut( Aig_Man_t * p, int fForward, int fVerbose ); +/*=== nwkBidec.c ==========================================================*/ +extern ABC_DLL void Nwk_ManBidecResyn( Nwk_Man_t * pNtk, int fVerbose ); +extern ABC_DLL Hop_Obj_t * Nwk_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare, float dProb ); +/*=== nwkCheck.c ==========================================================*/ +extern ABC_DLL int Nwk_ManCheck( Nwk_Man_t * p ); +/*=== nwkDfs.c ==========================================================*/ +extern ABC_DLL int Nwk_ManVerifyTopoOrder( Nwk_Man_t * pNtk ); +extern ABC_DLL int Nwk_ManLevelBackup( Nwk_Man_t * pNtk ); +extern ABC_DLL int Nwk_ManLevel( Nwk_Man_t * pNtk ); +extern ABC_DLL int Nwk_ManLevelMax( Nwk_Man_t * pNtk ); +extern ABC_DLL Vec_Vec_t * Nwk_ManLevelize( Nwk_Man_t * pNtk ); +extern ABC_DLL Vec_Ptr_t * Nwk_ManDfs( Nwk_Man_t * pNtk ); +extern ABC_DLL Vec_Ptr_t * Nwk_ManDfsNodes( Nwk_Man_t * pNtk, Nwk_Obj_t ** ppNodes, int nNodes ); +extern ABC_DLL Vec_Ptr_t * Nwk_ManDfsReverse( Nwk_Man_t * pNtk ); +extern ABC_DLL Vec_Ptr_t * Nwk_ManSupportNodes( Nwk_Man_t * pNtk, Nwk_Obj_t ** ppNodes, int nNodes ); +extern ABC_DLL void Nwk_ManSupportSum( Nwk_Man_t * pNtk ); +extern ABC_DLL int Nwk_ObjMffcLabel( Nwk_Obj_t * pNode ); +/*=== nwkFanio.c ==========================================================*/ +extern ABC_DLL void Nwk_ObjCollectFanins( Nwk_Obj_t * pNode, Vec_Ptr_t * vNodes ); +extern ABC_DLL void Nwk_ObjCollectFanouts( Nwk_Obj_t * pNode, Vec_Ptr_t * vNodes ); +extern ABC_DLL int Nwk_ObjFindFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanin ); +extern ABC_DLL int Nwk_ObjFindFanout( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanout ); +extern ABC_DLL void Nwk_ObjAddFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanin ); +extern ABC_DLL void Nwk_ObjDeleteFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanin ); +extern ABC_DLL void Nwk_ObjPatchFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFaninOld, Nwk_Obj_t * pFaninNew ); +extern ABC_DLL void Nwk_ObjTransferFanout( Nwk_Obj_t * pNodeFrom, Nwk_Obj_t * pNodeTo ); +extern ABC_DLL void Nwk_ObjReplace( Nwk_Obj_t * pNodeOld, Nwk_Obj_t * pNodeNew ); +/*=== nwkFlow.c ============================================================*/ +extern ABC_DLL Vec_Ptr_t * Nwk_ManRetimeCutForward( Nwk_Man_t * pMan, int nLatches, int fVerbose ); +extern ABC_DLL Vec_Ptr_t * Nwk_ManRetimeCutBackward( Nwk_Man_t * pMan, int nLatches, int fVerbose ); +/*=== nwkMan.c ============================================================*/ +extern ABC_DLL Nwk_Man_t * Nwk_ManAlloc(); +extern ABC_DLL void Nwk_ManFree( Nwk_Man_t * p ); +extern ABC_DLL float Nwl_ManComputeTotalSwitching( Nwk_Man_t * pNtk ); +extern ABC_DLL void Nwk_ManPrintStats( Nwk_Man_t * p, If_Lib_t * pLutLib, int fSaveBest, int fDumpResult, int fPower, Ntl_Man_t * pNtl ); +/*=== nwkMap.c ============================================================*/ +extern ABC_DLL Nwk_Man_t * Nwk_MappingIf( Aig_Man_t * p, Tim_Man_t * pManTime, If_Par_t * pPars ); +/*=== nwkObj.c ============================================================*/ +extern ABC_DLL Nwk_Obj_t * Nwk_ManCreateCi( Nwk_Man_t * pMan, int nFanouts ); +extern ABC_DLL Nwk_Obj_t * Nwk_ManCreateCo( Nwk_Man_t * pMan ); +extern ABC_DLL Nwk_Obj_t * Nwk_ManCreateNode( Nwk_Man_t * pMan, int nFanins, int nFanouts ); +extern ABC_DLL Nwk_Obj_t * Nwk_ManCreateBox( Nwk_Man_t * pMan, int nFanins, int nFanouts ); +extern ABC_DLL Nwk_Obj_t * Nwk_ManCreateLatch( Nwk_Man_t * pMan ); +extern ABC_DLL void Nwk_ManDeleteNode( Nwk_Obj_t * pObj ); +extern ABC_DLL void Nwk_ManDeleteNode_rec( Nwk_Obj_t * pObj ); +/*=== nwkSpeedup.c ============================================================*/ +extern ABC_DLL Aig_Man_t * Nwk_ManSpeedup( Nwk_Man_t * pNtk, int fUseLutLib, int Percentage, int Degree, int fVerbose, int fVeryVerbose ); +/*=== nwkStrash.c ============================================================*/ +extern ABC_DLL Aig_Man_t * Nwk_ManStrash( Nwk_Man_t * pNtk ); +/*=== nwkTiming.c ============================================================*/ +extern ABC_DLL int Nwk_ManVerifyTiming( Nwk_Man_t * pNtk ); +extern ABC_DLL void Nwk_ManDelayTraceSortPins( Nwk_Obj_t * pNode, int * pPinPerm, float * pPinDelays ); +extern ABC_DLL float Nwk_ManDelayTraceLut( Nwk_Man_t * pNtk ); +extern ABC_DLL void Nwk_ManDelayTracePrint( Nwk_Man_t * pNtk ); +extern ABC_DLL void Nwk_ManUpdate( Nwk_Obj_t * pObj, Nwk_Obj_t * pObjNew, Vec_Vec_t * vLevels ); +extern ABC_DLL int Nwk_ManVerifyLevel( Nwk_Man_t * pNtk ); +/*=== nwkUtil.c ============================================================*/ +extern ABC_DLL void Nwk_ManIncrementTravId( Nwk_Man_t * pNtk ); +extern ABC_DLL int Nwk_ManGetFaninMax( Nwk_Man_t * pNtk ); +extern ABC_DLL int Nwk_ManGetTotalFanins( Nwk_Man_t * pNtk ); +extern ABC_DLL int Nwk_ManPiNum( Nwk_Man_t * pNtk ); +extern ABC_DLL int Nwk_ManPoNum( Nwk_Man_t * pNtk ); +extern ABC_DLL int Nwk_ManGetAigNodeNum( Nwk_Man_t * pNtk ); +extern ABC_DLL int Nwk_NodeCompareLevelsIncrease( Nwk_Obj_t ** pp1, Nwk_Obj_t ** pp2 ); +extern ABC_DLL int Nwk_NodeCompareLevelsDecrease( Nwk_Obj_t ** pp1, Nwk_Obj_t ** pp2 ); +extern ABC_DLL void Nwk_ObjPrint( Nwk_Obj_t * pObj ); +extern ABC_DLL void Nwk_ManDumpBlif( Nwk_Man_t * pNtk, char * pFileName, Vec_Ptr_t * vCiNames, Vec_Ptr_t * vCoNames ); +extern ABC_DLL void Nwk_ManPrintFanioNew( Nwk_Man_t * pNtk ); +extern ABC_DLL void Nwk_ManCleanMarks( Nwk_Man_t * pNtk ); +extern ABC_DLL void Nwk_ManMinimumBase( Nwk_Man_t * pNtk, int fVerbose ); +extern ABC_DLL void Nwk_ManRemoveDupFanins( Nwk_Man_t * pNtk, int fVerbose ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/opt/nwk/nwkAig.c b/src/opt/nwk/nwkAig.c new file mode 100644 index 00000000..7dae0dca --- /dev/null +++ b/src/opt/nwk/nwkAig.c @@ -0,0 +1,112 @@ +/**CFile**************************************************************** + + FileName [nwkAig.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Netlist representation.] + + Synopsis [Translating of AIG into the network.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: nwkAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "nwk.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Converts AIG into the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Nwk_Man_t * Nwk_ManDeriveFromAig( Aig_Man_t * p ) +{ + Nwk_Man_t * pNtk; + Aig_Obj_t * pObj; + int i; + pNtk = Nwk_ManAlloc(); + pNtk->nFanioPlus = 0; + Hop_ManStop( pNtk->pManHop ); + pNtk->pManHop = NULL; + pNtk->pName = Abc_UtilStrsav( p->pName ); + pNtk->pSpec = Abc_UtilStrsav( p->pSpec ); + pObj = Aig_ManConst1(p); + pObj->pData = Nwk_ManCreateNode( pNtk, 0, pObj->nRefs ); + Aig_ManForEachPi( p, pObj, i ) + pObj->pData = Nwk_ManCreateCi( pNtk, pObj->nRefs ); + Aig_ManForEachNode( p, pObj, i ) + { + pObj->pData = Nwk_ManCreateNode( pNtk, 2, pObj->nRefs ); + Nwk_ObjAddFanin( (Nwk_Obj_t *)pObj->pData, (Nwk_Obj_t *)Aig_ObjFanin0(pObj)->pData ); + Nwk_ObjAddFanin( (Nwk_Obj_t *)pObj->pData, (Nwk_Obj_t *)Aig_ObjFanin1(pObj)->pData ); + } + Aig_ManForEachPo( p, pObj, i ) + { + pObj->pData = Nwk_ManCreateCo( pNtk ); + Nwk_ObjAddFanin( (Nwk_Obj_t *)pObj->pData, (Nwk_Obj_t *)Aig_ObjFanin0(pObj)->pData ); + } + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Converts AIG into the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Nwk_ManDeriveRetimingCut( Aig_Man_t * p, int fForward, int fVerbose ) +{ + Vec_Ptr_t * vNodes; + Nwk_Man_t * pNtk; + Nwk_Obj_t * pNode; + Aig_Obj_t * pObj; + int i; + pNtk = Nwk_ManDeriveFromAig( p ); + if ( fForward ) + vNodes = Nwk_ManRetimeCutForward( pNtk, Aig_ManRegNum(p), fVerbose ); + else + vNodes = Nwk_ManRetimeCutBackward( pNtk, Aig_ManRegNum(p), fVerbose ); + Aig_ManForEachObj( p, pObj, i ) + ((Nwk_Obj_t *)pObj->pData)->pCopy = pObj; + Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pNode, i ) + Vec_PtrWriteEntry( vNodes, i, pNode->pCopy ); + Nwk_ManFree( pNtk ); +// assert( Vec_PtrSize(vNodes) <= Aig_ManRegNum(p) ); + return vNodes; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/nwk/nwkBidec.c b/src/opt/nwk/nwkBidec.c new file mode 100644 index 00000000..1b6439d2 --- /dev/null +++ b/src/opt/nwk/nwkBidec.c @@ -0,0 +1,177 @@ +/**CFile**************************************************************** + + FileName [nwkBidec.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Logic network representation.] + + Synopsis [Bi-decomposition of local functions.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: nwkBidec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "nwk.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Extra_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } +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_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 Hop_Obj_t * Bdc_FunCopyHop( Bdc_Fun_t * pObj ) { return Hop_NotCond( (Hop_Obj_t *)Bdc_FuncCopy(Bdc_Regular(pObj)), Bdc_IsComplement(pObj) ); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Resynthesizes nodes using bi-decomposition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Nwk_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare, float dProb ) +{ + unsigned * pTruth; + Bdc_Fun_t * pFunc; + int nNodes, i; + assert( nVars <= 16 ); + // derive truth table + pTruth = Hop_ManConvertAigToTruth( pHop, Hop_Regular(pRoot), nVars, vTruth, 0 ); + if ( Hop_IsComplement(pRoot) ) + for ( i = Abc_TruthWordNum(nVars)-1; i >= 0; i-- ) + pTruth[i] = ~pTruth[i]; + // perform power-aware decomposition + if ( dProb >= 0.0 ) + { + float Prob = (float)2.0 * dProb * (1.0 - dProb); + assert( Prob >= 0.0 && Prob <= 0.5 ); + if ( Prob >= 0.4 ) + { + Extra_TruthNot( puCare, puCare, nVars ); + if ( dProb > 0.5 ) // more 1s than 0s + Extra_TruthOr( pTruth, pTruth, puCare, nVars ); + else + Extra_TruthSharp( pTruth, pTruth, puCare, nVars ); + Extra_TruthNot( puCare, puCare, nVars ); + // decompose truth table + Bdc_ManDecompose( p, pTruth, NULL, nVars, NULL, 1000 ); + } + else + { + // decompose truth table + Bdc_ManDecompose( p, pTruth, puCare, nVars, NULL, 1000 ); + } + } + else + { + // decompose truth table + Bdc_ManDecompose( p, pTruth, puCare, nVars, NULL, 1000 ); + } + // convert back into HOP + Bdc_FuncSetCopy( Bdc_ManFunc( p, 0 ), Hop_ManConst1( pHop ) ); + for ( i = 0; i < nVars; i++ ) + Bdc_FuncSetCopy( Bdc_ManFunc( p, i+1 ), Hop_ManPi( pHop, i ) ); + nNodes = Bdc_ManNodeNum(p); + for ( i = nVars + 1; i < nNodes; i++ ) + { + pFunc = Bdc_ManFunc( p, i ); + Bdc_FuncSetCopy( pFunc, Hop_And( pHop, Bdc_FunCopyHop(Bdc_FuncFanin0(pFunc)), Bdc_FunCopyHop(Bdc_FuncFanin1(pFunc)) ) ); + } + return Bdc_FunCopyHop( Bdc_ManRoot(p) ); +} + +/**Function************************************************************* + + Synopsis [Resynthesizes nodes using bi-decomposition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManBidecResyn( Nwk_Man_t * pNtk, int fVerbose ) +{ + Bdc_Par_t Pars = {0}, * pPars = &Pars; + Bdc_Man_t * p; + Nwk_Obj_t * pObj; + Vec_Int_t * vTruth; + int i, nGainTotal = 0, nNodes1, nNodes2; + int clk = clock(); + pPars->nVarsMax = Nwk_ManGetFaninMax( pNtk ); + pPars->fVerbose = fVerbose; + if ( pPars->nVarsMax < 2 ) + { + printf( "Resynthesis is not performed for networks whose nodes are less than 2 inputs.\n" ); + return; + } + if ( pPars->nVarsMax > 15 ) + { + if ( fVerbose ) + printf( "Resynthesis is not performed for nodes with more than 15 inputs.\n" ); + pPars->nVarsMax = 15; + } + vTruth = Vec_IntAlloc( 0 ); + p = Bdc_ManAlloc( pPars ); + Nwk_ManForEachNode( pNtk, pObj, i ) + { + if ( Nwk_ObjFaninNum(pObj) > 15 ) + continue; + nNodes1 = Hop_DagSize(pObj->pFunc); + pObj->pFunc = Nwk_NodeIfNodeResyn( p, pNtk->pManHop, pObj->pFunc, Nwk_ObjFaninNum(pObj), vTruth, NULL, -1.0 ); + nNodes2 = Hop_DagSize(pObj->pFunc); + nGainTotal += nNodes1 - nNodes2; + } + Bdc_ManFree( p ); + Vec_IntFree( vTruth ); + if ( fVerbose ) + { + printf( "Total gain in AIG nodes = %d. ", nGainTotal ); + ABC_PRT( "Total runtime", clock() - clk ); + } +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/nwk/nwkCheck.c b/src/opt/nwk/nwkCheck.c new file mode 100644 index 00000000..24a0d513 --- /dev/null +++ b/src/opt/nwk/nwkCheck.c @@ -0,0 +1,76 @@ +/**CFile**************************************************************** + + FileName [nwkCheck.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Logic network representation.] + + Synopsis [Consistency checking procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: nwkCheck.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "nwk.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checking the logic network for consistency.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManCheck( Nwk_Man_t * p ) +{ + Nwk_Obj_t * pObj, * pNext; + int i, k, m; + // check if the nodes have duplicated fanins + Nwk_ManForEachNode( p, pObj, i ) + { + for ( k = 0; k < pObj->nFanins; k++ ) + for ( m = k + 1; m < pObj->nFanins; m++ ) + if ( pObj->pFanio[k] == pObj->pFanio[m] ) + printf( "Node %d has duplicated fanin %d.\n", pObj->Id, pObj->pFanio[k]->Id ); + } + // check if all nodes are in the correct fanin/fanout relationship + Nwk_ManForEachObj( p, pObj, i ) + { + Nwk_ObjForEachFanin( pObj, pNext, k ) + if ( Nwk_ObjFanoutNum(pNext) < 100 && Nwk_ObjFindFanout( pNext, pObj ) == -1 ) + printf( "Nwk_ManCheck(): Object %d has fanin %d which does not have a corresponding fanout.\n", pObj->Id, pNext->Id ); + Nwk_ObjForEachFanout( pObj, pNext, k ) + if ( Nwk_ObjFindFanin( pNext, pObj ) == -1 ) + printf( "Nwk_ManCheck(): Object %d has fanout %d which does not have a corresponding fanin.\n", pObj->Id, pNext->Id ); + } + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/nwk/nwkDfs.c b/src/opt/nwk/nwkDfs.c new file mode 100644 index 00000000..59752c59 --- /dev/null +++ b/src/opt/nwk/nwkDfs.c @@ -0,0 +1,664 @@ +/**CFile**************************************************************** + + FileName [nwkDfs.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Logic network representation.] + + Synopsis [DFS traversals.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: nwkDfs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "nwk.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Verifies that the objects are in a topo order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManVerifyTopoOrder( Nwk_Man_t * pNtk ) +{ + Nwk_Obj_t * pObj, * pNext; + int i, k, iBox, iTerm1, nTerms; + Nwk_ManIncrementTravId( pNtk ); + Nwk_ManForEachObj( pNtk, pObj, i ) + { + if ( Nwk_ObjIsNode(pObj) || Nwk_ObjIsCo(pObj) ) + { + Nwk_ObjForEachFanin( pObj, pNext, k ) + { + if ( !Nwk_ObjIsTravIdCurrent(pNext) ) + { + printf( "Node %d has fanin %d that is not in a topological order.\n", pObj->Id, pNext->Id ); + return 0; + } + } + } + else if ( Nwk_ObjIsCi(pObj) ) + { + if ( pNtk->pManTime ) + { + iBox = Tim_ManBoxForCi( pNtk->pManTime, pObj->PioId ); + if ( iBox >= 0 ) // this is not a true PI + { + iTerm1 = Tim_ManBoxInputFirst( pNtk->pManTime, iBox ); + nTerms = Tim_ManBoxInputNum( pNtk->pManTime, iBox ); + for ( k = 0; k < nTerms; k++ ) + { + pNext = Nwk_ManCo( pNtk, iTerm1 + k ); + if ( !Nwk_ObjIsTravIdCurrent(pNext) ) + { + printf( "Box %d has input %d that is not in a topological order.\n", iBox, pNext->Id ); + return 0; + } + } + } + } + } + else + assert( 0 ); + Nwk_ObjSetTravIdCurrent( pObj ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes the number of logic levels not counting PIs/POs.] + + Description [Assumes that white boxes have unit level.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManLevelBackup( Nwk_Man_t * pNtk ) +{ + Tim_Man_t * pManTimeUnit; + Nwk_Obj_t * pObj, * pFanin; + int i, k, LevelMax, Level; + assert( Nwk_ManVerifyTopoOrder(pNtk) ); + // clean the levels + Nwk_ManForEachObj( pNtk, pObj, i ) + Nwk_ObjSetLevel( pObj, 0 ); + // perform level computation + LevelMax = 0; + pManTimeUnit = pNtk->pManTime ? Tim_ManDupUnit( pNtk->pManTime ) : NULL; + if ( pManTimeUnit ) + Tim_ManIncrementTravId( pManTimeUnit ); + Nwk_ManForEachObj( pNtk, pObj, i ) + { + if ( Nwk_ObjIsCi(pObj) ) + { + Level = pManTimeUnit? (int)Tim_ManGetCiArrival( pManTimeUnit, pObj->PioId ) : 0; + Nwk_ObjSetLevel( pObj, Level ); + } + else if ( Nwk_ObjIsCo(pObj) ) + { + Level = Nwk_ObjLevel( Nwk_ObjFanin0(pObj) ); + if ( pManTimeUnit ) + Tim_ManSetCoArrival( pManTimeUnit, pObj->PioId, (float)Level ); + Nwk_ObjSetLevel( pObj, Level ); + if ( LevelMax < Nwk_ObjLevel(pObj) ) + LevelMax = Nwk_ObjLevel(pObj); + } + else if ( Nwk_ObjIsNode(pObj) ) + { + Level = 0; + Nwk_ObjForEachFanin( pObj, pFanin, k ) + if ( Level < Nwk_ObjLevel(pFanin) ) + Level = Nwk_ObjLevel(pFanin); + Nwk_ObjSetLevel( pObj, Level + 1 ); + } + else + assert( 0 ); + } + // set the old timing manager + if ( pManTimeUnit ) + Tim_ManStop( pManTimeUnit ); + return LevelMax; +} + +/**Function************************************************************* + + Synopsis [Computes the number of logic levels not counting PIs/POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManLevel_rec( Nwk_Obj_t * pObj ) +{ + Tim_Man_t * pManTime = pObj->pMan->pManTime; + Nwk_Obj_t * pNext; + int i, iBox, iTerm1, nTerms, LevelMax = 0; + if ( Nwk_ObjIsTravIdCurrent( pObj ) ) + return; + Nwk_ObjSetTravIdCurrent( pObj ); + if ( Nwk_ObjIsCi(pObj) ) + { + if ( pManTime ) + { + iBox = Tim_ManBoxForCi( pManTime, pObj->PioId ); + if ( iBox >= 0 ) // this is not a true PI + { + iTerm1 = Tim_ManBoxInputFirst( pManTime, iBox ); + nTerms = Tim_ManBoxInputNum( pManTime, iBox ); + for ( i = 0; i < nTerms; i++ ) + { + pNext = Nwk_ManCo(pObj->pMan, iTerm1 + i); + Nwk_ManLevel_rec( pNext ); + if ( LevelMax < Nwk_ObjLevel(pNext) ) + LevelMax = Nwk_ObjLevel(pNext); + } + LevelMax++; + } + } + } + else if ( Nwk_ObjIsNode(pObj) || Nwk_ObjIsCo(pObj) ) + { + Nwk_ObjForEachFanin( pObj, pNext, i ) + { + Nwk_ManLevel_rec( pNext ); + if ( LevelMax < Nwk_ObjLevel(pNext) ) + LevelMax = Nwk_ObjLevel(pNext); + } + if ( Nwk_ObjIsNode(pObj) && Nwk_ObjFaninNum(pObj) > 0 ) + LevelMax++; + } + else + assert( 0 ); + Nwk_ObjSetLevel( pObj, LevelMax ); +} + +/**Function************************************************************* + + Synopsis [Computes the number of logic levels not counting PIs/POs.] + + Description [Does not assume that the objects are in a topo order.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManLevel( Nwk_Man_t * pNtk ) +{ + Nwk_Obj_t * pObj; + int i, LevelMax = 0; + Nwk_ManForEachObj( pNtk, pObj, i ) + Nwk_ObjSetLevel( pObj, 0 ); + Nwk_ManIncrementTravId( pNtk ); + Nwk_ManForEachPo( pNtk, pObj, i ) + { + Nwk_ManLevel_rec( pObj ); + if ( LevelMax < Nwk_ObjLevel(pObj) ) + LevelMax = Nwk_ObjLevel(pObj); + } + Nwk_ManForEachCi( pNtk, pObj, i ) + { + Nwk_ManLevel_rec( pObj ); + if ( LevelMax < Nwk_ObjLevel(pObj) ) + LevelMax = Nwk_ObjLevel(pObj); + } + return LevelMax; +} + +/**Function************************************************************* + + Synopsis [Computes the number of logic levels not counting PIs/POs.] + + Description [Does not assume that the objects are in a topo order.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManLevelMax( Nwk_Man_t * pNtk ) +{ + Nwk_Obj_t * pObj; + int i, LevelMax = 0; + Nwk_ManForEachPo( pNtk, pObj, i ) + if ( LevelMax < Nwk_ObjLevel(pObj) ) + LevelMax = Nwk_ObjLevel(pObj); + return LevelMax; +} + +/**Function************************************************************* + + Synopsis [Returns the array of objects in the AIG manager ordered by level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Vec_t * Nwk_ManLevelize( Nwk_Man_t * pNtk ) +{ + Nwk_Obj_t * pObj; + Vec_Vec_t * vLevels; + int nLevels, i; + assert( Nwk_ManVerifyLevel(pNtk) ); + nLevels = Nwk_ManLevelMax( pNtk ); + vLevels = Vec_VecStart( nLevels + 1 ); + Nwk_ManForEachNode( pNtk, pObj, i ) + { + assert( Nwk_ObjLevel(pObj) <= nLevels ); + Vec_VecPush( vLevels, Nwk_ObjLevel(pObj), pObj ); + } + return vLevels; +} + + + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManDfs_rec( Nwk_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + Nwk_Obj_t * pNext; + int i; + if ( Nwk_ObjIsTravIdCurrent( pObj ) ) + return; + Nwk_ObjSetTravIdCurrent( pObj ); + Nwk_ObjForEachFanin( pObj, pNext, i ) + Nwk_ManDfs_rec( pNext, vNodes ); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Returns the DFS ordered array of all objects except latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Nwk_ManDfs( Nwk_Man_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Nwk_Obj_t * pObj; + int i; + Nwk_ManIncrementTravId( pNtk ); + vNodes = Vec_PtrAlloc( 100 ); + Nwk_ManForEachObj( pNtk, pObj, i ) + { + if ( Nwk_ObjIsCi(pObj) ) + { + Nwk_ObjSetTravIdCurrent( pObj ); + Vec_PtrPush( vNodes, pObj ); + } + else if ( Nwk_ObjIsCo(pObj) ) + Nwk_ManDfs_rec( pObj, vNodes ); + } + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManDfsNodes_rec( Nwk_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + Nwk_Obj_t * pNext; + int i; + if ( Nwk_ObjIsTravIdCurrent( pObj ) ) + return; + Nwk_ObjSetTravIdCurrent( pObj ); + if ( Nwk_ObjIsCi(pObj) ) + return; + assert( Nwk_ObjIsNode(pObj) ); + Nwk_ObjForEachFanin( pObj, pNext, i ) + Nwk_ManDfsNodes_rec( pNext, vNodes ); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Returns the set of internal nodes rooted in the given nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Nwk_ManDfsNodes( Nwk_Man_t * pNtk, Nwk_Obj_t ** ppNodes, int nNodes ) +{ + Vec_Ptr_t * vNodes; + int i; + // set the traversal ID + Nwk_ManIncrementTravId( 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 ( Nwk_ObjIsCo(ppNodes[i]) ) + Nwk_ManDfsNodes_rec( Nwk_ObjFanin0(ppNodes[i]), vNodes ); + else + Nwk_ManDfsNodes_rec( ppNodes[i], vNodes ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManDfsReverse_rec( Nwk_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + Nwk_Obj_t * pNext; + int i, iBox, iTerm1, nTerms; + if ( Nwk_ObjIsTravIdCurrent( pObj ) ) + return; + Nwk_ObjSetTravIdCurrent( pObj ); + if ( Nwk_ObjIsCo(pObj) ) + { + if ( pObj->pMan->pManTime ) + { + iBox = Tim_ManBoxForCo( pObj->pMan->pManTime, pObj->PioId ); + if ( iBox >= 0 ) // this is not a true PO + { + iTerm1 = Tim_ManBoxOutputFirst( pObj->pMan->pManTime, iBox ); + nTerms = Tim_ManBoxOutputNum( pObj->pMan->pManTime, iBox ); + for ( i = 0; i < nTerms; i++ ) + { + pNext = Nwk_ManCi(pObj->pMan, iTerm1 + i); + Nwk_ManDfsReverse_rec( pNext, vNodes ); + } + } + } + } + else if ( Nwk_ObjIsNode(pObj) || Nwk_ObjIsCi(pObj) ) + { + Nwk_ObjForEachFanout( pObj, pNext, i ) + Nwk_ManDfsReverse_rec( pNext, vNodes ); + } + else + assert( 0 ); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Returns the DFS ordered array of all objects except latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Nwk_ManDfsReverse( Nwk_Man_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Nwk_Obj_t * pObj; + int i; + Nwk_ManIncrementTravId( pNtk ); + vNodes = Vec_PtrAlloc( 100 ); + Nwk_ManForEachPi( pNtk, pObj, i ) + Nwk_ManDfsReverse_rec( pObj, vNodes ); + // add nodes without fanins + Nwk_ManForEachNode( pNtk, pObj, i ) + if ( Nwk_ObjFaninNum(pObj) == 0 && !Nwk_ObjIsTravIdCurrent(pObj) ) + Vec_PtrPush( vNodes, pObj ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManSupportNodes_rec( Nwk_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Nwk_Obj_t * pFanin; + int i; + // if this node is already visited, skip + if ( Nwk_ObjIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Nwk_ObjSetTravIdCurrent( pNode ); + // collect the CI + if ( Nwk_ObjIsCi(pNode) ) + { + Vec_PtrPush( vNodes, pNode ); + return; + } + assert( Nwk_ObjIsNode( pNode ) ); + // visit the transitive fanin of the node + Nwk_ObjForEachFanin( pNode, pFanin, i ) + Nwk_ManSupportNodes_rec( pFanin, vNodes ); +} + +/**Function************************************************************* + + Synopsis [Returns the set of CI nodes in the support of the given nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Nwk_ManSupportNodes( Nwk_Man_t * pNtk, Nwk_Obj_t ** ppNodes, int nNodes ) +{ + Vec_Ptr_t * vNodes; + int i; + // set the traversal ID + Nwk_ManIncrementTravId( 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 ( Nwk_ObjIsCo(ppNodes[i]) ) + Nwk_ManSupportNodes_rec( Nwk_ObjFanin0(ppNodes[i]), vNodes ); + else + Nwk_ManSupportNodes_rec( ppNodes[i], vNodes ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Computes the sum total of supports of all outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManSupportSum( Nwk_Man_t * pNtk ) +{ + Vec_Ptr_t * vSupp; + Nwk_Obj_t * pObj; + int i, nTotalSupps = 0; + Nwk_ManForEachCo( pNtk, pObj, i ) + { + vSupp = Nwk_ManSupportNodes( pNtk, &pObj, 1 ); + nTotalSupps += Vec_PtrSize( vSupp ); + Vec_PtrFree( vSupp ); + } + printf( "Total supports = %d.\n", nTotalSupps ); +} + + +/**Function************************************************************* + + Synopsis [Dereferences the node's MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ObjDeref_rec( Nwk_Obj_t * pNode ) +{ + Nwk_Obj_t * pFanin; + int i, Counter = 1; + if ( Nwk_ObjIsCi(pNode) ) + return 0; + Nwk_ObjForEachFanin( pNode, pFanin, i ) + { + assert( pFanin->nFanouts > 0 ); + if ( --pFanin->nFanouts == 0 ) + Counter += Nwk_ObjDeref_rec( pFanin ); + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [References the node's MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ObjRef_rec( Nwk_Obj_t * pNode ) +{ + Nwk_Obj_t * pFanin; + int i, Counter = 1; + if ( Nwk_ObjIsCi(pNode) ) + return 0; + Nwk_ObjForEachFanin( pNode, pFanin, i ) + { + if ( pFanin->nFanouts++ == 0 ) + Counter += Nwk_ObjRef_rec( pFanin ); + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Collects the internal and boundary nodes in the derefed MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ObjMffcLabel_rec( Nwk_Obj_t * pNode, int fTopmost ) +{ + Nwk_Obj_t * pFanin; + int i; + // add to the new support nodes + if ( !fTopmost && (Nwk_ObjIsCi(pNode) || pNode->nFanouts > 0) ) + return; + // skip visited nodes + if ( Nwk_ObjIsTravIdCurrent(pNode) ) + return; + Nwk_ObjSetTravIdCurrent(pNode); + // recur on the children + Nwk_ObjForEachFanin( pNode, pFanin, i ) + Nwk_ObjMffcLabel_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 Nwk_ObjMffcLabel( Nwk_Obj_t * pNode ) +{ + int Count1, Count2; + // dereference the node + Count1 = Nwk_ObjDeref_rec( pNode ); + // collect the nodes inside the MFFC + Nwk_ManIncrementTravId( pNode->pMan ); + Nwk_ObjMffcLabel_rec( pNode, 1 ); + // reference it back + Count2 = Nwk_ObjRef_rec( pNode ); + assert( Count1 == Count2 ); + return Count1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/nwk/nwkFanio.c b/src/opt/nwk/nwkFanio.c new file mode 100644 index 00000000..79fc5b3a --- /dev/null +++ b/src/opt/nwk/nwkFanio.c @@ -0,0 +1,320 @@ +/**CFile**************************************************************** + + FileName [nwkFanio.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Logic network representation.] + + Synopsis [Manipulation of fanins/fanouts.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: nwkFanio.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "nwk.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Collects fanins of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ObjCollectFanins( Nwk_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Nwk_Obj_t * pFanin; + int i; + Vec_PtrClear(vNodes); + Nwk_ObjForEachFanin( pNode, pFanin, i ) + Vec_PtrPush( vNodes, pFanin ); +} + +/**Function************************************************************* + + Synopsis [Collects fanouts of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ObjCollectFanouts( Nwk_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Nwk_Obj_t * pFanout; + int i; + Vec_PtrClear(vNodes); + Nwk_ObjForEachFanout( pNode, pFanout, i ) + Vec_PtrPush( vNodes, pFanout ); +} + +/**Function************************************************************* + + Synopsis [Returns the number of the fanin of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ObjFindFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanin ) +{ + Nwk_Obj_t * pTemp; + int i; + Nwk_ObjForEachFanin( pObj, pTemp, i ) + if ( pTemp == pFanin ) + return i; + return -1; +} + +/**Function************************************************************* + + Synopsis [Returns the number of the fanout of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ObjFindFanout( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanout ) +{ + Nwk_Obj_t * pTemp; + int i; + Nwk_ObjForEachFanout( pObj, pTemp, i ) + if ( pTemp == pFanout ) + return i; + return -1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node has to be reallocated.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Nwk_ObjReallocIsNeeded( Nwk_Obj_t * pObj ) +{ + return pObj->nFanins + pObj->nFanouts == pObj->nFanioAlloc; +} + +/**Function************************************************************* + + Synopsis [Reallocates the object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Nwk_Obj_t * Nwk_ManReallocNode( Nwk_Obj_t * pObj ) +{ + Nwk_Obj_t ** pFanioOld = pObj->pFanio; + assert( Nwk_ObjReallocIsNeeded(pObj) ); + pObj->pFanio = (Nwk_Obj_t **)Aig_MmFlexEntryFetch( pObj->pMan->pMemObjs, 2 * pObj->nFanioAlloc * sizeof(Nwk_Obj_t *) ); + memmove( pObj->pFanio, pFanioOld, pObj->nFanioAlloc * sizeof(Nwk_Obj_t *) ); + pObj->nFanioAlloc *= 2; + pObj->pMan->nRealloced++; + return NULL; +} + +/**Function************************************************************* + + Synopsis [Creates fanout/fanin relationship between the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ObjAddFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanin ) +{ + int i; + assert( pObj->pMan == pFanin->pMan ); + assert( pObj->Id >= 0 && pFanin->Id >= 0 ); + if ( Nwk_ObjReallocIsNeeded(pObj) ) + Nwk_ManReallocNode( pObj ); + if ( Nwk_ObjReallocIsNeeded(pFanin) ) + Nwk_ManReallocNode( pFanin ); + for ( i = pObj->nFanins + pObj->nFanouts; i > pObj->nFanins; i-- ) + pObj->pFanio[i] = pObj->pFanio[i-1]; + pObj->pFanio[pObj->nFanins++] = pFanin; + pFanin->pFanio[pFanin->nFanins + pFanin->nFanouts++] = pObj; + pObj->Level = Abc_MaxInt( pObj->Level, pFanin->Level + Nwk_ObjIsNode(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Removes fanout/fanin relationship between the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ObjDeleteFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanin ) +{ + int i, k, Limit, fFound; + // remove pFanin from the fanin list of pObj + Limit = pObj->nFanins + pObj->nFanouts; + fFound = 0; + for ( k = i = 0; i < Limit; i++ ) + if ( fFound || pObj->pFanio[i] != pFanin ) + pObj->pFanio[k++] = pObj->pFanio[i]; + else + fFound = 1; + assert( i == k + 1 ); // if it fails, likely because of duplicated fanin + pObj->nFanins--; + // remove pObj from the fanout list of pFanin + Limit = pFanin->nFanins + pFanin->nFanouts; + fFound = 0; + for ( k = i = pFanin->nFanins; i < Limit; i++ ) + if ( fFound || pFanin->pFanio[i] != pObj ) + pFanin->pFanio[k++] = pFanin->pFanio[i]; + else + fFound = 1; + assert( i == k + 1 ); // if it fails, likely because of duplicated fanout + pFanin->nFanouts--; +} + +/**Function************************************************************* + + Synopsis [Replaces a fanin of the node.] + + Description [The node is pObj. An old fanin of this node (pFaninOld) has to be + replaced by a new fanin (pFaninNew). Assumes that the node and the old fanin + are not complemented. The new fanin can be complemented. In this case, the + polarity of the new fanin will change, compared to the polarity of the old fanin.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ObjPatchFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFaninOld, Nwk_Obj_t * pFaninNew ) +{ + int i, k, iFanin, Limit; + assert( pFaninOld != pFaninNew ); + assert( pObj != pFaninOld ); + assert( pObj != pFaninNew ); + assert( pObj->pMan == pFaninOld->pMan ); + assert( pObj->pMan == pFaninNew->pMan ); + // update the fanin + iFanin = Nwk_ObjFindFanin( pObj, pFaninOld ); + if ( iFanin == -1 ) + { + printf( "Nwk_ObjPatchFanin(); Error! Node %d is not among", pFaninOld->Id ); + printf( " the fanins of node %d...\n", pObj->Id ); + return; + } + pObj->pFanio[iFanin] = pFaninNew; + // remove pObj from the fanout list of pFaninOld + Limit = pFaninOld->nFanins + pFaninOld->nFanouts; + for ( k = i = pFaninOld->nFanins; i < Limit; i++ ) + if ( pFaninOld->pFanio[i] != pObj ) + pFaninOld->pFanio[k++] = pFaninOld->pFanio[i]; + pFaninOld->nFanouts--; + // add pObj to the fanout list of pFaninNew + if ( Nwk_ObjReallocIsNeeded(pFaninNew) ) + Nwk_ManReallocNode( pFaninNew ); + pFaninNew->pFanio[pFaninNew->nFanins + pFaninNew->nFanouts++] = pObj; +} + + +/**Function************************************************************* + + Synopsis [Transfers fanout from the old node to the new node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ObjTransferFanout( Nwk_Obj_t * pNodeFrom, Nwk_Obj_t * pNodeTo ) +{ + Vec_Ptr_t * vFanouts = pNodeFrom->pMan->vTemp; + Nwk_Obj_t * pTemp; + int nFanoutsOld, i; + assert( !Nwk_ObjIsCo(pNodeFrom) && !Nwk_ObjIsCo(pNodeTo) ); + assert( pNodeFrom->pMan == pNodeTo->pMan ); + assert( pNodeFrom != pNodeTo ); + assert( Nwk_ObjFanoutNum(pNodeFrom) > 0 ); + // get the fanouts of the old node + nFanoutsOld = Nwk_ObjFanoutNum(pNodeTo); + Nwk_ObjCollectFanouts( pNodeFrom, vFanouts ); + // patch the fanin of each of them + Vec_PtrForEachEntry( Nwk_Obj_t *, vFanouts, pTemp, i ) + Nwk_ObjPatchFanin( pTemp, pNodeFrom, pNodeTo ); + assert( Nwk_ObjFanoutNum(pNodeFrom) == 0 ); + assert( Nwk_ObjFanoutNum(pNodeTo) == nFanoutsOld + Vec_PtrSize(vFanouts) ); +} + +/**Function************************************************************* + + Synopsis [Replaces the node by a new node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ObjReplace( Nwk_Obj_t * pNodeOld, Nwk_Obj_t * pNodeNew ) +{ + assert( pNodeOld->pMan == pNodeNew->pMan ); + assert( pNodeOld != pNodeNew ); + assert( Nwk_ObjFanoutNum(pNodeOld) > 0 ); + // transfer the fanouts to the old node + Nwk_ObjTransferFanout( pNodeOld, pNodeNew ); + // remove the old node + Nwk_ManDeleteNode_rec( pNodeOld ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/nwk/nwkFlow.c b/src/opt/nwk/nwkFlow.c new file mode 100644 index 00000000..3961e5c2 --- /dev/null +++ b/src/opt/nwk/nwkFlow.c @@ -0,0 +1,606 @@ +/**CFile**************************************************************** + + FileName [nwkFlow.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Netlist representation.] + + Synopsis [Max-flow/min-cut computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: nwkFlow.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "nwk.h" + +ABC_NAMESPACE_IMPL_START + + +/* + This code is based on the papers: + A. Hurst, A. Mishchenko, and R. Brayton, "Fast minimum-register retiming + via binary maximum-flow", Proc. FMCAD '07, pp. 181-187. + A. Hurst, A. Mishchenko, and R. Brayton, "Scalable min-area retiming + under simultaneous delay and initial state constraints". Proc. DAC'08. +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// predecessors +static inline Nwk_Obj_t * Nwk_ObjPred( Nwk_Obj_t * pObj ) { return (Nwk_Obj_t *)pObj->pCopy; } +static inline int Nwk_ObjSetPred( Nwk_Obj_t * pObj, Nwk_Obj_t * p ) { pObj->pCopy = p; return 1; } +// sink +static inline int Nwk_ObjIsSink( Nwk_Obj_t * pObj ) { return pObj->MarkA; } +static inline void Nwk_ObjSetSink( Nwk_Obj_t * pObj ) { pObj->MarkA = 1; } +// flow +static inline int Nwk_ObjHasFlow( Nwk_Obj_t * pObj ) { return pObj->MarkB; } +static inline void Nwk_ObjSetFlow( Nwk_Obj_t * pObj ) { pObj->MarkB = 1; } +static inline void Nwk_ObjClearFlow( Nwk_Obj_t * pObj ) { pObj->MarkB = 0; } + +// representation of visited nodes +// pObj->TravId < pNtk->nTravIds-2 --- not visited +// pObj->TravId == pNtk->nTravIds-2 --- visited bot only +// pObj->TravId == pNtk->nTravIds-1 --- visited top only +// pObj->TravId == pNtk->nTravIds --- visited bot and top +static inline int Nwk_ObjVisitedBotOnly( Nwk_Obj_t * pObj ) +{ + return pObj->TravId == pObj->pMan->nTravIds - 2; +} +static inline int Nwk_ObjVisitedBot( Nwk_Obj_t * pObj ) +{ + return pObj->TravId == pObj->pMan->nTravIds - 2 || pObj->TravId == pObj->pMan->nTravIds; +} +static inline int Nwk_ObjVisitedTop( Nwk_Obj_t * pObj ) +{ + return pObj->TravId == pObj->pMan->nTravIds - 1 || pObj->TravId == pObj->pMan->nTravIds; +} +static inline void Nwk_ObjSetVisitedBot( Nwk_Obj_t * pObj ) +{ + if ( pObj->TravId < pObj->pMan->nTravIds - 2 ) + pObj->TravId = pObj->pMan->nTravIds - 2; + else if ( pObj->TravId == pObj->pMan->nTravIds - 1 ) + pObj->TravId = pObj->pMan->nTravIds; + else + assert( 0 ); +} +static inline void Nwk_ObjSetVisitedTop( Nwk_Obj_t * pObj ) +{ + if ( pObj->TravId < pObj->pMan->nTravIds - 2 ) + pObj->TravId = pObj->pMan->nTravIds - 1; + else if ( pObj->TravId == pObj->pMan->nTravIds - 2 ) + pObj->TravId = pObj->pMan->nTravIds; + else + assert( 0 ); +} +static inline void Nwk_ManIncrementTravIdFlow( Nwk_Man_t * pMan ) +{ + Nwk_ManIncrementTravId( pMan ); + Nwk_ManIncrementTravId( pMan ); + Nwk_ManIncrementTravId( pMan ); +} + +static int Nwk_ManPushForwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ); +static int Nwk_ManPushForwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ); + +static int Nwk_ManPushBackwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ); +static int Nwk_ManPushBackwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Marks TFI of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManMarkTfiCone_rec( Nwk_Obj_t * pObj ) +{ + Nwk_Obj_t * pNext; + int i; + if ( pObj->MarkA ) + return; + pObj->MarkA = 1; + Nwk_ObjForEachFanin( pObj, pNext, i ) + Nwk_ManMarkTfiCone_rec( pNext ); +} + +/**Function************************************************************* + + Synopsis [Marks TFO of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManMarkTfoCone_rec( Nwk_Obj_t * pObj ) +{ + Nwk_Obj_t * pNext; + int i; + if ( pObj->MarkA ) + return; + pObj->MarkA = 1; + Nwk_ObjForEachFanout( pObj, pNext, i ) + Nwk_ManMarkTfoCone_rec( pNext ); +} + +/**Function************************************************************* + + Synopsis [Fast forward flow pushing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManPushForwardFast_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) +{ + Nwk_Obj_t * pNext; + int i; + if ( Nwk_ObjIsTravIdCurrent( pObj ) ) + return 0; + Nwk_ObjSetTravIdCurrent( pObj ); + if ( Nwk_ObjHasFlow(pObj) ) + return 0; + if ( Nwk_ObjIsSink(pObj) ) + { + Nwk_ObjSetFlow(pObj); + return Nwk_ObjSetPred( pObj, pPred ); + } + Nwk_ObjForEachFanout( pObj, pNext, i ) + if ( Nwk_ManPushForwardFast_rec( pNext, pObj ) ) + { + Nwk_ObjSetFlow(pObj); + return Nwk_ObjSetPred( pObj, pPred ); + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Fast backward flow pushing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManPushBackwardFast_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) +{ + Nwk_Obj_t * pNext; + int i; + if ( Nwk_ObjIsTravIdCurrent( pObj ) ) + return 0; + Nwk_ObjSetTravIdCurrent( pObj ); + if ( Nwk_ObjHasFlow(pObj) ) + return 0; + if ( Nwk_ObjIsSink(pObj) ) + { + Nwk_ObjSetFlow(pObj); + return Nwk_ObjSetPred( pObj, pPred ); + } + Nwk_ObjForEachFanin( pObj, pNext, i ) + if ( Nwk_ManPushBackwardFast_rec( pNext, pObj ) ) + { + Nwk_ObjSetFlow(pObj); + return Nwk_ObjSetPred( pObj, pPred ); + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Pushing the flow through the bottom part of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManPushForwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) +{ + Nwk_Obj_t * pNext; + int i; + if ( Nwk_ObjVisitedBot(pObj) ) + return 0; + Nwk_ObjSetVisitedBot(pObj); + // propagate through the internal edge + if ( Nwk_ObjHasFlow(pObj) ) + { + if ( Nwk_ObjPred(pObj) ) + if ( Nwk_ManPushForwardTop_rec( Nwk_ObjPred(pObj), Nwk_ObjPred(pObj) ) ) + return Nwk_ObjSetPred( pObj, pPred ); + } + else if ( Nwk_ManPushForwardTop_rec(pObj, pObj) ) + { + Nwk_ObjSetFlow( pObj ); + return Nwk_ObjSetPred( pObj, pPred ); + } + // try to push through the fanins + Nwk_ObjForEachFanin( pObj, pNext, i ) + if ( Nwk_ManPushForwardBot_rec( pNext, pPred ) ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Pushing the flow through the top part of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManPushForwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) +{ + Nwk_Obj_t * pNext; + int i; + if ( Nwk_ObjVisitedTop(pObj) ) + return 0; + Nwk_ObjSetVisitedTop(pObj); + // check if this is the sink + if ( Nwk_ObjIsSink(pObj) ) + return 1; + // try to push through the fanouts + Nwk_ObjForEachFanout( pObj, pNext, i ) + if ( Nwk_ManPushForwardBot_rec( pNext, pPred ) ) + return 1; + // redirect the flow + if ( Nwk_ObjHasFlow(pObj) && !Nwk_ObjIsCi(pObj) ) + if ( Nwk_ManPushForwardBot_rec( pObj, Nwk_ObjPred(pObj) ) ) + { + Nwk_ObjClearFlow( pObj ); + return Nwk_ObjSetPred( pObj, NULL ); + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Pushing the flow through the bottom part of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManPushBackwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) +{ + if ( Nwk_ObjVisitedBot(pObj) ) + return 0; + Nwk_ObjSetVisitedBot(pObj); + // propagate through the internal edge + if ( Nwk_ObjHasFlow(pObj) ) + { + if ( Nwk_ObjPred(pObj) ) + if ( Nwk_ManPushBackwardTop_rec( Nwk_ObjPred(pObj), Nwk_ObjPred(pObj) ) ) + return Nwk_ObjSetPred( pObj, pPred ); + } + else if ( Nwk_ManPushBackwardTop_rec(pObj, pObj) ) + { + Nwk_ObjSetFlow( pObj ); + return Nwk_ObjSetPred( pObj, pPred ); + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Pushing the flow through the top part of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManPushBackwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) +{ + Nwk_Obj_t * pNext; + int i; + if ( Nwk_ObjVisitedTop(pObj) ) + return 0; + Nwk_ObjSetVisitedTop(pObj); + // check if this is the sink + if ( Nwk_ObjIsSink(pObj) ) + return 1; + // try to push through the fanins + Nwk_ObjForEachFanin( pObj, pNext, i ) + if ( Nwk_ManPushBackwardBot_rec( pNext, pPred ) ) + return 1; + // try to push through the fanouts + Nwk_ObjForEachFanout( pObj, pNext, i ) + if ( !Nwk_ObjIsCo(pObj) && Nwk_ManPushBackwardTop_rec( pNext, pPred ) ) + return 1; + // redirect the flow + if ( Nwk_ObjHasFlow(pObj) ) + if ( Nwk_ObjPred(pObj) && Nwk_ManPushBackwardBot_rec( pObj, Nwk_ObjPred(pObj) ) ) + { + Nwk_ObjClearFlow( pObj ); + return Nwk_ObjSetPred( pObj, NULL ); + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 0 if there is an unmarked path to a CI.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManVerifyCut_rec( Nwk_Obj_t * pObj ) +{ + Nwk_Obj_t * pNext; + int i; + if ( pObj->MarkA ) + return 1; + if ( Nwk_ObjIsLo(pObj) ) + return 0; + if ( Nwk_ObjIsTravIdCurrent( pObj ) ) + return 1; + Nwk_ObjSetTravIdCurrent( pObj ); + Nwk_ObjForEachFanin( pObj, pNext, i ) + if ( !Nwk_ManVerifyCut_rec( pNext ) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Verifies the forward cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManRetimeVerifyCutForward( Nwk_Man_t * pMan, Vec_Ptr_t * vNodes ) +{ + Nwk_Obj_t * pObj; + int i; + // mark the nodes + Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i ) + { + assert( pObj->MarkA == 0 ); + pObj->MarkA = 1; + } + // traverse from the COs + Nwk_ManIncrementTravId( pMan ); + Nwk_ManForEachCo( pMan, pObj, i ) + if ( !Nwk_ManVerifyCut_rec( pObj ) ) + printf( "Nwk_ManRetimeVerifyCutForward(): Internal cut verification failed.\n" ); + // unmark the nodes + Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i ) + pObj->MarkA = 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Verifies the forward cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManRetimeVerifyCutBackward( Nwk_Man_t * pMan, Vec_Ptr_t * vNodes ) +{ + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes minimum cut for forward retiming.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Nwk_ManRetimeCutForward( Nwk_Man_t * pMan, int nLatches, int fVerbose ) +{ + Vec_Ptr_t * vNodes; + Nwk_Obj_t * pObj; + int i, RetValue, Counter = 0, Counter2 = 0; + int clk = clock(); + // set the sequential parameters + pMan->nLatches = nLatches; + pMan->nTruePis = Nwk_ManCiNum(pMan) - nLatches; + pMan->nTruePos = Nwk_ManCoNum(pMan) - nLatches; + // mark the COs and the TFO of PIs + Nwk_ManForEachCo( pMan, pObj, i ) + pObj->MarkA = 1; + Nwk_ManForEachPiSeq( pMan, pObj, i ) + Nwk_ManMarkTfoCone_rec( pObj ); + // start flow computation from each LO + Nwk_ManIncrementTravIdFlow( pMan ); + Nwk_ManForEachLoSeq( pMan, pObj, i ) + { + if ( !Nwk_ManPushForwardFast_rec( pObj, NULL ) ) + continue; + Nwk_ManIncrementTravIdFlow( pMan ); + Counter++; + } + if ( fVerbose ) + printf( "Forward: Max-flow = %4d -> ", Counter ); + // continue flow computation from each LO + Nwk_ManIncrementTravIdFlow( pMan ); + Nwk_ManForEachLoSeq( pMan, pObj, i ) + { + if ( !Nwk_ManPushForwardBot_rec( pObj, NULL ) ) + continue; + Nwk_ManIncrementTravIdFlow( pMan ); + Counter2++; + } + if ( fVerbose ) + printf( "%4d. ", Counter+Counter2 ); + // repeat flow computation from each LO + if ( Counter2 > 0 ) + { + Nwk_ManIncrementTravIdFlow( pMan ); + Nwk_ManForEachLoSeq( pMan, pObj, i ) + { + RetValue = Nwk_ManPushForwardBot_rec( pObj, NULL ); + assert( !RetValue ); + } + } + // cut is a set of nodes whose bottom is visited but top is not visited + vNodes = Vec_PtrAlloc( Counter+Counter2 ); + Counter = 0; + Nwk_ManForEachObj( pMan, pObj, i ) + { + if ( Nwk_ObjVisitedBotOnly(pObj) ) + { + assert( Nwk_ObjHasFlow(pObj) ); + assert( !Nwk_ObjIsCo(pObj) ); + Vec_PtrPush( vNodes, pObj ); + Counter += Nwk_ObjIsCi(pObj); + } + } + Nwk_ManCleanMarks( pMan ); +// assert( Nwk_ManRetimeVerifyCutForward(pMan, vNodes) ); + if ( fVerbose ) + { + printf( "Min-cut = %4d. Unmoved = %4d. ", Vec_PtrSize(vNodes), Counter ); + ABC_PRT( "Time", clock() - clk ); + } + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Computes minimum cut for backward retiming.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Nwk_ManRetimeCutBackward( Nwk_Man_t * pMan, int nLatches, int fVerbose ) +{ + Vec_Ptr_t * vNodes; + Nwk_Obj_t * pObj; + int i, RetValue, Counter = 0, Counter2 = 0; + int clk = clock(); + // set the sequential parameters + pMan->nLatches = nLatches; + pMan->nTruePis = Nwk_ManCiNum(pMan) - nLatches; + pMan->nTruePos = Nwk_ManCoNum(pMan) - nLatches; + // mark the CIs, the TFI of POs, and the constant nodes + Nwk_ManForEachCi( pMan, pObj, i ) + pObj->MarkA = 1; + Nwk_ManForEachPoSeq( pMan, pObj, i ) + Nwk_ManMarkTfiCone_rec( pObj ); + Nwk_ManForEachNode( pMan, pObj, i ) + if ( Nwk_ObjFaninNum(pObj) == 0 ) + pObj->MarkA = 1; + // start flow computation from each LI driver + Nwk_ManIncrementTravIdFlow( pMan ); + Nwk_ManForEachLiSeq( pMan, pObj, i ) + { + if ( !Nwk_ManPushBackwardFast_rec( Nwk_ObjFanin0(pObj), NULL ) ) + continue; + Nwk_ManIncrementTravIdFlow( pMan ); + Counter++; + } + if ( fVerbose ) + printf( "Backward: Max-flow = %4d -> ", Counter ); + // continue flow computation from each LI driver + Nwk_ManIncrementTravIdFlow( pMan ); + Nwk_ManForEachLiSeq( pMan, pObj, i ) + { + if ( !Nwk_ManPushBackwardBot_rec( Nwk_ObjFanin0(pObj), NULL ) ) + continue; + Nwk_ManIncrementTravIdFlow( pMan ); + Counter2++; + } + if ( fVerbose ) + printf( "%4d. ", Counter+Counter2 ); + // repeat flow computation from each LI driver + if ( Counter2 > 0 ) + { + Nwk_ManIncrementTravIdFlow( pMan ); + Nwk_ManForEachLiSeq( pMan, pObj, i ) + { + RetValue = Nwk_ManPushBackwardBot_rec( Nwk_ObjFanin0(pObj), NULL ); + assert( !RetValue ); + } + } + // cut is a set of nodes whose bottom is visited but top is not visited + vNodes = Vec_PtrAlloc( Counter+Counter2 ); + Nwk_ManForEachObj( pMan, pObj, i ) + { + if ( Nwk_ObjVisitedBotOnly(pObj) ) + { + assert( Nwk_ObjHasFlow(pObj) ); + assert( !Nwk_ObjIsCo(pObj) ); + Vec_PtrPush( vNodes, pObj ); + } + } + // count CO drivers + Counter = 0; + Nwk_ManForEachLiSeq( pMan, pObj, i ) + if ( Nwk_ObjVisitedBotOnly( Nwk_ObjFanin0(pObj) ) ) + Counter++; + Nwk_ManCleanMarks( pMan ); +// assert( Nwk_ManRetimeVerifyCutBackward(pMan, vNodes) ); + if ( fVerbose ) + { + printf( "Min-cut = %4d. Unmoved = %4d. ", Vec_PtrSize(vNodes), Counter ); + ABC_PRT( "Time", clock() - clk ); + } + return vNodes; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/nwk/nwkFlow_depth.c b/src/opt/nwk/nwkFlow_depth.c new file mode 100644 index 00000000..6c2e7eb9 --- /dev/null +++ b/src/opt/nwk/nwkFlow_depth.c @@ -0,0 +1,631 @@ +/**CFile**************************************************************** + + FileName [nwkFlow.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Netlist representation.] + + Synopsis [Max-flow/min-cut computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: nwkFlow.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "nwk.h" + +ABC_NAMESPACE_IMPL_START + + +/* + This code is based on the papers: + A. Hurst, A. Mishchenko, and R. Brayton, "Fast minimum-register retiming + via binary maximum-flow", Proc. FMCAD '07, pp. 181-187. + A. Hurst, A. Mishchenko, and R. Brayton, "Scalable min-area retiming + under simultaneous delay and initial state constraints". Proc. DAC'08. +*/ + +int DepthFwd, DepthBwd, DepthFwdMax, DepthBwdMax; + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// predecessors +static inline Nwk_Obj_t * Nwk_ObjPred( Nwk_Obj_t * pObj ) { return pObj->pCopy; } +static inline int Nwk_ObjSetPred( Nwk_Obj_t * pObj, Nwk_Obj_t * p ) { pObj->pCopy = p; return 1; } +// sink +static inline int Nwk_ObjIsSink( Nwk_Obj_t * pObj ) { return pObj->MarkA; } +static inline void Nwk_ObjSetSink( Nwk_Obj_t * pObj ) { pObj->MarkA = 1; } +// flow +static inline int Nwk_ObjHasFlow( Nwk_Obj_t * pObj ) { return pObj->MarkB; } +static inline void Nwk_ObjSetFlow( Nwk_Obj_t * pObj ) { pObj->MarkB = 1; } +static inline void Nwk_ObjClearFlow( Nwk_Obj_t * pObj ) { pObj->MarkB = 0; } + +// representation of visited nodes +// pObj->TravId < pNtk->nTravIds-2 --- not visited +// pObj->TravId == pNtk->nTravIds-2 --- visited bot only +// pObj->TravId == pNtk->nTravIds-1 --- visited top only +// pObj->TravId == pNtk->nTravIds --- visited bot and top +static inline int Nwk_ObjVisitedBotOnly( Nwk_Obj_t * pObj ) +{ + return pObj->TravId == pObj->pMan->nTravIds - 2; +} +static inline int Nwk_ObjVisitedBot( Nwk_Obj_t * pObj ) +{ + return pObj->TravId == pObj->pMan->nTravIds - 2 || pObj->TravId == pObj->pMan->nTravIds; +} +static inline int Nwk_ObjVisitedTop( Nwk_Obj_t * pObj ) +{ + return pObj->TravId == pObj->pMan->nTravIds - 1 || pObj->TravId == pObj->pMan->nTravIds; +} +static inline void Nwk_ObjSetVisitedBot( Nwk_Obj_t * pObj ) +{ + if ( pObj->TravId < pObj->pMan->nTravIds - 2 ) + pObj->TravId = pObj->pMan->nTravIds - 2; + else if ( pObj->TravId == pObj->pMan->nTravIds - 1 ) + pObj->TravId = pObj->pMan->nTravIds; + else + assert( 0 ); +} +static inline void Nwk_ObjSetVisitedTop( Nwk_Obj_t * pObj ) +{ + if ( pObj->TravId < pObj->pMan->nTravIds - 2 ) + pObj->TravId = pObj->pMan->nTravIds - 1; + else if ( pObj->TravId == pObj->pMan->nTravIds - 2 ) + pObj->TravId = pObj->pMan->nTravIds; + else + assert( 0 ); +} +static inline Nwk_ManIncrementTravIdFlow( Nwk_Man_t * pMan ) +{ + Nwk_ManIncrementTravId( pMan ); + Nwk_ManIncrementTravId( pMan ); + Nwk_ManIncrementTravId( pMan ); +} + +static int Nwk_ManPushForwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ); +static int Nwk_ManPushForwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ); + +static int Nwk_ManPushBackwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ); +static int Nwk_ManPushBackwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Marks TFI of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManMarkTfiCone_rec( Nwk_Obj_t * pObj ) +{ + Nwk_Obj_t * pNext; + int i; + if ( pObj->MarkA ) + return; + pObj->MarkA = 1; + Nwk_ObjForEachFanin( pObj, pNext, i ) + Nwk_ManMarkTfiCone_rec( pNext ); +} + +/**Function************************************************************* + + Synopsis [Marks TFO of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManMarkTfoCone_rec( Nwk_Obj_t * pObj ) +{ + Nwk_Obj_t * pNext; + int i; + if ( pObj->MarkA ) + return; + pObj->MarkA = 1; + Nwk_ObjForEachFanout( pObj, pNext, i ) + Nwk_ManMarkTfoCone_rec( pNext ); +} + +/**Function************************************************************* + + Synopsis [Fast forward flow pushing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManPushForwardFast_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) +{ + Nwk_Obj_t * pNext; + int i; + if ( Nwk_ObjIsTravIdCurrent( pObj ) ) + return 0; + Nwk_ObjSetTravIdCurrent( pObj ); + if ( Nwk_ObjHasFlow(pObj) ) + return 0; + if ( Nwk_ObjIsSink(pObj) ) + { + Nwk_ObjSetFlow(pObj); + return Nwk_ObjSetPred( pObj, pPred ); + } + Nwk_ObjForEachFanout( pObj, pNext, i ) + if ( Nwk_ManPushForwardFast_rec( pNext, pObj ) ) + { + Nwk_ObjSetFlow(pObj); + return Nwk_ObjSetPred( pObj, pPred ); + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Fast backward flow pushing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManPushBackwardFast_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) +{ + Nwk_Obj_t * pNext; + int i; + if ( Nwk_ObjIsTravIdCurrent( pObj ) ) + return 0; + Nwk_ObjSetTravIdCurrent( pObj ); + if ( Nwk_ObjHasFlow(pObj) ) + return 0; + if ( Nwk_ObjIsSink(pObj) ) + { + Nwk_ObjSetFlow(pObj); + return Nwk_ObjSetPred( pObj, pPred ); + } + Nwk_ObjForEachFanin( pObj, pNext, i ) + if ( Nwk_ManPushBackwardFast_rec( pNext, pObj ) ) + { + Nwk_ObjSetFlow(pObj); + return Nwk_ObjSetPred( pObj, pPred ); + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Pushing the flow through the bottom part of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManPushForwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) +{ + Nwk_Obj_t * pNext; + int i; + if ( Nwk_ObjVisitedBot(pObj) ) + return 0; + Nwk_ObjSetVisitedBot(pObj); + DepthFwd++; + if ( DepthFwdMax < DepthFwd ) + DepthFwdMax = DepthFwd; + // propagate through the internal edge + if ( Nwk_ObjHasFlow(pObj) ) + { + if ( Nwk_ObjPred(pObj) ) + if ( Nwk_ManPushForwardTop_rec( Nwk_ObjPred(pObj), Nwk_ObjPred(pObj) ) ) + { + DepthFwd--; + return Nwk_ObjSetPred( pObj, pPred ); + } + } + else if ( Nwk_ManPushForwardTop_rec(pObj, pObj) ) + { + DepthFwd--; + Nwk_ObjSetFlow( pObj ); + return Nwk_ObjSetPred( pObj, pPred ); + } + // try to push through the fanins + Nwk_ObjForEachFanin( pObj, pNext, i ) + if ( Nwk_ManPushForwardBot_rec( pNext, pPred ) ) + { + DepthFwd--; + return 1; + } + DepthFwd--; + return 0; +} + +/**Function************************************************************* + + Synopsis [Pushing the flow through the top part of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManPushForwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) +{ + Nwk_Obj_t * pNext; + int i; + if ( Nwk_ObjVisitedTop(pObj) ) + return 0; + Nwk_ObjSetVisitedTop(pObj); + // check if this is the sink + if ( Nwk_ObjIsSink(pObj) ) + return 1; + DepthFwd++; + if ( DepthFwdMax < DepthFwd ) + DepthFwdMax = DepthFwd; + // try to push through the fanouts + Nwk_ObjForEachFanout( pObj, pNext, i ) + if ( Nwk_ManPushForwardBot_rec( pNext, pPred ) ) + { + DepthFwd--; + return 1; + } + // redirect the flow + if ( Nwk_ObjHasFlow(pObj) && !Nwk_ObjIsCi(pObj) ) + if ( Nwk_ManPushForwardBot_rec( pObj, Nwk_ObjPred(pObj) ) ) + { + DepthFwd--; + Nwk_ObjClearFlow( pObj ); + return Nwk_ObjSetPred( pObj, NULL ); + } + DepthFwd--; + return 0; +} + +/**Function************************************************************* + + Synopsis [Pushing the flow through the bottom part of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManPushBackwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) +{ + if ( Nwk_ObjVisitedBot(pObj) ) + return 0; + Nwk_ObjSetVisitedBot(pObj); + // propagate through the internal edge + if ( Nwk_ObjHasFlow(pObj) ) + { + if ( Nwk_ObjPred(pObj) ) + if ( Nwk_ManPushBackwardTop_rec( Nwk_ObjPred(pObj), Nwk_ObjPred(pObj) ) ) + return Nwk_ObjSetPred( pObj, pPred ); + } + else if ( Nwk_ManPushBackwardTop_rec(pObj, pObj) ) + { + Nwk_ObjSetFlow( pObj ); + return Nwk_ObjSetPred( pObj, pPred ); + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Pushing the flow through the top part of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManPushBackwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) +{ + Nwk_Obj_t * pNext; + int i; + if ( Nwk_ObjVisitedTop(pObj) ) + return 0; + Nwk_ObjSetVisitedTop(pObj); + // check if this is the sink + if ( Nwk_ObjIsSink(pObj) ) + return 1; + // try to push through the fanins + Nwk_ObjForEachFanin( pObj, pNext, i ) + if ( Nwk_ManPushBackwardBot_rec( pNext, pPred ) ) + return 1; + // try to push through the fanouts + Nwk_ObjForEachFanout( pObj, pNext, i ) + if ( !Nwk_ObjIsCo(pObj) && Nwk_ManPushBackwardTop_rec( pNext, pPred ) ) + return 1; + // redirect the flow + if ( Nwk_ObjHasFlow(pObj) ) + if ( Nwk_ObjPred(pObj) && Nwk_ManPushBackwardBot_rec( pObj, Nwk_ObjPred(pObj) ) ) + { + Nwk_ObjClearFlow( pObj ); + return Nwk_ObjSetPred( pObj, NULL ); + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 0 if there is an unmarked path to a CI.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManVerifyCut_rec( Nwk_Obj_t * pObj ) +{ + Nwk_Obj_t * pNext; + int i; + if ( pObj->MarkA ) + return 1; + if ( Nwk_ObjIsLo(pObj) ) + return 0; + if ( Nwk_ObjIsTravIdCurrent( pObj ) ) + return 1; + Nwk_ObjSetTravIdCurrent( pObj ); + Nwk_ObjForEachFanin( pObj, pNext, i ) + if ( !Nwk_ManVerifyCut_rec( pNext ) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Verifies the forward cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManRetimeVerifyCutForward( Nwk_Man_t * pMan, Vec_Ptr_t * vNodes ) +{ + Nwk_Obj_t * pObj; + int i; + // mark the nodes + Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i ) + { + assert( pObj->MarkA == 0 ); + pObj->MarkA = 1; + } + // traverse from the COs + Nwk_ManIncrementTravId( pMan ); + Nwk_ManForEachCo( pMan, pObj, i ) + if ( !Nwk_ManVerifyCut_rec( pObj ) ) + printf( "Nwk_ManRetimeVerifyCutForward(): Internal cut verification failed.\n" ); + // unmark the nodes + Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i ) + pObj->MarkA = 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Verifies the forward cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManRetimeVerifyCutBackward( Nwk_Man_t * pMan, Vec_Ptr_t * vNodes ) +{ + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes minimum cut for forward retiming.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Nwk_ManRetimeCutForward( Nwk_Man_t * pMan, int nLatches, int fVerbose ) +{ + Vec_Ptr_t * vNodes; + Nwk_Obj_t * pObj; + int i, RetValue, Counter = 0, Counter2 = 0; + int clk = clock(); + // set the sequential parameters + pMan->nLatches = nLatches; + pMan->nTruePis = Nwk_ManCiNum(pMan) - nLatches; + pMan->nTruePos = Nwk_ManCoNum(pMan) - nLatches; + // mark the COs and the TFO of PIs + Nwk_ManForEachCo( pMan, pObj, i ) + pObj->MarkA = 1; + Nwk_ManForEachPiSeq( pMan, pObj, i ) + Nwk_ManMarkTfoCone_rec( pObj ); + // start flow computation from each LO + Nwk_ManIncrementTravIdFlow( pMan ); + Nwk_ManForEachLoSeq( pMan, pObj, i ) + { + if ( !Nwk_ManPushForwardFast_rec( pObj, NULL ) ) + continue; + Nwk_ManIncrementTravIdFlow( pMan ); + Counter++; + } + if ( fVerbose ) + printf( "Forward: Max-flow = %4d -> ", Counter ); + // continue flow computation from each LO + DepthFwdMax = DepthFwd = 0; + Nwk_ManIncrementTravIdFlow( pMan ); + Nwk_ManForEachLoSeq( pMan, pObj, i ) + { + printf( "%d ", DepthFwdMax ); + if ( !Nwk_ManPushForwardBot_rec( pObj, NULL ) ) + continue; + assert( DepthFwd == 0 ); + Nwk_ManIncrementTravIdFlow( pMan ); + Counter2++; + } + printf( "DepthMax = %d.\n", DepthFwdMax ); + if ( fVerbose ) + printf( "%4d. ", Counter+Counter2 ); + // repeat flow computation from each LO + if ( Counter2 > 0 ) + { + Nwk_ManIncrementTravIdFlow( pMan ); + Nwk_ManForEachLoSeq( pMan, pObj, i ) + { + RetValue = Nwk_ManPushForwardBot_rec( pObj, NULL ); + assert( !RetValue ); + } + } + // cut is a set of nodes whose bottom is visited but top is not visited + vNodes = Vec_PtrAlloc( Counter+Counter2 ); + Counter = 0; + Nwk_ManForEachObj( pMan, pObj, i ) + { + if ( Nwk_ObjVisitedBotOnly(pObj) ) + { + assert( Nwk_ObjHasFlow(pObj) ); + assert( !Nwk_ObjIsCo(pObj) ); + Vec_PtrPush( vNodes, pObj ); + Counter += Nwk_ObjIsCi(pObj); + } + } + Nwk_ManCleanMarks( pMan ); + assert( Nwk_ManRetimeVerifyCutForward(pMan, vNodes) ); + if ( fVerbose ) + { + printf( "Min-cut = %4d. Unmoved = %4d. ", Vec_PtrSize(vNodes), Counter ); + PRT( "Time", clock() - clk ); + } + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Computes minimum cut for backward retiming.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Nwk_ManRetimeCutBackward( Nwk_Man_t * pMan, int nLatches, int fVerbose ) +{ + Vec_Ptr_t * vNodes; + Nwk_Obj_t * pObj; + int i, RetValue, Counter = 0, Counter2 = 0; + int clk = clock(); + // set the sequential parameters + pMan->nLatches = nLatches; + pMan->nTruePis = Nwk_ManCiNum(pMan) - nLatches; + pMan->nTruePos = Nwk_ManCoNum(pMan) - nLatches; + // mark the CIs, the TFI of POs, and the constant nodes + Nwk_ManForEachCi( pMan, pObj, i ) + pObj->MarkA = 1; + Nwk_ManForEachPoSeq( pMan, pObj, i ) + Nwk_ManMarkTfiCone_rec( pObj ); + Nwk_ManForEachNode( pMan, pObj, i ) + if ( Nwk_ObjFaninNum(pObj) == 0 ) + pObj->MarkA = 1; + // start flow computation from each LI driver + Nwk_ManIncrementTravIdFlow( pMan ); + Nwk_ManForEachLiSeq( pMan, pObj, i ) + { + if ( !Nwk_ManPushBackwardFast_rec( Nwk_ObjFanin0(pObj), NULL ) ) + continue; + Nwk_ManIncrementTravIdFlow( pMan ); + Counter++; + } + if ( fVerbose ) + printf( "Backward: Max-flow = %4d -> ", Counter ); + // continue flow computation from each LI driver + Nwk_ManIncrementTravIdFlow( pMan ); + Nwk_ManForEachLiSeq( pMan, pObj, i ) + { + if ( !Nwk_ManPushBackwardBot_rec( Nwk_ObjFanin0(pObj), NULL ) ) + continue; + Nwk_ManIncrementTravIdFlow( pMan ); + Counter2++; + } + if ( fVerbose ) + printf( "%4d. ", Counter+Counter2 ); + // repeat flow computation from each LI driver + if ( Counter2 > 0 ) + { + Nwk_ManIncrementTravIdFlow( pMan ); + Nwk_ManForEachLiSeq( pMan, pObj, i ) + { + RetValue = Nwk_ManPushBackwardBot_rec( Nwk_ObjFanin0(pObj), NULL ); + assert( !RetValue ); + } + } + // cut is a set of nodes whose bottom is visited but top is not visited + vNodes = Vec_PtrAlloc( Counter+Counter2 ); + Nwk_ManForEachObj( pMan, pObj, i ) + { + if ( Nwk_ObjVisitedBotOnly(pObj) ) + { + assert( Nwk_ObjHasFlow(pObj) ); + assert( !Nwk_ObjIsCo(pObj) ); + Vec_PtrPush( vNodes, pObj ); + } + } + // count CO drivers + Counter = 0; + Nwk_ManForEachLiSeq( pMan, pObj, i ) + if ( Nwk_ObjVisitedBotOnly( Nwk_ObjFanin0(pObj) ) ) + Counter++; + Nwk_ManCleanMarks( pMan ); + assert( Nwk_ManRetimeVerifyCutBackward(pMan, vNodes) ); + if ( fVerbose ) + { + printf( "Min-cut = %4d. Unmoved = %4d. ", Vec_PtrSize(vNodes), Counter ); + PRT( "Time", clock() - clk ); + } + return vNodes; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/nwk/nwkMan.c b/src/opt/nwk/nwkMan.c new file mode 100644 index 00000000..f286dc50 --- /dev/null +++ b/src/opt/nwk/nwkMan.c @@ -0,0 +1,278 @@ +/**CFile**************************************************************** + + FileName [nwkMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Logic network representation.] + + Synopsis [Network manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: nwkMan.c,v 1.1 2008/10/10 14:09:30 mjarvin Exp $] + +***********************************************************************/ + +#include "nwk.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Nwk_Man_t * Nwk_ManAlloc() +{ + Nwk_Man_t * p; + p = ABC_ALLOC( Nwk_Man_t, 1 ); + memset( p, 0, sizeof(Nwk_Man_t) ); + p->vCis = Vec_PtrAlloc( 1000 ); + p->vCos = Vec_PtrAlloc( 1000 ); + p->vObjs = Vec_PtrAlloc( 1000 ); + p->vTemp = Vec_PtrAlloc( 1000 ); + p->nFanioPlus = 2; + p->pMemObjs = Aig_MmFlexStart(); + p->pManHop = Hop_ManStart(); + return p; +} + +/**Function************************************************************* + + Synopsis [Deallocates the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManFree( Nwk_Man_t * p ) +{ +// printf( "The number of realloced nodes = %d.\n", p->nRealloced ); + if ( p->pName ) ABC_FREE( p->pName ); + if ( p->pSpec ) ABC_FREE( p->pSpec ); + if ( p->vCis ) Vec_PtrFree( p->vCis ); + if ( p->vCos ) Vec_PtrFree( p->vCos ); + if ( p->vObjs ) Vec_PtrFree( p->vObjs ); + if ( p->vTemp ) Vec_PtrFree( p->vTemp ); + if ( p->pManTime ) Tim_ManStop( p->pManTime ); + if ( p->pMemObjs ) Aig_MmFlexStop( p->pMemObjs, 0 ); + if ( p->pManHop ) Hop_ManStop( p->pManHop ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Prints stats of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManPrintLutSizes( Nwk_Man_t * p, If_Lib_t * pLutLib ) +{ + Nwk_Obj_t * pObj; + int i, Counters[256] = {0}; + Nwk_ManForEachNode( p, pObj, i ) + Counters[Nwk_ObjFaninNum(pObj)]++; + printf( "LUTs by size: " ); + for ( i = 0; i <= pLutLib->LutMax; i++ ) + printf( "%d:%d ", i, Counters[i] ); +} + +/**Function************************************************************* + + Synopsis [If the network is best, saves it in "best.blif" and returns 1.] + + Description [If the networks are incomparable, saves the new network, + returns its parameters in the internal parameter structure, and returns 1. + If the new network is not a logic network, quits without saving and returns 0.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManCompareAndSaveBest( Nwk_Man_t * pNtk, void * pNtl ) +{ +// extern void Ntl_WriteBlifLogic( Nwk_Man_t * pNtk, void * pNtl, char * pFileName ); + extern void Nwk_ManDumpBlif( Nwk_Man_t * pNtk, char * pFileName, Vec_Ptr_t * vPiNames, Vec_Ptr_t * vPoNames ); + static struct ParStruct { + char * pName; // name of the best saved network + int Depth; // depth of the best saved network + int Flops; // flops in the best saved network + int Nodes; // nodes in the best saved network + int nPis; // the number of primary inputs + int nPos; // the number of primary outputs + } ParsNew, ParsBest = { 0 }; + // free storage for the name + if ( pNtk == NULL ) + { + ABC_FREE( ParsBest.pName ); + return 0; + } + // get the parameters + ParsNew.Depth = Nwk_ManLevel( pNtk ); + ParsNew.Flops = Nwk_ManLatchNum( pNtk ); + ParsNew.Nodes = Nwk_ManNodeNum( pNtk ); + ParsNew.nPis = Nwk_ManPiNum( pNtk ); + ParsNew.nPos = Nwk_ManPoNum( pNtk ); + // reset the parameters if the network has the same name + if ( ParsBest.pName == NULL || + strcmp(ParsBest.pName, pNtk->pName) || + ParsBest.Depth > ParsNew.Depth || + (ParsBest.Depth == ParsNew.Depth && ParsBest.Flops > ParsNew.Flops) || + (ParsBest.Depth == ParsNew.Depth && ParsBest.Flops == ParsNew.Flops && ParsBest.Nodes > ParsNew.Nodes) ) + { + ABC_FREE( ParsBest.pName ); + ParsBest.pName = Abc_UtilStrsav( pNtk->pName ); + ParsBest.Depth = ParsNew.Depth; + ParsBest.Flops = ParsNew.Flops; + ParsBest.Nodes = ParsNew.Nodes; + ParsBest.nPis = ParsNew.nPis; + ParsBest.nPos = ParsNew.nPos; + // write the network +// Ntl_WriteBlifLogic( pNtk, pNtl, "best.blif" ); +// Nwk_ManDumpBlif( pNtk, "best_map.blif", NULL, NULL ); + return 1; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Nwk_FileNameGeneric( char * FileName ) +{ + char * pDot, * pRes; + pRes = Abc_UtilStrsav( FileName ); + if ( (pDot = strrchr( pRes, '.' )) ) + *pDot = 0; + return pRes; +} + +/**Function************************************************************* + + Synopsis [Marks nodes for power-optimization.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Nwl_ManComputeTotalSwitching( Nwk_Man_t * pNtk ) +{ + extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ); + Vec_Int_t * vSwitching; + float * pSwitching; + Aig_Man_t * pAig; + Aig_Obj_t * pObjAig; + Nwk_Obj_t * pObjAbc; + float Result = (float)0; + int i; + // strash the network + // map network into an AIG + pAig = Nwk_ManStrash( pNtk ); + vSwitching = Saig_ManComputeSwitchProbs( pAig, 48, 16, 0 ); + pSwitching = (float *)vSwitching->pArray; + Nwk_ManForEachObj( pNtk, pObjAbc, i ) + { + if ( (pObjAig = Aig_Regular((Aig_Obj_t *)pObjAbc->pCopy)) ) + Result += Nwk_ObjFanoutNum(pObjAbc) * pSwitching[pObjAig->Id]; + } + Vec_IntFree( vSwitching ); + Aig_ManStop( pAig ); + return Result; +} + +/**Function************************************************************* + + Synopsis [Prints stats of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManPrintStats( Nwk_Man_t * pNtk, If_Lib_t * pLutLib, int fSaveBest, int fDumpResult, int fPower, Ntl_Man_t * pNtl ) +{ +// extern int Ntl_ManLatchNum( Ntl_Man_t * p ); +// extern void Ntl_ManWriteBlifLogic( Nwk_Man_t * pNtk, void * pNtl, char * pFileName ); + if ( fSaveBest ) + Nwk_ManCompareAndSaveBest( pNtk, pNtl ); + if ( fDumpResult ) + { + char Buffer[1000] = {0}; + const char * pNameGen = pNtk->pSpec? Nwk_FileNameGeneric( pNtk->pSpec ) : "nameless_"; + sprintf( Buffer, "%s_dump.blif", pNameGen ); +// Ntl_ManWriteBlifLogic( pNtk, pNtl, Buffer ); +// sprintf( Buffer, "%s_dump_map.blif", pNameGen ); +// Nwk_ManDumpBlif( pNtk, Buffer, NULL, NULL ); + if ( pNtk->pSpec ) ABC_FREE( pNameGen ); + } + + pNtk->pLutLib = pLutLib; + printf( "%-15s : ", pNtk->pName ); + printf( "pi = %5d ", Nwk_ManPiNum(pNtk) ); + printf( "po = %5d ", Nwk_ManPoNum(pNtk) ); + printf( "ci = %5d ", Nwk_ManCiNum(pNtk) ); + printf( "co = %5d ", Nwk_ManCoNum(pNtk) ); +// printf( "lat = %5d ", Ntl_ManLatchNum(pNtl) ); + printf( "node = %5d ", Nwk_ManNodeNum(pNtk) ); + printf( "edge = %5d ", Nwk_ManGetTotalFanins(pNtk) ); + printf( "aig = %6d ", Nwk_ManGetAigNodeNum(pNtk) ); + printf( "lev = %3d ", Nwk_ManLevel(pNtk) ); +// printf( "lev2 = %3d ", Nwk_ManLevelBackup(pNtk) ); + printf( "delay = %5.2f ", Nwk_ManDelayTraceLut(pNtk) ); + if ( fPower ) + printf( "power = %7.2f ", Nwl_ManComputeTotalSwitching(pNtk) ); + Nwk_ManPrintLutSizes( pNtk, pLutLib ); + printf( "\n" ); +// Nwk_ManDelayTracePrint( pNtk, pLutLib ); + fflush( stdout ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/nwk/nwkMap.c b/src/opt/nwk/nwkMap.c new file mode 100644 index 00000000..61ee50e8 --- /dev/null +++ b/src/opt/nwk/nwkMap.c @@ -0,0 +1,396 @@ +/**CFile**************************************************************** + + FileName [nwkMap.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Logic network representation.] + + Synopsis [Interface to technology mapping.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: nwkMap.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "nwk.h" +#include "src/map/if/if.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Load the network into FPGA manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_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->Epsilon = (float)0.005; + pPars->fPreprocess = 1; + pPars->fArea = 0; + pPars->fFancy = 0; + pPars->fExpRed = 1; //// + pPars->fLatchPaths = 0; + pPars->fEdge = 1; + pPars->fPower = 0; + pPars->fCutMin = 0; + pPars->fSeqMap = 0; + pPars->fVerbose = 0; + // internal parameters + pPars->fTruth = 0; + 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 * Nwk_ManToIf( Aig_Man_t * p, If_Par_t * pPars, Vec_Ptr_t * vAigToIf ) +{ + extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ); + Vec_Int_t * vSwitching = NULL, * vSwitching2 = NULL; + float * pSwitching, * pSwitching2; + If_Man_t * pIfMan; + If_Obj_t * pIfObj; + Aig_Obj_t * pNode, * pFanin, * pPrev; + int i, clk = clock(); + // set the number of registers (switch activity will be combinational) + Aig_ManSetRegNum( p, 0 ); + if ( pPars->fPower ) + { + vSwitching = Saig_ManComputeSwitchProbs( p, 48, 16, 0 ); + if ( pPars->fVerbose ) + { + ABC_PRT( "Computing switching activity", clock() - clk ); + } + pSwitching = (float *)vSwitching->pArray; + vSwitching2 = Vec_IntStart( Aig_ManObjNumMax(p) ); + pSwitching2 = (float *)vSwitching2->pArray; + } + // start the mapping manager and set its parameters + pIfMan = If_ManStart( pPars ); + pIfMan->vSwitching = vSwitching2; + // load the AIG into the mapper + Aig_ManForEachObj( p, pNode, i ) + { + if ( Aig_ObjIsAnd(pNode) ) + { + pIfObj = 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) ) ); +// printf( "no%d=%d\n ", If_ObjId(pIfObj), If_ObjLevel(pIfObj) ); + } + else if ( Aig_ObjIsPi(pNode) ) + { + pIfObj = If_ManCreateCi( pIfMan ); + If_ObjSetLevel( pIfObj, Aig_ObjLevel(pNode) ); +// printf( "pi%d=%d\n ", If_ObjId(pIfObj), If_ObjLevel(pIfObj) ); + if ( pIfMan->nLevelMax < (int)pIfObj->Level ) + pIfMan->nLevelMax = (int)pIfObj->Level; + } + else if ( Aig_ObjIsPo(pNode) ) + { + pIfObj = If_ManCreateCo( pIfMan, If_NotCond( (If_Obj_t *)Aig_ObjFanin0(pNode)->pData, Aig_ObjFaninC0(pNode) ) ); +// printf( "po%d=%d\n ", If_ObjId(pIfObj), If_ObjLevel(pIfObj) ); + } + else if ( Aig_ObjIsConst1(pNode) ) + pIfObj = If_ManConst1( pIfMan ); + else // add the node to the mapper + assert( 0 ); + // save the result + assert( Vec_PtrEntry(vAigToIf, i) == NULL ); + Vec_PtrWriteEntry( vAigToIf, i, pIfObj ); + pNode->pData = pIfObj; + if ( vSwitching2 ) + pSwitching2[pIfObj->Id] = pSwitching[pNode->Id]; + // set up the choice node + if ( Aig_ObjIsChoice( p, pNode ) ) + { + pIfMan->nChoices++; + for ( pPrev = pNode, pFanin = Aig_ObjEquiv(p, pNode); pFanin; pPrev = pFanin, pFanin = Aig_ObjEquiv(p, pFanin) ) + If_ObjSetChoice( (If_Obj_t *)pPrev->pData, (If_Obj_t *)pFanin->pData ); + If_ManCreateChoice( pIfMan, (If_Obj_t *)pNode->pData ); + } +// assert( If_ObjLevel(pIfObj) == Aig_ObjLevel(pNode) ); + } + if ( vSwitching ) + Vec_IntFree( vSwitching ); + return pIfMan; +} + + +/**Function************************************************************* + + Synopsis [Recursively derives the local AIG for the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Nwk_NodeIfToHop2_rec( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited ) +{ + If_Cut_t * pCut; + If_Obj_t * pTemp; + 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 (Hop_Obj_t *)If_CutData(pCut); + // mark the node as visited + Vec_PtrPush( vVisited, pCut ); + // insert the worst case + If_CutSetData( pCut, (void *)1 ); + // skip in case of primary input + if ( If_ObjIsCi(pIfObj) ) + return (Hop_Obj_t *)If_CutData(pCut); + // compute the functions of the children + for ( pTemp = pIfObj; pTemp; pTemp = pTemp->pEquiv ) + { + gFunc0 = Nwk_NodeIfToHop2_rec( pHopMan, pIfMan, pTemp->pFanin0, vVisited ); + if ( gFunc0 == (void *)1 ) + continue; + gFunc1 = Nwk_NodeIfToHop2_rec( pHopMan, pIfMan, pTemp->pFanin1, vVisited ); + if ( gFunc1 == (void *)1 ) + continue; + // both branches are solved + gFunc = Hop_And( pHopMan, Hop_NotCond(gFunc0, pTemp->fCompl0), Hop_NotCond(gFunc1, pTemp->fCompl1) ); + if ( pTemp->fPhase != pIfObj->fPhase ) + gFunc = Hop_Not(gFunc); + If_CutSetData( pCut, gFunc ); + break; + } + return (Hop_Obj_t *)If_CutData(pCut); +} + +/**Function************************************************************* + + Synopsis [Derives the local AIG for the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Nwk_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 = Nwk_NodeIfToHop2_rec( pHopMan, pIfMan, pIfObj, pIfMan->vTemp ); + if ( gFunc == (void *)1 ) + { + printf( "Nwk_NodeIfToHop(): Computing local AIG has failed.\n" ); + return NULL; + } +// printf( "%d ", Vec_PtrSize(p->vTemp) ); + // clean the cuts + If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) + If_CutSetData( If_ObjCutBest(pLeaf), NULL ); + Vec_PtrForEachEntry( If_Cut_t *, pIfMan->vTemp, pCut, i ) + If_CutSetData( pCut, NULL ); + return gFunc; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Nwk_Man_t * Nwk_ManFromIf( If_Man_t * pIfMan, Aig_Man_t * p, Vec_Ptr_t * vAigToIf ) +{ + Vec_Ptr_t * vIfToAig; + Nwk_Man_t * pNtk; + Nwk_Obj_t * pObjNew; + Aig_Obj_t * pObj, * pObjRepr; + If_Obj_t * pIfObj; + If_Cut_t * pCutBest; + int i, k, nLeaves, * ppLeaves; + assert( Aig_ManPiNum(p) == If_ManCiNum(pIfMan) ); + assert( Aig_ManPoNum(p) == If_ManCoNum(pIfMan) ); + assert( Aig_ManNodeNum(p) == If_ManAndNum(pIfMan) ); + Aig_ManCleanData( p ); + If_ManCleanCutData( pIfMan ); + // create mapping of IF to AIG + vIfToAig = Vec_PtrStart( If_ManObjNum(pIfMan) ); + Aig_ManForEachObj( p, pObj, i ) + { + pIfObj = (If_Obj_t *)Vec_PtrEntry( vAigToIf, i ); + Vec_PtrWriteEntry( vIfToAig, pIfObj->Id, pObj ); + } + // construct the network + pNtk = Nwk_ManAlloc(); + pNtk->pName = Abc_UtilStrsav( p->pName ); + pNtk->pSpec = Abc_UtilStrsav( p->pSpec ); +// pNtk->nLatches = Aig_ManRegNum(p); +// pNtk->nTruePis = Nwk_ManCiNum(pNtk) - pNtk->nLatches; +// pNtk->nTruePos = Nwk_ManCoNum(pNtk) - pNtk->nLatches; + Aig_ManForEachObj( p, pObj, i ) + { + pIfObj = (If_Obj_t *)Vec_PtrEntry( vAigToIf, i ); + if ( pIfObj->nRefs == 0 && !If_ObjIsTerm(pIfObj) ) + continue; + if ( Aig_ObjIsNode(pObj) ) + { + pCutBest = If_ObjCutBest( pIfObj ); + nLeaves = If_CutLeaveNum( pCutBest ); + ppLeaves = If_CutLeaves( pCutBest ); + // create node + pObjNew = Nwk_ManCreateNode( pNtk, nLeaves, pIfObj->nRefs ); + for ( k = 0; k < nLeaves; k++ ) + { + pObjRepr = (Aig_Obj_t *)Vec_PtrEntry( vIfToAig, ppLeaves[k] ); + Nwk_ObjAddFanin( pObjNew, (Nwk_Obj_t *)pObjRepr->pData ); + } + // get the functionality + pObjNew->pFunc = Nwk_NodeIfToHop( pNtk->pManHop, pIfMan, pIfObj ); + } + else if ( Aig_ObjIsPi(pObj) ) + pObjNew = Nwk_ManCreateCi( pNtk, pIfObj->nRefs ); + else if ( Aig_ObjIsPo(pObj) ) + { + pObjNew = Nwk_ManCreateCo( pNtk ); + pObjNew->fInvert = Aig_ObjFaninC0(pObj); + Nwk_ObjAddFanin( pObjNew, (Nwk_Obj_t *)Aig_ObjFanin0(pObj)->pData ); +//printf( "%d ", pObjNew->Id ); + } + else if ( Aig_ObjIsConst1(pObj) ) + { + pObjNew = Nwk_ManCreateNode( pNtk, 0, pIfObj->nRefs ); + pObjNew->pFunc = Hop_ManConst1( pNtk->pManHop ); + } + else + assert( 0 ); + pObj->pData = pObjNew; + } +//printf( "\n" ); + Vec_PtrFree( vIfToAig ); + pNtk->pManTime = Tim_ManDup( pIfMan->pManTim, 0 ); + Nwk_ManMinimumBase( pNtk, 0 ); + assert( Nwk_ManCheck( pNtk ) ); + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Interface with the FPGA mapping package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Nwk_Man_t * Nwk_MappingIf( Aig_Man_t * p, Tim_Man_t * pManTime, If_Par_t * pPars ) +{ + Nwk_Man_t * pNtk; + If_Man_t * pIfMan; + Vec_Ptr_t * vAigToIf; + // set the arrival times + pPars->pTimesArr = ABC_ALLOC( float, Aig_ManPiNum(p) ); + memset( pPars->pTimesArr, 0, sizeof(float) * Aig_ManPiNum(p) ); + // translate into the mapper + vAigToIf = Vec_PtrStart( Aig_ManObjNumMax(p) ); + pIfMan = Nwk_ManToIf( p, pPars, vAigToIf ); + if ( pIfMan == NULL ) + return NULL; + pIfMan->pManTim = Tim_ManDup( pManTime, 0 ); + pIfMan->pPars->fCutMin = 0; // is not compatible with deriving result + if ( !If_ManPerformMapping( pIfMan ) ) + { + If_ManStop( pIfMan ); + return NULL; + } + // transform the result of mapping into the new network + pNtk = Nwk_ManFromIf( pIfMan, p, vAigToIf ); + if ( pPars->fBidec && pPars->nLutSize <= 8 ) + Nwk_ManBidecResyn( pNtk, 0 ); + If_ManStop( pIfMan ); + Vec_PtrFree( vAigToIf ); + return pNtk; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/nwk/nwkMerge.c b/src/opt/nwk/nwkMerge.c new file mode 100644 index 00000000..fa9f7c78 --- /dev/null +++ b/src/opt/nwk/nwkMerge.c @@ -0,0 +1,1044 @@ +/**CFile**************************************************************** + + FileName [nwkMerge.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Netlist representation.] + + Synopsis [LUT merging algorithm.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: nwkMerge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "nwk.h" +#include "nwkMerge.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates the graph.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Nwk_Grf_t * Nwk_ManGraphAlloc( int nVertsMax ) +{ + Nwk_Grf_t * p; + p = ABC_ALLOC( Nwk_Grf_t, 1 ); + memset( p, 0, sizeof(Nwk_Grf_t) ); + p->nVertsMax = nVertsMax; + p->nEdgeHash = Abc_PrimeCudd( 3 * nVertsMax ); + p->pEdgeHash = ABC_CALLOC( Nwk_Edg_t *, p->nEdgeHash ); + p->pMemEdges = Aig_MmFixedStart( sizeof(Nwk_Edg_t), p->nEdgeHash ); + p->vPairs = Vec_IntAlloc( 1000 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Deallocates the graph.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManGraphFree( Nwk_Grf_t * p ) +{ + if ( p->vPairs ) Vec_IntFree( p->vPairs ); + if ( p->pMemEdges ) Aig_MmFixedStop( p->pMemEdges, 0 ); + if ( p->pMemVerts ) Aig_MmFlexStop( p->pMemVerts, 0 ); + ABC_FREE( p->pVerts ); + ABC_FREE( p->pEdgeHash ); + ABC_FREE( p->pMapLut2Id ); + ABC_FREE( p->pMapId2Lut ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Prepares the graph for solving the problem.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManGraphReportMemoryUsage( Nwk_Grf_t * p ) +{ + p->nMemBytes1 = + sizeof(Nwk_Grf_t) + + sizeof(void *) * p->nEdgeHash + + sizeof(int) * (p->nObjs + p->nVertsMax) + + sizeof(Nwk_Edg_t) * p->nEdges; + p->nMemBytes2 = + sizeof(Nwk_Vrt_t) * p->nVerts + + sizeof(int) * 2 * p->nEdges; + printf( "Memory usage stats: Preprocessing = %.2f Mb. Solving = %.2f Mb.\n", + 1.0 * p->nMemBytes1 / (1<<20), 1.0 * p->nMemBytes2 / (1<<20) ); +} + + +/**Function************************************************************* + + Synopsis [Finds or adds the edge to the graph.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManGraphHashEdge( Nwk_Grf_t * p, int iLut1, int iLut2 ) +{ + Nwk_Edg_t * pEntry; + unsigned Key; + if ( iLut1 == iLut2 ) + return; + if ( iLut1 > iLut2 ) + { + Key = iLut1; + iLut1 = iLut2; + iLut2 = Key; + } + assert( iLut1 < iLut2 ); + if ( p->nObjs < iLut2 ) + p->nObjs = iLut2; + Key = (unsigned)(741457 * iLut1 + 4256249 * iLut2) % p->nEdgeHash; + for ( pEntry = p->pEdgeHash[Key]; pEntry; pEntry = pEntry->pNext ) + if ( pEntry->iNode1 == iLut1 && pEntry->iNode2 == iLut2 ) + return; + pEntry = (Nwk_Edg_t *)Aig_MmFixedEntryFetch( p->pMemEdges ); + pEntry->iNode1 = iLut1; + pEntry->iNode2 = iLut2; + pEntry->pNext = p->pEdgeHash[Key]; + p->pEdgeHash[Key] = pEntry; + p->nEdges++; +} + +/**Function************************************************************* + + Synopsis [Adds one entry to the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Nwk_ManGraphListAdd( Nwk_Grf_t * p, int * pList, Nwk_Vrt_t * pVertex ) +{ + if ( *pList ) + { + Nwk_Vrt_t * pHead; + pHead = p->pVerts[*pList]; + pVertex->iPrev = 0; + pVertex->iNext = pHead->Id; + pHead->iPrev = pVertex->Id; + } + *pList = pVertex->Id; +} + +/**Function************************************************************* + + Synopsis [Deletes one entry from the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Nwk_ManGraphListDelete( Nwk_Grf_t * p, int * pList, Nwk_Vrt_t * pVertex ) +{ + assert( *pList ); + if ( pVertex->iPrev ) + { +// assert( p->pVerts[pVertex->iPrev]->iNext == pVertex->Id ); + p->pVerts[pVertex->iPrev]->iNext = pVertex->iNext; + } + if ( pVertex->iNext ) + { +// assert( p->pVerts[pVertex->iNext]->iPrev == pVertex->Id ); + p->pVerts[pVertex->iNext]->iPrev = pVertex->iPrev; + } + if ( *pList == pVertex->Id ) + *pList = pVertex->iNext; + pVertex->iPrev = pVertex->iNext = 0; +} + +/**Function************************************************************* + + Synopsis [Inserts the edge into one of the linked lists.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Nwk_ManGraphListInsert( Nwk_Grf_t * p, Nwk_Vrt_t * pVertex ) +{ + Nwk_Vrt_t * pNext; + assert( pVertex->nEdges > 0 ); + + if ( pVertex->nEdges == 1 ) + { + pNext = p->pVerts[ pVertex->pEdges[0] ]; + if ( pNext->nEdges >= NWK_MAX_LIST ) + Nwk_ManGraphListAdd( p, p->pLists1 + NWK_MAX_LIST, pVertex ); + else + Nwk_ManGraphListAdd( p, p->pLists1 + pNext->nEdges, pVertex ); + } + else + { + if ( pVertex->nEdges >= NWK_MAX_LIST ) + Nwk_ManGraphListAdd( p, p->pLists2 + NWK_MAX_LIST, pVertex ); + else + Nwk_ManGraphListAdd( p, p->pLists2 + pVertex->nEdges, pVertex ); + } +} + +/**Function************************************************************* + + Synopsis [Extracts the edge from one of the linked lists.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Nwk_ManGraphListExtract( Nwk_Grf_t * p, Nwk_Vrt_t * pVertex ) +{ + Nwk_Vrt_t * pNext; + assert( pVertex->nEdges > 0 ); + + if ( pVertex->nEdges == 1 ) + { + pNext = p->pVerts[ pVertex->pEdges[0] ]; + if ( pNext->nEdges >= NWK_MAX_LIST ) + Nwk_ManGraphListDelete( p, p->pLists1 + NWK_MAX_LIST, pVertex ); + else + Nwk_ManGraphListDelete( p, p->pLists1 + pNext->nEdges, pVertex ); + } + else + { + if ( pVertex->nEdges >= NWK_MAX_LIST ) + Nwk_ManGraphListDelete( p, p->pLists2 + NWK_MAX_LIST, pVertex ); + else + Nwk_ManGraphListDelete( p, p->pLists2 + pVertex->nEdges, pVertex ); + } +} + +/**Function************************************************************* + + Synopsis [Prepares the graph for solving the problem.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManGraphPrepare( Nwk_Grf_t * p ) +{ + Nwk_Edg_t * pEntry; + Nwk_Vrt_t * pVertex; + int * pnEdges, nBytes, i; + // allocate memory for the present objects + p->pMapLut2Id = ABC_ALLOC( int, p->nObjs+1 ); + p->pMapId2Lut = ABC_ALLOC( int, p->nVertsMax+1 ); + memset( p->pMapLut2Id, 0xff, sizeof(int) * (p->nObjs+1) ); + memset( p->pMapId2Lut, 0xff, sizeof(int) * (p->nVertsMax+1) ); + // mark present objects + Nwk_GraphForEachEdge( p, pEntry, i ) + { + assert( pEntry->iNode1 <= p->nObjs ); + assert( pEntry->iNode2 <= p->nObjs ); + p->pMapLut2Id[ pEntry->iNode1 ] = 0; + p->pMapLut2Id[ pEntry->iNode2 ] = 0; + } + // map objects + p->nVerts = 0; + for ( i = 0; i <= p->nObjs; i++ ) + { + if ( p->pMapLut2Id[i] == 0 ) + { + p->pMapLut2Id[i] = ++p->nVerts; + p->pMapId2Lut[p->nVerts] = i; + } + } + // count the edges and mark present objects + pnEdges = ABC_CALLOC( int, p->nVerts+1 ); + Nwk_GraphForEachEdge( p, pEntry, i ) + { + // translate into vertices + assert( pEntry->iNode1 <= p->nObjs ); + assert( pEntry->iNode2 <= p->nObjs ); + pEntry->iNode1 = p->pMapLut2Id[pEntry->iNode1]; + pEntry->iNode2 = p->pMapLut2Id[pEntry->iNode2]; + // count the edges + assert( pEntry->iNode1 <= p->nVerts ); + assert( pEntry->iNode2 <= p->nVerts ); + pnEdges[pEntry->iNode1]++; + pnEdges[pEntry->iNode2]++; + } + // allocate the real graph + p->pMemVerts = Aig_MmFlexStart(); + p->pVerts = ABC_ALLOC( Nwk_Vrt_t *, p->nVerts + 1 ); + p->pVerts[0] = NULL; + for ( i = 1; i <= p->nVerts; i++ ) + { + assert( pnEdges[i] > 0 ); + nBytes = sizeof(Nwk_Vrt_t) + sizeof(int) * pnEdges[i]; + p->pVerts[i] = (Nwk_Vrt_t *)Aig_MmFlexEntryFetch( p->pMemVerts, nBytes ); + memset( p->pVerts[i], 0, nBytes ); + p->pVerts[i]->Id = i; + } + // add edges to the real graph + Nwk_GraphForEachEdge( p, pEntry, i ) + { + pVertex = p->pVerts[pEntry->iNode1]; + pVertex->pEdges[ pVertex->nEdges++ ] = pEntry->iNode2; + pVertex = p->pVerts[pEntry->iNode2]; + pVertex->pEdges[ pVertex->nEdges++ ] = pEntry->iNode1; + } + // put vertices into the data structure + for ( i = 1; i <= p->nVerts; i++ ) + { + assert( p->pVerts[i]->nEdges == pnEdges[i] ); + Nwk_ManGraphListInsert( p, p->pVerts[i] ); + } + // clean up + Aig_MmFixedStop( p->pMemEdges, 0 ); p->pMemEdges = NULL; + ABC_FREE( p->pEdgeHash ); +// p->nEdgeHash = 0; + ABC_FREE( pnEdges ); +} + +/**Function************************************************************* + + Synopsis [Sort pairs by the first vertex in the topological order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManGraphSortPairs( Nwk_Grf_t * p ) +{ + int nSize = Vec_IntSize(p->vPairs); + int * pIdToPair, i; + // allocate storage + pIdToPair = ABC_ALLOC( int, p->nObjs+1 ); + for ( i = 0; i <= p->nObjs; i++ ) + pIdToPair[i] = -1; + // create mapping + for ( i = 0; i < p->vPairs->nSize; i += 2 ) + { + assert( pIdToPair[ p->vPairs->pArray[i] ] == -1 ); + pIdToPair[ p->vPairs->pArray[i] ] = p->vPairs->pArray[i+1]; + } + // recreate pairs + Vec_IntClear( p->vPairs ); + for ( i = 0; i <= p->nObjs; i++ ) + if ( pIdToPair[i] >= 0 ) + { + assert( i < pIdToPair[i] ); + Vec_IntPush( p->vPairs, i ); + Vec_IntPush( p->vPairs, pIdToPair[i] ); + } + assert( nSize == Vec_IntSize(p->vPairs) ); + ABC_FREE( pIdToPair ); +} + + +/**Function************************************************************* + + Synopsis [Updates the problem after pulling out one edge.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManGraphCheckLists( Nwk_Grf_t * p ) +{ + Nwk_Vrt_t * pVertex, * pNext; + int i, j; + assert( p->pLists1[0] == 0 ); + for ( i = 1; i <= NWK_MAX_LIST; i++ ) + if ( p->pLists1[i] ) + { + pVertex = p->pVerts[ p->pLists1[i] ]; + assert( pVertex->nEdges == 1 ); + pNext = p->pVerts[ pVertex->pEdges[0] ]; + assert( pNext->nEdges == i || pNext->nEdges > NWK_MAX_LIST ); + } + // find the next vertext to extract + assert( p->pLists2[0] == 0 ); + assert( p->pLists2[1] == 0 ); + for ( j = 2; j <= NWK_MAX_LIST; j++ ) + if ( p->pLists2[j] ) + { + pVertex = p->pVerts[ p->pLists2[j] ]; + assert( pVertex->nEdges == j || pVertex->nEdges > NWK_MAX_LIST ); + } +} + +/**Function************************************************************* + + Synopsis [Extracts the edge from one of the linked lists.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Nwk_ManGraphVertexRemoveEdge( Nwk_Vrt_t * pThis, Nwk_Vrt_t * pNext ) +{ + int k; + for ( k = 0; k < pThis->nEdges; k++ ) + if ( pThis->pEdges[k] == pNext->Id ) + break; + assert( k < pThis->nEdges ); + pThis->nEdges--; + for ( ; k < pThis->nEdges; k++ ) + pThis->pEdges[k] = pThis->pEdges[k+1]; +} + +/**Function************************************************************* + + Synopsis [Updates the problem after pulling out one edge.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManGraphUpdate( Nwk_Grf_t * p, Nwk_Vrt_t * pVertex, Nwk_Vrt_t * pNext ) +{ + Nwk_Vrt_t * pChanged, * pOther; + int i, k; +// Nwk_ManGraphCheckLists( p ); + Nwk_ManGraphListExtract( p, pVertex ); + Nwk_ManGraphListExtract( p, pNext ); + // update neihbors of pVertex + Nwk_VertexForEachAdjacent( p, pVertex, pChanged, i ) + { + if ( pChanged == pNext ) + continue; + Nwk_ManGraphListExtract( p, pChanged ); + // move those that use this one + if ( pChanged->nEdges > 1 ) + Nwk_VertexForEachAdjacent( p, pChanged, pOther, k ) + { + if ( pOther == pVertex || pOther->nEdges > 1 ) + continue; + assert( pOther->nEdges == 1 ); + Nwk_ManGraphListExtract( p, pOther ); + pChanged->nEdges--; + Nwk_ManGraphListInsert( p, pOther ); + pChanged->nEdges++; + } + // remove the edge + Nwk_ManGraphVertexRemoveEdge( pChanged, pVertex ); + // add the changed vertex back + if ( pChanged->nEdges > 0 ) + Nwk_ManGraphListInsert( p, pChanged ); + } + // update neihbors of pNext + Nwk_VertexForEachAdjacent( p, pNext, pChanged, i ) + { + if ( pChanged == pVertex ) + continue; + Nwk_ManGraphListExtract( p, pChanged ); + // move those that use this one + if ( pChanged->nEdges > 1 ) + Nwk_VertexForEachAdjacent( p, pChanged, pOther, k ) + { + if ( pOther == pNext || pOther->nEdges > 1 ) + continue; + assert( pOther->nEdges == 1 ); + Nwk_ManGraphListExtract( p, pOther ); + pChanged->nEdges--; + Nwk_ManGraphListInsert( p, pOther ); + pChanged->nEdges++; + } + // remove the edge + Nwk_ManGraphVertexRemoveEdge( pChanged, pNext ); + // add the changed vertex back + if ( pChanged->nEdges > 0 ) + Nwk_ManGraphListInsert( p, pChanged ); + } + // add to the result + if ( pVertex->Id < pNext->Id ) + { + Vec_IntPush( p->vPairs, p->pMapId2Lut[pVertex->Id] ); + Vec_IntPush( p->vPairs, p->pMapId2Lut[pNext->Id] ); + } + else + { + Vec_IntPush( p->vPairs, p->pMapId2Lut[pNext->Id] ); + Vec_IntPush( p->vPairs, p->pMapId2Lut[pVertex->Id] ); + } +// Nwk_ManGraphCheckLists( p ); +} + +/**Function************************************************************* + + Synopsis [Counts the number of entries in the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManGraphListLength( Nwk_Grf_t * p, int List ) +{ + Nwk_Vrt_t * pThis; + int fVerbose = 0; + int Counter = 0; + Nwk_ListForEachVertex( p, List, pThis ) + { + if ( fVerbose && Counter < 20 ) + printf( "%d ", p->pVerts[pThis->pEdges[0]]->nEdges ); + Counter++; + } + if ( fVerbose ) + printf( "\n" ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns the adjacent vertex with the mininum number of edges.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Nwk_Vrt_t * Nwk_ManGraphListFindMinEdge( Nwk_Grf_t * p, Nwk_Vrt_t * pVert ) +{ + Nwk_Vrt_t * pThis, * pMinCost = NULL; + int k; + Nwk_VertexForEachAdjacent( p, pVert, pThis, k ) + { + if ( pMinCost == NULL || pMinCost->nEdges > pThis->nEdges ) + pMinCost = pThis; + } + return pMinCost; +} + +/**Function************************************************************* + + Synopsis [Finds the best vertext in the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Nwk_Vrt_t * Nwk_ManGraphListFindMin( Nwk_Grf_t * p, int List ) +{ + Nwk_Vrt_t * pThis, * pMinCost = NULL; + int k, Counter = 10000, BestCost = 1000000; + Nwk_ListForEachVertex( p, List, pThis ) + { + for ( k = 0; k < pThis->nEdges; k++ ) + { + if ( pMinCost == NULL || BestCost > p->pVerts[pThis->pEdges[k]]->nEdges ) + { + BestCost = p->pVerts[pThis->pEdges[k]]->nEdges; + pMinCost = pThis; + } + } + if ( --Counter == 0 ) + break; + } + return pMinCost; +} + +/**Function************************************************************* + + Synopsis [Solves the problem by extracting one edge at a time.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManGraphSolve( Nwk_Grf_t * p ) +{ + Nwk_Vrt_t * pVertex, * pNext; + int i, j; + Nwk_ManGraphPrepare( p ); + while ( 1 ) + { + // find the next vertex to extract + assert( p->pLists1[0] == 0 ); + for ( i = 1; i <= NWK_MAX_LIST; i++ ) + if ( p->pLists1[i] ) + { +// printf( "%d ", i ); +// printf( "ListA = %2d. Length = %5d.\n", i, Nwk_ManGraphListLength(p,p->pLists1[i]) ); + pVertex = p->pVerts[ p->pLists1[i] ]; + assert( pVertex->nEdges == 1 ); + pNext = p->pVerts[ pVertex->pEdges[0] ]; + Nwk_ManGraphUpdate( p, pVertex, pNext ); + break; + } + if ( i < NWK_MAX_LIST + 1 ) + continue; + // find the next vertex to extract + assert( p->pLists2[0] == 0 ); + assert( p->pLists2[1] == 0 ); + for ( j = 2; j <= NWK_MAX_LIST; j++ ) + if ( p->pLists2[j] ) + { +// printf( "***%d ", j ); +// printf( "ListB = %2d. Length = %5d.\n", j, Nwk_ManGraphListLength(p,p->pLists2[j]) ); + pVertex = Nwk_ManGraphListFindMin( p, p->pLists2[j] ); + assert( pVertex->nEdges == j || j == NWK_MAX_LIST ); + pNext = Nwk_ManGraphListFindMinEdge( p, pVertex ); + Nwk_ManGraphUpdate( p, pVertex, pNext ); + break; + } + if ( j == NWK_MAX_LIST + 1 ) + break; + } + Nwk_ManGraphSortPairs( p ); +} + +/**Function************************************************************* + + Synopsis [Reads graph from file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Nwk_Grf_t * Nwk_ManLutMergeReadGraph( char * pFileName ) +{ + Nwk_Grf_t * p; + FILE * pFile; + char Buffer[100]; + int nNodes, nEdges, iNode1, iNode2; + pFile = fopen( pFileName, "r" ); + fscanf( pFile, "%s %d", Buffer, &nNodes ); + fscanf( pFile, "%s %d", Buffer, &nEdges ); + p = Nwk_ManGraphAlloc( nNodes ); + while ( fscanf( pFile, "%s %d %d", Buffer, &iNode1, &iNode2 ) == 3 ) + Nwk_ManGraphHashEdge( p, iNode1, iNode2 ); + assert( p->nEdges == nEdges ); + fclose( pFile ); + return p; +} + +/**Function************************************************************* + + Synopsis [Solves the graph coming from file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManLutMergeGraphTest( char * pFileName ) +{ + int nPairs; + Nwk_Grf_t * p; + int clk = clock(); + p = Nwk_ManLutMergeReadGraph( pFileName ); + ABC_PRT( "Reading", clock() - clk ); + clk = clock(); + Nwk_ManGraphSolve( p ); + printf( "GRAPH: Nodes = %6d. Edges = %6d. Pairs = %6d. ", + p->nVerts, p->nEdges, Vec_IntSize(p->vPairs)/2 ); + ABC_PRT( "Solving", clock() - clk ); + nPairs = Vec_IntSize(p->vPairs)/2; + Nwk_ManGraphReportMemoryUsage( p ); + Nwk_ManGraphFree( p ); + return nPairs; +} + + + + +/**Function************************************************************* + + Synopsis [Marks the fanins of the node with the current trav ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManMarkFanins_rec( Nwk_Obj_t * pLut, int nLevMin ) +{ + Nwk_Obj_t * pNext; + int i; + if ( !Nwk_ObjIsNode(pLut) ) + return; + if ( Nwk_ObjIsTravIdCurrent( pLut ) ) + return; + Nwk_ObjSetTravIdCurrent( pLut ); + if ( Nwk_ObjLevel(pLut) < nLevMin ) + return; + Nwk_ObjForEachFanin( pLut, pNext, i ) + Nwk_ManMarkFanins_rec( pNext, nLevMin ); +} + +/**Function************************************************************* + + Synopsis [Marks the fanouts of the node with the current trav ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManMarkFanouts_rec( Nwk_Obj_t * pLut, int nLevMax, int nFanMax ) +{ + Nwk_Obj_t * pNext; + int i; + if ( !Nwk_ObjIsNode(pLut) ) + return; + if ( Nwk_ObjIsTravIdCurrent( pLut ) ) + return; + Nwk_ObjSetTravIdCurrent( pLut ); + if ( Nwk_ObjLevel(pLut) > nLevMax ) + return; + if ( Nwk_ObjFanoutNum(pLut) > nFanMax ) + return; + Nwk_ObjForEachFanout( pLut, pNext, i ) + Nwk_ManMarkFanouts_rec( pNext, nLevMax, nFanMax ); +} + +/**Function************************************************************* + + Synopsis [Collects the circle of nodes around the given set.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManCollectCircle( Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, int nFanMax ) +{ + Nwk_Obj_t * pObj, * pNext; + int i, k; + Vec_PtrClear( vNext ); + Vec_PtrForEachEntry( Nwk_Obj_t *, vStart, pObj, i ) + { + Nwk_ObjForEachFanin( pObj, pNext, k ) + { + if ( !Nwk_ObjIsNode(pNext) ) + continue; + if ( Nwk_ObjIsTravIdCurrent( pNext ) ) + continue; + Nwk_ObjSetTravIdCurrent( pNext ); + Vec_PtrPush( vNext, pNext ); + } + Nwk_ObjForEachFanout( pObj, pNext, k ) + { + if ( !Nwk_ObjIsNode(pNext) ) + continue; + if ( Nwk_ObjIsTravIdCurrent( pNext ) ) + continue; + Nwk_ObjSetTravIdCurrent( pNext ); + if ( Nwk_ObjFanoutNum(pNext) > nFanMax ) + continue; + Vec_PtrPush( vNext, pNext ); + } + } +} + +/**Function************************************************************* + + Synopsis [Collects the circle of nodes removes from the given one.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManCollectNonOverlapCands( Nwk_Obj_t * pLut, Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars ) +{ + Vec_Ptr_t * vTemp; + Nwk_Obj_t * pObj; + int i, k; + Vec_PtrClear( vCands ); + if ( pPars->nMaxSuppSize - Nwk_ObjFaninNum(pLut) <= 1 ) + return; + + // collect nodes removed by this distance + assert( pPars->nMaxDistance > 0 ); + Vec_PtrClear( vStart ); + Vec_PtrPush( vStart, pLut ); + Nwk_ManIncrementTravId( pLut->pMan ); + Nwk_ObjSetTravIdCurrent( pLut ); + for ( i = 1; i <= pPars->nMaxDistance; i++ ) + { + Nwk_ManCollectCircle( vStart, vNext, pPars->nMaxFanout ); + vTemp = vStart; + vStart = vNext; + vNext = vTemp; + // collect the nodes in vStart + Vec_PtrForEachEntry( Nwk_Obj_t *, vStart, pObj, k ) + Vec_PtrPush( vCands, pObj ); + } + + // mark the TFI/TFO nodes + Nwk_ManIncrementTravId( pLut->pMan ); + if ( pPars->fUseTfiTfo ) + Nwk_ObjSetTravIdCurrent( pLut ); + else + { + Nwk_ObjSetTravIdPrevious( pLut ); + Nwk_ManMarkFanins_rec( pLut, Nwk_ObjLevel(pLut) - pPars->nMaxDistance ); + Nwk_ObjSetTravIdPrevious( pLut ); + Nwk_ManMarkFanouts_rec( pLut, Nwk_ObjLevel(pLut) + pPars->nMaxDistance, pPars->nMaxFanout ); + } + + // collect nodes satisfying the following conditions: + // - they are close enough in terms of distance + // - they are not in the TFI/TFO of the LUT + // - they have no more than the given number of fanins + // - they have no more than the given diff in delay + k = 0; + Vec_PtrForEachEntry( Nwk_Obj_t *, vCands, pObj, i ) + { + if ( Nwk_ObjIsTravIdCurrent(pObj) ) + continue; + if ( Nwk_ObjFaninNum(pLut) + Nwk_ObjFaninNum(pObj) > pPars->nMaxSuppSize ) + continue; + if ( Nwk_ObjLevel(pLut) - Nwk_ObjLevel(pObj) > pPars->nMaxLevelDiff || + Nwk_ObjLevel(pObj) - Nwk_ObjLevel(pLut) > pPars->nMaxLevelDiff ) + continue; + Vec_PtrWriteEntry( vCands, k++, pObj ); + } + Vec_PtrShrink( vCands, k ); +} + + +/**Function************************************************************* + + Synopsis [Count the total number of fanins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManCountTotalFanins( Nwk_Obj_t * pLut, Nwk_Obj_t * pCand ) +{ + Nwk_Obj_t * pFanin; + int i, nCounter = Nwk_ObjFaninNum(pLut); + Nwk_ObjForEachFanin( pCand, pFanin, i ) + nCounter += !pFanin->MarkC; + return nCounter; +} + +/**Function************************************************************* + + Synopsis [Collects overlapping candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManCollectOverlapCands( Nwk_Obj_t * pLut, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars ) +{ + Nwk_Obj_t * pFanin, * pObj; + int i, k; + // mark fanins of pLut + Nwk_ObjForEachFanin( pLut, pFanin, i ) + pFanin->MarkC = 1; + // collect the matching fanouts of each fanin of the node + Vec_PtrClear( vCands ); + Nwk_ManIncrementTravId( pLut->pMan ); + Nwk_ObjSetTravIdCurrent( pLut ); + Nwk_ObjForEachFanin( pLut, pFanin, i ) + { + if ( !Nwk_ObjIsNode(pFanin) ) + continue; + if ( Nwk_ObjFanoutNum(pFanin) > pPars->nMaxFanout ) + continue; + Nwk_ObjForEachFanout( pFanin, pObj, k ) + { + if ( !Nwk_ObjIsNode(pObj) ) + continue; + if ( Nwk_ObjIsTravIdCurrent( pObj ) ) + continue; + Nwk_ObjSetTravIdCurrent( pObj ); + // check the difference in delay + if ( Nwk_ObjLevel(pLut) - Nwk_ObjLevel(pObj) > pPars->nMaxLevelDiff || + Nwk_ObjLevel(pObj) - Nwk_ObjLevel(pLut) > pPars->nMaxLevelDiff ) + continue; + // check the total number of fanins of the node + if ( Nwk_ManCountTotalFanins(pLut, pObj) > pPars->nMaxSuppSize ) + continue; + Vec_PtrPush( vCands, pObj ); + } + } + // unmark fanins of pLut + Nwk_ObjForEachFanin( pLut, pFanin, i ) + pFanin->MarkC = 0; +} + +/**Function************************************************************* + + Synopsis [Performs LUT merging with parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Nwk_ManLutMerge( Nwk_Man_t * pNtk, void * pParsInit ) +{ + Nwk_LMPars_t * pPars = (Nwk_LMPars_t *)pParsInit; + Nwk_Grf_t * p; + Vec_Int_t * vResult; + Vec_Ptr_t * vStart, * vNext, * vCands1, * vCands2; + Nwk_Obj_t * pLut, * pCand; + int i, k, nVertsMax, nCands, clk = clock(); + // count the number of vertices + nVertsMax = 0; + Nwk_ManForEachNode( pNtk, pLut, i ) + nVertsMax += (int)(Nwk_ObjFaninNum(pLut) <= pPars->nMaxLutSize); + p = Nwk_ManGraphAlloc( nVertsMax ); + // create graph + vStart = Vec_PtrAlloc( 1000 ); + vNext = Vec_PtrAlloc( 1000 ); + vCands1 = Vec_PtrAlloc( 1000 ); + vCands2 = Vec_PtrAlloc( 1000 ); + nCands = 0; + Nwk_ManForEachNode( pNtk, pLut, i ) + { + if ( Nwk_ObjFaninNum(pLut) > pPars->nMaxLutSize ) + continue; + Nwk_ManCollectOverlapCands( pLut, vCands1, pPars ); + if ( pPars->fUseDiffSupp ) + Nwk_ManCollectNonOverlapCands( pLut, vStart, vNext, vCands2, pPars ); + if ( Vec_PtrSize(vCands1) == 0 && Vec_PtrSize(vCands2) == 0 ) + continue; + nCands += Vec_PtrSize(vCands1) + Vec_PtrSize(vCands2); + // save candidates + Vec_PtrForEachEntry( Nwk_Obj_t *, vCands1, pCand, k ) + Nwk_ManGraphHashEdge( p, Nwk_ObjId(pLut), Nwk_ObjId(pCand) ); + Vec_PtrForEachEntry( Nwk_Obj_t *, vCands2, pCand, k ) + Nwk_ManGraphHashEdge( p, Nwk_ObjId(pLut), Nwk_ObjId(pCand) ); + // print statistics about this node + if ( pPars->fVeryVerbose ) + printf( "Node %6d : Fanins = %d. Fanouts = %3d. Cand1 = %3d. Cand2 = %3d.\n", + Nwk_ObjId(pLut), Nwk_ObjFaninNum(pLut), Nwk_ObjFaninNum(pLut), + Vec_PtrSize(vCands1), Vec_PtrSize(vCands2) ); + } + Vec_PtrFree( vStart ); + Vec_PtrFree( vNext ); + Vec_PtrFree( vCands1 ); + Vec_PtrFree( vCands2 ); + if ( pPars->fVerbose ) + { + printf( "Mergable LUTs = %6d. Total cands = %6d. ", p->nVertsMax, nCands ); + ABC_PRT( "Deriving graph", clock() - clk ); + } + // solve the graph problem + clk = clock(); + Nwk_ManGraphSolve( p ); + if ( pPars->fVerbose ) + { + printf( "GRAPH: Nodes = %6d. Edges = %6d. Pairs = %6d. ", + p->nVerts, p->nEdges, Vec_IntSize(p->vPairs)/2 ); + ABC_PRT( "Solving", clock() - clk ); + Nwk_ManGraphReportMemoryUsage( p ); + } + vResult = p->vPairs; p->vPairs = NULL; +/* + for ( i = 0; i < vResult->nSize; i += 2 ) + printf( "(%d,%d) ", vResult->pArray[i], vResult->pArray[i+1] ); + printf( "\n" ); +*/ + Nwk_ManGraphFree( p ); + return vResult; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/nwk/nwkMerge.h b/src/opt/nwk/nwkMerge.h new file mode 100644 index 00000000..f6be760f --- /dev/null +++ b/src/opt/nwk/nwkMerge.h @@ -0,0 +1,153 @@ +/**CFile**************************************************************** + + FileName [nwkMerge.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Logic network representation.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: nwkMerge.h,v 1.1 2008/05/14 22:13:09 wudenni Exp $] + +***********************************************************************/ + +#ifndef __NWK_MERGE_H__ +#define __NWK_MERGE_H__ + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +#define NWK_MAX_LIST 16 + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +// the LUT merging parameters +typedef struct Nwk_LMPars_t_ Nwk_LMPars_t; +struct Nwk_LMPars_t_ +{ + int nMaxLutSize; // the max LUT size for merging (N=5) + int nMaxSuppSize; // the max total support size after merging (S=5) + int nMaxDistance; // the max number of nodes separating LUTs + int nMaxLevelDiff; // the max difference in levels + int nMaxFanout; // the max number of fanouts to traverse + int fUseDiffSupp; // enables the use of nodes with different support + int fUseTfiTfo; // enables the use of TFO/TFO nodes as candidates + int fVeryVerbose; // enables additional verbose output + int fVerbose; // enables verbose output +}; + +// edge of the graph +typedef struct Nwk_Edg_t_ Nwk_Edg_t; +struct Nwk_Edg_t_ +{ + int iNode1; // the first node + int iNode2; // the second node + Nwk_Edg_t * pNext; // the next edge +}; + +// vertex of the graph +typedef struct Nwk_Vrt_t_ Nwk_Vrt_t; +struct Nwk_Vrt_t_ +{ + int Id; // the vertex number + int iPrev; // the previous vertex in the list + int iNext; // the next vertex in the list + int nEdges; // the number of edges + int pEdges[0]; // the array of edges +}; + +// the connectivity graph +typedef struct Nwk_Grf_t_ Nwk_Grf_t; +struct Nwk_Grf_t_ +{ + // preliminary graph representation + int nObjs; // the number of objects + int nVertsMax; // the upper bound on the number of vertices + int nEdgeHash; // an approximate number of edges + Nwk_Edg_t ** pEdgeHash; // hash table for edges + Aig_MmFixed_t * pMemEdges; // memory for edges + // graph representation + int nEdges; // the number of edges + int nVerts; // the number of vertices + Nwk_Vrt_t ** pVerts; // the array of vertices + Aig_MmFlex_t * pMemVerts; // memory for vertices + // intermediate data + int pLists1[NWK_MAX_LIST+1]; // lists of nodes with one edge + int pLists2[NWK_MAX_LIST+1]; // lists of nodes with more than one edge + // the results of matching + Vec_Int_t * vPairs; // pairs matched in the graph + // object mappings + int * pMapLut2Id; // LUT numbers into vertex IDs + int * pMapId2Lut; // vertex IDs into LUT numbers + // other things + int nMemBytes1; // memory usage in bytes + int nMemBytes2; // memory usage in bytes +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define Nwk_GraphForEachEdge( p, pEdge, k ) \ + for ( k = 0; k < p->nEdgeHash; k++ ) \ + for ( pEdge = p->pEdgeHash[k]; pEdge; pEdge = pEdge->pNext ) + +#define Nwk_ListForEachVertex( p, List, pVrt ) \ + for ( pVrt = List? p->pVerts[List] : NULL; pVrt; \ + pVrt = pVrt->iNext? p->pVerts[pVrt->iNext] : NULL ) + +#define Nwk_VertexForEachAdjacent( p, pVrt, pNext, k ) \ + for ( k = 0; (k < pVrt->nEdges) && (((pNext) = p->pVerts[pVrt->pEdges[k]]), 1); k++ ) + +//////////////////////////////////////////////////////////////////////// +/// INLINED FUNCTIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== nwkMerge.c ==========================================================*/ +extern ABC_DLL Nwk_Grf_t * Nwk_ManGraphAlloc( int nVertsMax ); +extern ABC_DLL void Nwk_ManGraphFree( Nwk_Grf_t * p ); +extern ABC_DLL void Nwk_ManGraphReportMemoryUsage( Nwk_Grf_t * p ); +extern ABC_DLL void Nwk_ManGraphHashEdge( Nwk_Grf_t * p, int iLut1, int iLut2 ); +extern ABC_DLL void Nwk_ManGraphSolve( Nwk_Grf_t * p ); +extern ABC_DLL int Nwk_ManLutMergeGraphTest( char * pFileName ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/opt/nwk/nwkObj.c b/src/opt/nwk/nwkObj.c new file mode 100644 index 00000000..e5930087 --- /dev/null +++ b/src/opt/nwk/nwkObj.c @@ -0,0 +1,204 @@ +/**CFile**************************************************************** + + FileName [nwkObj.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Logic network representation.] + + Synopsis [Manipulation of objects.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: nwkObj.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "nwk.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates an object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Nwk_Obj_t * Nwk_ManCreateObj( Nwk_Man_t * p, int nFanins, int nFanouts ) +{ + Nwk_Obj_t * pObj; + pObj = (Nwk_Obj_t *)Aig_MmFlexEntryFetch( p->pMemObjs, sizeof(Nwk_Obj_t) + (nFanins + nFanouts + p->nFanioPlus) * sizeof(Nwk_Obj_t *) ); + memset( pObj, 0, sizeof(Nwk_Obj_t) ); + pObj->pFanio = (Nwk_Obj_t **)((char *)pObj + sizeof(Nwk_Obj_t)); + pObj->Id = Vec_PtrSize( p->vObjs ); + Vec_PtrPush( p->vObjs, pObj ); + pObj->pMan = p; + pObj->nFanioAlloc = nFanins + nFanouts + p->nFanioPlus; + return pObj; +} + + +/**Function************************************************************* + + Synopsis [Creates a primary input.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Nwk_Obj_t * Nwk_ManCreateCi( Nwk_Man_t * p, int nFanouts ) +{ + Nwk_Obj_t * pObj; + pObj = Nwk_ManCreateObj( p, 1, nFanouts ); + pObj->PioId = Vec_PtrSize( p->vCis ); + Vec_PtrPush( p->vCis, pObj ); + pObj->Type = NWK_OBJ_CI; + p->nObjs[NWK_OBJ_CI]++; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Creates a primary output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Nwk_Obj_t * Nwk_ManCreateCo( Nwk_Man_t * p ) +{ + Nwk_Obj_t * pObj; + pObj = Nwk_ManCreateObj( p, 1, 1 ); + pObj->PioId = Vec_PtrSize( p->vCos ); + Vec_PtrPush( p->vCos, pObj ); + pObj->Type = NWK_OBJ_CO; + p->nObjs[NWK_OBJ_CO]++; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Creates a latch.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Nwk_Obj_t * Nwk_ManCreateLatch( Nwk_Man_t * p ) +{ + Nwk_Obj_t * pObj; + pObj = Nwk_ManCreateObj( p, 1, 1 ); + pObj->Type = NWK_OBJ_LATCH; + p->nObjs[NWK_OBJ_LATCH]++; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Creates a node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Nwk_Obj_t * Nwk_ManCreateNode( Nwk_Man_t * p, int nFanins, int nFanouts ) +{ + Nwk_Obj_t * pObj; + pObj = Nwk_ManCreateObj( p, nFanins, nFanouts ); + pObj->Type = NWK_OBJ_NODE; + p->nObjs[NWK_OBJ_NODE]++; + return pObj; +} + + +/**Function************************************************************* + + Synopsis [Deletes the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManDeleteNode( Nwk_Obj_t * pObj ) +{ + Vec_Ptr_t * vNodes = pObj->pMan->vTemp; + Nwk_Obj_t * pTemp; + int i; + assert( Nwk_ObjFanoutNum(pObj) == 0 ); + // delete fanins + Nwk_ObjCollectFanins( pObj, vNodes ); + Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pTemp, i ) + Nwk_ObjDeleteFanin( pObj, pTemp ); + // remove from the list of objects + Vec_PtrWriteEntry( pObj->pMan->vObjs, pObj->Id, NULL ); + pObj->pMan->nObjs[pObj->Type]--; + memset( pObj, 0, sizeof(Nwk_Obj_t) ); + pObj->Id = -1; +} + +/**Function************************************************************* + + Synopsis [Deletes the node and MFFC of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManDeleteNode_rec( Nwk_Obj_t * pObj ) +{ + Vec_Ptr_t * vNodes; + int i; + assert( !Nwk_ObjIsCi(pObj) ); + assert( Nwk_ObjFanoutNum(pObj) == 0 ); + vNodes = Vec_PtrAlloc( 100 ); + Nwk_ObjCollectFanins( pObj, vNodes ); + Nwk_ManDeleteNode( pObj ); + Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i ) + if ( Nwk_ObjIsNode(pObj) && Nwk_ObjFanoutNum(pObj) == 0 ) + Nwk_ManDeleteNode_rec( pObj ); + Vec_PtrFree( vNodes ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/nwk/nwkSpeedup.c b/src/opt/nwk/nwkSpeedup.c new file mode 100644 index 00000000..335d50f8 --- /dev/null +++ b/src/opt/nwk/nwkSpeedup.c @@ -0,0 +1,382 @@ +/**CFile**************************************************************** + + FileName [nwkSpeedup.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Netlist representation.] + + Synopsis [Global delay optimization using structural choices.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: nwkSpeedup.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "nwk.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Adds strashed nodes for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManSpeedupNode_rec( Aig_Man_t * pAig, Aig_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + if ( Aig_ObjIsTravIdCurrent(pAig, pNode) ) + return 1; + if ( Aig_ObjIsPi(pNode) ) + return 0; + assert( Aig_ObjIsNode(pNode) ); + Aig_ObjSetTravIdCurrent( pAig, pNode ); + if ( !Aig_ManSpeedupNode_rec( pAig, Aig_ObjFanin0(pNode), vNodes ) ) + return 0; + if ( !Aig_ManSpeedupNode_rec( pAig, Aig_ObjFanin1(pNode), vNodes ) ) + return 0; + Vec_PtrPush( vNodes, pNode ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Adds strashed nodes for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManSpeedupNode( Nwk_Man_t * pNtk, Aig_Man_t * pAig, Nwk_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vTimes ) +{ + Vec_Ptr_t * vNodes; + Nwk_Obj_t * pObj, * pObj2; + Aig_Obj_t * ppCofs[32], * pAnd, * pTemp; + int nCofs, i, k, nSkip; + + // quit of regulars are the same + Vec_PtrForEachEntry( Nwk_Obj_t *, vLeaves, pObj, i ) + Vec_PtrForEachEntry( Nwk_Obj_t *, vLeaves, pObj2, k ) + if ( i != k && Aig_Regular((Aig_Obj_t *)pObj->pCopy) == Aig_Regular((Aig_Obj_t *)pObj2->pCopy) ) + { +// printf( "Identical after structural hashing!!!\n" ); + return; + } + + // collect the AIG nodes + vNodes = Vec_PtrAlloc( 100 ); + Aig_ManIncrementTravId( pAig ); + Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) ); + Vec_PtrForEachEntry( Nwk_Obj_t *, vLeaves, pObj, i ) + { + pAnd = (Aig_Obj_t *)pObj->pCopy; + Aig_ObjSetTravIdCurrent( pAig, Aig_Regular(pAnd) ); + } + // traverse from the root node + pAnd = (Aig_Obj_t *)pNode->pCopy; + if ( !Aig_ManSpeedupNode_rec( pAig, Aig_Regular(pAnd), vNodes ) ) + { +// printf( "Bad node!!!\n" ); + Vec_PtrFree( vNodes ); + return; + } + + // derive cofactors + nCofs = (1 << Vec_PtrSize(vTimes)); + for ( i = 0; i < nCofs; i++ ) + { + Vec_PtrForEachEntry( Nwk_Obj_t *, vLeaves, pObj, k ) + { + pAnd = (Aig_Obj_t *)pObj->pCopy; + Aig_Regular(pAnd)->pData = Aig_Regular(pAnd); + } + Vec_PtrForEachEntry( Nwk_Obj_t *, vTimes, pObj, k ) + { + pAnd = (Aig_Obj_t *)pObj->pCopy; + Aig_Regular(pAnd)->pData = Aig_NotCond( Aig_ManConst1(pAig), ((i & (1<pData = Aig_And( pAig, Aig_ObjChild0Copy(pTemp), Aig_ObjChild1Copy(pTemp) ); + // save the result + pAnd = (Aig_Obj_t *)pNode->pCopy; + ppCofs[i] = Aig_NotCond( (Aig_Obj_t *)Aig_Regular(pAnd)->pData, Aig_IsComplement(pAnd) ); + } + Vec_PtrFree( vNodes ); + +//Nwk_ObjAddFanin( Nwk_ManCreatePo(pAig), ppCofs[0] ); +//Nwk_ObjAddFanin( Nwk_ManCreatePo(pAig), ppCofs[1] ); + + // collect the resulting tree + Vec_PtrForEachEntry( Nwk_Obj_t *, vTimes, pObj, k ) + for ( nSkip = (1<pCopy; + ppCofs[i] = Aig_Mux( pAig, Aig_Regular(pAnd), ppCofs[i+nSkip], ppCofs[i] ); + } +//Nwk_ObjAddFanin( Nwk_ManCreatePo(pAig), ppCofs[0] ); + + // create choice node + pAnd = Aig_Regular((Aig_Obj_t *)pNode->pCopy); // repr + pTemp = Aig_Regular(ppCofs[0]); // new + if ( Aig_ObjEquiv(pAig, pAnd) == NULL && Aig_ObjEquiv(pAig, pTemp) == NULL && !Aig_ObjCheckTfi(pAig, pTemp, pAnd) ) + pAig->pEquivs[pAnd->Id] = pTemp; +} + +/**Function************************************************************* + + Synopsis [Determines timing-critical edges of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Nwk_ManDelayTraceTCEdges( Nwk_Man_t * pNtk, Nwk_Obj_t * pNode, float tDelta, int fUseLutLib ) +{ + int pPinPerm[32]; + float pPinDelays[32]; + If_Lib_t * pLutLib = fUseLutLib? pNtk->pLutLib : NULL; + Nwk_Obj_t * pFanin; + unsigned uResult = 0; + float tRequired, * pDelays; + int k; + tRequired = Nwk_ObjRequired(pNode); + if ( pLutLib == NULL ) + { + Nwk_ObjForEachFanin( pNode, pFanin, k ) + if ( tRequired < Nwk_ObjArrival(pFanin) + 1.0 + tDelta ) + uResult |= (1 << k); + } + else if ( !pLutLib->fVarPinDelays ) + { + pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pNode)]; + Nwk_ObjForEachFanin( pNode, pFanin, k ) + if ( tRequired < Nwk_ObjArrival(pFanin) + pDelays[0] + tDelta ) + uResult |= (1 << k); + } + else + { + pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pNode)]; + Nwk_ManDelayTraceSortPins( pNode, pPinPerm, pPinDelays ); + Nwk_ObjForEachFanin( pNode, pFanin, k ) + if ( tRequired < Nwk_ObjArrival(Nwk_ObjFanin(pNode,pPinPerm[k])) + pDelays[k] + tDelta ) + uResult |= (1 << pPinPerm[k]); + } + return uResult; +} + +/**Function************************************************************* + + Synopsis [Adds choices to speed up the network by the given percentage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Nwk_ManSpeedup( Nwk_Man_t * pNtk, int fUseLutLib, int Percentage, int Degree, int fVerbose, int fVeryVerbose ) +{ + Aig_Man_t * pAig, * pTemp; + Vec_Ptr_t * vTimeCries, * vTimeFanins; + Nwk_Obj_t * pNode, * pFanin, * pFanin2; + Aig_Obj_t * pAnd; + If_Lib_t * pTempLib = pNtk->pLutLib; + Tim_Man_t * pTempTim = NULL; + float tDelta, tArrival; + int i, k, k2, Counter, CounterRes, nTimeCris; + unsigned * puTCEdges; + // perform delay trace + if ( !fUseLutLib ) + { + pNtk->pLutLib = NULL; + if ( pNtk->pManTime ) + { + pTempTim = pNtk->pManTime; + pNtk->pManTime = Tim_ManDup( pTempTim, 1 ); + } + } + tArrival = Nwk_ManDelayTraceLut( pNtk ); + tDelta = fUseLutLib ? tArrival*Percentage/100.0 : 1.0; + if ( fVerbose ) + { + printf( "Max delay = %.2f. Delta = %.2f. ", tArrival, tDelta ); + printf( "Using %s model. ", fUseLutLib? "LUT library" : "unit-delay" ); + if ( fUseLutLib ) + printf( "Percentage = %d. ", Percentage ); + printf( "\n" ); + } + // mark the timing critical nodes and edges + puTCEdges = ABC_ALLOC( unsigned, Nwk_ManObjNumMax(pNtk) ); + memset( puTCEdges, 0, sizeof(unsigned) * Nwk_ManObjNumMax(pNtk) ); + Nwk_ManForEachNode( pNtk, pNode, i ) + { + if ( Nwk_ObjSlack(pNode) >= tDelta ) + continue; + puTCEdges[pNode->Id] = Nwk_ManDelayTraceTCEdges( pNtk, pNode, tDelta, fUseLutLib ); + } + if ( fVerbose ) + { + Counter = CounterRes = 0; + Nwk_ManForEachNode( pNtk, pNode, i ) + { + Nwk_ObjForEachFanin( pNode, pFanin, k ) + if ( !Nwk_ObjIsCi(pFanin) && Nwk_ObjSlack(pFanin) < tDelta ) + Counter++; + CounterRes += Aig_WordCountOnes( puTCEdges[pNode->Id] ); + } + printf( "Edges: Total = %7d. 0-slack = %7d. Critical = %7d. Ratio = %4.2f\n", + Nwk_ManGetTotalFanins(pNtk), Counter, CounterRes, Counter? 1.0*CounterRes/Counter : 0.0 ); + } + // start the resulting network + pAig = Nwk_ManStrash( pNtk ); + pAig->pEquivs = ABC_ALLOC( Aig_Obj_t *, 3 * Aig_ManObjNumMax(pAig) ); + memset( pAig->pEquivs, 0, sizeof(Aig_Obj_t *) * 3 * Aig_ManObjNumMax(pAig) ); + + // collect nodes to be used for resynthesis + Counter = CounterRes = 0; + vTimeCries = Vec_PtrAlloc( 16 ); + vTimeFanins = Vec_PtrAlloc( 16 ); + Nwk_ManForEachNode( pNtk, pNode, i ) + { + if ( Nwk_ObjSlack(pNode) >= tDelta ) + continue; + // count the number of non-PI timing-critical nodes + nTimeCris = 0; + Nwk_ObjForEachFanin( pNode, pFanin, k ) + if ( !Nwk_ObjIsCi(pFanin) && (puTCEdges[pNode->Id] & (1<Id] & (1<Id] & (1< Degree) ) + if ( (Vec_PtrSize(vTimeCries) == 0 || Vec_PtrSize(vTimeCries) > Degree) ) + continue; + CounterRes++; + // collect second generation nodes + Vec_PtrClear( vTimeFanins ); + Nwk_ObjForEachFanin( pNode, pFanin, k ) + { + if ( Nwk_ObjIsCi(pFanin) ) + Vec_PtrPushUnique( vTimeFanins, pFanin ); + else + Nwk_ObjForEachFanin( pFanin, pFanin2, k2 ) + Vec_PtrPushUnique( vTimeFanins, pFanin2 ); + } + // print the results + if ( fVeryVerbose ) + { + printf( "%5d Node %5d : %d %2d %2d ", Counter, pNode->Id, + nTimeCris, Vec_PtrSize(vTimeCries), Vec_PtrSize(vTimeFanins) ); + Nwk_ObjForEachFanin( pNode, pFanin, k ) + printf( "%d(%.2f)%s ", pFanin->Id, Nwk_ObjSlack(pFanin), (puTCEdges[pNode->Id] & (1< Degree ) + continue; + // order the fanins in the increasing order of criticalily + if ( Vec_PtrSize(vTimeCries) > 1 ) + { + pFanin = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 0 ); + pFanin2 = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 1 ); + if ( Nwk_ObjSlack(pFanin) < Nwk_ObjSlack(pFanin2) ) + { + Vec_PtrWriteEntry( vTimeCries, 0, pFanin2 ); + Vec_PtrWriteEntry( vTimeCries, 1, pFanin ); + } + } + if ( Vec_PtrSize(vTimeCries) > 2 ) + { + pFanin = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 1 ); + pFanin2 = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 2 ); + if ( Nwk_ObjSlack(pFanin) < Nwk_ObjSlack(pFanin2) ) + { + Vec_PtrWriteEntry( vTimeCries, 1, pFanin2 ); + Vec_PtrWriteEntry( vTimeCries, 2, pFanin ); + } + pFanin = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 0 ); + pFanin2 = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 1 ); + if ( Nwk_ObjSlack(pFanin) < Nwk_ObjSlack(pFanin2) ) + { + Vec_PtrWriteEntry( vTimeCries, 0, pFanin2 ); + Vec_PtrWriteEntry( vTimeCries, 1, pFanin ); + } + } + // add choice + Aig_ManSpeedupNode( pNtk, pAig, pNode, vTimeFanins, vTimeCries ); + } + Vec_PtrFree( vTimeCries ); + Vec_PtrFree( vTimeFanins ); + ABC_FREE( puTCEdges ); + if ( fVerbose ) + printf( "Nodes: Total = %7d. 0-slack = %7d. Workable = %7d. Ratio = %4.2f\n", + Nwk_ManNodeNum(pNtk), Counter, CounterRes, Counter? 1.0*CounterRes/Counter : 0.0 ); + + // remove invalid choice nodes + Aig_ManForEachNode( pAig, pAnd, i ) + if ( Aig_ObjEquiv(pAig, pAnd) ) + { + if ( Aig_ObjRefs(Aig_ObjEquiv(pAig, pAnd)) > 0 ) + pAig->pEquivs[pAnd->Id] = NULL; + } + + // put back the library + if ( !fUseLutLib ) + pNtk->pLutLib = pTempLib; + if ( pTempTim ) + { + Tim_ManStop( pNtk->pManTime ); + pNtk->pManTime = pTempTim; + } + + // reconstruct the network + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + // reset levels + Aig_ManChoiceLevel( pAig ); + return pAig; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/nwk/nwkStrash.c b/src/opt/nwk/nwkStrash.c new file mode 100644 index 00000000..74fc4d56 --- /dev/null +++ b/src/opt/nwk/nwkStrash.c @@ -0,0 +1,149 @@ +/**CFile**************************************************************** + + FileName [nwkStrash.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Logic network representation.] + + Synopsis [Performs structural hashing for the network.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: nwkStrash.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "nwk.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Derives AIG from the local functions of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManStrashNode_rec( Aig_Man_t * p, Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return; + Nwk_ManStrashNode_rec( p, Hop_ObjFanin0(pObj) ); + Nwk_ManStrashNode_rec( p, Hop_ObjFanin1(pObj) ); + pObj->pData = Aig_And( p, (Aig_Obj_t *)Hop_ObjChild0Copy(pObj), (Aig_Obj_t *)Hop_ObjChild1Copy(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Derives AIG from the local functions of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Nwk_ManStrashNode( Aig_Man_t * p, Nwk_Obj_t * pObj ) +{ + Hop_Man_t * pMan = pObj->pMan->pManHop; + Hop_Obj_t * pRoot = pObj->pFunc; + Nwk_Obj_t * pFanin; + int i; + assert( Nwk_ObjIsNode(pObj) ); + // check the constant case + if ( Hop_Regular(pRoot) == Hop_ManConst1(pMan) ) + return Aig_NotCond( Aig_ManConst1(p), Hop_IsComplement(pRoot) ); + // set elementary variables + Nwk_ObjForEachFanin( pObj, pFanin, i ) + Hop_IthVar(pMan, i)->pData = pFanin->pCopy; + // strash the AIG of this node + Nwk_ManStrashNode_rec( p, Hop_Regular(pRoot) ); + Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); + // return the final node + return Aig_NotCond( (Aig_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); +} + +/**Function************************************************************* + + Synopsis [Derives AIG from the logic network.] + + Description [Assumes topological ordering of nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Nwk_ManStrash( Nwk_Man_t * pNtk ) +{ + Vec_Ptr_t * vObjs; + Aig_Man_t * pMan; + Aig_Obj_t * pObjNew; + Nwk_Obj_t * pObj; + int i, Level; + pMan = Aig_ManStart( Nwk_ManGetAigNodeNum(pNtk) ); + pMan->pName = Abc_UtilStrsav( pNtk->pName ); + pMan->pSpec = Abc_UtilStrsav( pNtk->pSpec ); + pMan->pManTime = Tim_ManDup( (Tim_Man_t *)pNtk->pManTime, 1 ); + Tim_ManIncrementTravId( (Tim_Man_t *)pMan->pManTime ); + Nwk_ManForEachObj( pNtk, pObj, i ) + pObj->pCopy = NULL; +// Nwk_ManForEachObj( pNtk, pObj, i ) + vObjs = Nwk_ManDfs( pNtk ); + Vec_PtrForEachEntry( Nwk_Obj_t *, vObjs, pObj, i ) + { + if ( Nwk_ObjIsCi(pObj) ) + { + pObjNew = Aig_ObjCreatePi(pMan); + Level = Tim_ManGetCiArrival( (Tim_Man_t *)pMan->pManTime, pObj->PioId ); + Aig_ObjSetLevel( pObjNew, Level ); + } + else if ( Nwk_ObjIsCo(pObj) ) + { + pObjNew = Aig_ObjCreatePo( pMan, Aig_NotCond((Aig_Obj_t *)Nwk_ObjFanin0(pObj)->pCopy, pObj->fInvert) ); + Level = Aig_ObjLevel( pObjNew ); + Tim_ManSetCoArrival( (Tim_Man_t *)pMan->pManTime, pObj->PioId, (float)Level ); + } + else if ( Nwk_ObjIsNode(pObj) ) + { + pObjNew = Nwk_ManStrashNode( pMan, pObj ); + } + else + assert( 0 ); + pObj->pCopy = pObjNew; + } + Vec_PtrFree( vObjs ); + Aig_ManCleanup( pMan ); + Aig_ManSetRegNum( pMan, 0 ); + return pMan; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/nwk/nwkTiming.c b/src/opt/nwk/nwkTiming.c new file mode 100644 index 00000000..9419c175 --- /dev/null +++ b/src/opt/nwk/nwkTiming.c @@ -0,0 +1,894 @@ +/**CFile**************************************************************** + + FileName [nwkTiming.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Logic network representation.] + + Synopsis [Manipulation of timing information.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: nwkTiming.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "nwk.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Cleans timing information for all nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManCleanTiming( Nwk_Man_t * pNtk ) +{ + Nwk_Obj_t * pObj; + int i; + Nwk_ManForEachObj( pNtk, pObj, i ) + { + pObj->tArrival = pObj->tSlack = 0.0; + pObj->tRequired = TIM_ETERNITY; + } +} + +/**Function************************************************************* + + Synopsis [Sorts the pins in the decreasing order of delays.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManDelayTraceSortPins( Nwk_Obj_t * pNode, int * pPinPerm, float * pPinDelays ) +{ + Nwk_Obj_t * pFanin; + int i, j, best_i, temp; + // start the trivial permutation and collect pin delays + Nwk_ObjForEachFanin( pNode, pFanin, i ) + { + pPinPerm[i] = i; + pPinDelays[i] = Nwk_ObjArrival(pFanin); + } + // 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 < Nwk_ObjFaninNum(pNode)-1; i++ ) + { + best_i = i; + for ( j = i+1; j < Nwk_ObjFaninNum(pNode); 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( Nwk_ObjFaninNum(pNode) == 0 || pPinPerm[0] < Nwk_ObjFaninNum(pNode) ); + for ( i = 1; i < Nwk_ObjFaninNum(pNode); i++ ) + { + assert( pPinPerm[i] < Nwk_ObjFaninNum(pNode) ); + assert( pPinDelays[pPinPerm[i-1]] >= pPinDelays[pPinPerm[i]] ); + } +} + +/**Function************************************************************* + + Synopsis [Sorts the pins in the decreasing order of delays.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManWhereIsPin( Nwk_Obj_t * pFanout, Nwk_Obj_t * pFanin, int * pPinPerm ) +{ + int i; + for ( i = 0; i < Nwk_ObjFaninNum(pFanout); i++ ) + if ( Nwk_ObjFanin(pFanout, pPinPerm[i]) == pFanin ) + return i; + return -1; +} + +/**Function************************************************************* + + Synopsis [Computes the arrival times for the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Nwk_NodeComputeArrival( Nwk_Obj_t * pObj, int fUseSorting ) +{ + If_Lib_t * pLutLib = pObj->pMan->pLutLib; + int pPinPerm[32]; + float pPinDelays[32]; + Nwk_Obj_t * pFanin; + float tArrival, * pDelays; + int k; + assert( Nwk_ObjIsNode(pObj) || Nwk_ObjIsCi(pObj) || Nwk_ObjIsCo(pObj) ); + if ( Nwk_ObjIsCi(pObj) ) + return Nwk_ObjArrival(pObj); + if ( Nwk_ObjIsCo(pObj) ) + return Nwk_ObjArrival( Nwk_ObjFanin0(pObj) ); + tArrival = -TIM_ETERNITY; + if ( pLutLib == NULL ) + { + Nwk_ObjForEachFanin( pObj, pFanin, k ) + if ( tArrival < Nwk_ObjArrival(pFanin) + 1.0 ) + tArrival = Nwk_ObjArrival(pFanin) + 1.0; + } + else if ( !pLutLib->fVarPinDelays ) + { + pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pObj)]; + Nwk_ObjForEachFanin( pObj, pFanin, k ) + if ( tArrival < Nwk_ObjArrival(pFanin) + pDelays[0] ) + tArrival = Nwk_ObjArrival(pFanin) + pDelays[0]; + } + else + { + pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pObj)]; + if ( fUseSorting ) + { + Nwk_ManDelayTraceSortPins( pObj, pPinPerm, pPinDelays ); + Nwk_ObjForEachFanin( pObj, pFanin, k ) + if ( tArrival < Nwk_ObjArrival(Nwk_ObjFanin(pObj,pPinPerm[k])) + pDelays[k] ) + tArrival = Nwk_ObjArrival(Nwk_ObjFanin(pObj,pPinPerm[k])) + pDelays[k]; + } + else + { + Nwk_ObjForEachFanin( pObj, pFanin, k ) + if ( tArrival < Nwk_ObjArrival(pFanin) + pDelays[k] ) + tArrival = Nwk_ObjArrival(pFanin) + pDelays[k]; + } + } + if ( Nwk_ObjFaninNum(pObj) == 0 ) + tArrival = 0.0; + return tArrival; +} + +/**Function************************************************************* + + Synopsis [Computes the required times for the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Nwk_NodeComputeRequired( Nwk_Obj_t * pObj, int fUseSorting ) +{ + If_Lib_t * pLutLib = pObj->pMan->pLutLib; + int pPinPerm[32]; + float pPinDelays[32]; + Nwk_Obj_t * pFanout; + float tRequired, tDelay, * pDelays; + int k, iFanin; + assert( Nwk_ObjIsNode(pObj) || Nwk_ObjIsCi(pObj) || Nwk_ObjIsCo(pObj) ); + if ( Nwk_ObjIsCo(pObj) ) + return Nwk_ObjRequired(pObj); + tRequired = TIM_ETERNITY; + if ( pLutLib == NULL ) + { + Nwk_ObjForEachFanout( pObj, pFanout, k ) + { + tDelay = Nwk_ObjIsCo(pFanout)? 0.0 : 1.0; + if ( tRequired > Nwk_ObjRequired(pFanout) - tDelay ) + tRequired = Nwk_ObjRequired(pFanout) - tDelay; + } + } + else if ( !pLutLib->fVarPinDelays ) + { + Nwk_ObjForEachFanout( pObj, pFanout, k ) + { + pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pFanout)]; + tDelay = Nwk_ObjIsCo(pFanout)? 0.0 : pDelays[0]; + if ( tRequired > Nwk_ObjRequired(pFanout) - tDelay ) + tRequired = Nwk_ObjRequired(pFanout) - tDelay; + } + } + else + { + if ( fUseSorting ) + { + Nwk_ObjForEachFanout( pObj, pFanout, k ) + { + pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pFanout)]; + Nwk_ManDelayTraceSortPins( pFanout, pPinPerm, pPinDelays ); + iFanin = Nwk_ManWhereIsPin( pFanout, pObj, pPinPerm ); + assert( Nwk_ObjFanin(pFanout,pPinPerm[iFanin]) == pObj ); + tDelay = Nwk_ObjIsCo(pFanout)? 0.0 : pDelays[iFanin]; + if ( tRequired > Nwk_ObjRequired(pFanout) - tDelay ) + tRequired = Nwk_ObjRequired(pFanout) - tDelay; + } + } + else + { + Nwk_ObjForEachFanout( pObj, pFanout, k ) + { + pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pFanout)]; + iFanin = Nwk_ObjFindFanin( pFanout, pObj ); + assert( Nwk_ObjFanin(pFanout,iFanin) == pObj ); + tDelay = Nwk_ObjIsCo(pFanout)? 0.0 : pDelays[iFanin]; + if ( tRequired > Nwk_ObjRequired(pFanout) - tDelay ) + tRequired = Nwk_ObjRequired(pFanout) - tDelay; + } + } + } + return tRequired; +} + +/**Function************************************************************* + + Synopsis [Propagates the required times through the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Nwk_NodePropagateRequired( Nwk_Obj_t * pObj, int fUseSorting ) +{ + If_Lib_t * pLutLib = pObj->pMan->pLutLib; + int pPinPerm[32]; + float pPinDelays[32]; + Nwk_Obj_t * pFanin; + float tRequired = 0.0; // Suppress "might be used uninitialized" + float * pDelays; + int k; + assert( Nwk_ObjIsNode(pObj) ); + if ( pLutLib == NULL ) + { + tRequired = Nwk_ObjRequired(pObj) - (float)1.0; + Nwk_ObjForEachFanin( pObj, pFanin, k ) + if ( Nwk_ObjRequired(pFanin) > tRequired ) + Nwk_ObjSetRequired( pFanin, tRequired ); + } + else if ( !pLutLib->fVarPinDelays ) + { + pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pObj)]; + tRequired = Nwk_ObjRequired(pObj) - pDelays[0]; + Nwk_ObjForEachFanin( pObj, pFanin, k ) + if ( Nwk_ObjRequired(pFanin) > tRequired ) + Nwk_ObjSetRequired( pFanin, tRequired ); + } + else + { + pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pObj)]; + if ( fUseSorting ) + { + Nwk_ManDelayTraceSortPins( pObj, pPinPerm, pPinDelays ); + Nwk_ObjForEachFanin( pObj, pFanin, k ) + { + tRequired = Nwk_ObjRequired(pObj) - pDelays[k]; + if ( Nwk_ObjRequired(Nwk_ObjFanin(pObj,pPinPerm[k])) > tRequired ) + Nwk_ObjSetRequired( Nwk_ObjFanin(pObj,pPinPerm[k]), tRequired ); + } + } + else + { + Nwk_ObjForEachFanin( pObj, pFanin, k ) + { + tRequired = Nwk_ObjRequired(pObj) - pDelays[k]; + if ( Nwk_ObjRequired(pFanin) > tRequired ) + Nwk_ObjSetRequired( pFanin, tRequired ); + } + } + } + return tRequired; +} + +/**Function************************************************************* + + Synopsis [Computes the delay trace of the given network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Nwk_ManDelayTraceLut( Nwk_Man_t * pNtk ) +{ + Vec_Ptr_t * vObjs; + int fUseSorting = 1; + If_Lib_t * pLutLib = pNtk->pLutLib; + Vec_Ptr_t * vNodes; + Nwk_Obj_t * pObj; + float tArrival, tRequired, tSlack; + int i; + + // get the library + if ( pLutLib && pLutLib->LutMax < Nwk_ManGetFaninMax(pNtk) ) + { + printf( "The max LUT size (%d) is less than the max fanin count (%d).\n", + pLutLib->LutMax, Nwk_ManGetFaninMax(pNtk) ); + return -TIM_ETERNITY; + } + + // compute the reverse order of all objects + vNodes = Nwk_ManDfsReverse( pNtk ); + + // initialize the arrival times + Nwk_ManCleanTiming( pNtk ); + + // propagate arrival times + if ( pNtk->pManTime ) + Tim_ManIncrementTravId( pNtk->pManTime ); +// Nwk_ManForEachObj( pNtk, pObj, i ) + vObjs = Nwk_ManDfs( pNtk ); + Vec_PtrForEachEntry( Nwk_Obj_t *, vObjs, pObj, i ) + { + tArrival = Nwk_NodeComputeArrival( pObj, fUseSorting ); + if ( Nwk_ObjIsCi(pObj) && pNtk->pManTime ) + tArrival = Tim_ManGetCiArrival( pNtk->pManTime, pObj->PioId ); + if ( Nwk_ObjIsCo(pObj) && pNtk->pManTime ) + Tim_ManSetCoArrival( pNtk->pManTime, pObj->PioId, tArrival ); + Nwk_ObjSetArrival( pObj, tArrival ); + } + Vec_PtrFree( vObjs ); + + // get the latest arrival times + tArrival = -TIM_ETERNITY; + Nwk_ManForEachPo( pNtk, pObj, i ) + if ( tArrival < Nwk_ObjArrival(pObj) ) + tArrival = Nwk_ObjArrival(pObj); + + // initialize the required times + if ( pNtk->pManTime ) + { + Tim_ManIncrementTravId( pNtk->pManTime ); + Tim_ManSetCoRequiredAll( pNtk->pManTime, tArrival ); + } + else + { + Nwk_ManForEachCo( pNtk, pObj, i ) + Nwk_ObjSetRequired( pObj, tArrival ); + } + + // propagate the required times + Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i ) + { + if ( Nwk_ObjIsNode(pObj) ) + { + Nwk_NodePropagateRequired( pObj, fUseSorting ); + } + else if ( Nwk_ObjIsCi(pObj) ) + { + if ( pNtk->pManTime ) + Tim_ManSetCiRequired( pNtk->pManTime, pObj->PioId, Nwk_ObjRequired(pObj) ); + } + else if ( Nwk_ObjIsCo(pObj) ) + { + if ( pNtk->pManTime ) + { + tRequired = Tim_ManGetCoRequired( pNtk->pManTime, pObj->PioId ); + Nwk_ObjSetRequired( pObj, tRequired ); + } + if ( Nwk_ObjRequired(Nwk_ObjFanin0(pObj)) > Nwk_ObjRequired(pObj) ) + Nwk_ObjSetRequired( Nwk_ObjFanin0(pObj), Nwk_ObjRequired(pObj) ); + } + + // set slack for this object + tSlack = Nwk_ObjRequired(pObj) - Nwk_ObjArrival(pObj); + assert( tSlack + 0.01 > 0.0 ); + Nwk_ObjSetSlack( pObj, tSlack < 0.0 ? 0.0 : tSlack ); + } + Vec_PtrFree( vNodes ); + return tArrival; +} + +/**Function************************************************************* + + Synopsis [Computes the arrival times for the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManVerifyTiming( Nwk_Man_t * pNtk ) +{ + Nwk_Obj_t * pObj; + float tArrival, tRequired; + int i; + Nwk_ManForEachObj( pNtk, pObj, i ) + { + if ( Nwk_ObjIsCi(pObj) && Nwk_ObjFanoutNum(pObj) == 0 ) + continue; + tArrival = Nwk_NodeComputeArrival( pObj, 1 ); + tRequired = Nwk_NodeComputeRequired( pObj, 1 ); + if ( !Nwk_ManTimeEqual( tArrival, Nwk_ObjArrival(pObj), (float)0.01 ) ) + printf( "Nwk_ManVerifyTiming(): Object %d has different arrival time (%.2f) from computed (%.2f).\n", + pObj->Id, Nwk_ObjArrival(pObj), tArrival ); + if ( !Nwk_ManTimeEqual( tRequired, Nwk_ObjRequired(pObj), (float)0.01 ) ) + printf( "Nwk_ManVerifyTiming(): Object %d has different required time (%.2f) from computed (%.2f).\n", + pObj->Id, Nwk_ObjRequired(pObj), tRequired ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Prints the delay trace for the given network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManDelayTracePrint( Nwk_Man_t * pNtk ) +{ + If_Lib_t * pLutLib = pNtk->pLutLib; + Nwk_Obj_t * pNode; + int i, Nodes, * pCounters; + float tArrival, tDelta, nSteps, Num; + // get the library + if ( pLutLib && pLutLib->LutMax < Nwk_ManGetFaninMax(pNtk) ) + { + printf( "The max LUT size (%d) is less than the max fanin count (%d).\n", + pLutLib->LutMax, Nwk_ManGetFaninMax(pNtk) ); + return; + } + // decide how many steps + nSteps = pLutLib ? 20 : Nwk_ManLevelMax(pNtk); + pCounters = ABC_ALLOC( int, nSteps + 1 ); + memset( pCounters, 0, sizeof(int)*(nSteps + 1) ); + // perform delay trace + tArrival = Nwk_ManDelayTraceLut( pNtk ); + tDelta = tArrival / nSteps; + // count how many nodes have slack in the corresponding intervals + Nwk_ManForEachNode( pNtk, pNode, i ) + { + if ( Nwk_ObjFaninNum(pNode) == 0 ) + continue; + Num = Nwk_ObjSlack(pNode) / tDelta; + if ( Num > nSteps ) + continue; + assert( Num >=0 && Num <= nSteps ); + pCounters[(int)Num]++; + } + // print the results + printf( "Max delay = %6.2f. Delay trace using %s model:\n", tArrival, pLutLib? "LUT library" : "unit-delay" ); + Nodes = 0; + for ( i = 0; i < nSteps; i++ ) + { + Nodes += pCounters[i]; + printf( "%3d %s : %5d (%6.2f %%)\n", pLutLib? 5*(i+1) : i+1, + pLutLib? "%":"lev", Nodes, 100.0*Nodes/Nwk_ManNodeNum(pNtk) ); + } + ABC_FREE( pCounters ); +} + + +/**Function************************************************************* + + Synopsis [Inserts node into the queue of nodes sorted by level.] + + Description [The inserted node should not go before the current position + given by iCurrent. If the arrival times are computed, the nodes are sorted + in the increasing order of levels. If the required times are computed, + the nodes are sorted in the decreasing order of levels.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_NodeUpdateAddToQueue( Vec_Ptr_t * vQueue, Nwk_Obj_t * pObj, int iCurrent, int fArrival ) +{ + Nwk_Obj_t * pTemp1, * pTemp2; + int i; + Vec_PtrPush( vQueue, pObj ); + for ( i = Vec_PtrSize(vQueue) - 1; i > iCurrent + 1; i-- ) + { + pTemp1 = (Nwk_Obj_t *)vQueue->pArray[i]; + pTemp2 = (Nwk_Obj_t *)vQueue->pArray[i-1]; + if ( fArrival ) + { + if ( Nwk_ObjLevel(pTemp2) <= Nwk_ObjLevel(pTemp1) ) + break; + } + else + { + if ( Nwk_ObjLevel(pTemp2) >= Nwk_ObjLevel(pTemp1) ) + break; + } + vQueue->pArray[i-1] = pTemp1; + vQueue->pArray[i] = pTemp2; + } + // verification + for ( i = iCurrent + 1; i < Vec_PtrSize(vQueue) - 1; i++ ) + { + pTemp1 = (Nwk_Obj_t *)vQueue->pArray[i]; + pTemp2 = (Nwk_Obj_t *)vQueue->pArray[i+1]; + if ( fArrival ) + assert( Nwk_ObjLevel(pTemp1) <= Nwk_ObjLevel(pTemp2) ); + else + assert( Nwk_ObjLevel(pTemp1) >= Nwk_ObjLevel(pTemp2) ); + } +} + +/**Function************************************************************* + + Synopsis [Incrementally updates arrival times of the node.] + + Description [Supports variable-pin delay model and white-boxes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_NodeUpdateArrival( Nwk_Obj_t * pObj ) +{ + Tim_Man_t * pManTime = pObj->pMan->pManTime; + Vec_Ptr_t * vQueue = pObj->pMan->vTemp; + Nwk_Obj_t * pTemp; + Nwk_Obj_t * pNext = NULL; // Suppress "might be used uninitialized" + float tArrival; + int iCur, k, iBox, iTerm1, nTerms; + assert( Nwk_ObjIsNode(pObj) ); + // verify the arrival time + tArrival = Nwk_NodeComputeArrival( pObj, 1 ); + assert( Nwk_ManTimeLess( tArrival, Nwk_ObjRequired(pObj), (float)0.01 ) ); + // initialize the queue with the node + Vec_PtrClear( vQueue ); + Vec_PtrPush( vQueue, pObj ); + pObj->MarkA = 1; + // process objects + if ( pManTime ) + Tim_ManIncrementTravId( pManTime ); + Vec_PtrForEachEntry( Nwk_Obj_t *, vQueue, pTemp, iCur ) + { + pTemp->MarkA = 0; + tArrival = Nwk_NodeComputeArrival( pTemp, 1 ); + if ( Nwk_ObjIsCi(pTemp) && pManTime ) + tArrival = Tim_ManGetCiArrival( pManTime, pTemp->PioId ); + if ( Nwk_ManTimeEqual( tArrival, Nwk_ObjArrival(pTemp), (float)0.01 ) ) + continue; + Nwk_ObjSetArrival( pTemp, tArrival ); + // add the fanouts to the queue + if ( Nwk_ObjIsCo(pTemp) ) + { + if ( pManTime ) + { + iBox = Tim_ManBoxForCo( pManTime, pTemp->PioId ); + if ( iBox >= 0 ) // this CO is an input of the box + { + // it may happen that a box-input (CO) was already marked as visited + // when some other box-input of the same box was visited - here we undo this + if ( Tim_ManIsCoTravIdCurrent( pManTime, pTemp->PioId ) ) + Tim_ManSetPreviousTravIdBoxInputs( pManTime, iBox ); + Tim_ManSetCoArrival( pManTime, pTemp->PioId, tArrival ); + Tim_ManSetCurrentTravIdBoxInputs( pManTime, iBox ); + iTerm1 = Tim_ManBoxOutputFirst( pManTime, iBox ); + nTerms = Tim_ManBoxOutputNum( pManTime, iBox ); + for ( k = 0; k < nTerms; k++ ) + { + pNext = Nwk_ManCi(pNext->pMan, iTerm1 + k); + if ( pNext->MarkA ) + continue; + Nwk_NodeUpdateAddToQueue( vQueue, pNext, iCur, 1 ); + pNext->MarkA = 1; + } + } + } + } + else + { + Nwk_ObjForEachFanout( pTemp, pNext, k ) + { + if ( pNext->MarkA ) + continue; + Nwk_NodeUpdateAddToQueue( vQueue, pNext, iCur, 1 ); + pNext->MarkA = 1; + } + } + } +} + +/**Function************************************************************* + + Synopsis [Incrementally updates required times of the node.] + + Description [Supports variable-pin delay model and white-boxes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_NodeUpdateRequired( Nwk_Obj_t * pObj ) +{ + Tim_Man_t * pManTime = pObj->pMan->pManTime; + Vec_Ptr_t * vQueue = pObj->pMan->vTemp; + Nwk_Obj_t * pTemp; + Nwk_Obj_t * pNext = NULL; // Suppress "might be used uninitialized" + float tRequired; + int iCur, k, iBox, iTerm1, nTerms; + assert( Nwk_ObjIsNode(pObj) ); + // make sure the node's required time remained the same + tRequired = Nwk_NodeComputeRequired( pObj, 1 ); + assert( Nwk_ManTimeEqual( tRequired, Nwk_ObjRequired(pObj), (float)0.01 ) ); + // initialize the queue with the node's faninsa and the old node's fanins + Vec_PtrClear( vQueue ); + Nwk_ObjForEachFanin( pObj, pNext, k ) + { + if ( pNext->MarkA ) + continue; + Nwk_NodeUpdateAddToQueue( vQueue, pNext, -1, 0 ); + pNext->MarkA = 1; + } + // process objects + if ( pManTime ) + Tim_ManIncrementTravId( pManTime ); + Vec_PtrForEachEntry( Nwk_Obj_t *, vQueue, pTemp, iCur ) + { + pTemp->MarkA = 0; + tRequired = Nwk_NodeComputeRequired( pTemp, 1 ); + if ( Nwk_ObjIsCo(pTemp) && pManTime ) + tRequired = Tim_ManGetCoRequired( pManTime, pTemp->PioId ); + if ( Nwk_ManTimeEqual( tRequired, Nwk_ObjRequired(pTemp), (float)0.01 ) ) + continue; + Nwk_ObjSetRequired( pTemp, tRequired ); + // add the fanins to the queue + if ( Nwk_ObjIsCi(pTemp) ) + { + if ( pManTime ) + { + iBox = Tim_ManBoxForCi( pManTime, pTemp->PioId ); + if ( iBox >= 0 ) // this CI is an output of the box + { + // it may happen that a box-output (CI) was already marked as visited + // when some other box-output of the same box was visited - here we undo this + if ( Tim_ManIsCiTravIdCurrent( pManTime, pTemp->PioId ) ) + Tim_ManSetPreviousTravIdBoxOutputs( pManTime, iBox ); + Tim_ManSetCiRequired( pManTime, pTemp->PioId, tRequired ); + Tim_ManSetCurrentTravIdBoxOutputs( pManTime, iBox ); + iTerm1 = Tim_ManBoxInputFirst( pManTime, iBox ); + nTerms = Tim_ManBoxInputNum( pManTime, iBox ); + for ( k = 0; k < nTerms; k++ ) + { + pNext = Nwk_ManCo(pNext->pMan, iTerm1 + k); + if ( pNext->MarkA ) + continue; + Nwk_NodeUpdateAddToQueue( vQueue, pNext, iCur, 0 ); + pNext->MarkA = 1; + } + } + } + } + else + { + Nwk_ObjForEachFanin( pTemp, pNext, k ) + { + if ( pNext->MarkA ) + continue; + Nwk_NodeUpdateAddToQueue( vQueue, pNext, iCur, 0 ); + pNext->MarkA = 1; + } + } + } +} + +/**Function************************************************************* + + Synopsis [Computes the level of the node using its fanin levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ObjLevelNew( Nwk_Obj_t * pObj ) +{ + Tim_Man_t * pManTime = pObj->pMan->pManTime; + Nwk_Obj_t * pFanin; + int i, iBox, iTerm1, nTerms, Level = 0; + if ( Nwk_ObjIsCi(pObj) || Nwk_ObjIsLatch(pObj) ) + { + if ( pManTime ) + { + iBox = Tim_ManBoxForCi( pManTime, pObj->PioId ); + if ( iBox >= 0 ) // this CI is an output of the box + { + iTerm1 = Tim_ManBoxInputFirst( pManTime, iBox ); + nTerms = Tim_ManBoxInputNum( pManTime, iBox ); + for ( i = 0; i < nTerms; i++ ) + { + pFanin = Nwk_ManCo(pObj->pMan, iTerm1 + i); + Level = Abc_MaxInt( Level, Nwk_ObjLevel(pFanin) ); + } + Level++; + } + } + return Level; + } + assert( Nwk_ObjIsNode(pObj) || Nwk_ObjIsCo(pObj) ); + Nwk_ObjForEachFanin( pObj, pFanin, i ) + Level = Abc_MaxInt( Level, Nwk_ObjLevel(pFanin) ); + return Level + (Nwk_ObjIsNode(pObj) && Nwk_ObjFaninNum(pObj) > 0); +} + +/**Function************************************************************* + + Synopsis [Incrementally updates level of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManUpdateLevel( Nwk_Obj_t * pObj ) +{ + Tim_Man_t * pManTime = pObj->pMan->pManTime; + Vec_Ptr_t * vQueue = pObj->pMan->vTemp; + Nwk_Obj_t * pTemp; + Nwk_Obj_t * pNext = NULL; // Suppress "might be used uninitialized" + int LevelNew, iCur, k, iBox, iTerm1, nTerms; + assert( Nwk_ObjIsNode(pObj) ); + // initialize the queue with the node + Vec_PtrClear( vQueue ); + Vec_PtrPush( vQueue, pObj ); + pObj->MarkA = 1; + // process objects + Vec_PtrForEachEntry( Nwk_Obj_t *, vQueue, pTemp, iCur ) + { + pTemp->MarkA = 0; + LevelNew = Nwk_ObjLevelNew( pTemp ); + if ( LevelNew == Nwk_ObjLevel(pTemp) ) + continue; + Nwk_ObjSetLevel( pTemp, LevelNew ); + // add the fanouts to the queue + if ( Nwk_ObjIsCo(pTemp) ) + { + if ( pManTime ) + { + iBox = Tim_ManBoxForCo( pManTime, pTemp->PioId ); + if ( iBox >= 0 ) // this is not a true PO + { + Tim_ManSetCurrentTravIdBoxInputs( pManTime, iBox ); + iTerm1 = Tim_ManBoxOutputFirst( pManTime, iBox ); + nTerms = Tim_ManBoxOutputNum( pManTime, iBox ); + for ( k = 0; k < nTerms; k++ ) + { + pNext = Nwk_ManCi(pNext->pMan, iTerm1 + k); + if ( pNext->MarkA ) + continue; + Nwk_NodeUpdateAddToQueue( vQueue, pNext, iCur, 1 ); + pNext->MarkA = 1; + } + } + } + } + else + { + Nwk_ObjForEachFanout( pTemp, pNext, k ) + { + if ( pNext->MarkA ) + continue; + Nwk_NodeUpdateAddToQueue( vQueue, pNext, iCur, 1 ); + pNext->MarkA = 1; + } + } + } +} + +/**Function************************************************************* + + Synopsis [Computes the level of the node using its fanin levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManVerifyLevel( Nwk_Man_t * pNtk ) +{ + Nwk_Obj_t * pObj; + int LevelNew, i; + Nwk_ManForEachObj( pNtk, pObj, i ) + { + assert( pObj->MarkA == 0 ); + LevelNew = Nwk_ObjLevelNew( pObj ); + if ( Nwk_ObjLevel(pObj) != LevelNew ) + { + printf( "Object %6d: Mismatch betweeh levels: Actual = %d. Correct = %d.\n", + i, Nwk_ObjLevel(pObj), LevelNew ); + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Replaces the node and incrementally updates levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManUpdate( Nwk_Obj_t * pObj, Nwk_Obj_t * pObjNew, Vec_Vec_t * vLevels ) +{ + assert( pObj->pMan == pObjNew->pMan ); + assert( pObj != pObjNew ); + assert( Nwk_ObjFanoutNum(pObj) > 0 ); + assert( Nwk_ObjIsNode(pObj) && !Nwk_ObjIsCo(pObjNew) ); + // transfer fanouts to the old node + Nwk_ObjTransferFanout( pObj, pObjNew ); + // transfer the timing information + // (this is needed because updating level happens if the level has changed; + // when we set the old level, it will be recomputed by the level updating + // procedure, which will update level of other nodes if there is a difference) + pObjNew->Level = pObj->Level; + pObjNew->tArrival = pObj->tArrival; + pObjNew->tRequired = pObj->tRequired; + // update required times of the old fanins + pObj->tRequired = TIM_ETERNITY; + Nwk_NodeUpdateRequired( pObj ); + // remove the old node + Nwk_ManDeleteNode_rec( pObj ); + // update the information of the new node + Nwk_ManUpdateLevel( pObjNew ); + Nwk_NodeUpdateArrival( pObjNew ); + Nwk_NodeUpdateRequired( pObjNew ); +//Nwk_ManVerifyTiming( pObjNew->pMan ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/nwk/nwkUtil.c b/src/opt/nwk/nwkUtil.c new file mode 100644 index 00000000..9d23c869 --- /dev/null +++ b/src/opt/nwk/nwkUtil.c @@ -0,0 +1,643 @@ +/**CFile**************************************************************** + + FileName [nwkUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Logic network representation.] + + Synopsis [Various utilities.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: nwkUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include "nwk.h" +#include "src/bool/kit/kit.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Increments the current traversal ID of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManIncrementTravId( Nwk_Man_t * pNtk ) +{ + Nwk_Obj_t * pObj; + int i; + if ( pNtk->nTravIds >= (1<<26)-1 ) + { + pNtk->nTravIds = 0; + Nwk_ManForEachObj( pNtk, pObj, i ) + pObj->TravId = 0; + } + pNtk->nTravIds++; +} + +/**Function************************************************************* + + Synopsis [Reads the maximum number of fanins of a node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManGetFaninMax( Nwk_Man_t * pNtk ) +{ + Nwk_Obj_t * pNode; + int i, nFaninsMax = 0; + Nwk_ManForEachNode( pNtk, pNode, i ) + { + if ( nFaninsMax < Nwk_ObjFaninNum(pNode) ) + nFaninsMax = Nwk_ObjFaninNum(pNode); + } + return nFaninsMax; +} + +/**Function************************************************************* + + Synopsis [Reads the total number of all fanins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManGetTotalFanins( Nwk_Man_t * pNtk ) +{ + Nwk_Obj_t * pNode; + int i, nFanins = 0; + Nwk_ManForEachNode( pNtk, pNode, i ) + nFanins += Nwk_ObjFaninNum(pNode); + return nFanins; +} + + +/**Function************************************************************* + + Synopsis [Returns the number of true PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManPiNum( Nwk_Man_t * pNtk ) +{ + Nwk_Obj_t * pNode; + int i, Counter = 0; + Nwk_ManForEachCi( pNtk, pNode, i ) + Counter += Nwk_ObjIsPi( pNode ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns the number of true POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManPoNum( Nwk_Man_t * pNtk ) +{ + Nwk_Obj_t * pNode; + int i, Counter = 0; + Nwk_ManForEachCo( pNtk, pNode, i ) + Counter += Nwk_ObjIsPo( pNode ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Reads the number of AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManGetAigNodeNum( Nwk_Man_t * pNtk ) +{ + Nwk_Obj_t * pNode; + int i, nNodes = 0; + Nwk_ManForEachNode( pNtk, pNode, i ) + { + if ( pNode->pFunc == NULL ) + { + printf( "Nwk_ManGetAigNodeNum(): Local AIG of node %d is not assigned.\n", pNode->Id ); + continue; + } + if ( Nwk_ObjFaninNum(pNode) < 2 ) + continue; + nNodes += Hop_DagSize( pNode->pFunc ); + } + return nNodes; +} + +/**Function************************************************************* + + Synopsis [Procedure used for sorting the nodes in increasing order of levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_NodeCompareLevelsIncrease( Nwk_Obj_t ** pp1, Nwk_Obj_t ** pp2 ) +{ + int Diff = (*pp1)->Level - (*pp2)->Level; + if ( Diff < 0 ) + return -1; + if ( Diff > 0 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_NodeCompareLevelsDecrease( Nwk_Obj_t ** pp1, Nwk_Obj_t ** pp2 ) +{ + int Diff = (*pp1)->Level - (*pp2)->Level; + if ( Diff > 0 ) + return -1; + if ( Diff < 0 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Prints the objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ObjPrint( Nwk_Obj_t * pObj ) +{ + Nwk_Obj_t * pNext; + int i; + printf( "ObjId = %5d. ", pObj->Id ); + if ( Nwk_ObjIsPi(pObj) ) + printf( "PI" ); + if ( Nwk_ObjIsPo(pObj) ) + printf( "PO" ); + if ( Nwk_ObjIsNode(pObj) ) + printf( "Node" ); + printf( " Fanins = " ); + Nwk_ObjForEachFanin( pObj, pNext, i ) + printf( "%d ", pNext->Id ); + printf( " Fanouts = " ); + Nwk_ObjForEachFanout( pObj, pNext, i ) + printf( "%d ", pNext->Id ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Dumps the BLIF file for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManDumpBlif( Nwk_Man_t * pNtk, char * pFileName, Vec_Ptr_t * vPiNames, Vec_Ptr_t * vPoNames ) +{ + FILE * pFile; + Vec_Ptr_t * vNodes; + Vec_Int_t * vTruth; + Vec_Int_t * vCover; + Nwk_Obj_t * pObj, * pFanin; + Aig_MmFlex_t * pMem; + char * pSop = NULL; + unsigned * pTruth; + int i, k, nDigits; + if ( Nwk_ManPoNum(pNtk) == 0 ) + { + printf( "Nwk_ManDumpBlif(): Network does not have POs.\n" ); + return; + } + // collect nodes in the DFS order + nDigits = Abc_Base10Log( Nwk_ManObjNumMax(pNtk) ); + // write the file + pFile = fopen( pFileName, "w" ); + fprintf( pFile, "# BLIF file written by procedure Nwk_ManDumpBlif()\n" ); +// fprintf( pFile, "# http://www.eecs.berkeley.edu/~alanmi/abc/\n" ); + fprintf( pFile, ".model %s\n", pNtk->pName ); + // write PIs + fprintf( pFile, ".inputs" ); + Nwk_ManForEachCi( pNtk, pObj, i ) + if ( vPiNames ) + fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPiNames, i) ); + else + fprintf( pFile, " n%0*d", nDigits, pObj->Id ); + fprintf( pFile, "\n" ); + // write POs + fprintf( pFile, ".outputs" ); + Nwk_ManForEachCo( pNtk, pObj, i ) + if ( vPoNames ) + fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPoNames, i) ); + else + fprintf( pFile, " n%0*d", nDigits, pObj->Id ); + fprintf( pFile, "\n" ); + // write nodes + pMem = Aig_MmFlexStart(); + vTruth = Vec_IntAlloc( 1 << 16 ); + vCover = Vec_IntAlloc( 1 << 16 ); + vNodes = Nwk_ManDfs( pNtk ); + Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i ) + { + if ( !Nwk_ObjIsNode(pObj) ) + continue; + // derive SOP for the AIG + pTruth = Hop_ManConvertAigToTruth( pNtk->pManHop, Hop_Regular(pObj->pFunc), Nwk_ObjFaninNum(pObj), vTruth, 0 ); + if ( Hop_IsComplement(pObj->pFunc) ) + Kit_TruthNot( pTruth, pTruth, Nwk_ObjFaninNum(pObj) ); + pSop = Kit_PlaFromTruth( pMem, pTruth, Nwk_ObjFaninNum(pObj), vCover ); + // write the node + fprintf( pFile, ".names" ); + if ( !Kit_TruthIsConst0(pTruth, Nwk_ObjFaninNum(pObj)) && !Kit_TruthIsConst1(pTruth, Nwk_ObjFaninNum(pObj)) ) + { + Nwk_ObjForEachFanin( pObj, pFanin, k ) + if ( vPiNames && Nwk_ObjIsPi(pFanin) ) + fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPiNames, Nwk_ObjPioNum(pFanin)) ); + else + fprintf( pFile, " n%0*d", nDigits, pFanin->Id ); + } + fprintf( pFile, " n%0*d\n", nDigits, pObj->Id ); + // write the function + fprintf( pFile, "%s", pSop ); + } + Vec_IntFree( vCover ); + Vec_IntFree( vTruth ); + Vec_PtrFree( vNodes ); + Aig_MmFlexStop( pMem, 0 ); + // write POs + Nwk_ManForEachCo( pNtk, pObj, i ) + { + fprintf( pFile, ".names" ); + if ( vPiNames && Nwk_ObjIsPi(Nwk_ObjFanin0(pObj)) ) + fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPiNames, Nwk_ObjPioNum(Nwk_ObjFanin0(pObj))) ); + else + fprintf( pFile, " n%0*d", nDigits, Nwk_ObjFanin0(pObj)->Id ); + if ( vPoNames ) + fprintf( pFile, " %s\n", (char*)Vec_PtrEntry(vPoNames, Nwk_ObjPioNum(pObj)) ); + else + fprintf( pFile, " n%0*d\n", nDigits, pObj->Id ); + fprintf( pFile, "%d 1\n", !pObj->fInvert ); + } + fprintf( pFile, ".end\n\n" ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Prints the distribution of fanins/fanouts in the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManPrintFanioNew( Nwk_Man_t * pNtk ) +{ + char Buffer[100]; + Nwk_Obj_t * pNode; + Vec_Int_t * vFanins, * vFanouts; + int nFanins, nFanouts, nFaninsMax, nFanoutsMax, nFaninsAll, nFanoutsAll; + int i, k, nSizeMax; + + // determine the largest fanin and fanout + nFaninsMax = nFanoutsMax = 0; + nFaninsAll = nFanoutsAll = 0; + Nwk_ManForEachNode( pNtk, pNode, i ) + { + nFanins = Nwk_ObjFaninNum(pNode); + nFanouts = Nwk_ObjFanoutNum(pNode); + nFaninsAll += nFanins; + nFanoutsAll += nFanouts; + nFaninsMax = Abc_MaxInt( nFaninsMax, nFanins ); + nFanoutsMax = Abc_MaxInt( nFanoutsMax, nFanouts ); + } + + // allocate storage for fanin/fanout numbers + nSizeMax = Abc_MaxInt( 10 * (Abc_Base10Log(nFaninsMax) + 1), 10 * (Abc_Base10Log(nFanoutsMax) + 1) ); + vFanins = Vec_IntStart( nSizeMax ); + vFanouts = Vec_IntStart( nSizeMax ); + + // count the number of fanins and fanouts + Nwk_ManForEachNode( pNtk, pNode, i ) + { + nFanins = Nwk_ObjFaninNum(pNode); + nFanouts = Nwk_ObjFanoutNum(pNode); +// nFanouts = Nwk_NodeMffcSize(pNode); + + if ( nFanins < 10 ) + Vec_IntAddToEntry( vFanins, nFanins, 1 ); + else if ( nFanins < 100 ) + Vec_IntAddToEntry( vFanins, 10 + nFanins/10, 1 ); + else if ( nFanins < 1000 ) + Vec_IntAddToEntry( vFanins, 20 + nFanins/100, 1 ); + else if ( nFanins < 10000 ) + Vec_IntAddToEntry( vFanins, 30 + nFanins/1000, 1 ); + else if ( nFanins < 100000 ) + Vec_IntAddToEntry( vFanins, 40 + nFanins/10000, 1 ); + else if ( nFanins < 1000000 ) + Vec_IntAddToEntry( vFanins, 50 + nFanins/100000, 1 ); + else if ( nFanins < 10000000 ) + Vec_IntAddToEntry( vFanins, 60 + nFanins/1000000, 1 ); + + if ( nFanouts < 10 ) + Vec_IntAddToEntry( vFanouts, nFanouts, 1 ); + else if ( nFanouts < 100 ) + Vec_IntAddToEntry( vFanouts, 10 + nFanouts/10, 1 ); + else if ( nFanouts < 1000 ) + Vec_IntAddToEntry( vFanouts, 20 + nFanouts/100, 1 ); + else if ( nFanouts < 10000 ) + Vec_IntAddToEntry( vFanouts, 30 + nFanouts/1000, 1 ); + else if ( nFanouts < 100000 ) + Vec_IntAddToEntry( vFanouts, 40 + nFanouts/10000, 1 ); + else if ( nFanouts < 1000000 ) + Vec_IntAddToEntry( vFanouts, 50 + nFanouts/100000, 1 ); + else if ( nFanouts < 10000000 ) + Vec_IntAddToEntry( vFanouts, 60 + nFanouts/1000000, 1 ); + } + + printf( "The distribution of fanins and fanouts in the network:\n" ); + printf( " Number Nodes with fanin Nodes with fanout\n" ); + for ( k = 0; k < nSizeMax; k++ ) + { + if ( vFanins->pArray[k] == 0 && vFanouts->pArray[k] == 0 ) + continue; + if ( k < 10 ) + printf( "%15d : ", k ); + else + { + sprintf( Buffer, "%d - %d", (int)pow((double)10, k/10) * (k%10), (int)pow((double)10, k/10) * (k%10+1) - 1 ); + printf( "%15s : ", Buffer ); + } + if ( vFanins->pArray[k] == 0 ) + printf( " " ); + else + printf( "%12d ", vFanins->pArray[k] ); + printf( " " ); + if ( vFanouts->pArray[k] == 0 ) + printf( " " ); + else + printf( "%12d ", vFanouts->pArray[k] ); + printf( "\n" ); + } + Vec_IntFree( vFanins ); + Vec_IntFree( vFanouts ); + + printf( "Fanins: Max = %d. Ave = %.2f. Fanouts: Max = %d. Ave = %.2f.\n", + nFaninsMax, 1.0*nFaninsAll/Nwk_ManNodeNum(pNtk), + nFanoutsMax, 1.0*nFanoutsAll/Nwk_ManNodeNum(pNtk) ); +} + +/**Function************************************************************* + + Synopsis [Cleans the temporary marks of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManCleanMarks( Nwk_Man_t * pMan ) +{ + Nwk_Obj_t * pObj; + int i; + Nwk_ManForEachObj( pMan, pObj, i ) + pObj->MarkA = pObj->MarkB = 0; +} + +/**Function************************************************************* + + Synopsis [Minimizes the support of all nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManMinimumBaseNode( Nwk_Obj_t * pObj, Vec_Int_t * vTruth, int fVerbose ) +{ + unsigned * pTruth; + Nwk_Obj_t * pFanin, * pObjNew; + Nwk_Man_t * pNtk = pObj->pMan; + int uSupp, nSuppSize, k, Counter = 0; + pTruth = Hop_ManConvertAigToTruth( pNtk->pManHop, Hop_Regular(pObj->pFunc), Nwk_ObjFaninNum(pObj), vTruth, 0 ); + nSuppSize = Kit_TruthSupportSize(pTruth, Nwk_ObjFaninNum(pObj)); + if ( nSuppSize == Nwk_ObjFaninNum(pObj) ) + return 0; + Counter++; + uSupp = Kit_TruthSupport( pTruth, Nwk_ObjFaninNum(pObj) ); + // create new node with the given support + pObjNew = Nwk_ManCreateNode( pNtk, nSuppSize, Nwk_ObjFanoutNum(pObj) ); + Nwk_ObjForEachFanin( pObj, pFanin, k ) + if ( uSupp & (1 << k) ) + Nwk_ObjAddFanin( pObjNew, pFanin ); + pObjNew->pFunc = Hop_Remap( pNtk->pManHop, pObj->pFunc, uSupp, Nwk_ObjFaninNum(pObj) ); + if ( fVerbose ) + printf( "Reducing node %d fanins from %d to %d.\n", + pObj->Id, Nwk_ObjFaninNum(pObj), Nwk_ObjFaninNum(pObjNew) ); + Nwk_ObjReplace( pObj, pObjNew ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Minimizes the support of all nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nwk_ManMinimumBaseInt( Nwk_Man_t * pNtk, int fVerbose ) +{ + Vec_Int_t * vTruth; + Nwk_Obj_t * pObj; + int i, Counter = 0; + vTruth = Vec_IntAlloc( 1 << 16 ); + Nwk_ManForEachNode( pNtk, pObj, i ) + Counter += Nwk_ManMinimumBaseNode( pObj, vTruth, fVerbose ); + if ( fVerbose && Counter ) + printf( "Support minimization reduced support of %d nodes.\n", Counter ); + Vec_IntFree( vTruth ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Minimizes the support of all nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManMinimumBaseRec( Nwk_Man_t * pNtk, int fVerbose ) +{ + int i, clk = clock(); + for ( i = 0; Nwk_ManMinimumBaseInt( pNtk, fVerbose ); i++ ); + ABC_PRT( "Minbase", clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [Minimizes the support of all nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManMinimumBase( Nwk_Man_t * pNtk, int fVerbose ) +{ + Vec_Int_t * vTruth; + Nwk_Obj_t * pObj; + int i, Counter = 0; + vTruth = Vec_IntAlloc( 1 << 16 ); + Nwk_ManForEachNode( pNtk, pObj, i ) + Counter += Nwk_ManMinimumBaseNode( pObj, vTruth, fVerbose ); + if ( fVerbose && Counter ) + printf( "Support minimization reduced support of %d nodes.\n", Counter ); + Vec_IntFree( vTruth ); +} + +/**Function************************************************************* + + Synopsis [Minimizes the support of all nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManRemoveDupFaninsNode( Nwk_Obj_t * pObj, int iFan0, int iFan1, Vec_Int_t * vTruth ) +{ + Hop_Man_t * pManHop = pObj->pMan->pManHop; +// Nwk_Obj_t * pFanin0 = pObj->pFanio[iFan0]; +// Nwk_Obj_t * pFanin1 = pObj->pFanio[iFan1]; + assert( pObj->pFanio[iFan0] == pObj->pFanio[iFan1] ); + pObj->pFunc = Hop_Compose( pManHop, pObj->pFunc, Hop_IthVar(pManHop,iFan0), iFan1 ); + Nwk_ManMinimumBaseNode( pObj, vTruth, 0 ); +} + +/**Function************************************************************* + + Synopsis [Minimizes the support of all nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManRemoveDupFanins( Nwk_Man_t * pNtk, int fVerbose ) +{ + Vec_Int_t * vTruth; + Nwk_Obj_t * pObj; + int i, k, m, fFound; + // check if the nodes have duplicated fanins + vTruth = Vec_IntAlloc( 1 << 16 ); + Nwk_ManForEachNode( pNtk, pObj, i ) + { + fFound = 0; + for ( k = 0; k < pObj->nFanins; k++ ) + { + for ( m = k + 1; m < pObj->nFanins; m++ ) + if ( pObj->pFanio[k] == pObj->pFanio[m] ) + { + if ( fVerbose ) + printf( "Removing duplicated fanins of node %d (fanins %d and %d).\n", + pObj->Id, pObj->pFanio[k]->Id, pObj->pFanio[m]->Id ); + Nwk_ManRemoveDupFaninsNode( pObj, k, m, vTruth ); + fFound = 1; + break; + } + if ( fFound ) + break; + } + } + Vec_IntFree( vTruth ); +// Nwk_ManMinimumBase( pNtk, fVerbose ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/nwk/nwk_.c b/src/opt/nwk/nwk_.c new file mode 100644 index 00000000..882b077c --- /dev/null +++ b/src/opt/nwk/nwk_.c @@ -0,0 +1,52 @@ +/**CFile**************************************************************** + + FileName [nwk_.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: nwk_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "nwk.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/res/res.h b/src/opt/res/res.h index bd328d54..0a941c59 100644 --- a/src/opt/res/res.h +++ b/src/opt/res/res.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __RES_H__ -#define __RES_H__ +#ifndef ABC__opt__res__res_h +#define ABC__opt__res__res_h //////////////////////////////////////////////////////////////////////// diff --git a/src/opt/res/resCore.c b/src/opt/res/resCore.c index eecdd481..effc7e65 100644 --- a/src/opt/res/resCore.c +++ b/src/opt/res/resCore.c @@ -18,10 +18,10 @@ ***********************************************************************/ -#include "abc.h" +#include "src/base/abc/abc.h" #include "resInt.h" -#include "kit.h" -#include "satStore.h" +#include "src/bool/kit/kit.h" +#include "src/sat/bsat/satStore.h" ABC_NAMESPACE_IMPL_START diff --git a/src/opt/res/resDivs.c b/src/opt/res/resDivs.c index 6d9ffd9f..f378991d 100644 --- a/src/opt/res/resDivs.c +++ b/src/opt/res/resDivs.c @@ -18,7 +18,7 @@ ***********************************************************************/ -#include "abc.h" +#include "src/base/abc/abc.h" #include "resInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/opt/res/resFilter.c b/src/opt/res/resFilter.c index b9d62dd8..188b9dc3 100644 --- a/src/opt/res/resFilter.c +++ b/src/opt/res/resFilter.c @@ -18,7 +18,7 @@ ***********************************************************************/ -#include "abc.h" +#include "src/base/abc/abc.h" #include "resInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/opt/res/resInt.h b/src/opt/res/resInt.h index ae238359..cd0cf84b 100644 --- a/src/opt/res/resInt.h +++ b/src/opt/res/resInt.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __RES_INT_H__ -#define __RES_INT_H__ +#ifndef ABC__opt__res__resInt_h +#define ABC__opt__res__resInt_h //////////////////////////////////////////////////////////////////////// diff --git a/src/opt/res/resSat.c b/src/opt/res/resSat.c index 17f3d661..111442b4 100644 --- a/src/opt/res/resSat.c +++ b/src/opt/res/resSat.c @@ -18,10 +18,10 @@ ***********************************************************************/ -#include "abc.h" +#include "src/base/abc/abc.h" #include "resInt.h" -#include "hop.h" -#include "satSolver.h" +#include "src/aig/hop/hop.h" +#include "src/sat/bsat/satSolver.h" ABC_NAMESPACE_IMPL_START diff --git a/src/opt/res/resSim.c b/src/opt/res/resSim.c index 740b7d0a..d8faf8bf 100644 --- a/src/opt/res/resSim.c +++ b/src/opt/res/resSim.c @@ -18,8 +18,7 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" #include "resInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/opt/res/resSim_old.c b/src/opt/res/resSim_old.c index ebadeec0..a6aced1d 100644 --- a/src/opt/res/resSim_old.c +++ b/src/opt/res/resSim_old.c @@ -18,7 +18,7 @@ ***********************************************************************/ -#include "abc.h" +#include "base/abc/abc.h" #include "resInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/opt/res/resStrash.c b/src/opt/res/resStrash.c index 1ee84957..c080a718 100644 --- a/src/opt/res/resStrash.c +++ b/src/opt/res/resStrash.c @@ -18,8 +18,7 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" #include "resInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/opt/res/resWin.c b/src/opt/res/resWin.c index e6eeac6a..09176833 100644 --- a/src/opt/res/resWin.c +++ b/src/opt/res/resWin.c @@ -18,7 +18,7 @@ ***********************************************************************/ -#include "abc.h" +#include "src/base/abc/abc.h" #include "resInt.h" ABC_NAMESPACE_IMPL_START @@ -145,10 +145,10 @@ int Res_WinCollectLeavesAndNodes( Res_Win_t * p ) // get the lowest leaf level p->nLevLeafMin = ABC_INFINITY; Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pObj, k ) - p->nLevLeafMin = ABC_MIN( p->nLevLeafMin, (int)pObj->Level ); + p->nLevLeafMin = Abc_MinInt( p->nLevLeafMin, (int)pObj->Level ); // set minimum traversal level - p->nLevTravMin = ABC_MAX( ((int)p->pNode->Level) - p->nWinTfiMax - p->nLevTfiMinus, p->nLevLeafMin ); + p->nLevTravMin = Abc_MaxInt( ((int)p->pNode->Level) - p->nWinTfiMax - p->nLevTfiMinus, p->nLevLeafMin ); assert( p->nLevTravMin >= 0 ); return 1; } diff --git a/src/opt/res/res_.c b/src/opt/res/res_.c index ffbc4946..8d18eeaf 100644 --- a/src/opt/res/res_.c +++ b/src/opt/res/res_.c @@ -18,7 +18,7 @@ ***********************************************************************/ -#include "abc.h" +#include "base/abc/abc.h" #include "res.h" ABC_NAMESPACE_IMPL_START diff --git a/src/opt/ret/retInt.h b/src/opt/ret/retInt.h index 39a6296e..9460f6e8 100644 --- a/src/opt/ret/retInt.h +++ b/src/opt/ret/retInt.h @@ -18,15 +18,15 @@ ***********************************************************************/ -#ifndef __RET_INT_H__ -#define __RET_INT_H__ +#ifndef ABC__opt__ret__retInt_h +#define ABC__opt__ret__retInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// -#include "abc.h" +#include "src/base/abc/abc.h" ABC_NAMESPACE_HEADER_START diff --git a/src/opt/rwr/rwr.h b/src/opt/rwr/rwr.h index ed05d4a3..50ea7998 100644 --- a/src/opt/rwr/rwr.h +++ b/src/opt/rwr/rwr.h @@ -18,16 +18,16 @@ ***********************************************************************/ -#ifndef __RWR_H__ -#define __RWR_H__ +#ifndef ABC__opt__rwr__rwr_h +#define ABC__opt__rwr__rwr_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// -#include "abc.h" -#include "cut.h" +#include "src/base/abc/abc.h" +#include "src/opt/cut/cut.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// diff --git a/src/opt/rwr/rwrDec.c b/src/opt/rwr/rwrDec.c index a280f5f1..c1860a7b 100644 --- a/src/opt/rwr/rwrDec.c +++ b/src/opt/rwr/rwrDec.c @@ -18,9 +18,8 @@ ***********************************************************************/ -#include "extra.h" #include "rwr.h" -#include "dec.h" +#include "src/bool/dec/dec.h" ABC_NAMESPACE_IMPL_START diff --git a/src/opt/rwr/rwrEva.c b/src/opt/rwr/rwrEva.c index 5d826da9..83eb8d7b 100644 --- a/src/opt/rwr/rwrEva.c +++ b/src/opt/rwr/rwrEva.c @@ -18,10 +18,9 @@ ***********************************************************************/ -#include "extra.h" #include "rwr.h" -#include "dec.h" -#include "ivy.h" +#include "src/bool/dec/dec.h" +#include "src/aig/ivy/ivy.h" ABC_NAMESPACE_IMPL_START @@ -487,7 +486,7 @@ int Rwr_NodeGetDepth_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves ) return 0; Depth0 = Rwr_NodeGetDepth_rec( Abc_ObjFanin0(pObj), vLeaves ); Depth1 = Rwr_NodeGetDepth_rec( Abc_ObjFanin1(pObj), vLeaves ); - return 1 + ABC_MAX( Depth0, Depth1 ); + return 1 + Abc_MaxInt( Depth0, Depth1 ); } diff --git a/src/opt/rwr/rwrExp.c b/src/opt/rwr/rwrExp.c index fa75f066..c4664fbf 100644 --- a/src/opt/rwr/rwrExp.c +++ b/src/opt/rwr/rwrExp.c @@ -18,7 +18,6 @@ ***********************************************************************/ -#include "extra.h" #include "rwr.h" ABC_NAMESPACE_IMPL_START diff --git a/src/opt/rwr/rwrLib.c b/src/opt/rwr/rwrLib.c index a7c01047..b1aa2ac7 100644 --- a/src/opt/rwr/rwrLib.c +++ b/src/opt/rwr/rwrLib.c @@ -18,7 +18,6 @@ ***********************************************************************/ -#include "extra.h" #include "rwr.h" ABC_NAMESPACE_IMPL_START @@ -76,7 +75,7 @@ void Rwr_ManPrecompute( Rwr_Man_t * p ) // break; // compute the level and volume of the new nodes - Level = 1 + ABC_MAX( p0->Level, p1->Level ); + Level = 1 + Abc_MaxInt( p0->Level, p1->Level ); Volume = 1 + Rwr_ManNodeVolume( p, p0, p1 ); // try four different AND nodes Rwr_ManTryNode( p, p0 , p1 , 0, Level, Volume ); diff --git a/src/opt/rwr/rwrMan.c b/src/opt/rwr/rwrMan.c index 0f32c0da..00273b38 100644 --- a/src/opt/rwr/rwrMan.c +++ b/src/opt/rwr/rwrMan.c @@ -18,10 +18,9 @@ ***********************************************************************/ -#include "extra.h" #include "rwr.h" -#include "main.h" -#include "dec.h" +#include "src/base/main/main.h" +#include "src/bool/dec/dec.h" ABC_NAMESPACE_IMPL_START diff --git a/src/opt/rwr/rwrPrint.c b/src/opt/rwr/rwrPrint.c index 5574df88..11a084d3 100644 --- a/src/opt/rwr/rwrPrint.c +++ b/src/opt/rwr/rwrPrint.c @@ -18,7 +18,6 @@ ***********************************************************************/ -#include "extra.h" #include "rwr.h" ABC_NAMESPACE_IMPL_START diff --git a/src/opt/rwr/rwrTemp.c b/src/opt/rwr/rwrTemp.c index 654e37c1..6a670c3a 100644 --- a/src/opt/rwr/rwrTemp.c +++ b/src/opt/rwr/rwrTemp.c @@ -18,7 +18,6 @@ ***********************************************************************/ -#include "extra.h" #include "rwr.h" ABC_NAMESPACE_IMPL_START diff --git a/src/opt/rwr/rwrUtil.c b/src/opt/rwr/rwrUtil.c index 7613691a..1b2e8760 100644 --- a/src/opt/rwr/rwrUtil.c +++ b/src/opt/rwr/rwrUtil.c @@ -18,7 +18,6 @@ ***********************************************************************/ -#include "extra.h" #include "rwr.h" ABC_NAMESPACE_IMPL_START @@ -491,7 +490,7 @@ void Rwr_ManLoadFromArray( Rwr_Man_t * p, int fVerbose ) p0 = (Rwr_Node_t *)p->vForest->pArray[Entry0 >> 1]; p1 = (Rwr_Node_t *)p->vForest->pArray[Entry1 >> 1]; // compute the level and volume of the new nodes - Level = 1 + ABC_MAX( p0->Level, p1->Level ); + Level = 1 + Abc_MaxInt( p0->Level, p1->Level ); Volume = 1 + Rwr_ManNodeVolume( p, p0, p1 ); // set the complemented attributes p0 = Rwr_NotCond( p0, (Entry0 & 1) ); @@ -586,7 +585,7 @@ void Rwr_ManLoadFromFile( Rwr_Man_t * p, char * pFileName ) p0 = (Rwr_Node_t *)p->vForest->pArray[pBuffer[2*i + 0] >> 1]; p1 = (Rwr_Node_t *)p->vForest->pArray[pBuffer[2*i + 1] >> 1]; // compute the level and volume of the new nodes - Level = 1 + ABC_MAX( p0->Level, p1->Level ); + Level = 1 + Abc_MaxInt( p0->Level, p1->Level ); Volume = 1 + Rwr_ManNodeVolume( p, p0, p1 ); // set the complemented attributes p0 = Rwr_NotCond( p0, (pBuffer[2*i + 0] & 1) ); diff --git a/src/opt/rwt/module.make b/src/opt/rwt/module.make new file mode 100644 index 00000000..a2a6f54c --- /dev/null +++ b/src/opt/rwt/module.make @@ -0,0 +1,3 @@ +SRC += src/opt/rwt/rwtDec.c \ + src/opt/rwt/rwtMan.c \ + src/opt/rwt/rwtUtil.c diff --git a/src/opt/rwt/rwt.h b/src/opt/rwt/rwt.h new file mode 100644 index 00000000..a528a307 --- /dev/null +++ b/src/opt/rwt/rwt.h @@ -0,0 +1,165 @@ +/**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 ABC__aig__rwt__rwt_h +#define ABC__aig__rwt__rwt_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +#include "src/misc/vec/vec.h" +#include "src/misc/extra/extra.h" +#include "src/misc/mem/mem.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// 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)(((ABC_PTRUINT_T)p) & 01); } +static inline Rwt_Node_t * Rwt_Regular( Rwt_Node_t * p ) { return (Rwt_Node_t *)((ABC_PTRUINT_T)(p) & ~01); } +static inline Rwt_Node_t * Rwt_Not( Rwt_Node_t * p ) { return (Rwt_Node_t *)((ABC_PTRUINT_T)(p) ^ 01); } +static inline Rwt_Node_t * Rwt_NotCond( Rwt_Node_t * p, int c ) { return (Rwt_Node_t *)((ABC_PTRUINT_T)(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 ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/opt/rwt/rwtDec.c b/src/opt/rwt/rwtDec.c new file mode 100644 index 00000000..82283a91 --- /dev/null +++ b/src/opt/rwt/rwtDec.c @@ -0,0 +1,155 @@ +/**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 "src/bool/deco/deco.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 = ABC_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] < 222 ); // Always >= 0 b/c unsigned. + 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( Rwt_Node_t *, 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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/rwt/rwtMan.c b/src/opt/rwt/rwtMan.c new file mode 100644 index 00000000..775d3a88 --- /dev/null +++ b/src/opt/rwt/rwtMan.c @@ -0,0 +1,363 @@ +/**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 "src/bool/deco/deco.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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() +{ + ABC_FREE( s_puCanons ); + ABC_FREE( s_pPhases ); + ABC_FREE( s_pPerms ); + ABC_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 = ABC_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 = ABC_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( Rwt_Node_t *, 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 ); + ABC_FREE( p->pMapInv ); + ABC_FREE( p->pTable ); + ABC_FREE( p->pPractical ); + ABC_FREE( p->pPerms4 ); + ABC_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 ); + ABC_PRT( "Start ", p->timeStart ); + ABC_PRT( "Cuts ", p->timeCut ); + ABC_PRT( "Truth ", p->timeTruth ); + ABC_PRT( "Resynthesis ", p->timeRes ); + ABC_PRT( " Mffc ", p->timeMffc ); + ABC_PRT( " Eval ", p->timeEval ); + ABC_PRT( "Update ", p->timeUpdate ); + ABC_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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/rwt/rwtUtil.c b/src/opt/rwt/rwtUtil.c new file mode 100644 index 00000000..6cdaf657 --- /dev/null +++ b/src/opt/rwt/rwtUtil.c @@ -0,0 +1,662 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// precomputed data +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 +}; + + +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 +}; + +//////////////////////////////////////////////////////////////////////// +/// 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( Rwt_Node_t *, 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 = (Rwt_Node_t *)p->vForest->pArray[Entry0 >> 1]; + p1 = (Rwt_Node_t *)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 ); ABC_PRT( "Loading", clock() - clk ); + } +} + +/**Function************************************************************* + + Synopsis [Create practical classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Rwt_ManGetPractical( Rwt_Man_t * p ) +{ + char * pPractical; + int i; + pPractical = ABC_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 +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/sim/sim.h b/src/opt/sim/sim.h index e1a34273..84b2ed51 100644 --- a/src/opt/sim/sim.h +++ b/src/opt/sim/sim.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __SIM_H__ -#define __SIM_H__ +#ifndef ABC__opt__sim__sim_h +#define ABC__opt__sim__sim_h /* diff --git a/src/opt/sim/simMan.c b/src/opt/sim/simMan.c index f3a9650b..9856f484 100644 --- a/src/opt/sim/simMan.c +++ b/src/opt/sim/simMan.c @@ -18,8 +18,7 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" #include "sim.h" ABC_NAMESPACE_IMPL_START diff --git a/src/opt/sim/simSat.c b/src/opt/sim/simSat.c index 5654c493..5c97055b 100644 --- a/src/opt/sim/simSat.c +++ b/src/opt/sim/simSat.c @@ -18,8 +18,7 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" #include "sim.h" ABC_NAMESPACE_IMPL_START diff --git a/src/opt/sim/simSeq.c b/src/opt/sim/simSeq.c index fd75ba8d..0efe7378 100644 --- a/src/opt/sim/simSeq.c +++ b/src/opt/sim/simSeq.c @@ -18,8 +18,7 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" #include "sim.h" ABC_NAMESPACE_IMPL_START diff --git a/src/opt/sim/simSupp.c b/src/opt/sim/simSupp.c index 67ac5efe..a7ceaee7 100644 --- a/src/opt/sim/simSupp.c +++ b/src/opt/sim/simSupp.c @@ -18,9 +18,8 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" -#include "fraig.h" +#include "src/base/abc/abc.h" +#include "src/proof/fraig/fraig.h" #include "sim.h" ABC_NAMESPACE_IMPL_START @@ -384,7 +383,7 @@ void Sim_UtilAssignFromFifo( Sim_Man_t * p ) iWordLim = iWord + 1; // set the pattern for all PIs from iBit to iWord + p->nInputs iBeg = p->iInput; - iEnd = ABC_MIN( iBeg + 32, p->nInputs ); + iEnd = Abc_MinInt( iBeg + 32, p->nInputs ); // for ( i = iBeg; i < iEnd; i++ ) Abc_NtkForEachCi( p->pNtk, pNode, i ) { diff --git a/src/opt/sim/simSwitch.c b/src/opt/sim/simSwitch.c index a9045ca1..26f8cd51 100644 --- a/src/opt/sim/simSwitch.c +++ b/src/opt/sim/simSwitch.c @@ -18,8 +18,7 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" #include "sim.h" ABC_NAMESPACE_IMPL_START diff --git a/src/opt/sim/simSym.c b/src/opt/sim/simSym.c index c6b588ac..801d4218 100644 --- a/src/opt/sim/simSym.c +++ b/src/opt/sim/simSym.c @@ -18,8 +18,7 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" #include "sim.h" ABC_NAMESPACE_IMPL_START diff --git a/src/opt/sim/simSymSat.c b/src/opt/sim/simSymSat.c index dcdff135..2043e2d7 100644 --- a/src/opt/sim/simSymSat.c +++ b/src/opt/sim/simSymSat.c @@ -18,10 +18,9 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" +#include "src/proof/fraig/fraig.h" #include "sim.h" -#include "fraig.h" ABC_NAMESPACE_IMPL_START diff --git a/src/opt/sim/simSymSim.c b/src/opt/sim/simSymSim.c index e1676117..fddf602e 100644 --- a/src/opt/sim/simSymSim.c +++ b/src/opt/sim/simSymSim.c @@ -18,8 +18,7 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" #include "sim.h" ABC_NAMESPACE_IMPL_START diff --git a/src/opt/sim/simSymStr.c b/src/opt/sim/simSymStr.c index 4d83dc61..b9d58b9f 100644 --- a/src/opt/sim/simSymStr.c +++ b/src/opt/sim/simSymStr.c @@ -18,8 +18,7 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" #include "sim.h" ABC_NAMESPACE_IMPL_START diff --git a/src/opt/sim/simUtils.c b/src/opt/sim/simUtils.c index 64814c0e..77597e83 100644 --- a/src/opt/sim/simUtils.c +++ b/src/opt/sim/simUtils.c @@ -18,8 +18,7 @@ ***********************************************************************/ -#include "abc.h" -#include "extra.h" +#include "src/base/abc/abc.h" #include "sim.h" ABC_NAMESPACE_IMPL_START diff --git a/src/phys/place/libhmetis.h b/src/phys/place/libhmetis.h index 277299b8..e6251325 100644 --- a/src/phys/place/libhmetis.h +++ b/src/phys/place/libhmetis.h @@ -1,7 +1,7 @@ // A. Hurst ahurst@eecs.berkeley.edu -#ifndef LIBHMETIS_H_ -#define LIBHMETIS_H_ +#ifndef ABC__phys__place__libhmetis_h +#define ABC__phys__place__libhmetis_h ABC_NAMESPACE_HEADER_START diff --git a/src/phys/place/place_base.h b/src/phys/place/place_base.h index ed15ef22..cbad1922 100644 --- a/src/phys/place/place_base.h +++ b/src/phys/place/place_base.h @@ -8,7 +8,7 @@ /*===================================================================*/ #if !defined(PLACE_BASE_H_) -#define PLACE_BASE_H_ +#define ABC__phys__place__place_base_h ABC_NAMESPACE_HEADER_START @@ -21,7 +21,7 @@ ABC_NAMESPACE_HEADER_START // --- a C++ bool-like type //typedef char bool; -#ifndef bool +#ifndef ABC__phys__place__place_base_h #define bool int #endif diff --git a/src/phys/place/place_gordian.h b/src/phys/place/place_gordian.h index 6be6d907..a959ae50 100644 --- a/src/phys/place/place_gordian.h +++ b/src/phys/place/place_gordian.h @@ -8,7 +8,7 @@ /*===================================================================*/ #if !defined(PLACE_GORDIAN_H_) -#define PLACE_GORDIAN_H_ +#define ABC__phys__place__place_gordian_h #include "place_base.h" diff --git a/src/phys/place/place_qpsolver.h b/src/phys/place/place_qpsolver.h index f859a6ff..9ddf6447 100644 --- a/src/phys/place/place_qpsolver.h +++ b/src/phys/place/place_qpsolver.h @@ -8,7 +8,7 @@ /*===================================================================*/ #if !defined(_QPS_H) -#define _QPS_H +#define ABC__phys__place__place_qpsolver_h #include diff --git a/src/proof/bbr/bbr.h b/src/proof/bbr/bbr.h new file mode 100644 index 00000000..71061759 --- /dev/null +++ b/src/proof/bbr/bbr.h @@ -0,0 +1,93 @@ +/**CFile**************************************************************** + + FileName [bbr.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD-based reachability analysis.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: bbr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__bbr__bbr_h +#define ABC__aig__bbr__bbr_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include "src/aig/aig/aig.h" +#include "src/aig/saig/saig.h" +#include "src/bdd/cudd/cuddInt.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline DdNode * Aig_ObjGlobalBdd( Aig_Obj_t * pObj ) { return (DdNode *)pObj->pData; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== bbrImage.c ==========================================================*/ +typedef struct Bbr_ImageTree_t_ Bbr_ImageTree_t; +extern Bbr_ImageTree_t * Bbr_bddImageStart( + DdManager * dd, DdNode * bCare, + int nParts, DdNode ** pbParts, + int nVars, DdNode ** pbVars, int nBddMax, int fVerbose ); +extern DdNode * Bbr_bddImageCompute( Bbr_ImageTree_t * pTree, DdNode * bCare ); +extern void Bbr_bddImageTreeDelete( Bbr_ImageTree_t * pTree ); +extern DdNode * Bbr_bddImageRead( Bbr_ImageTree_t * pTree ); +typedef struct Bbr_ImageTree2_t_ Bbr_ImageTree2_t; +extern Bbr_ImageTree2_t * Bbr_bddImageStart2( + DdManager * dd, DdNode * bCare, + int nParts, DdNode ** pbParts, + int nVars, DdNode ** pbVars, int fVerbose ); +extern DdNode * Bbr_bddImageCompute2( Bbr_ImageTree2_t * pTree, DdNode * bCare ); +extern void Bbr_bddImageTreeDelete2( Bbr_ImageTree2_t * pTree ); +extern DdNode * Bbr_bddImageRead2( Bbr_ImageTree2_t * pTree ); +/*=== bbrNtbdd.c ==========================================================*/ +extern void Aig_ManFreeGlobalBdds( Aig_Man_t * p, DdManager * dd ); +extern int Aig_ManSizeOfGlobalBdds( Aig_Man_t * p ); +extern DdManager * Aig_ManComputeGlobalBdds( Aig_Man_t * p, int nBddSizeMax, int fDropInternal, int fReorder, int fVerbose ); +/*=== bbrReach.c ==========================================================*/ +extern int Aig_ManVerifyUsingBdds( Aig_Man_t * p, Saig_ParBbr_t * pPars ); +extern void Bbr_ManSetDefaultParams( Saig_ParBbr_t * p ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/proof/bbr/bbrCex.c b/src/proof/bbr/bbrCex.c new file mode 100644 index 00000000..7ee95e7c --- /dev/null +++ b/src/proof/bbr/bbrCex.c @@ -0,0 +1,172 @@ +/**CFile**************************************************************** + + FileName [bbrCex.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD-based reachability analysis.] + + Synopsis [Procedures to derive a satisfiable counter-example.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: bbrCex.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "bbr.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern DdNode * Bbr_bddComputeRangeCube( DdManager * dd, int iStart, int iStop ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Derives the counter-example using the set of reached states.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Aig_ManVerifyUsingBddsCountExample( Aig_Man_t * p, DdManager * dd, + DdNode ** pbParts, Vec_Ptr_t * vOnionRings, DdNode * bCubeFirst, + int iOutput, int fVerbose, int fSilent ) +{ + Abc_Cex_t * pCex; + Aig_Obj_t * pObj; + Bbr_ImageTree_t * pTree; + DdNode * bCubeNs, * bState, * bImage; + DdNode * bTemp, * bVar, * bRing; + int i, v, RetValue, nPiOffset; + char * pValues; + int clk = clock(); +//printf( "\nDeriving counter-example.\n" ); + + // allocate room for the counter-example + pCex = Abc_CexAlloc( Saig_ManRegNum(p), Saig_ManPiNum(p), Vec_PtrSize(vOnionRings)+1 ); + pCex->iFrame = Vec_PtrSize(vOnionRings); + pCex->iPo = iOutput; + nPiOffset = Saig_ManRegNum(p) + Saig_ManPiNum(p) * Vec_PtrSize(vOnionRings); + + // create the cube of NS variables + bCubeNs = Bbr_bddComputeRangeCube( dd, Saig_ManCiNum(p), Saig_ManCiNum(p)+Saig_ManRegNum(p) ); Cudd_Ref( bCubeNs ); + pTree = Bbr_bddImageStart( dd, bCubeNs, Saig_ManRegNum(p), pbParts, Saig_ManCiNum(p), dd->vars, 100000000, fVerbose ); + Cudd_RecursiveDeref( dd, bCubeNs ); + if ( pTree == NULL ) + { + if ( !fSilent ) + printf( "BDDs blew up during qualitification scheduling. " ); + return NULL; + } + + // allocate room for the cube + pValues = ABC_ALLOC( char, dd->size ); + + // get the last cube + RetValue = Cudd_bddPickOneCube( dd, bCubeFirst, pValues ); + assert( RetValue ); + + // write PIs of counter-example + Saig_ManForEachPi( p, pObj, i ) + if ( pValues[i] == 1 ) + Abc_InfoSetBit( pCex->pData, nPiOffset + i ); + nPiOffset -= Saig_ManPiNum(p); + + // write state in terms of NS variables + bState = (dd)->one; Cudd_Ref( bState ); + Saig_ManForEachLo( p, pObj, i ) + { + bVar = Cudd_NotCond( dd->vars[Saig_ManCiNum(p)+i], pValues[Saig_ManPiNum(p)+i] != 1 ); + bState = Cudd_bddAnd( dd, bTemp = bState, bVar ); Cudd_Ref( bState ); + Cudd_RecursiveDeref( dd, bTemp ); + } + + // perform backward analysis + Vec_PtrForEachEntryReverse( DdNode *, vOnionRings, bRing, v ) + { + // compute the next states + bImage = Bbr_bddImageCompute( pTree, bState ); + if ( bImage == NULL ) + { + Cudd_RecursiveDeref( dd, bState ); + if ( !fSilent ) + printf( "BDDs blew up during image computation. " ); + Bbr_bddImageTreeDelete( pTree ); + ABC_FREE( pValues ); + return NULL; + } + Cudd_Ref( bImage ); + Cudd_RecursiveDeref( dd, bState ); + + // intersect with the previous set + bImage = Cudd_bddAnd( dd, bTemp = bImage, bRing ); Cudd_Ref( bImage ); + Cudd_RecursiveDeref( dd, bTemp ); + + // find any assignment of the BDD + RetValue = Cudd_bddPickOneCube( dd, bImage, pValues ); + assert( RetValue ); + Cudd_RecursiveDeref( dd, bImage ); + + // write PIs of counter-example + Saig_ManForEachPi( p, pObj, i ) + if ( pValues[i] == 1 ) + Abc_InfoSetBit( pCex->pData, nPiOffset + i ); + nPiOffset -= Saig_ManPiNum(p); + + // check that we get the init state + if ( v == 0 ) + { + Saig_ManForEachLo( p, pObj, i ) + assert( pValues[Saig_ManPiNum(p)+i] == 0 ); + break; + } + + // write state in terms of NS variables + bState = (dd)->one; Cudd_Ref( bState ); + Saig_ManForEachLo( p, pObj, i ) + { + bVar = Cudd_NotCond( dd->vars[Saig_ManCiNum(p)+i], pValues[Saig_ManPiNum(p)+i] != 1 ); + bState = Cudd_bddAnd( dd, bTemp = bState, bVar ); Cudd_Ref( bState ); + Cudd_RecursiveDeref( dd, bTemp ); + } + } + // cleanup + Bbr_bddImageTreeDelete( pTree ); + ABC_FREE( pValues ); + // verify the counter example + if ( Vec_PtrSize(vOnionRings) < 1000 ) + { + RetValue = Saig_ManVerifyCex( p, pCex ); + if ( RetValue == 0 && !fSilent ) + printf( "Aig_ManVerifyUsingBdds(): Counter-example verification has FAILED.\n" ); + } + if ( fVerbose && !fSilent ) + { + ABC_PRT( "Counter-example generation time", clock() - clk ); + } + return pCex; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/bbr/bbrImage.c b/src/proof/bbr/bbrImage.c new file mode 100644 index 00000000..23b43169 --- /dev/null +++ b/src/proof/bbr/bbrImage.c @@ -0,0 +1,1327 @@ +/**CFile**************************************************************** + + FileName [bbrImage.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD-based reachability analysis.] + + Synopsis [Performs image computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: bbrImage.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "bbr.h" +#include "src/bdd/mtr/mtr.h" + +ABC_NAMESPACE_IMPL_START + + +/* + The ideas implemented in this file are inspired by the paper: + Pankaj Chauhan, Edmund Clarke, Somesh Jha, Jim Kukula, Tom Shiple, + Helmut Veith, Dong Wang. Non-linear Quantification Scheduling in + Image Computation. ICCAD, 2001. +*/ + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +typedef struct Bbr_ImageNode_t_ Bbr_ImageNode_t; +typedef struct Bbr_ImagePart_t_ Bbr_ImagePart_t; +typedef struct Bbr_ImageVar_t_ Bbr_ImageVar_t; + +struct Bbr_ImageTree_t_ +{ + Bbr_ImageNode_t * pRoot; // the root of quantification tree + Bbr_ImageNode_t * pCare; // the leaf node with the care set + DdNode * bCareSupp; // the cube to quantify from the care + int fVerbose; // the verbosity flag + int nNodesMax; // the max number of nodes in one iter + int nNodesMaxT; // the overall max number of nodes + int nIter; // the number of iterations with this tree + int nBddMax; // the number of node to stop +}; + +struct Bbr_ImageNode_t_ +{ + DdManager * dd; // the manager + DdNode * bCube; // the cube to quantify + DdNode * bImage; // the partial image + Bbr_ImageNode_t * pNode1; // the first branch + Bbr_ImageNode_t * pNode2; // the second branch + Bbr_ImagePart_t * pPart; // the partition (temporary) +}; + +struct Bbr_ImagePart_t_ +{ + DdNode * bFunc; // the partition + DdNode * bSupp; // the support of this partition + int nNodes; // the number of BDD nodes + short nSupp; // the number of support variables + short iPart; // the number of this partition +}; + +struct Bbr_ImageVar_t_ +{ + int iNum; // the BDD index of this variable + DdNode * bParts; // the partition numbers + int nParts; // the number of partitions +}; + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +#define b0 Cudd_Not((dd)->one) +#define b1 (dd)->one + +#ifndef ABC_PRB +#define ABC_PRB(dd,f) printf("%s = ", #f); Bbr_bddPrint(dd,f); printf("\n") +#endif + +/**AutomaticStart*************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static Bbr_ImagePart_t ** Bbr_CreateParts( DdManager * dd, + int nParts, DdNode ** pbParts, DdNode * bCare ); +static Bbr_ImageVar_t ** Bbr_CreateVars( DdManager * dd, + int nParts, Bbr_ImagePart_t ** pParts, + int nVars, DdNode ** pbVarsNs ); +static Bbr_ImageNode_t ** Bbr_CreateNodes( DdManager * dd, + int nParts, Bbr_ImagePart_t ** pParts, + int nVars, Bbr_ImageVar_t ** pVars ); +static void Bbr_DeleteParts_rec( Bbr_ImageNode_t * pNode ); +static int Bbr_BuildTreeNode( DdManager * dd, + int nNodes, Bbr_ImageNode_t ** pNodes, + int nVars, Bbr_ImageVar_t ** pVars, int * pfStop, int nBddMax ); +static Bbr_ImageNode_t * Bbr_MergeTopNodes( DdManager * dd, + int nNodes, Bbr_ImageNode_t ** pNodes ); +static void Bbr_bddImageTreeDelete_rec( Bbr_ImageNode_t * pNode ); +static int Bbr_bddImageCompute_rec( Bbr_ImageTree_t * pTree, Bbr_ImageNode_t * pNode ); +static int Bbr_FindBestVariable( DdManager * dd, + int nNodes, Bbr_ImageNode_t ** pNodes, + int nVars, Bbr_ImageVar_t ** pVars ); +static void Bbr_FindBestPartitions( DdManager * dd, DdNode * bParts, + int nNodes, Bbr_ImageNode_t ** pNodes, + int * piNode1, int * piNode2 ); +static Bbr_ImageNode_t * Bbr_CombineTwoNodes( DdManager * dd, DdNode * bCube, + Bbr_ImageNode_t * pNode1, Bbr_ImageNode_t * pNode2 ); + +static void Bbr_bddImagePrintLatchDependency( DdManager * dd, DdNode * bCare, + int nParts, DdNode ** pbParts, + int nVars, DdNode ** pbVars ); +static void Bbr_bddImagePrintLatchDependencyOne( DdManager * dd, DdNode * bFunc, + DdNode * bVarsCs, DdNode * bVarsNs, int iPart ); + +static void Bbr_bddImagePrintTree( Bbr_ImageTree_t * pTree ); +static void Bbr_bddImagePrintTree_rec( Bbr_ImageNode_t * pNode, int nOffset ); + +static void Bbr_bddPrint( DdManager * dd, DdNode * F ); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function************************************************************* + + Synopsis [Starts the image computation using tree-based scheduling.] + + Description [This procedure starts the image computation. It uses + the given care set to test-run the image computation and creates the + quantification tree by scheduling variable quantifications. The tree can + be used to compute images for other care sets without rescheduling. + In this case, Bbr_bddImageCompute() should be called.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bbr_ImageTree_t * Bbr_bddImageStart( + DdManager * dd, DdNode * bCare, // the care set + int nParts, DdNode ** pbParts, // the partitions for image computation + int nVars, DdNode ** pbVars, int nBddMax, int fVerbose ) // the NS and parameter variables (not quantified!) +{ + Bbr_ImageTree_t * pTree; + Bbr_ImagePart_t ** pParts; + Bbr_ImageVar_t ** pVars; + Bbr_ImageNode_t ** pNodes, * pCare; + int fStop, v; + + if ( fVerbose && dd->size <= 80 ) + Bbr_bddImagePrintLatchDependency( dd, bCare, nParts, pbParts, nVars, pbVars ); + + // create variables, partitions and leaf nodes + pParts = Bbr_CreateParts( dd, nParts, pbParts, bCare ); + pVars = Bbr_CreateVars( dd, nParts + 1, pParts, nVars, pbVars ); + pNodes = Bbr_CreateNodes( dd, nParts + 1, pParts, dd->size, pVars ); + pCare = pNodes[nParts]; + + // process the nodes + while ( Bbr_BuildTreeNode( dd, nParts + 1, pNodes, dd->size, pVars, &fStop, nBddMax ) ); + + // consider the case of BDD node blowup + if ( fStop ) + { + for ( v = 0; v < dd->size; v++ ) + if ( pVars[v] ) + ABC_FREE( pVars[v] ); + ABC_FREE( pVars ); + for ( v = 0; v <= nParts; v++ ) + if ( pNodes[v] ) + { + Bbr_DeleteParts_rec( pNodes[v] ); + Bbr_bddImageTreeDelete_rec( pNodes[v] ); + } + ABC_FREE( pNodes ); + ABC_FREE( pParts ); + return NULL; + } + + // make sure the variables are gone + for ( v = 0; v < dd->size; v++ ) + assert( pVars[v] == NULL ); + ABC_FREE( pVars ); + + // create the tree + pTree = ABC_ALLOC( Bbr_ImageTree_t, 1 ); + memset( pTree, 0, sizeof(Bbr_ImageTree_t) ); + pTree->pCare = pCare; + pTree->nBddMax = nBddMax; + pTree->fVerbose = fVerbose; + + // merge the topmost nodes + while ( (pTree->pRoot = Bbr_MergeTopNodes( dd, nParts + 1, pNodes )) == NULL ); + + // make sure the nodes are gone + for ( v = 0; v < nParts + 1; v++ ) + assert( pNodes[v] == NULL ); + ABC_FREE( pNodes ); + +// if ( fVerbose ) +// Bbr_bddImagePrintTree( pTree ); + + // set the support of the care set + pTree->bCareSupp = Cudd_Support( dd, bCare ); Cudd_Ref( pTree->bCareSupp ); + + // clean the partitions + Bbr_DeleteParts_rec( pTree->pRoot ); + ABC_FREE( pParts ); + + return pTree; +} + +/**Function************************************************************* + + Synopsis [Compute the image.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Bbr_bddImageCompute( Bbr_ImageTree_t * pTree, DdNode * bCare ) +{ + DdManager * dd = pTree->pCare->dd; + DdNode * bSupp, * bRem; + + pTree->nIter++; + + // make sure the supports are okay + bSupp = Cudd_Support( dd, bCare ); Cudd_Ref( bSupp ); + if ( bSupp != pTree->bCareSupp ) + { + bRem = Cudd_bddExistAbstract( dd, bSupp, pTree->bCareSupp ); Cudd_Ref( bRem ); + if ( bRem != b1 ) + { +printf( "Original care set support: " ); +ABC_PRB( dd, pTree->bCareSupp ); +printf( "Current care set support: " ); +ABC_PRB( dd, bSupp ); + Cudd_RecursiveDeref( dd, bSupp ); + Cudd_RecursiveDeref( dd, bRem ); + printf( "The care set depends on some vars that were not in the care set during scheduling.\n" ); + return NULL; + } + Cudd_RecursiveDeref( dd, bRem ); + } + Cudd_RecursiveDeref( dd, bSupp ); + + // remove the previous image + Cudd_RecursiveDeref( dd, pTree->pCare->bImage ); + pTree->pCare->bImage = bCare; Cudd_Ref( bCare ); + + // compute the image + pTree->nNodesMax = 0; + if ( !Bbr_bddImageCompute_rec( pTree, pTree->pRoot ) ) + return NULL; + if ( pTree->nNodesMaxT < pTree->nNodesMax ) + pTree->nNodesMaxT = pTree->nNodesMax; + +// if ( pTree->fVerbose ) +// printf( "Iter %2d : Max nodes = %5d.\n", pTree->nIter, pTree->nNodesMax ); + return pTree->pRoot->bImage; +} + +/**Function************************************************************* + + Synopsis [Delete the tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbr_bddImageTreeDelete( Bbr_ImageTree_t * pTree ) +{ + if ( pTree->bCareSupp ) + Cudd_RecursiveDeref( pTree->pRoot->dd, pTree->bCareSupp ); + Bbr_bddImageTreeDelete_rec( pTree->pRoot ); + ABC_FREE( pTree ); +} + +/**Function************************************************************* + + Synopsis [Reads the image from the tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Bbr_bddImageRead( Bbr_ImageTree_t * pTree ) +{ + return pTree->pRoot->bImage; +} + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Outputs the BDD in a readable format.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +void Bbr_bddPrint( DdManager * dd, DdNode * F ) +{ + DdGen * Gen; + int * Cube; + CUDD_VALUE_TYPE Value; + int nVars = dd->size; + int fFirstCube = 1; + int i; + + if ( F == NULL ) + { + printf("NULL"); + return; + } + if ( F == b0 ) + { + printf("Constant 0"); + return; + } + if ( F == b1 ) + { + printf("Constant 1"); + return; + } + + Cudd_ForeachCube( dd, F, Gen, Cube, Value ) + { + if ( fFirstCube ) + fFirstCube = 0; + else +// Output << " + "; + printf( " + " ); + + for ( i = 0; i < nVars; i++ ) + if ( Cube[i] == 0 ) + printf( "[%d]'", i ); +// printf( "%c'", (char)('a'+i) ); + else if ( Cube[i] == 1 ) + printf( "[%d]", i ); +// printf( "%c", (char)('a'+i) ); + } + +// printf("\n"); +} + +/*---------------------------------------------------------------------------*/ +/* Definition of static Functions */ +/*---------------------------------------------------------------------------*/ + +/**Function************************************************************* + + Synopsis [Creates partitions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bbr_ImagePart_t ** Bbr_CreateParts( DdManager * dd, + int nParts, DdNode ** pbParts, DdNode * bCare ) +{ + Bbr_ImagePart_t ** pParts; + int i; + + // start the partitions + pParts = ABC_ALLOC( Bbr_ImagePart_t *, nParts + 1 ); + // create structures for each variable + for ( i = 0; i < nParts; i++ ) + { + pParts[i] = ABC_ALLOC( Bbr_ImagePart_t, 1 ); + pParts[i]->bFunc = pbParts[i]; Cudd_Ref( pParts[i]->bFunc ); + pParts[i]->bSupp = Cudd_Support( dd, pParts[i]->bFunc ); Cudd_Ref( pParts[i]->bSupp ); + pParts[i]->nSupp = Cudd_SupportSize( dd, pParts[i]->bSupp ); + pParts[i]->nNodes = Cudd_DagSize( pParts[i]->bFunc ); + pParts[i]->iPart = i; + } + // add the care set as the last partition + pParts[nParts] = ABC_ALLOC( Bbr_ImagePart_t, 1 ); + pParts[nParts]->bFunc = bCare; Cudd_Ref( pParts[nParts]->bFunc ); + pParts[nParts]->bSupp = Cudd_Support( dd, pParts[nParts]->bFunc ); Cudd_Ref( pParts[nParts]->bSupp ); + pParts[nParts]->nSupp = Cudd_SupportSize( dd, pParts[nParts]->bSupp ); + pParts[nParts]->nNodes = Cudd_DagSize( pParts[nParts]->bFunc ); + pParts[nParts]->iPart = nParts; + return pParts; +} + +/**Function************************************************************* + + Synopsis [Creates variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bbr_ImageVar_t ** Bbr_CreateVars( DdManager * dd, + int nParts, Bbr_ImagePart_t ** pParts, + int nVars, DdNode ** pbVars ) +{ + Bbr_ImageVar_t ** pVars; + DdNode ** pbFuncs; + DdNode * bCubeNs, * bSupp, * bParts, * bTemp, * bSuppTemp; + int nVarsTotal, iVar, p, Counter; + + // put all the functions into one array + pbFuncs = ABC_ALLOC( DdNode *, nParts ); + for ( p = 0; p < nParts; p++ ) + pbFuncs[p] = pParts[p]->bSupp; + bSupp = Cudd_VectorSupport( dd, pbFuncs, nParts ); Cudd_Ref( bSupp ); + ABC_FREE( pbFuncs ); + + // remove the NS vars + bCubeNs = Cudd_bddComputeCube( dd, pbVars, NULL, nVars ); Cudd_Ref( bCubeNs ); + bSupp = Cudd_bddExistAbstract( dd, bTemp = bSupp, bCubeNs ); Cudd_Ref( bSupp ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCubeNs ); + + // get the number of I and CS variables to be quantified + nVarsTotal = Cudd_SupportSize( dd, bSupp ); + + // start the variables + pVars = ABC_ALLOC( Bbr_ImageVar_t *, dd->size ); + memset( pVars, 0, sizeof(Bbr_ImageVar_t *) * dd->size ); + // create structures for each variable + for ( bSuppTemp = bSupp; bSuppTemp != b1; bSuppTemp = cuddT(bSuppTemp) ) + { + iVar = bSuppTemp->index; + pVars[iVar] = ABC_ALLOC( Bbr_ImageVar_t, 1 ); + pVars[iVar]->iNum = iVar; + // collect all the parts this var belongs to + Counter = 0; + bParts = b1; Cudd_Ref( bParts ); + for ( p = 0; p < nParts; p++ ) + if ( Cudd_bddLeq( dd, pParts[p]->bSupp, dd->vars[bSuppTemp->index] ) ) + { + bParts = Cudd_bddAnd( dd, bTemp = bParts, dd->vars[p] ); Cudd_Ref( bParts ); + Cudd_RecursiveDeref( dd, bTemp ); + Counter++; + } + pVars[iVar]->bParts = bParts; // takes ref + pVars[iVar]->nParts = Counter; + } + Cudd_RecursiveDeref( dd, bSupp ); + return pVars; +} + +/**Function************************************************************* + + Synopsis [Creates variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bbr_ImageNode_t ** Bbr_CreateNodes( DdManager * dd, + int nParts, Bbr_ImagePart_t ** pParts, + int nVars, Bbr_ImageVar_t ** pVars ) +{ + Bbr_ImageNode_t ** pNodes; + Bbr_ImageNode_t * pNode; + DdNode * bTemp; + int i, v, iPart; +/* + DdManager * dd; // the manager + DdNode * bCube; // the cube to quantify + DdNode * bImage; // the partial image + Bbr_ImageNode_t * pNode1; // the first branch + Bbr_ImageNode_t * pNode2; // the second branch + Bbr_ImagePart_t * pPart; // the partition (temporary) +*/ + // start the partitions + pNodes = ABC_ALLOC( Bbr_ImageNode_t *, nParts ); + // create structures for each leaf nodes + for ( i = 0; i < nParts; i++ ) + { + pNodes[i] = ABC_ALLOC( Bbr_ImageNode_t, 1 ); + memset( pNodes[i], 0, sizeof(Bbr_ImageNode_t) ); + pNodes[i]->dd = dd; + pNodes[i]->pPart = pParts[i]; + } + // find the quantification cubes for each leaf node + for ( v = 0; v < nVars; v++ ) + { + if ( pVars[v] == NULL ) + continue; + assert( pVars[v]->nParts > 0 ); + if ( pVars[v]->nParts > 1 ) + continue; + iPart = pVars[v]->bParts->index; + if ( pNodes[iPart]->bCube == NULL ) + { + pNodes[iPart]->bCube = dd->vars[v]; + Cudd_Ref( dd->vars[v] ); + } + else + { + pNodes[iPart]->bCube = Cudd_bddAnd( dd, bTemp = pNodes[iPart]->bCube, dd->vars[v] ); + Cudd_Ref( pNodes[iPart]->bCube ); + Cudd_RecursiveDeref( dd, bTemp ); + } + // remove these variables + Cudd_RecursiveDeref( dd, pVars[v]->bParts ); + ABC_FREE( pVars[v] ); + } + + // assign the leaf node images + for ( i = 0; i < nParts; i++ ) + { + pNode = pNodes[i]; + if ( pNode->bCube ) + { + // update the partition + pParts[i]->bFunc = Cudd_bddExistAbstract( dd, bTemp = pParts[i]->bFunc, pNode->bCube ); + Cudd_Ref( pParts[i]->bFunc ); + Cudd_RecursiveDeref( dd, bTemp ); + // update the support the partition + pParts[i]->bSupp = Cudd_bddExistAbstract( dd, bTemp = pParts[i]->bSupp, pNode->bCube ); + Cudd_Ref( pParts[i]->bSupp ); + Cudd_RecursiveDeref( dd, bTemp ); + // update the numbers + pParts[i]->nSupp = Cudd_SupportSize( dd, pParts[i]->bSupp ); + pParts[i]->nNodes = Cudd_DagSize( pParts[i]->bFunc ); + // get rid of the cube + // save the last (care set) quantification cube + if ( i < nParts - 1 ) + { + Cudd_RecursiveDeref( dd, pNode->bCube ); + pNode->bCube = NULL; + } + } + // copy the function + pNode->bImage = pParts[i]->bFunc; Cudd_Ref( pNode->bImage ); + } +/* + for ( i = 0; i < nParts; i++ ) + { + pNode = pNodes[i]; +ABC_PRB( dd, pNode->bCube ); +ABC_PRB( dd, pNode->pPart->bFunc ); +ABC_PRB( dd, pNode->pPart->bSupp ); +printf( "\n" ); + } +*/ + return pNodes; +} + + +/**Function************************************************************* + + Synopsis [Delete the partitions from the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbr_DeleteParts_rec( Bbr_ImageNode_t * pNode ) +{ + Bbr_ImagePart_t * pPart; + if ( pNode->pNode1 ) + Bbr_DeleteParts_rec( pNode->pNode1 ); + if ( pNode->pNode2 ) + Bbr_DeleteParts_rec( pNode->pNode2 ); + pPart = pNode->pPart; + Cudd_RecursiveDeref( pNode->dd, pPart->bFunc ); + Cudd_RecursiveDeref( pNode->dd, pPart->bSupp ); + ABC_FREE( pNode->pPart ); +} + +/**Function************************************************************* + + Synopsis [Delete the partitions from the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbr_bddImageTreeDelete_rec( Bbr_ImageNode_t * pNode ) +{ + if ( pNode->pNode1 ) + Bbr_bddImageTreeDelete_rec( pNode->pNode1 ); + if ( pNode->pNode2 ) + Bbr_bddImageTreeDelete_rec( pNode->pNode2 ); + if ( pNode->bCube ) + Cudd_RecursiveDeref( pNode->dd, pNode->bCube ); + if ( pNode->bImage ) + Cudd_RecursiveDeref( pNode->dd, pNode->bImage ); + assert( pNode->pPart == NULL ); + ABC_FREE( pNode ); +} + +/**Function************************************************************* + + Synopsis [Recompute the image.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bbr_bddImageCompute_rec( Bbr_ImageTree_t * pTree, Bbr_ImageNode_t * pNode ) +{ + DdManager * dd = pNode->dd; + DdNode * bTemp; + int nNodes; + + // trivial case + if ( pNode->pNode1 == NULL ) + { + if ( pNode->bCube ) + { + pNode->bImage = Cudd_bddExistAbstract( dd, bTemp = pNode->bImage, pNode->bCube ); + Cudd_Ref( pNode->bImage ); + Cudd_RecursiveDeref( dd, bTemp ); + } + return 1; + } + + // compute the children + if ( pNode->pNode1 ) + if ( !Bbr_bddImageCompute_rec( pTree, pNode->pNode1 ) ) + return 0; + if ( pNode->pNode2 ) + if ( !Bbr_bddImageCompute_rec( pTree, pNode->pNode2 ) ) + return 0; + + // clean the old image + if ( pNode->bImage ) + Cudd_RecursiveDeref( dd, pNode->bImage ); + pNode->bImage = NULL; + + // compute the new image + if ( pNode->bCube ) + pNode->bImage = Cudd_bddAndAbstract( dd, + pNode->pNode1->bImage, pNode->pNode2->bImage, pNode->bCube ); + else + pNode->bImage = Cudd_bddAnd( dd, pNode->pNode1->bImage, pNode->pNode2->bImage ); + Cudd_Ref( pNode->bImage ); + + if ( pTree->fVerbose ) + { + nNodes = Cudd_DagSize( pNode->bImage ); + if ( pTree->nNodesMax < nNodes ) + pTree->nNodesMax = nNodes; + } + if ( dd->keys-dd->dead > (unsigned)pTree->nBddMax ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Builds the tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bbr_BuildTreeNode( DdManager * dd, + int nNodes, Bbr_ImageNode_t ** pNodes, + int nVars, Bbr_ImageVar_t ** pVars, int * pfStop, int nBddMax ) +{ + Bbr_ImageNode_t * pNode1, * pNode2; + Bbr_ImageVar_t * pVar; + Bbr_ImageNode_t * pNode; + DdNode * bCube, * bTemp, * bSuppTemp;//, * bParts; + int iNode1, iNode2; + int iVarBest, nSupp, v; + + // find the best variable + iVarBest = Bbr_FindBestVariable( dd, nNodes, pNodes, nVars, pVars ); + if ( iVarBest == -1 ) + return 0; +/* +for ( v = 0; v < nVars; v++ ) +{ + DdNode * bSupp; + if ( pVars[v] == NULL ) + continue; + printf( "%3d :", v ); + printf( "%3d ", pVars[v]->nParts ); + bSupp = Cudd_Support( dd, pVars[v]->bParts ); Cudd_Ref( bSupp ); + Bbr_bddPrint( dd, bSupp ); printf( "\n" ); + Cudd_RecursiveDeref( dd, bSupp ); +} +*/ + pVar = pVars[iVarBest]; + + // this var cannot appear in one partition only + nSupp = Cudd_SupportSize( dd, pVar->bParts ); + assert( nSupp == pVar->nParts ); + assert( nSupp != 1 ); +//printf( "var = %d supp = %d\n\n", iVarBest, nSupp ); + + // if it appears in only two partitions, quantify it + if ( pVar->nParts == 2 ) + { + // get the nodes + iNode1 = pVar->bParts->index; + iNode2 = cuddT(pVar->bParts)->index; + pNode1 = pNodes[iNode1]; + pNode2 = pNodes[iNode2]; + + // get the quantification cube + bCube = dd->vars[pVar->iNum]; Cudd_Ref( bCube ); + // add the variables that appear only in these partitions + for ( v = 0; v < nVars; v++ ) + if ( pVars[v] && v != iVarBest && pVars[v]->bParts == pVars[iVarBest]->bParts ) + { + // add this var + bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[pVars[v]->iNum] ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( dd, bTemp ); + // clean this var + Cudd_RecursiveDeref( dd, pVars[v]->bParts ); + ABC_FREE( pVars[v] ); + } + // clean the best var + Cudd_RecursiveDeref( dd, pVars[iVarBest]->bParts ); + ABC_FREE( pVars[iVarBest] ); + + // combines two nodes + pNode = Bbr_CombineTwoNodes( dd, bCube, pNode1, pNode2 ); + Cudd_RecursiveDeref( dd, bCube ); + } + else // if ( pVar->nParts > 2 ) + { + // find two smallest BDDs that have this var + Bbr_FindBestPartitions( dd, pVar->bParts, nNodes, pNodes, &iNode1, &iNode2 ); + pNode1 = pNodes[iNode1]; + pNode2 = pNodes[iNode2]; +//printf( "smallest bdds with this var: %d %d\n", iNode1, iNode2 ); +/* + // it is not possible that a var appears only in these two + // otherwise, it would have a different cost + bParts = Cudd_bddAnd( dd, dd->vars[iNode1], dd->vars[iNode2] ); Cudd_Ref( bParts ); + for ( v = 0; v < nVars; v++ ) + if ( pVars[v] && pVars[v]->bParts == bParts ) + assert( 0 ); + Cudd_RecursiveDeref( dd, bParts ); +*/ + // combines two nodes + pNode = Bbr_CombineTwoNodes( dd, b1, pNode1, pNode2 ); + } + + // clean the old nodes + pNodes[iNode1] = pNode; + pNodes[iNode2] = NULL; +//printf( "Removing node %d (leaving node %d)\n", iNode2, iNode1 ); + + // update the variables that appear in pNode[iNode2] + for ( bSuppTemp = pNode2->pPart->bSupp; bSuppTemp != b1; bSuppTemp = cuddT(bSuppTemp) ) + { + pVar = pVars[bSuppTemp->index]; + if ( pVar == NULL ) // this variable is not be quantified + continue; + // quantify this var + assert( Cudd_bddLeq( dd, pVar->bParts, dd->vars[iNode2] ) ); + pVar->bParts = Cudd_bddExistAbstract( dd, bTemp = pVar->bParts, dd->vars[iNode2] ); Cudd_Ref( pVar->bParts ); + Cudd_RecursiveDeref( dd, bTemp ); + // add the new var + pVar->bParts = Cudd_bddAnd( dd, bTemp = pVar->bParts, dd->vars[iNode1] ); Cudd_Ref( pVar->bParts ); + Cudd_RecursiveDeref( dd, bTemp ); + // update the score + pVar->nParts = Cudd_SupportSize( dd, pVar->bParts ); + } + + *pfStop = 0; + if ( dd->keys-dd->dead > (unsigned)nBddMax ) + { + *pfStop = 1; + return 0; + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Merges the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bbr_ImageNode_t * Bbr_MergeTopNodes( + DdManager * dd, int nNodes, Bbr_ImageNode_t ** pNodes ) +{ + Bbr_ImageNode_t * pNode; + int n1 = -1, n2 = -1, n; + + // find the first and the second non-empty spots + for ( n = 0; n < nNodes; n++ ) + if ( pNodes[n] ) + { + if ( n1 == -1 ) + n1 = n; + else if ( n2 == -1 ) + { + n2 = n; + break; + } + } + assert( n1 != -1 ); + // check the situation when only one such node is detected + if ( n2 == -1 ) + { + // save the node + pNode = pNodes[n1]; + // clean the node + pNodes[n1] = NULL; + return pNode; + } + + // combines two nodes + pNode = Bbr_CombineTwoNodes( dd, b1, pNodes[n1], pNodes[n2] ); + + // clean the old nodes + pNodes[n1] = pNode; + pNodes[n2] = NULL; + return NULL; +} + +/**Function************************************************************* + + Synopsis [Merges two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bbr_ImageNode_t * Bbr_CombineTwoNodes( DdManager * dd, DdNode * bCube, + Bbr_ImageNode_t * pNode1, Bbr_ImageNode_t * pNode2 ) +{ + Bbr_ImageNode_t * pNode; + Bbr_ImagePart_t * pPart; + + // create a new partition + pPart = ABC_ALLOC( Bbr_ImagePart_t, 1 ); + memset( pPart, 0, sizeof(Bbr_ImagePart_t) ); + // create the function + pPart->bFunc = Cudd_bddAndAbstract( dd, pNode1->pPart->bFunc, pNode2->pPart->bFunc, bCube ); + Cudd_Ref( pPart->bFunc ); + // update the support the partition + pPart->bSupp = Cudd_bddAndAbstract( dd, pNode1->pPart->bSupp, pNode2->pPart->bSupp, bCube ); + Cudd_Ref( pPart->bSupp ); + // update the numbers + pPart->nSupp = Cudd_SupportSize( dd, pPart->bSupp ); + pPart->nNodes = Cudd_DagSize( pPart->bFunc ); + pPart->iPart = -1; +/* +ABC_PRB( dd, pNode1->pPart->bSupp ); +ABC_PRB( dd, pNode2->pPart->bSupp ); +ABC_PRB( dd, pPart->bSupp ); +*/ + // create a new node + pNode = ABC_ALLOC( Bbr_ImageNode_t, 1 ); + memset( pNode, 0, sizeof(Bbr_ImageNode_t) ); + pNode->dd = dd; + pNode->pPart = pPart; + pNode->pNode1 = pNode1; + pNode->pNode2 = pNode2; + // compute the image + pNode->bImage = Cudd_bddAndAbstract( dd, pNode1->bImage, pNode2->bImage, bCube ); + Cudd_Ref( pNode->bImage ); + // save the cube + if ( bCube != b1 ) + { + pNode->bCube = bCube; Cudd_Ref( bCube ); + } + return pNode; +} + +/**Function************************************************************* + + Synopsis [Computes the best variable.] + + Description [The variables is the best if the sum of squares of the + BDD sizes of the partitions, in which it participates, is the minimum.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bbr_FindBestVariable( DdManager * dd, + int nNodes, Bbr_ImageNode_t ** pNodes, + int nVars, Bbr_ImageVar_t ** pVars ) +{ + DdNode * bTemp; + int iVarBest, v; + double CostBest, CostCur; + + CostBest = 100000000000000.0; + iVarBest = -1; + + // check if there are two-variable partitions + for ( v = 0; v < nVars; v++ ) + if ( pVars[v] && pVars[v]->nParts == 2 ) + { + CostCur = 0; + for ( bTemp = pVars[v]->bParts; bTemp != b1; bTemp = cuddT(bTemp) ) + CostCur += pNodes[bTemp->index]->pPart->nNodes * + pNodes[bTemp->index]->pPart->nNodes; + if ( CostBest > CostCur ) + { + CostBest = CostCur; + iVarBest = v; + } + } + if ( iVarBest >= 0 ) + return iVarBest; + + // find other partition + for ( v = 0; v < nVars; v++ ) + if ( pVars[v] ) + { + assert( pVars[v]->nParts > 1 ); + CostCur = 0; + for ( bTemp = pVars[v]->bParts; bTemp != b1; bTemp = cuddT(bTemp) ) + CostCur += pNodes[bTemp->index]->pPart->nNodes * + pNodes[bTemp->index]->pPart->nNodes; + if ( CostBest > CostCur ) + { + CostBest = CostCur; + iVarBest = v; + } + } + return iVarBest; +} + +/**Function************************************************************* + + Synopsis [Computes two smallest partions that have this var.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbr_FindBestPartitions( DdManager * dd, DdNode * bParts, + int nNodes, Bbr_ImageNode_t ** pNodes, + int * piNode1, int * piNode2 ) +{ + DdNode * bTemp; + int iPart1, iPart2; + int CostMin1, CostMin2, Cost; + + // go through the partitions + iPart1 = iPart2 = -1; + CostMin1 = CostMin2 = 1000000; + for ( bTemp = bParts; bTemp != b1; bTemp = cuddT(bTemp) ) + { + Cost = pNodes[bTemp->index]->pPart->nNodes; + if ( CostMin1 > Cost ) + { + CostMin2 = CostMin1; iPart2 = iPart1; + CostMin1 = Cost; iPart1 = bTemp->index; + } + else if ( CostMin2 > Cost ) + { + CostMin2 = Cost; iPart2 = bTemp->index; + } + } + + *piNode1 = iPart1; + *piNode2 = iPart2; +} + +/**Function************************************************************* + + Synopsis [Prints the latch dependency matrix.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbr_bddImagePrintLatchDependency( + DdManager * dd, DdNode * bCare, // the care set + int nParts, DdNode ** pbParts, // the partitions for image computation + int nVars, DdNode ** pbVars ) // the NS and parameter variables (not quantified!) +{ + int i; + DdNode * bVarsCs, * bVarsNs; + + bVarsCs = Cudd_Support( dd, bCare ); Cudd_Ref( bVarsCs ); + bVarsNs = Cudd_bddComputeCube( dd, pbVars, NULL, nVars ); Cudd_Ref( bVarsNs ); + + printf( "The latch dependency matrix:\n" ); + printf( "Partitions = %d Variables: total = %d non-quantifiable = %d\n", + nParts, dd->size, nVars ); + printf( " : " ); + for ( i = 0; i < dd->size; i++ ) + printf( "%d", i % 10 ); + printf( "\n" ); + + for ( i = 0; i < nParts; i++ ) + Bbr_bddImagePrintLatchDependencyOne( dd, pbParts[i], bVarsCs, bVarsNs, i ); + Bbr_bddImagePrintLatchDependencyOne( dd, bCare, bVarsCs, bVarsNs, nParts ); + + Cudd_RecursiveDeref( dd, bVarsCs ); + Cudd_RecursiveDeref( dd, bVarsNs ); +} + +/**Function************************************************************* + + Synopsis [Prints one row of the latch dependency matrix.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbr_bddImagePrintLatchDependencyOne( + DdManager * dd, DdNode * bFunc, // the function + DdNode * bVarsCs, DdNode * bVarsNs, // the current/next state vars + int iPart ) +{ + DdNode * bSupport; + int v; + bSupport = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupport ); + printf( " %3d : ", iPart ); + for ( v = 0; v < dd->size; v++ ) + { + if ( Cudd_bddLeq( dd, bSupport, dd->vars[v] ) ) + { + if ( Cudd_bddLeq( dd, bVarsCs, dd->vars[v] ) ) + printf( "c" ); + else if ( Cudd_bddLeq( dd, bVarsNs, dd->vars[v] ) ) + printf( "n" ); + else + printf( "i" ); + } + else + printf( "." ); + } + printf( "\n" ); + Cudd_RecursiveDeref( dd, bSupport ); +} + + +/**Function************************************************************* + + Synopsis [Prints the tree for quenstification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbr_bddImagePrintTree( Bbr_ImageTree_t * pTree ) +{ + printf( "The quantification scheduling tree:\n" ); + Bbr_bddImagePrintTree_rec( pTree->pRoot, 1 ); +} + +/**Function************************************************************* + + Synopsis [Prints the tree for quenstification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbr_bddImagePrintTree_rec( Bbr_ImageNode_t * pNode, int Offset ) +{ + DdNode * Cube; + int i; + + Cube = pNode->bCube; + + if ( pNode->pNode1 == NULL ) + { + printf( "<%d> ", pNode->pPart->iPart ); + if ( Cube != NULL ) + { + ABC_PRB( pNode->dd, Cube ); + } + else + printf( "\n" ); + return; + } + + printf( "<*> " ); + if ( Cube != NULL ) + { + ABC_PRB( pNode->dd, Cube ); + } + else + printf( "\n" ); + + for ( i = 0; i < Offset; i++ ) + printf( " " ); + Bbr_bddImagePrintTree_rec( pNode->pNode1, Offset + 1 ); + + for ( i = 0; i < Offset; i++ ) + printf( " " ); + Bbr_bddImagePrintTree_rec( pNode->pNode2, Offset + 1 ); +} + +/**Function******************************************************************** + + Synopsis [Computes the positive polarty cube composed of the first vars in the array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Bbr_bddComputeCube( DdManager * dd, DdNode ** bXVars, int nVars ) +{ + DdNode * bRes; + DdNode * bTemp; + int i; + + bRes = b1; Cudd_Ref( bRes ); + for ( i = 0; i < nVars; i++ ) + { + bRes = Cudd_bddAnd( dd, bTemp = bRes, bXVars[i] ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + } + + Cudd_Deref( bRes ); + return bRes; +} + + + + + +struct Bbr_ImageTree2_t_ +{ + DdManager * dd; + DdNode * bRel; + DdNode * bCube; + DdNode * bImage; +}; + +/**Function************************************************************* + + Synopsis [Starts the monolithic image computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bbr_ImageTree2_t * Bbr_bddImageStart2( + DdManager * dd, DdNode * bCare, + int nParts, DdNode ** pbParts, + int nVars, DdNode ** pbVars, int fVerbose ) +{ + Bbr_ImageTree2_t * pTree; + DdNode * bCubeAll, * bCubeNot, * bTemp; + int i; + + pTree = ABC_ALLOC( Bbr_ImageTree2_t, 1 ); + pTree->dd = dd; + pTree->bImage = NULL; + + bCubeAll = Bbr_bddComputeCube( dd, dd->vars, dd->size ); Cudd_Ref( bCubeAll ); + bCubeNot = Bbr_bddComputeCube( dd, pbVars, nVars ); Cudd_Ref( bCubeNot ); + pTree->bCube = Cudd_bddExistAbstract( dd, bCubeAll, bCubeNot ); Cudd_Ref( pTree->bCube ); + Cudd_RecursiveDeref( dd, bCubeAll ); + Cudd_RecursiveDeref( dd, bCubeNot ); + + // derive the monolithic relation + pTree->bRel = b1; Cudd_Ref( pTree->bRel ); + for ( i = 0; i < nParts; i++ ) + { + pTree->bRel = Cudd_bddAnd( dd, bTemp = pTree->bRel, pbParts[i] ); Cudd_Ref( pTree->bRel ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Bbr_bddImageCompute2( pTree, bCare ); + return pTree; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Bbr_bddImageCompute2( Bbr_ImageTree2_t * pTree, DdNode * bCare ) +{ + if ( pTree->bImage ) + Cudd_RecursiveDeref( pTree->dd, pTree->bImage ); + pTree->bImage = Cudd_bddAndAbstract( pTree->dd, pTree->bRel, bCare, pTree->bCube ); + Cudd_Ref( pTree->bImage ); + return pTree->bImage; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbr_bddImageTreeDelete2( Bbr_ImageTree2_t * pTree ) +{ + if ( pTree->bRel ) + Cudd_RecursiveDeref( pTree->dd, pTree->bRel ); + if ( pTree->bCube ) + Cudd_RecursiveDeref( pTree->dd, pTree->bCube ); + if ( pTree->bImage ) + Cudd_RecursiveDeref( pTree->dd, pTree->bImage ); + ABC_FREE( pTree ); +} + +/**Function************************************************************* + + Synopsis [Returns the previously computed image.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Bbr_bddImageRead2( Bbr_ImageTree2_t * pTree ) +{ + return pTree->bImage; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/bbr/bbrNtbdd.c b/src/proof/bbr/bbrNtbdd.c new file mode 100644 index 00000000..09456df0 --- /dev/null +++ b/src/proof/bbr/bbrNtbdd.c @@ -0,0 +1,218 @@ +/**CFile**************************************************************** + + FileName [bbrNtbdd.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD-based reachability analysis.] + + Synopsis [Procedures to construct global BDDs for the network.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: bbrNtbdd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "bbr.h" +//#include "bar.h" + +ABC_NAMESPACE_IMPL_START + + +typedef char ProgressBar; + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline void Aig_ObjSetGlobalBdd( Aig_Obj_t * pObj, DdNode * bFunc ) { pObj->pData = bFunc; } +static inline void Aig_ObjCleanGlobalBdd( DdManager * dd, Aig_Obj_t * pObj ) { Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); pObj->pData = NULL; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Derives the global BDD for one AIG node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Bbr_NodeGlobalBdds_rec( DdManager * dd, Aig_Obj_t * pNode, int nBddSizeMax, int fDropInternal, ProgressBar * pProgress, int * pCounter, int fVerbose ) +{ + DdNode * bFunc, * bFunc0, * bFunc1; + assert( !Aig_IsComplement(pNode) ); + if ( Cudd_ReadKeys(dd)-Cudd_ReadDead(dd) > (unsigned)nBddSizeMax ) + { +// Extra_ProgressBarStop( pProgress ); + if ( fVerbose ) + printf( "The number of live nodes reached %d.\n", nBddSizeMax ); + fflush( stdout ); + return NULL; + } + // if the result is available return + if ( Aig_ObjGlobalBdd(pNode) == NULL ) + { + // compute the result for both branches + bFunc0 = Bbr_NodeGlobalBdds_rec( dd, Aig_ObjFanin0(pNode), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); + if ( bFunc0 == NULL ) + return NULL; + Cudd_Ref( bFunc0 ); + bFunc1 = Bbr_NodeGlobalBdds_rec( dd, Aig_ObjFanin1(pNode), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); + if ( bFunc1 == NULL ) + return NULL; + Cudd_Ref( bFunc1 ); + bFunc0 = Cudd_NotCond( bFunc0, Aig_ObjFaninC0(pNode) ); + bFunc1 = Cudd_NotCond( bFunc1, Aig_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( Aig_ObjGlobalBdd(pNode) == NULL ); + Aig_ObjSetGlobalBdd( pNode, bFunc ); + // increment the progress bar +// if ( pProgress ) +// Extra_ProgressBarUpdate( pProgress, *pCounter, NULL ); + } + // prepare the return value + bFunc = Aig_ObjGlobalBdd(pNode); + // dereference BDD at the node + if ( --pNode->nRefs == 0 && fDropInternal ) + { + Cudd_Deref( bFunc ); + Aig_ObjSetGlobalBdd( pNode, NULL ); + } + return bFunc; +} + +/**Function************************************************************* + + Synopsis [Frees the global BDDs of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManFreeGlobalBdds( Aig_Man_t * p, DdManager * dd ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachObj( p, pObj, i ) + if ( Aig_ObjGlobalBdd(pObj) ) + Aig_ObjCleanGlobalBdd( dd, pObj ); +} + +/**Function************************************************************* + + Synopsis [Returns the shared size of global BDDs of the COs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManSizeOfGlobalBdds( Aig_Man_t * p ) +{ + Vec_Ptr_t * vFuncsGlob; + Aig_Obj_t * pObj; + int RetValue, i; + // complement the global functions + vFuncsGlob = Vec_PtrAlloc( Aig_ManPoNum(p) ); + Aig_ManForEachPo( p, pObj, i ) + Vec_PtrPush( vFuncsGlob, Aig_ObjGlobalBdd(pObj) ); + RetValue = Cudd_SharingSize( (DdNode **)Vec_PtrArray(vFuncsGlob), Vec_PtrSize(vFuncsGlob) ); + Vec_PtrFree( vFuncsGlob ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Recursively computes global BDDs for the AIG in the manager.] + + Description [On exit, BDDs are stored in the pNode->pData fields.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdManager * Aig_ManComputeGlobalBdds( Aig_Man_t * p, int nBddSizeMax, int fDropInternal, int fReorder, int fVerbose ) +{ + ProgressBar * pProgress = NULL; + Aig_Obj_t * pObj; + DdManager * dd; + DdNode * bFunc; + int i, Counter; + // start the manager + dd = Cudd_Init( Aig_ManPiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + // set reordering + if ( fReorder ) + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + // prepare to construct global BDDs + Aig_ManCleanData( p ); + // assign the constant node BDD + Aig_ObjSetGlobalBdd( Aig_ManConst1(p), dd->one ); Cudd_Ref( dd->one ); + // set the elementary variables + Aig_ManForEachPi( p, pObj, i ) + { + Aig_ObjSetGlobalBdd( pObj, dd->vars[i] ); Cudd_Ref( dd->vars[i] ); + } + + // collect the global functions of the COs + Counter = 0; + // construct the BDDs +// pProgress = Extra_ProgressBarStart( stdout, Aig_ManNodeNum(p) ); + Aig_ManForEachPo( p, pObj, i ) + { + bFunc = Bbr_NodeGlobalBdds_rec( dd, Aig_ObjFanin0(pObj), nBddSizeMax, fDropInternal, pProgress, &Counter, fVerbose ); + if ( bFunc == NULL ) + { + if ( fVerbose ) + printf( "Constructing global BDDs is aborted.\n" ); + Aig_ManFreeGlobalBdds( p, dd ); + Cudd_Quit( dd ); + // reset references + Aig_ManResetRefs( p ); + return NULL; + } + bFunc = Cudd_NotCond( bFunc, Aig_ObjFaninC0(pObj) ); Cudd_Ref( bFunc ); + Aig_ObjSetGlobalBdd( pObj, bFunc ); + } +// Extra_ProgressBarStop( pProgress ); + // reset references + Aig_ManResetRefs( p ); + // reorder one more time + if ( fReorder ) + { + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 ); + Cudd_AutodynDisable( dd ); + } +// Cudd_PrintInfo( dd, stdout ); + return dd; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/bbr/bbrReach.c b/src/proof/bbr/bbrReach.c new file mode 100644 index 00000000..1b5c3984 --- /dev/null +++ b/src/proof/bbr/bbrReach.c @@ -0,0 +1,606 @@ +/**CFile**************************************************************** + + FileName [bbrReach.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD-based reachability analysis.] + + Synopsis [Procedures to perform reachability analysis.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: bbrReach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "bbr.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern Abc_Cex_t * Aig_ManVerifyUsingBddsCountExample( Aig_Man_t * p, DdManager * dd, + DdNode ** pbParts, Vec_Ptr_t * vOnionRings, DdNode * bCubeFirst, + int iOutput, int fVerbose, int fSilent ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [This procedure sets default resynthesis parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbr_ManSetDefaultParams( Saig_ParBbr_t * p ) +{ + memset( p, 0, sizeof(Saig_ParBbr_t) ); + p->TimeLimit = 0; + p->nBddMax = 50000; + p->nIterMax = 1000; + p->fPartition = 1; + p->fReorder = 1; + p->fReorderImage = 1; + p->fVerbose = 0; + p->fSilent = 0; + p->iFrame = -1; +} + +/**Function******************************************************************** + + Synopsis [Performs the reordering-sensitive step of Extra_bddMove().] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Bbr_bddComputeRangeCube( DdManager * dd, int iStart, int iStop ) +{ + DdNode * bTemp, * bProd; + int i; + assert( iStart <= iStop ); + assert( iStart >= 0 && iStart <= dd->size ); + assert( iStop >= 0 && iStop <= dd->size ); + bProd = (dd)->one; Cudd_Ref( bProd ); + for ( i = iStart; i < iStop; i++ ) + { + bProd = Cudd_bddAnd( dd, bTemp = bProd, dd->vars[i] ); Cudd_Ref( bProd ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bProd ); + return bProd; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbr_StopManager( DdManager * dd ) +{ + int RetValue; + // check for remaining references in the package + RetValue = Cudd_CheckZeroRef( dd ); + if ( RetValue > 0 ) + printf( "\nThe number of referenced nodes = %d\n\n", RetValue ); +// Cudd_PrintInfo( dd, stdout ); + Cudd_Quit( dd ); +} + +/**Function************************************************************* + + Synopsis [Computes the initial state and sets up the variable map.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Aig_ManInitStateVarMap( DdManager * dd, Aig_Man_t * p, int fVerbose ) +{ + DdNode ** pbVarsX, ** pbVarsY; + DdNode * bTemp, * bProd; + Aig_Obj_t * pLatch; + int i; + + // set the variable mapping for Cudd_bddVarMap() + pbVarsX = ABC_ALLOC( DdNode *, dd->size ); + pbVarsY = ABC_ALLOC( DdNode *, dd->size ); + bProd = (dd)->one; Cudd_Ref( bProd ); + Saig_ManForEachLo( p, pLatch, i ) + { + pbVarsX[i] = dd->vars[ Saig_ManPiNum(p) + i ]; + pbVarsY[i] = dd->vars[ Saig_ManCiNum(p) + i ]; + // get the initial value of the latch + bProd = Cudd_bddAnd( dd, bTemp = bProd, Cudd_Not(pbVarsX[i]) ); Cudd_Ref( bProd ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_SetVarMap( dd, pbVarsX, pbVarsY, Saig_ManRegNum(p) ); + ABC_FREE( pbVarsX ); + ABC_FREE( pbVarsY ); + + Cudd_Deref( bProd ); + return bProd; +} + +/**Function************************************************************* + + Synopsis [Collects the array of output BDDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode ** Aig_ManCreateOutputs( DdManager * dd, Aig_Man_t * p ) +{ + DdNode ** pbOutputs; + Aig_Obj_t * pNode; + int i; + // compute the transition relation + pbOutputs = ABC_ALLOC( DdNode *, Saig_ManPoNum(p) ); + Saig_ManForEachPo( p, pNode, i ) + { + pbOutputs[i] = Aig_ObjGlobalBdd(pNode); Cudd_Ref( pbOutputs[i] ); + } + return pbOutputs; +} + +/**Function************************************************************* + + Synopsis [Collects the array of partition BDDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode ** Aig_ManCreatePartitions( DdManager * dd, Aig_Man_t * p, int fReorder, int fVerbose ) +{ + DdNode ** pbParts; + DdNode * bVar; + Aig_Obj_t * pNode; + int i; + + // extand the BDD manager to represent NS variables + assert( dd->size == Saig_ManCiNum(p) ); + Cudd_bddIthVar( dd, Saig_ManCiNum(p) + Saig_ManRegNum(p) - 1 ); + + // enable reordering + if ( fReorder ) + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + else + Cudd_AutodynDisable( dd ); + + // compute the transition relation + pbParts = ABC_ALLOC( DdNode *, Saig_ManRegNum(p) ); + Saig_ManForEachLi( p, pNode, i ) + { + bVar = Cudd_bddIthVar( dd, Saig_ManCiNum(p) + i ); + pbParts[i] = Cudd_bddXnor( dd, bVar, Aig_ObjGlobalBdd(pNode) ); Cudd_Ref( pbParts[i] ); + } + // free global BDDs + Aig_ManFreeGlobalBdds( p, dd ); + + // reorder and disable reordering + if ( fReorder ) + { + if ( fVerbose ) + fprintf( stdout, "BDD nodes in the partitions before reordering %d.\n", Cudd_SharingSize(pbParts,Saig_ManRegNum(p)) ); + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); + Cudd_AutodynDisable( dd ); + if ( fVerbose ) + fprintf( stdout, "BDD nodes in the partitions after reordering %d.\n", Cudd_SharingSize(pbParts,Saig_ManRegNum(p)) ); + } + return pbParts; +} + +/**Function************************************************************* + + Synopsis [Computes the set of unreachable states.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManComputeReachable( DdManager * dd, Aig_Man_t * p, DdNode ** pbParts, DdNode * bInitial, DdNode ** pbOutputs, Saig_ParBbr_t * pPars, int fCheckOutputs ) +{ + int fInternalReorder = 0; + Bbr_ImageTree_t * pTree = NULL; // Suppress "might be used uninitialized" + Bbr_ImageTree2_t * pTree2 = NULL; // Supprses "might be used uninitialized" + DdNode * bReached, * bCubeCs; + DdNode * bCurrent; + DdNode * bNext = NULL; // Suppress "might be used uninitialized" + DdNode * bTemp; + Cudd_ReorderingType method; + int i, nIters, nBddSize = 0, status; + int nThreshold = 10000, clk = clock(); + Vec_Ptr_t * vOnionRings; + + status = Cudd_ReorderingStatus( dd, &method ); + if ( status ) + Cudd_AutodynDisable( dd ); + + // start the image computation + bCubeCs = Bbr_bddComputeRangeCube( dd, Saig_ManPiNum(p), Saig_ManCiNum(p) ); Cudd_Ref( bCubeCs ); + if ( pPars->fPartition ) + pTree = Bbr_bddImageStart( dd, bCubeCs, Saig_ManRegNum(p), pbParts, Saig_ManRegNum(p), dd->vars+Saig_ManCiNum(p), pPars->nBddMax, pPars->fVerbose ); + else + pTree2 = Bbr_bddImageStart2( dd, bCubeCs, Saig_ManRegNum(p), pbParts, Saig_ManRegNum(p), dd->vars+Saig_ManCiNum(p), pPars->fVerbose ); + Cudd_RecursiveDeref( dd, bCubeCs ); + if ( pTree == NULL ) + { + if ( !pPars->fSilent ) + printf( "BDDs blew up during qualitification scheduling. " ); + return -1; + } + + if ( status ) + Cudd_AutodynEnable( dd, method ); + + // start the onion rings + vOnionRings = Vec_PtrAlloc( 1000 ); + + // perform reachability analysis + bCurrent = bInitial; Cudd_Ref( bCurrent ); + bReached = bInitial; Cudd_Ref( bReached ); + Vec_PtrPush( vOnionRings, bCurrent ); Cudd_Ref( bCurrent ); + for ( nIters = 0; nIters < pPars->nIterMax; nIters++ ) + { + // check the runtime limit + if ( pPars->TimeLimit && ((float)pPars->TimeLimit <= (float)(clock()-clk)/(float)(CLOCKS_PER_SEC)) ) + { + printf( "Reached timeout after image computation (%d seconds).\n", pPars->TimeLimit ); + Vec_PtrFree( vOnionRings ); + // undo the image tree + if ( pPars->fPartition ) + Bbr_bddImageTreeDelete( pTree ); + else + Bbr_bddImageTreeDelete2( pTree2 ); + pPars->iFrame = nIters - 1; + return -1; + } + + // compute the next states + if ( pPars->fPartition ) + bNext = Bbr_bddImageCompute( pTree, bCurrent ); + else + bNext = Bbr_bddImageCompute2( pTree2, bCurrent ); + if ( bNext == NULL ) + { + if ( !pPars->fSilent ) + printf( "BDDs blew up during image computation. " ); + if ( pPars->fPartition ) + Bbr_bddImageTreeDelete( pTree ); + else + Bbr_bddImageTreeDelete2( pTree2 ); + Vec_PtrFree( vOnionRings ); + pPars->iFrame = nIters - 1; + return -1; + } + Cudd_Ref( bNext ); + Cudd_RecursiveDeref( dd, bCurrent ); + + // remap these states into the current state vars + bNext = Cudd_bddVarMap( dd, bTemp = bNext ); Cudd_Ref( bNext ); + Cudd_RecursiveDeref( dd, bTemp ); + // check if there are any new states + if ( Cudd_bddLeq( dd, bNext, bReached ) ) + break; + // check the BDD size + nBddSize = Cudd_DagSize(bNext); + if ( nBddSize > pPars->nBddMax ) + break; + // check the result + for ( i = 0; i < Saig_ManPoNum(p); i++ ) + { + if ( fCheckOutputs && !Cudd_bddLeq( dd, bNext, Cudd_Not(pbOutputs[i]) ) ) + { + DdNode * bIntersect; + bIntersect = Cudd_bddIntersect( dd, bNext, pbOutputs[i] ); Cudd_Ref( bIntersect ); + assert( p->pSeqModel == NULL ); + p->pSeqModel = Aig_ManVerifyUsingBddsCountExample( p, dd, pbParts, + vOnionRings, bIntersect, i, pPars->fVerbose, pPars->fSilent ); + Cudd_RecursiveDeref( dd, bIntersect ); + if ( !pPars->fSilent ) + printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump a witness). ", i, Vec_PtrSize(vOnionRings) ); + Cudd_RecursiveDeref( dd, bReached ); + bReached = NULL; + pPars->iFrame = nIters; + break; + } + } + if ( i < Saig_ManPoNum(p) ) + break; + // get the new states + bCurrent = Cudd_bddAnd( dd, bNext, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); + Vec_PtrPush( vOnionRings, bCurrent ); Cudd_Ref( bCurrent ); + // minimize the new states with the reached states +// bCurrent = Cudd_bddConstrain( dd, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); +// Cudd_RecursiveDeref( dd, bTemp ); + // add to the reached states + bReached = Cudd_bddOr( dd, bTemp = bReached, bNext ); Cudd_Ref( bReached ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bNext ); + if ( pPars->fVerbose ) + fprintf( stdout, "Frame = %3d. BDD = %5d. ", nIters, nBddSize ); + if ( fInternalReorder && pPars->fReorder && nBddSize > nThreshold ) + { + if ( pPars->fVerbose ) + fprintf( stdout, "Reordering... Before = %5d. ", Cudd_DagSize(bReached) ); + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); + Cudd_AutodynDisable( dd ); + if ( pPars->fVerbose ) + fprintf( stdout, "After = %5d.\r", Cudd_DagSize(bReached) ); + nThreshold *= 2; + } + if ( pPars->fVerbose ) +// fprintf( stdout, "\r" ); + fprintf( stdout, "\n" ); + + if ( pPars->fVerbose ) + { + double nMints = Cudd_CountMinterm(dd, bReached, Saig_ManRegNum(p) ); +// Extra_bddPrint( dd, bReached );printf( "\n" ); + fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p)) ); + fflush( stdout ); + } + + } + Cudd_RecursiveDeref( dd, bNext ); + // free the onion rings + Vec_PtrForEachEntry( DdNode *, vOnionRings, bTemp, i ) + Cudd_RecursiveDeref( dd, bTemp ); + Vec_PtrFree( vOnionRings ); + // undo the image tree + if ( pPars->fPartition ) + Bbr_bddImageTreeDelete( pTree ); + else + Bbr_bddImageTreeDelete2( pTree2 ); + if ( bReached == NULL ) + return 0; // proved reachable + // report the stats + if ( pPars->fVerbose ) + { + double nMints = Cudd_CountMinterm(dd, bReached, Saig_ManRegNum(p) ); + if ( nIters > pPars->nIterMax || nBddSize > pPars->nBddMax ) + fprintf( stdout, "Reachability analysis is stopped after %d frames.\n", nIters ); + else + fprintf( stdout, "Reachability analysis completed after %d frames.\n", nIters ); + fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p)) ); + fflush( stdout ); + } +//ABC_PRB( dd, bReached ); + Cudd_RecursiveDeref( dd, bReached ); + if ( nIters > pPars->nIterMax || nBddSize > pPars->nBddMax ) + { + if ( !pPars->fSilent ) + printf( "Verified only for states reachable in %d frames. ", nIters ); + return -1; // undecided + } + if ( !pPars->fSilent ) + printf( "The miter is proved unreachable after %d iterations. ", nIters ); + pPars->iFrame = nIters - 1; + return 1; // unreachable +} + +/**Function************************************************************* + + Synopsis [Performs reachability to see if any PO can be asserted.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManVerifyUsingBdds_int( Aig_Man_t * p, Saig_ParBbr_t * pPars ) +{ + int fCheckOutputs = !pPars->fSkipOutCheck; + DdManager * dd; + DdNode ** pbParts, ** pbOutputs; + DdNode * bInitial, * bTemp; + int RetValue, i, clk = clock(); + Vec_Ptr_t * vOnionRings; + + assert( Saig_ManRegNum(p) > 0 ); + + // compute the global BDDs of the latches + dd = Aig_ManComputeGlobalBdds( p, pPars->nBddMax, 1, pPars->fReorder, pPars->fVerbose ); + if ( dd == NULL ) + { + if ( !pPars->fSilent ) + printf( "The number of intermediate BDD nodes exceeded the limit (%d).\n", pPars->nBddMax ); + return -1; + } + if ( pPars->fVerbose ) + printf( "Shared BDD size is %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + + // check the runtime limit + if ( pPars->TimeLimit && ((float)pPars->TimeLimit <= (float)(clock()-clk)/(float)(CLOCKS_PER_SEC)) ) + { + printf( "Reached timeout after constructing global BDDs (%d seconds).\n", pPars->TimeLimit ); + Cudd_Quit( dd ); + return -1; + } + + // start the onion rings + vOnionRings = Vec_PtrAlloc( 1000 ); + + // save outputs + pbOutputs = Aig_ManCreateOutputs( dd, p ); + + // create partitions + pbParts = Aig_ManCreatePartitions( dd, p, pPars->fReorder, pPars->fVerbose ); + + // create the initial state and the variable map + bInitial = Aig_ManInitStateVarMap( dd, p, pPars->fVerbose ); Cudd_Ref( bInitial ); + + // set reordering + if ( pPars->fReorderImage ) + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + + // check the result + RetValue = -1; + for ( i = 0; i < Saig_ManPoNum(p); i++ ) + { + if ( fCheckOutputs && !Cudd_bddLeq( dd, bInitial, Cudd_Not(pbOutputs[i]) ) ) + { + DdNode * bIntersect; + bIntersect = Cudd_bddIntersect( dd, bInitial, pbOutputs[i] ); Cudd_Ref( bIntersect ); + assert( p->pSeqModel == NULL ); + p->pSeqModel = Aig_ManVerifyUsingBddsCountExample( p, dd, pbParts, + vOnionRings, bIntersect, i, pPars->fVerbose, pPars->fSilent ); + Cudd_RecursiveDeref( dd, bIntersect ); + if ( !pPars->fSilent ) + printf( "The miter output %d is proved REACHABLE in the initial state (use \"write_counter\" to dump a witness). ", i ); + RetValue = 0; + break; + } + } + // free the onion rings + Vec_PtrForEachEntry( DdNode *, vOnionRings, bTemp, i ) + Cudd_RecursiveDeref( dd, bTemp ); + Vec_PtrFree( vOnionRings ); + // explore reachable states + if ( RetValue == -1 ) + RetValue = Aig_ManComputeReachable( dd, p, pbParts, bInitial, pbOutputs, pPars, fCheckOutputs ); + + // cleanup + Cudd_RecursiveDeref( dd, bInitial ); + for ( i = 0; i < Saig_ManRegNum(p); i++ ) + Cudd_RecursiveDeref( dd, pbParts[i] ); + ABC_FREE( pbParts ); + for ( i = 0; i < Saig_ManPoNum(p); i++ ) + Cudd_RecursiveDeref( dd, pbOutputs[i] ); + ABC_FREE( pbOutputs ); +// if ( RetValue == -1 ) + Cudd_Quit( dd ); +// else +// Bbr_StopManager( dd ); + + // report the runtime + if ( !pPars->fSilent ) + { + ABC_PRT( "Time", clock() - clk ); + fflush( stdout ); + } + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Performs reachability to see if any PO can be asserted.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManVerifyUsingBdds( Aig_Man_t * pInit, Saig_ParBbr_t * pPars ) +{ + Abc_Cex_t * pCexOld, * pCexNew; + Aig_Man_t * p; + Aig_Obj_t * pObj; + Vec_Int_t * vInputMap; + int i, k, Entry, iBitOld, iBitNew, RetValue; +// pPars->fVerbose = 1; + // check if there are PIs without fanout + Saig_ManForEachPi( pInit, pObj, i ) + if ( Aig_ObjRefs(pObj) == 0 ) + break; + if ( i == Saig_ManPiNum(pInit) ) + return Aig_ManVerifyUsingBdds_int( pInit, pPars ); + // create new AIG + p = Aig_ManDupTrim( pInit ); + assert( Aig_ManPiNum(p) < Aig_ManPiNum(pInit) ); + assert( Aig_ManRegNum(p) == Aig_ManRegNum(pInit) ); + RetValue = Aig_ManVerifyUsingBdds_int( p, pPars ); + if ( RetValue != 0 ) + { + Aig_ManStop( p ); + return RetValue; + } + // the problem is satisfiable - remap the pattern + pCexOld = p->pSeqModel; + assert( pCexOld != NULL ); + // create input map + vInputMap = Vec_IntAlloc( Saig_ManPiNum(pInit) ); + Saig_ManForEachPi( pInit, pObj, i ) + if ( pObj->pData != NULL ) + Vec_IntPush( vInputMap, Aig_ObjPioNum((Aig_Obj_t *)pObj->pData) ); + else + Vec_IntPush( vInputMap, -1 ); + // create new pattern + pCexNew = Abc_CexAlloc( Saig_ManRegNum(pInit), Saig_ManPiNum(pInit), pCexOld->iFrame+1 ); + pCexNew->iFrame = pCexOld->iFrame; + pCexNew->iPo = pCexOld->iPo; + // copy the bit-data + for ( iBitOld = 0; iBitOld < pCexOld->nRegs; iBitOld++ ) + if ( Abc_InfoHasBit( pCexOld->pData, iBitOld ) ) + Abc_InfoSetBit( pCexNew->pData, iBitOld ); + // copy the primary input data + iBitNew = iBitOld; + for ( i = 0; i <= pCexNew->iFrame; i++ ) + { + Vec_IntForEachEntry( vInputMap, Entry, k ) + { + if ( Entry == -1 ) + continue; + if ( Abc_InfoHasBit( pCexOld->pData, iBitOld + Entry ) ) + Abc_InfoSetBit( pCexNew->pData, iBitNew + k ); + } + iBitOld += Saig_ManPiNum(p); + iBitNew += Saig_ManPiNum(pInit); + } + assert( iBitOld < iBitNew ); + assert( iBitOld == pCexOld->nBits ); + assert( iBitNew == pCexNew->nBits ); + Vec_IntFree( vInputMap ); + pInit->pSeqModel = pCexNew; + Aig_ManStop( p ); + return 0; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/bbr/bbr_.c b/src/proof/bbr/bbr_.c new file mode 100644 index 00000000..df934f7d --- /dev/null +++ b/src/proof/bbr/bbr_.c @@ -0,0 +1,52 @@ +/**CFile**************************************************************** + + FileName [.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: .c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "__Int.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/bbr/module.make b/src/proof/bbr/module.make new file mode 100644 index 00000000..11ba768e --- /dev/null +++ b/src/proof/bbr/module.make @@ -0,0 +1,4 @@ +SRC += src/proof/bbr/bbrCex.c \ + src/proof/bbr/bbrImage.c \ + src/proof/bbr/bbrNtbdd.c \ + src/proof/bbr/bbrReach.c diff --git a/src/proof/cec/cec.c b/src/proof/cec/cec.c new file mode 100644 index 00000000..6968a599 --- /dev/null +++ b/src/proof/cec/cec.c @@ -0,0 +1,53 @@ +/**CFile**************************************************************** + + FileName [cec.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinational equivalence checking.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cecInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/cec/cec.h b/src/proof/cec/cec.h new file mode 100644 index 00000000..10b06c28 --- /dev/null +++ b/src/proof/cec/cec.h @@ -0,0 +1,233 @@ +/**CFile**************************************************************** + + FileName [cec.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinational equivalence checking.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__cec__cec_h +#define ABC__aig__cec__cec_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +// dynamic SAT parameters +typedef struct Cec_ParSat_t_ Cec_ParSat_t; +struct Cec_ParSat_t_ +{ + int nBTLimit; // conflict limit at a node + int nSatVarMax; // the max number of SAT variables + int nCallsRecycle; // calls to perform before recycling SAT solver + int fNonChrono; // use non-chronological backtracling (for circuit SAT only) + int fPolarFlip; // flops polarity of variables + int fCheckMiter; // the circuit is the miter +// int fFirstStop; // stop on the first sat output + int fLearnCls; // perform clause learning + int fVerbose; // verbose stats +}; + +// simulation parameters +typedef struct Cec_ParSim_t_ Cec_ParSim_t; +struct Cec_ParSim_t_ +{ + int nWords; // the number of simulation words + int nFrames; // the number of simulation frames + int nRounds; // the number of simulation rounds + int nNonRefines; // the max number of rounds without refinement + int TimeLimit; // the runtime limit in seconds + int fDualOut; // miter with separate outputs + int fCheckMiter; // the circuit is the miter +// int fFirstStop; // stop on the first sat output + int fSeqSimulate; // performs sequential simulation + int fLatchCorr; // consider only latch outputs + int fConstCorr; // consider only constants + int fVeryVerbose; // verbose stats + int fVerbose; // verbose stats +}; + +// semiformal parameters +typedef struct Cec_ParSmf_t_ Cec_ParSmf_t; +struct Cec_ParSmf_t_ +{ + int nWords; // the number of simulation words + int nRounds; // the number of simulation rounds + int nFrames; // the max number of time frames + int nNonRefines; // the max number of rounds without refinement + int nMinOutputs; // the min outputs to accumulate + int nBTLimit; // conflict limit at a node + int TimeLimit; // the runtime limit in seconds + int fDualOut; // miter with separate outputs + int fCheckMiter; // the circuit is the miter +// int fFirstStop; // stop on the first sat output + int fVerbose; // verbose stats +}; + +// combinational SAT sweeping parameters +typedef struct Cec_ParFra_t_ Cec_ParFra_t; +struct Cec_ParFra_t_ +{ + int nWords; // the number of simulation words + int nRounds; // the number of simulation rounds + int nItersMax; // the maximum number of iterations of SAT sweeping + int nBTLimit; // conflict limit at a node + int TimeLimit; // the runtime limit in seconds + int nLevelMax; // restriction on the level nodes to be swept + int nDepthMax; // the depth in terms of steps of speculative reduction + int fRewriting; // enables AIG rewriting + int fCheckMiter; // the circuit is the miter +// int fFirstStop; // stop on the first sat output + int fDualOut; // miter with separate outputs + int fColorDiff; // miter with separate outputs + int fSatSweeping; // enable SAT sweeping + int fVeryVerbose; // verbose stats + int fVerbose; // verbose stats + int iOutFail; // the failed output +}; + +// combinational equivalence checking parameters +typedef struct Cec_ParCec_t_ Cec_ParCec_t; +struct Cec_ParCec_t_ +{ + int nBTLimit; // conflict limit at a node + int TimeLimit; // the runtime limit in seconds +// int fFirstStop; // stop on the first sat output + int fUseSmartCnf; // use smart CNF computation + int fRewriting; // enables AIG rewriting + int fVeryVerbose; // verbose stats + int fVerbose; // verbose stats + int iOutFail; // the number of failed output +}; + +// sequential register correspodence parameters +typedef struct Cec_ParCor_t_ Cec_ParCor_t; +struct Cec_ParCor_t_ +{ + int nWords; // the number of simulation words + int nRounds; // the number of simulation rounds + int nFrames; // the number of time frames + int nPrefix; // the number of time frames in the prefix + int nBTLimit; // conflict limit at a node + int nLevelMax; // (scorr only) the max number of levels + int nStepsMax; // (scorr only) the max number of induction steps + int fLatchCorr; // consider only latch outputs + int fConstCorr; // consider only constants + int fUseRings; // use rings + int fMakeChoices; // use equilvaences as choices + int fUseCSat; // use circuit-based solver +// int fFirstStop; // stop on the first sat output + int fUseSmartCnf; // use smart CNF computation + int fVerboseFlops; // verbose stats + int fVeryVerbose; // verbose stats + int fVerbose; // verbose stats + // callback + void * pData; + void * pFunc; +}; + +// sequential register correspodence parameters +typedef struct Cec_ParChc_t_ Cec_ParChc_t; +struct Cec_ParChc_t_ +{ + int nWords; // the number of simulation words + int nRounds; // the number of simulation rounds + int nBTLimit; // conflict limit at a node + int fUseRings; // use rings + int fUseCSat; // use circuit-based solver + int fVeryVerbose; // verbose stats + int fVerbose; // verbose stats +}; + +// sequential synthesis parameters +typedef struct Cec_ParSeq_t_ Cec_ParSeq_t; +struct Cec_ParSeq_t_ +{ + int fUseLcorr; // enables latch correspondence + int fUseScorr; // enables signal correspondence + int nBTLimit; // (scorr/lcorr) conflict limit at a node + int nFrames; // (scorr/lcorr) the number of timeframes + int nLevelMax; // (scorr only) the max number of levels + int fConsts; // (scl only) merging constants + int fEquivs; // (scl only) merging equivalences + int fUseMiniSat; // enables MiniSat in lcorr/scorr + int nMinDomSize; // the size of minimum clock domain + int fVeryVerbose; // verbose stats + int fVerbose; // verbose stats +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== cecCec.c ==========================================================*/ +extern int Cec_ManVerify( Gia_Man_t * p, Cec_ParCec_t * pPars ); +extern int Cec_ManVerifyTwo( Gia_Man_t * p0, Gia_Man_t * p1, int fVerbose ); +/*=== cecChoice.c ==========================================================*/ +extern Gia_Man_t * Cec_ManChoiceComputation( Gia_Man_t * pAig, Cec_ParChc_t * pPars ); +/*=== cecCorr.c ==========================================================*/ +extern int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars ); +extern Gia_Man_t * Cec_ManLSCorrespondence( Gia_Man_t * pAig, Cec_ParCor_t * pPars ); +/*=== cecCore.c ==========================================================*/ +extern void Cec_ManSatSetDefaultParams( Cec_ParSat_t * p ); +extern void Cec_ManSimSetDefaultParams( Cec_ParSim_t * p ); +extern void Cec_ManSmfSetDefaultParams( Cec_ParSmf_t * p ); +extern void Cec_ManFraSetDefaultParams( Cec_ParFra_t * p ); +extern void Cec_ManCecSetDefaultParams( Cec_ParCec_t * p ); +extern void Cec_ManCorSetDefaultParams( Cec_ParCor_t * p ); +extern void Cec_ManChcSetDefaultParams( Cec_ParChc_t * p ); +extern Gia_Man_t * Cec_ManSatSweeping( Gia_Man_t * pAig, Cec_ParFra_t * pPars ); +extern Gia_Man_t * Cec_ManSatSolving( Gia_Man_t * pAig, Cec_ParSat_t * pPars ); +extern void Cec_ManSimulation( Gia_Man_t * pAig, Cec_ParSim_t * pPars ); +/*=== cecSeq.c ==========================================================*/ +extern int Cec_ManSeqResimulateCounter( Gia_Man_t * pAig, Cec_ParSim_t * pPars, Abc_Cex_t * pCex ); +extern int Cec_ManSeqSemiformal( Gia_Man_t * pAig, Cec_ParSmf_t * pPars ); +extern int Cec_ManCheckNonTrivialCands( Gia_Man_t * pAig ); +/*=== cecSynth.c ==========================================================*/ +extern int Cec_SeqReadMinDomSize( Cec_ParSeq_t * p ); +extern int Cec_SeqReadVerbose( Cec_ParSeq_t * p ); +extern void Cec_SeqSynthesisSetDefaultParams( Cec_ParSeq_t * pPars ); +extern int Cec_SequentialSynthesisPart( Gia_Man_t * p, Cec_ParSeq_t * pPars ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/proof/cec/cecCec.c b/src/proof/cec/cecCec.c new file mode 100644 index 00000000..1460ba91 --- /dev/null +++ b/src/proof/cec/cecCec.c @@ -0,0 +1,373 @@ +/**CFile**************************************************************** + + FileName [cecCec.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinational equivalence checking.] + + Synopsis [Integrated combinatinal equivalence checker.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cecCec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cecInt.h" +#include "src/proof/fra/fra.h" +#include "src/aig/gia/giaAig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Saves the input pattern with the given number.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManTransformPattern( Gia_Man_t * p, int iOut, int * pValues ) +{ + int i; + assert( p->pCexComb == NULL ); + p->pCexComb = (Abc_Cex_t *)ABC_CALLOC( char, + sizeof(Abc_Cex_t) + sizeof(unsigned) * Abc_BitWordNum(Gia_ManCiNum(p)) ); + p->pCexComb->iPo = iOut; + p->pCexComb->nPis = Gia_ManCiNum(p); + p->pCexComb->nBits = Gia_ManCiNum(p); + for ( i = 0; i < Gia_ManCiNum(p); i++ ) + if ( pValues[i] ) + Abc_InfoSetBit( p->pCexComb->pData, i ); +} + +/**Function************************************************************* + + Synopsis [Interface to the old CEC engine] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManVerifyOld( Gia_Man_t * pMiter, int fVerbose, int * piOutFail ) +{ +// extern int Fra_FraigCec( Aig_Man_t ** ppAig, int nConfLimit, int fVerbose ); + extern int Ssw_SecCexResimulate( Aig_Man_t * p, int * pModel, int * pnOutputs ); + Gia_Man_t * pTemp = Gia_ManTransformMiter( pMiter ); + Aig_Man_t * pMiterCec = Gia_ManToAig( pTemp, 0 ); + int RetValue, iOut, nOuts, clkTotal = clock(); + if ( piOutFail ) + *piOutFail = -1; + Gia_ManStop( pTemp ); + // run CEC on this miter + RetValue = Fra_FraigCec( &pMiterCec, 10000000, fVerbose ); + // report the miter + if ( RetValue == 1 ) + { + Abc_Print( 1, "Networks are equivalent. " ); +Abc_PrintTime( 1, "Time", clock() - clkTotal ); + } + else if ( RetValue == 0 ) + { + Abc_Print( 1, "Networks are NOT EQUIVALENT. " ); +Abc_PrintTime( 1, "Time", clock() - clkTotal ); + if ( pMiterCec->pData == NULL ) + Abc_Print( 1, "Counter-example is not available.\n" ); + else + { + iOut = Ssw_SecCexResimulate( pMiterCec, (int *)pMiterCec->pData, &nOuts ); + if ( iOut == -1 ) + Abc_Print( 1, "Counter-example verification has failed.\n" ); + else + { +// Aig_Obj_t * pObj = Aig_ManPo(pMiterCec, iOut); +// Aig_Obj_t * pFan = Aig_ObjFanin0(pObj); + Abc_Print( 1, "Primary output %d has failed", iOut ); + if ( nOuts-1 >= 0 ) + Abc_Print( 1, ", along with other %d incorrect outputs", nOuts-1 ); + Abc_Print( 1, ".\n" ); + if ( piOutFail ) + *piOutFail = iOut; + } + Cec_ManTransformPattern( pMiter, iOut, (int *)pMiterCec->pData ); + } + } + else + { + Abc_Print( 1, "Networks are UNDECIDED. " ); +Abc_PrintTime( 1, "Time", clock() - clkTotal ); + } + fflush( stdout ); + Aig_ManStop( pMiterCec ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [New CEC engine.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManVerify( Gia_Man_t * pInit, Cec_ParCec_t * pPars ) +{ + int fDumpUndecided = 0; + Cec_ParFra_t ParsFra, * pParsFra = &ParsFra; + Gia_Man_t * p, * pNew; + int RetValue, clk = clock(); + double clkTotal = clock(); + // preprocess + p = Gia_ManDup( pInit ); + Gia_ManEquivFixOutputPairs( p ); + p = Gia_ManCleanup( pNew = p ); + Gia_ManStop( pNew ); + // sweep for equivalences + Cec_ManFraSetDefaultParams( pParsFra ); + pParsFra->nItersMax = 1000; + pParsFra->nBTLimit = pPars->nBTLimit; + pParsFra->TimeLimit = pPars->TimeLimit; + pParsFra->fVerbose = pPars->fVerbose; + pParsFra->fCheckMiter = 1; + pParsFra->fDualOut = 1; + pNew = Cec_ManSatSweeping( p, pParsFra ); + pPars->iOutFail = pParsFra->iOutFail; + // update + pInit->pCexComb = p->pCexComb; p->pCexComb = NULL; + Gia_ManStop( p ); + p = pInit; + // continue + if ( pNew == NULL ) + { + if ( p->pCexComb != NULL ) + { + if ( p->pCexComb && !Gia_ManVerifyCex( p, p->pCexComb, 1 ) ) + Abc_Print( 1, "Counter-example simulation has failed.\n" ); + Abc_Print( 1, "Networks are NOT EQUIVALENT. " ); + Abc_PrintTime( 1, "Time", clock() - clk ); + return 0; + } + p = Gia_ManDup( pInit ); + Gia_ManEquivFixOutputPairs( p ); + p = Gia_ManCleanup( pNew = p ); + Gia_ManStop( pNew ); + pNew = p; + } + if ( Gia_ManAndNum(pNew) == 0 ) + { + Gia_Obj_t * pObj1, * pObj2; + int i; + Gia_ManForEachPo( pNew, pObj1, i ) + { + pObj2 = Gia_ManPo( pNew, ++i ); + if ( Gia_ObjChild0(pObj1) != Gia_ObjChild0(pObj2) ) + { + Abc_Print( 1, "Networks are NOT EQUIVALENT. Outputs %d trivially differ. ", i/2 ); + Abc_PrintTime( 1, "Time", clock() - clk ); + Gia_ManStop( pNew ); + pPars->iOutFail = i/2; + return 0; + } + } + Abc_Print( 1, "Networks are equivalent. " ); + Abc_PrintTime( 1, "Time", clock() - clk ); + Gia_ManStop( pNew ); + return 1; + } + if ( pPars->fVerbose ) + { + Abc_Print( 1, "Networks are UNDECIDED after the new CEC engine. " ); + Abc_PrintTime( 1, "Time", clock() - clk ); + } + if ( fDumpUndecided ) + { + ABC_FREE( pNew->pReprs ); + ABC_FREE( pNew->pNexts ); + Gia_WriteAiger( pNew, "gia_cec_undecided.aig", 0, 0 ); + Abc_Print( 1, "The result is written into file \"%s\".\n", "gia_cec_undecided.aig" ); + } + if ( pPars->TimeLimit && ((double)clock() - clkTotal)/CLOCKS_PER_SEC >= pPars->TimeLimit ) + { + Gia_ManStop( pNew ); + return -1; + } + // call other solver + if ( pPars->fVerbose ) + Abc_Print( 1, "Calling the old CEC engine.\n" ); + fflush( stdout ); + RetValue = Cec_ManVerifyOld( pNew, pPars->fVerbose, &pPars->iOutFail ); + p->pCexComb = pNew->pCexComb; pNew->pCexComb = NULL; + if ( p->pCexComb && !Gia_ManVerifyCex( p, p->pCexComb, 1 ) ) + Abc_Print( 1, "Counter-example simulation has failed.\n" ); + Gia_ManStop( pNew ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [New CEC engine applied to two circuits.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManVerifyTwo( Gia_Man_t * p0, Gia_Man_t * p1, int fVerbose ) +{ + Cec_ParCec_t ParsCec, * pPars = &ParsCec; + Gia_Man_t * pMiter; + int RetValue; + Cec_ManCecSetDefaultParams( pPars ); + pPars->fVerbose = fVerbose; + pMiter = Gia_ManMiter( p0, p1, 1, 0, pPars->fVerbose ); + if ( pMiter == NULL ) + return -1; + RetValue = Cec_ManVerify( pMiter, pPars ); + p0->pCexComb = pMiter->pCexComb; pMiter->pCexComb = NULL; + Gia_ManStop( pMiter ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [New CEC engine applied to two circuits.] + + Description [Returns 1 if equivalent, 0 if counter-example, -1 if undecided. + Counter-example is returned in the first manager as pAig0->pSeqModel. + The format is given in Abc_Cex_t (file "abc\src\aig\gia\gia.h").] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManVerifyTwoAigs( Aig_Man_t * pAig0, Aig_Man_t * pAig1, int fVerbose ) +{ + Gia_Man_t * p0, * p1, * pTemp; + int RetValue; + + p0 = Gia_ManFromAig( pAig0 ); + p0 = Gia_ManCleanup( pTemp = p0 ); + Gia_ManStop( pTemp ); + + p1 = Gia_ManFromAig( pAig1 ); + p1 = Gia_ManCleanup( pTemp = p1 ); + Gia_ManStop( pTemp ); + + RetValue = Cec_ManVerifyTwo( p0, p1, fVerbose ); + pAig0->pSeqModel = p0->pCexComb; p0->pCexComb = NULL; + Gia_ManStop( p0 ); + Gia_ManStop( p1 ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Implementation of new signal correspodence.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Cec_LatchCorrespondence( Aig_Man_t * pAig, int nConfs, int fUseCSat ) +{ + Gia_Man_t * pGia; + Cec_ParCor_t CorPars, * pCorPars = &CorPars; + Cec_ManCorSetDefaultParams( pCorPars ); + pCorPars->fLatchCorr = 1; + pCorPars->fUseCSat = fUseCSat; + pCorPars->nBTLimit = nConfs; + pGia = Gia_ManFromAigSimple( pAig ); + Cec_ManLSCorrespondenceClasses( pGia, pCorPars ); + Gia_ManReprToAigRepr( pAig, pGia ); + Gia_ManStop( pGia ); + return Aig_ManDupSimple( pAig ); +} + +/**Function************************************************************* + + Synopsis [Implementation of new signal correspodence.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Cec_SignalCorrespondence( Aig_Man_t * pAig, int nConfs, int fUseCSat ) +{ + Gia_Man_t * pGia; + Cec_ParCor_t CorPars, * pCorPars = &CorPars; + Cec_ManCorSetDefaultParams( pCorPars ); + pCorPars->fUseCSat = fUseCSat; + pCorPars->nBTLimit = nConfs; + pGia = Gia_ManFromAigSimple( pAig ); + Cec_ManLSCorrespondenceClasses( pGia, pCorPars ); + Gia_ManReprToAigRepr( pAig, pGia ); + Gia_ManStop( pGia ); + return Aig_ManDupSimple( pAig ); +} + +/**Function************************************************************* + + Synopsis [Implementation of fraiging.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Cec_FraigCombinational( Aig_Man_t * pAig, int nConfs, int fVerbose ) +{ + Gia_Man_t * pGia; + Cec_ParFra_t FraPars, * pFraPars = &FraPars; + Cec_ManFraSetDefaultParams( pFraPars ); + pFraPars->fSatSweeping = 1; + pFraPars->nBTLimit = nConfs; + pFraPars->nItersMax = 20; + pFraPars->fVerbose = fVerbose; + pGia = Gia_ManFromAigSimple( pAig ); + Cec_ManSatSweeping( pGia, pFraPars ); + Gia_ManReprToAigRepr( pAig, pGia ); + Gia_ManStop( pGia ); + return Aig_ManDupSimple( pAig ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/cec/cecChoice.c b/src/proof/cec/cecChoice.c new file mode 100644 index 00000000..3ddb975e --- /dev/null +++ b/src/proof/cec/cecChoice.c @@ -0,0 +1,409 @@ +/**CFile**************************************************************** + + FileName [cecChoice.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinational equivalence checking.] + + Synopsis [Computation of structural choices.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cecChoice.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cecInt.h" +#include "src/aig/gia/giaAig.h" +#include "src/proof/dch/dch.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Cec_ManCombSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ); + +extern int Cec_ManResimulateCounterExamplesComb( Cec_ManSim_t * pSim, Vec_Int_t * vCexStore ); +extern int Gia_ManCheckRefinements( Gia_Man_t * p, Vec_Str_t * vStatus, Vec_Int_t * vOutputs, Cec_ManSim_t * pSim, int fRings ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes the real value of the literal w/o spec reduction.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cec_ManCombSpecReal( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + assert( Gia_ObjIsAnd(pObj) ); + Cec_ManCombSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Cec_ManCombSpecReduce_rec( pNew, p, Gia_ObjFanin1(pObj) ); + return Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Recursively performs speculative reduction for the object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManCombSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + Gia_Obj_t * pRepr; + if ( ~pObj->Value ) + return; + if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) + { + Cec_ManCombSpecReduce_rec( pNew, p, pRepr ); + pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); + return; + } + pObj->Value = Cec_ManCombSpecReal( pNew, p, pObj ); +} + +/**Function************************************************************* + + Synopsis [Derives SRM for signal correspondence.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Cec_ManCombSpecReduce( Gia_Man_t * p, Vec_Int_t ** pvOutputs, int fRings ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pRepr; + Vec_Int_t * vXorLits; + int i, iPrev, iObj, iPrevNew, iObjNew; + assert( p->pReprs != NULL ); + Gia_ManSetPhase( p ); + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManHashAlloc( pNew ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + *pvOutputs = Vec_IntAlloc( 1000 ); + vXorLits = Vec_IntAlloc( 1000 ); + if ( fRings ) + { + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsConst( p, i ) ) + { + iObjNew = Cec_ManCombSpecReal( pNew, p, pObj ); + iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ); + if ( iObjNew != 0 ) + { + Vec_IntPush( *pvOutputs, 0 ); + Vec_IntPush( *pvOutputs, i ); + Vec_IntPush( vXorLits, iObjNew ); + } + } + else if ( Gia_ObjIsHead( p, i ) ) + { + iPrev = i; + Gia_ClassForEachObj1( p, i, iObj ) + { + iPrevNew = Cec_ManCombSpecReal( pNew, p, Gia_ManObj(p, iPrev) ); + iObjNew = Cec_ManCombSpecReal( pNew, p, Gia_ManObj(p, iObj) ); + iPrevNew = Abc_LitNotCond( iPrevNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) ); + iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) ); + if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 ) + { + Vec_IntPush( *pvOutputs, iPrev ); + Vec_IntPush( *pvOutputs, iObj ); + Vec_IntPush( vXorLits, Gia_ManHashAnd(pNew, iPrevNew, Abc_LitNot(iObjNew)) ); + } + iPrev = iObj; + } + iObj = i; + iPrevNew = Cec_ManCombSpecReal( pNew, p, Gia_ManObj(p, iPrev) ); + iObjNew = Cec_ManCombSpecReal( pNew, p, Gia_ManObj(p, iObj) ); + iPrevNew = Abc_LitNotCond( iPrevNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) ); + iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) ); + if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 ) + { + Vec_IntPush( *pvOutputs, iPrev ); + Vec_IntPush( *pvOutputs, iObj ); + Vec_IntPush( vXorLits, Gia_ManHashAnd(pNew, iPrevNew, Abc_LitNot(iObjNew)) ); + } + } + } + } + else + { + Gia_ManForEachObj1( p, pObj, i ) + { + pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); + if ( pRepr == NULL ) + continue; + iPrevNew = Gia_ObjIsConst(p, i)? 0 : Cec_ManCombSpecReal( pNew, p, pRepr ); + iObjNew = Cec_ManCombSpecReal( pNew, p, pObj ); + iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); + if ( iPrevNew != iObjNew ) + { + Vec_IntPush( *pvOutputs, Gia_ObjId(p, pRepr) ); + Vec_IntPush( *pvOutputs, Gia_ObjId(p, pObj) ); + Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, iPrevNew, iObjNew) ); + } + } + } + Vec_IntForEachEntry( vXorLits, iObjNew, i ) + Gia_ManAppendCo( pNew, iObjNew ); + Vec_IntFree( vXorLits ); + Gia_ManHashStop( pNew ); +//Abc_Print( 1, "Before sweeping = %d\n", Gia_ManAndNum(pNew) ); + pNew = Gia_ManCleanup( pTemp = pNew ); +//Abc_Print( 1, "After sweeping = %d\n", Gia_ManAndNum(pNew) ); + Gia_ManStop( pTemp ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManChoiceComputation_int( Gia_Man_t * pAig, Cec_ParChc_t * pPars ) +{ + int nItersMax = 1000; + Vec_Str_t * vStatus; + Vec_Int_t * vOutputs; + Vec_Int_t * vCexStore; + Cec_ParSim_t ParsSim, * pParsSim = &ParsSim; + Cec_ParSat_t ParsSat, * pParsSat = &ParsSat; + Cec_ManSim_t * pSim; + Gia_Man_t * pSrm; + int r, RetValue; + int clkSat = 0, clkSim = 0, clkSrm = 0, clkTotal = clock(); + int clk2, clk = clock(); + ABC_FREE( pAig->pReprs ); + ABC_FREE( pAig->pNexts ); + Gia_ManRandom( 1 ); + // prepare simulation manager + Cec_ManSimSetDefaultParams( pParsSim ); + pParsSim->nWords = pPars->nWords; + pParsSim->nFrames = pPars->nRounds; + pParsSim->fVerbose = pPars->fVerbose; + pParsSim->fLatchCorr = 0; + pParsSim->fSeqSimulate = 0; + // create equivalence classes of registers + pSim = Cec_ManSimStart( pAig, pParsSim ); + Cec_ManSimClassesPrepare( pSim, -1 ); + Cec_ManSimClassesRefine( pSim ); + // prepare SAT solving + Cec_ManSatSetDefaultParams( pParsSat ); + pParsSat->nBTLimit = pPars->nBTLimit; + pParsSat->fVerbose = pPars->fVerbose; + if ( pPars->fVerbose ) + { + Abc_Print( 1, "Obj = %7d. And = %7d. Conf = %5d. Ring = %d. CSat = %d.\n", + Gia_ManObjNum(pAig), Gia_ManAndNum(pAig), pPars->nBTLimit, pPars->fUseRings, pPars->fUseCSat ); + Cec_ManRefinedClassPrintStats( pAig, NULL, 0, clock() - clk ); + } + // perform refinement of equivalence classes + for ( r = 0; r < nItersMax; r++ ) + { + clk = clock(); + // perform speculative reduction + clk2 = clock(); + pSrm = Cec_ManCombSpecReduce( pAig, &vOutputs, pPars->fUseRings ); + assert( Gia_ManRegNum(pSrm) == 0 && Gia_ManCiNum(pSrm) == Gia_ManCiNum(pAig) ); + clkSrm += clock() - clk2; + if ( Gia_ManCoNum(pSrm) == 0 ) + { + if ( pPars->fVerbose ) + Cec_ManRefinedClassPrintStats( pAig, NULL, r+1, clock() - clk ); + Vec_IntFree( vOutputs ); + Gia_ManStop( pSrm ); + break; + } +//Gia_DumpAiger( pSrm, "choicesrm", r, 2 ); + // found counter-examples to speculation + clk2 = clock(); + if ( pPars->fUseCSat ) + vCexStore = Cbs_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0 ); + else + vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus ); + Gia_ManStop( pSrm ); + clkSat += clock() - clk2; + if ( Vec_IntSize(vCexStore) == 0 ) + { + if ( pPars->fVerbose ) + Cec_ManRefinedClassPrintStats( pAig, vStatus, r+1, clock() - clk ); + Vec_IntFree( vCexStore ); + Vec_StrFree( vStatus ); + Vec_IntFree( vOutputs ); + break; + } + // refine classes with these counter-examples + clk2 = clock(); + RetValue = Cec_ManResimulateCounterExamplesComb( pSim, vCexStore ); + Vec_IntFree( vCexStore ); + clkSim += clock() - clk2; + Gia_ManCheckRefinements( pAig, vStatus, vOutputs, pSim, pPars->fUseRings ); + if ( pPars->fVerbose ) + Cec_ManRefinedClassPrintStats( pAig, vStatus, r+1, clock() - clk ); + Vec_StrFree( vStatus ); + Vec_IntFree( vOutputs ); +//Gia_ManEquivPrintClasses( pAig, 1, 0 ); + } + // check the overflow + if ( r == nItersMax ) + Abc_Print( 1, "The refinement was not finished. The result may be incorrect.\n" ); + Cec_ManSimStop( pSim ); + clkTotal = clock() - clkTotal; + // report the results + if ( pPars->fVerbose ) + { + Abc_PrintTimeP( 1, "Srm ", clkSrm, clkTotal ); + Abc_PrintTimeP( 1, "Sat ", clkSat, clkTotal ); + Abc_PrintTimeP( 1, "Sim ", clkSim, clkTotal ); + Abc_PrintTimeP( 1, "Other", clkTotal-clkSat-clkSrm-clkSim, clkTotal ); + Abc_PrintTime( 1, "TOTAL", clkTotal ); + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Computes choices for the vector of AIGs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Cec_ManChoiceComputationVec( Gia_Man_t * pGia, int nGias, Cec_ParChc_t * pPars ) +{ + Gia_Man_t * pNew; + int RetValue; + // compute equivalences of the miter +// pMiter = Gia_ManChoiceMiter( vGias ); +// Gia_ManSetRegNum( pMiter, 0 ); + RetValue = Cec_ManChoiceComputation_int( pGia, pPars ); + // derive AIG with choices + pNew = Gia_ManEquivToChoices( pGia, nGias ); + Gia_ManHasChoices( pNew ); +// Gia_ManStop( pMiter ); + // report the results + if ( pPars->fVerbose ) + { +// Abc_Print( 1, "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n", +// Gia_ManAndNum(pAig), Gia_ManAndNum(pNew), +// 100.0*(Gia_ManAndNum(pAig)-Gia_ManAndNum(pNew))/(Gia_ManAndNum(pAig)?Gia_ManAndNum(pAig):1), +// Gia_ManRegNum(pAig), Gia_ManRegNum(pNew), +// 100.0*(Gia_ManRegNum(pAig)-Gia_ManRegNum(pNew))/(Gia_ManRegNum(pAig)?Gia_ManRegNum(pAig):1) ); + } + return pNew; +} + +/**Function************************************************************* + + Synopsis [Computes choices for one AIGs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Cec_ManChoiceComputation( Gia_Man_t * pAig, Cec_ParChc_t * pParsChc ) +{ +// extern Aig_Man_t * Dar_ManChoiceNew( Aig_Man_t * pAig, Dch_Pars_t * pPars ); + Dch_Pars_t Pars, * pPars = &Pars; + Aig_Man_t * pMan, * pManNew; + Gia_Man_t * pGia; + if ( 0 ) + { + pGia = Cec_ManChoiceComputationVec( pAig, 3, pParsChc ); + } + else + { + pMan = Gia_ManToAig( pAig, 0 ); + Dch_ManSetDefaultParams( pPars ); + pPars->fUseGia = 1; + pPars->nBTLimit = pParsChc->nBTLimit; + pPars->fUseCSat = pParsChc->fUseCSat; + pPars->fVerbose = pParsChc->fVerbose; + pManNew = Dar_ManChoiceNew( pMan, pPars ); + pGia = Gia_ManFromAig( pManNew ); + Aig_ManStop( pManNew ); +// Aig_ManStop( pMan ); + } + return pGia; +} + +/**Function************************************************************* + + Synopsis [Performs computation of AIGs with choices.] + + Description [Takes several AIGs and performs choicing.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Cec_ComputeChoices( Gia_Man_t * pGia, Dch_Pars_t * pPars ) +{ + Cec_ParChc_t ParsChc, * pParsChc = &ParsChc; + Aig_Man_t * pAig; + if ( pPars->fVerbose ) + Abc_PrintTime( 1, "Synthesis time", pPars->timeSynth ); + Cec_ManChcSetDefaultParams( pParsChc ); + pParsChc->nBTLimit = pPars->nBTLimit; + pParsChc->fUseCSat = pPars->fUseCSat; + if ( pParsChc->fUseCSat && pParsChc->nBTLimit > 100 ) + pParsChc->nBTLimit = 100; + pParsChc->fVerbose = pPars->fVerbose; + pGia = Cec_ManChoiceComputationVec( pGia, 3, pParsChc ); + Gia_ManSetRegNum( pGia, Gia_ManRegNum(pGia) ); + pAig = Gia_ManToAig( pGia, 1 ); + Gia_ManStop( pGia ); + return pAig; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/cec/cecClass.c b/src/proof/cec/cecClass.c new file mode 100644 index 00000000..46e585a9 --- /dev/null +++ b/src/proof/cec/cecClass.c @@ -0,0 +1,931 @@ +/**CFile**************************************************************** + + FileName [cecClass.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinational equivalence checking.] + + Synopsis [Equivalence class refinement.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cecClass.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cecInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline unsigned * Cec_ObjSim( Cec_ManSim_t * p, int Id ) { return p->pMems + p->pSimInfo[Id] + 1; } +static inline void Cec_ObjSetSim( Cec_ManSim_t * p, int Id, int n ) { p->pSimInfo[Id] = n; } + +static inline float Cec_MemUsage( Cec_ManSim_t * p ) { return 1.0*p->nMemsMax*(p->pPars->nWords+1)/(1<<20); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Compares simulation info of one node with constant 0.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManSimCompareConst( unsigned * p, int nWords ) +{ + int w; + if ( p[0] & 1 ) + { + for ( w = 0; w < nWords; w++ ) + if ( p[w] != ~0 ) + return 0; + return 1; + } + else + { + for ( w = 0; w < nWords; w++ ) + if ( p[w] != 0 ) + return 0; + return 1; + } +} + +/**Function************************************************************* + + Synopsis [Compares simulation info of two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManSimCompareEqual( unsigned * p0, unsigned * p1, int nWords ) +{ + int w; + if ( (p0[0] & 1) == (p1[0] & 1) ) + { + for ( w = 0; w < nWords; w++ ) + if ( p0[w] != p1[w] ) + return 0; + return 1; + } + else + { + for ( w = 0; w < nWords; w++ ) + if ( p0[w] != ~p1[w] ) + return 0; + return 1; + } +} + +/**Function************************************************************* + + Synopsis [Returns the number of the first non-equal bit.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManSimCompareConstFirstBit( unsigned * p, int nWords ) +{ + int w; + if ( p[0] & 1 ) + { + for ( w = 0; w < nWords; w++ ) + if ( p[w] != ~0 ) + return 32*w + Gia_WordFindFirstBit( ~p[w] ); + return -1; + } + else + { + for ( w = 0; w < nWords; w++ ) + if ( p[w] != 0 ) + return 32*w + Gia_WordFindFirstBit( p[w] ); + return -1; + } +} + +/**Function************************************************************* + + Synopsis [Compares simulation info of two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManSimCompareEqualFirstBit( unsigned * p0, unsigned * p1, int nWords ) +{ + int w; + if ( (p0[0] & 1) == (p1[0] & 1) ) + { + for ( w = 0; w < nWords; w++ ) + if ( p0[w] != p1[w] ) + return 32*w + Gia_WordFindFirstBit( p0[w] ^ p1[w] ); + return -1; + } + else + { + for ( w = 0; w < nWords; w++ ) + if ( p0[w] != ~p1[w] ) + return 32*w + Gia_WordFindFirstBit( p0[w] ^ ~p1[w] ); + return -1; + } +} + +/**Function************************************************************* + + Synopsis [Returns the number of the first non-equal bit.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManSimCompareConstScore( unsigned * p, int nWords, int * pScores ) +{ + int w, b; + if ( p[0] & 1 ) + { + for ( w = 0; w < nWords; w++ ) + if ( p[w] != ~0 ) + for ( b = 0; b < 32; b++ ) + if ( ((~p[w]) >> b ) & 1 ) + pScores[32*w + b]++; + } + else + { + for ( w = 0; w < nWords; w++ ) + if ( p[w] != 0 ) + for ( b = 0; b < 32; b++ ) + if ( ((p[w]) >> b ) & 1 ) + pScores[32*w + b]++; + } +} + +/**Function************************************************************* + + Synopsis [Compares simulation info of two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManSimCompareEqualScore( unsigned * p0, unsigned * p1, int nWords, int * pScores ) +{ + int w, b; + if ( (p0[0] & 1) == (p1[0] & 1) ) + { + for ( w = 0; w < nWords; w++ ) + if ( p0[w] != p1[w] ) + for ( b = 0; b < 32; b++ ) + if ( ((p0[w] ^ p1[w]) >> b ) & 1 ) + pScores[32*w + b]++; + } + else + { + for ( w = 0; w < nWords; w++ ) + if ( p0[w] != ~p1[w] ) + for ( b = 0; b < 32; b++ ) + if ( ((p0[w] ^ ~p1[w]) >> b ) & 1 ) + pScores[32*w + b]++; + } +} + +/**Function************************************************************* + + Synopsis [Creates equivalence class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManSimClassCreate( Gia_Man_t * p, Vec_Int_t * vClass ) +{ + int Repr = GIA_VOID, EntPrev = -1, Ent, i; + assert( Vec_IntSize(vClass) > 0 ); + Vec_IntForEachEntry( vClass, Ent, i ) + { + if ( i == 0 ) + { + Repr = Ent; + Gia_ObjSetRepr( p, Ent, GIA_VOID ); + EntPrev = Ent; + } + else + { + assert( Repr < Ent ); + Gia_ObjSetRepr( p, Ent, Repr ); + Gia_ObjSetNext( p, EntPrev, Ent ); + EntPrev = Ent; + } + } + Gia_ObjSetNext( p, EntPrev, 0 ); +} + +/**Function************************************************************* + + Synopsis [Refines one equivalence class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManSimClassRefineOne( Cec_ManSim_t * p, int i ) +{ + unsigned * pSim0, * pSim1; + int Ent; + Vec_IntClear( p->vClassOld ); + Vec_IntClear( p->vClassNew ); + Vec_IntPush( p->vClassOld, i ); + pSim0 = Cec_ObjSim(p, i); + Gia_ClassForEachObj1( p->pAig, i, Ent ) + { + pSim1 = Cec_ObjSim(p, Ent); + if ( Cec_ManSimCompareEqual( pSim0, pSim1, p->nWords ) ) + Vec_IntPush( p->vClassOld, Ent ); + else + { + Vec_IntPush( p->vClassNew, Ent ); + if ( p->pBestState ) + Cec_ManSimCompareEqualScore( pSim0, pSim1, p->nWords, p->pScores ); + } + } + if ( Vec_IntSize( p->vClassNew ) == 0 ) + return 0; + Cec_ManSimClassCreate( p->pAig, p->vClassOld ); + Cec_ManSimClassCreate( p->pAig, p->vClassNew ); + if ( Vec_IntSize(p->vClassNew) > 1 ) + return 1 + Cec_ManSimClassRefineOne( p, Vec_IntEntry(p->vClassNew,0) ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Refines one equivalence class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManSimClassRemoveOne( Cec_ManSim_t * p, int i ) +{ + int iRepr, Ent; + if ( Gia_ObjIsConst(p->pAig, i) ) + { + Gia_ObjSetRepr( p->pAig, i, GIA_VOID ); + return 1; + } + if ( !Gia_ObjIsClass(p->pAig, i) ) + return 0; + assert( Gia_ObjIsClass(p->pAig, i) ); + iRepr = Gia_ObjRepr( p->pAig, i ); + if ( iRepr == GIA_VOID ) + iRepr = i; + // collect nodes + Vec_IntClear( p->vClassOld ); + Vec_IntClear( p->vClassNew ); + Gia_ClassForEachObj( p->pAig, iRepr, Ent ) + { + if ( Ent == i ) + Vec_IntPush( p->vClassNew, Ent ); + else + Vec_IntPush( p->vClassOld, Ent ); + } + assert( Vec_IntSize( p->vClassNew ) == 1 ); + Cec_ManSimClassCreate( p->pAig, p->vClassOld ); + Cec_ManSimClassCreate( p->pAig, p->vClassNew ); + assert( !Gia_ObjIsClass(p->pAig, i) ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes hash key of the simuation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManSimHashKey( unsigned * pSim, int nWords, int nTableSize ) +{ + static int s_Primes[16] = { + 1291, 1699, 1999, 2357, 2953, 3313, 3907, 4177, + 4831, 5147, 5647, 6343, 6899, 7103, 7873, 8147 }; + unsigned uHash = 0; + int i; + if ( pSim[0] & 1 ) + for ( i = 0; i < nWords; i++ ) + uHash ^= ~pSim[i] * s_Primes[i & 0xf]; + else + for ( i = 0; i < nWords; i++ ) + uHash ^= pSim[i] * s_Primes[i & 0xf]; + return (int)(uHash % nTableSize); + +} + +/**Function************************************************************* + + Synopsis [Resets pointers to the simulation memory.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManSimMemRelink( Cec_ManSim_t * p ) +{ + unsigned * pPlace, Ent; + pPlace = (unsigned *)&p->MemFree; + for ( Ent = p->nMems * (p->nWords + 1); + Ent + p->nWords + 1 < (unsigned)p->nWordsAlloc; + Ent += p->nWords + 1 ) + { + *pPlace = Ent; + pPlace = p->pMems + Ent; + } + *pPlace = 0; + p->nWordsOld = p->nWords; +} + +/**Function************************************************************* + + Synopsis [References simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Cec_ManSimSimRef( Cec_ManSim_t * p, int i ) +{ + unsigned * pSim; + assert( p->pSimInfo[i] == 0 ); + if ( p->MemFree == 0 ) + { + if ( p->nWordsAlloc == 0 ) + { + assert( p->pMems == NULL ); + p->nWordsAlloc = (1<<17); // -> 1Mb + p->nMems = 1; + } + p->nWordsAlloc *= 2; + p->pMems = ABC_REALLOC( unsigned, p->pMems, p->nWordsAlloc ); + Cec_ManSimMemRelink( p ); + } + p->pSimInfo[i] = p->MemFree; + pSim = p->pMems + p->MemFree; + p->MemFree = pSim[0]; + pSim[0] = Gia_ObjValue( Gia_ManObj(p->pAig, i) ); + p->nMems++; + if ( p->nMemsMax < p->nMems ) + p->nMemsMax = p->nMems; + return pSim; +} + +/**Function************************************************************* + + Synopsis [Dereferences simulaton info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Cec_ManSimSimDeref( Cec_ManSim_t * p, int i ) +{ + unsigned * pSim; + assert( p->pSimInfo[i] > 0 ); + pSim = p->pMems + p->pSimInfo[i]; + if ( --pSim[0] == 0 ) + { + pSim[0] = p->MemFree; + p->MemFree = p->pSimInfo[i]; + p->pSimInfo[i] = 0; + p->nMems--; + } + return pSim; +} + +/**Function************************************************************* + + Synopsis [Refines nodes belonging to candidate constant class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManSimProcessRefined( Cec_ManSim_t * p, Vec_Int_t * vRefined ) +{ + unsigned * pSim; + int * pTable, nTableSize, i, k, Key; + if ( Vec_IntSize(vRefined) == 0 ) + return; + nTableSize = Abc_PrimeCudd( 100 + Vec_IntSize(vRefined) / 3 ); + pTable = ABC_CALLOC( int, nTableSize ); + Vec_IntForEachEntry( vRefined, i, k ) + { + pSim = Cec_ObjSim( p, i ); + assert( !Cec_ManSimCompareConst( pSim, p->nWords ) ); + Key = Cec_ManSimHashKey( pSim, p->nWords, nTableSize ); + if ( pTable[Key] == 0 ) + { + assert( Gia_ObjRepr(p->pAig, i) == 0 ); + assert( Gia_ObjNext(p->pAig, i) == 0 ); + Gia_ObjSetRepr( p->pAig, i, GIA_VOID ); + } + else + { + Gia_ObjSetNext( p->pAig, pTable[Key], i ); + Gia_ObjSetRepr( p->pAig, i, Gia_ObjRepr(p->pAig, pTable[Key]) ); + if ( Gia_ObjRepr(p->pAig, i) == GIA_VOID ) + Gia_ObjSetRepr( p->pAig, i, pTable[Key] ); + assert( Gia_ObjRepr(p->pAig, i) > 0 ); + } + pTable[Key] = i; + } + Vec_IntForEachEntry( vRefined, i, k ) + { + if ( Gia_ObjIsHead( p->pAig, i ) ) + Cec_ManSimClassRefineOne( p, i ); + } + Vec_IntForEachEntry( vRefined, i, k ) + Cec_ManSimSimDeref( p, i ); + ABC_FREE( pTable ); +} + + +/**Function************************************************************* + + Synopsis [Saves the input pattern with the given number.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManSimSavePattern( Cec_ManSim_t * p, int iPat ) +{ + unsigned * pInfo; + int i; + assert( p->pCexComb == NULL ); + assert( iPat >= 0 && iPat < 32 * p->nWords ); + p->pCexComb = (Abc_Cex_t *)ABC_CALLOC( char, + sizeof(Abc_Cex_t) + sizeof(unsigned) * Abc_BitWordNum(Gia_ManCiNum(p->pAig)) ); + p->pCexComb->iPo = p->iOut; + p->pCexComb->nPis = Gia_ManCiNum(p->pAig); + p->pCexComb->nBits = Gia_ManCiNum(p->pAig); + for ( i = 0; i < Gia_ManCiNum(p->pAig); i++ ) + { + pInfo = (unsigned *)Vec_PtrEntry( p->vCiSimInfo, i ); + if ( Abc_InfoHasBit( pInfo, iPat ) ) + Abc_InfoSetBit( p->pCexComb->pData, i ); + } +} + +/**Function************************************************************* + + Synopsis [Find the best pattern using the scores.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManSimFindBestPattern( Cec_ManSim_t * p ) +{ + unsigned * pInfo; + int i, ScoreBest = 0, iPatBest = 1; // set the first pattern + // find the best pattern + for ( i = 0; i < 32 * p->nWords; i++ ) + if ( ScoreBest < p->pScores[i] ) + { + ScoreBest = p->pScores[i]; + iPatBest = i; + } + // compare this with the available patterns - and save + if ( p->pBestState->iPo <= ScoreBest ) + { + assert( p->pBestState->nRegs == Gia_ManRegNum(p->pAig) ); + for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) + { + pInfo = (unsigned *)Vec_PtrEntry( p->vCiSimInfo, Gia_ManPiNum(p->pAig) + i ); + if ( Abc_InfoHasBit(p->pBestState->pData, i) != Abc_InfoHasBit(pInfo, iPatBest) ) + Abc_InfoXorBit( p->pBestState->pData, i ); + } + p->pBestState->iPo = ScoreBest; + } +} + +/**Function************************************************************* + + Synopsis [Returns 1 if computation should stop.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManSimAnalyzeOutputs( Cec_ManSim_t * p ) +{ + unsigned * pInfo, * pInfo2; + int i; + if ( !p->pPars->fCheckMiter ) + return 0; + assert( p->vCoSimInfo != NULL ); + // compare outputs with 0 + if ( p->pPars->fDualOut ) + { + assert( (Gia_ManPoNum(p->pAig) & 1) == 0 ); + for ( i = 0; i < Gia_ManPoNum(p->pAig); i++ ) + { + pInfo = (unsigned *)Vec_PtrEntry( p->vCoSimInfo, i ); + pInfo2 = (unsigned *)Vec_PtrEntry( p->vCoSimInfo, ++i ); + if ( !Cec_ManSimCompareEqual( pInfo, pInfo2, p->nWords ) ) + { + if ( p->iOut == -1 ) + { + p->iOut = i/2; + Cec_ManSimSavePattern( p, Cec_ManSimCompareEqualFirstBit(pInfo, pInfo2, p->nWords) ); + } + if ( p->pCexes == NULL ) + p->pCexes = ABC_CALLOC( void *, Gia_ManPoNum(p->pAig)/2 ); + if ( p->pCexes[i/2] == NULL ) + { + p->nOuts++; + p->pCexes[i/2] = (void *)1; + } + } + } + } + else + { + for ( i = 0; i < Gia_ManPoNum(p->pAig); i++ ) + { + pInfo = (unsigned *)Vec_PtrEntry( p->vCoSimInfo, i ); + if ( !Cec_ManSimCompareConst( pInfo, p->nWords ) ) + { + if ( p->iOut == -1 ) + { + p->iOut = i; + Cec_ManSimSavePattern( p, Cec_ManSimCompareConstFirstBit(pInfo, p->nWords) ); + } + if ( p->pCexes == NULL ) + p->pCexes = ABC_CALLOC( void *, Gia_ManPoNum(p->pAig) ); + if ( p->pCexes[i] == NULL ) + { + p->nOuts++; + p->pCexes[i] = (void *)1; + } + } + } + } + return p->pCexes != NULL; +} + +/**Function************************************************************* + + Synopsis [Simulates one round.] + + Description [Returns the number of PO entry if failed; 0 otherwise.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManSimSimulateRound( Cec_ManSim_t * p, Vec_Ptr_t * vInfoCis, Vec_Ptr_t * vInfoCos ) +{ + Gia_Obj_t * pObj; + unsigned * pRes0, * pRes1, * pRes; + int i, k, w, Ent, iCiId = 0, iCoId = 0; + // prepare internal storage + if ( p->nWordsOld != p->nWords ) + Cec_ManSimMemRelink( p ); + p->nMemsMax = 0; + // allocate score counters + ABC_FREE( p->pScores ); + if ( p->pBestState ) + p->pScores = ABC_CALLOC( int, 32 * p->nWords ); + // simulate nodes + Vec_IntClear( p->vRefinedC ); + if ( Gia_ObjValue(Gia_ManConst0(p->pAig)) ) + { + pRes = Cec_ManSimSimRef( p, 0 ); + for ( w = 1; w <= p->nWords; w++ ) + pRes[w] = 0; + } + Gia_ManForEachObj1( p->pAig, pObj, i ) + { + if ( Gia_ObjIsCi(pObj) ) + { + if ( Gia_ObjValue(pObj) == 0 ) + { + iCiId++; + continue; + } + pRes = Cec_ManSimSimRef( p, i ); + if ( vInfoCis ) + { + pRes0 = (unsigned *)Vec_PtrEntry( vInfoCis, iCiId++ ); + for ( w = 1; w <= p->nWords; w++ ) + pRes[w] = pRes0[w-1]; + } + else + { + for ( w = 1; w <= p->nWords; w++ ) + pRes[w] = Gia_ManRandom( 0 ); + } + // make sure the first pattern is always zero + pRes[1] ^= (pRes[1] & 1); + goto references; + } + if ( Gia_ObjIsCo(pObj) ) // co always has non-zero 1st fanin and zero 2nd fanin + { + pRes0 = Cec_ManSimSimDeref( p, Gia_ObjFaninId0(pObj,i) ); + if ( vInfoCos ) + { + pRes = (unsigned *)Vec_PtrEntry( vInfoCos, iCoId++ ); + if ( Gia_ObjFaninC0(pObj) ) + for ( w = 1; w <= p->nWords; w++ ) + pRes[w-1] = ~pRes0[w]; + else + for ( w = 1; w <= p->nWords; w++ ) + pRes[w-1] = pRes0[w]; + } + continue; + } + assert( Gia_ObjValue(pObj) ); + pRes = Cec_ManSimSimRef( p, i ); + pRes0 = Cec_ManSimSimDeref( p, Gia_ObjFaninId0(pObj,i) ); + pRes1 = Cec_ManSimSimDeref( p, Gia_ObjFaninId1(pObj,i) ); + +// Abc_Print( 1, "%d,%d ", Gia_ObjValue( Gia_ObjFanin0(pObj) ), Gia_ObjValue( Gia_ObjFanin1(pObj) ) ); + + if ( Gia_ObjFaninC0(pObj) ) + { + if ( Gia_ObjFaninC1(pObj) ) + for ( w = 1; w <= p->nWords; w++ ) + pRes[w] = ~(pRes0[w] | pRes1[w]); + else + for ( w = 1; w <= p->nWords; w++ ) + pRes[w] = ~pRes0[w] & pRes1[w]; + } + else + { + if ( Gia_ObjFaninC1(pObj) ) + for ( w = 1; w <= p->nWords; w++ ) + pRes[w] = pRes0[w] & ~pRes1[w]; + else + for ( w = 1; w <= p->nWords; w++ ) + pRes[w] = pRes0[w] & pRes1[w]; + } + +references: + // if this node is candidate constant, collect it + if ( Gia_ObjIsConst(p->pAig, i) && !Cec_ManSimCompareConst(pRes + 1, p->nWords) ) + { + pRes[0]++; + Vec_IntPush( p->vRefinedC, i ); + if ( p->pBestState ) + Cec_ManSimCompareConstScore( pRes + 1, p->nWords, p->pScores ); + } + // if the node belongs to a class, save it + if ( Gia_ObjIsClass(p->pAig, i) ) + pRes[0]++; + // if this is the last node of the class, process it + if ( Gia_ObjIsTail(p->pAig, i) ) + { + Vec_IntClear( p->vClassTemp ); + Gia_ClassForEachObj( p->pAig, Gia_ObjRepr(p->pAig, i), Ent ) + Vec_IntPush( p->vClassTemp, Ent ); + Cec_ManSimClassRefineOne( p, Gia_ObjRepr(p->pAig, i) ); + Vec_IntForEachEntry( p->vClassTemp, Ent, k ) + Cec_ManSimSimDeref( p, Ent ); + } + } + + if ( p->pPars->fConstCorr ) + { + Vec_IntForEachEntry( p->vRefinedC, i, k ) + { + Gia_ObjSetRepr( p->pAig, i, GIA_VOID ); + Cec_ManSimSimDeref( p, i ); + } + Vec_IntClear( p->vRefinedC ); + } + + if ( Vec_IntSize(p->vRefinedC) > 0 ) + Cec_ManSimProcessRefined( p, p->vRefinedC ); + assert( vInfoCis == NULL || iCiId == Gia_ManCiNum(p->pAig) ); + assert( vInfoCos == NULL || iCoId == Gia_ManCoNum(p->pAig) ); + assert( p->nMems == 1 ); + if ( p->nMems != 1 ) + Abc_Print( 1, "Cec_ManSimSimulateRound(): Memory management error!\n" ); + if ( p->pPars->fVeryVerbose ) + Gia_ManEquivPrintClasses( p->pAig, 0, Cec_MemUsage(p) ); + if ( p->pBestState ) + Cec_ManSimFindBestPattern( p ); +/* + if ( p->nMems > 1 ) { + for ( i = 1; i < p->nObjs; i++ ) + if ( p->pSims[i] ) { + int x = 0; + } + } +*/ + return Cec_ManSimAnalyzeOutputs( p ); +} + + + +/**Function************************************************************* + + Synopsis [Creates simulation info for this round.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManSimCreateInfo( Cec_ManSim_t * p, Vec_Ptr_t * vInfoCis, Vec_Ptr_t * vInfoCos ) +{ + unsigned * pRes0, * pRes1; + int i, w; + if ( p->pPars->fSeqSimulate && Gia_ManRegNum(p->pAig) > 0 ) + { + assert( vInfoCis && vInfoCos ); + for ( i = 0; i < Gia_ManPiNum(p->pAig); i++ ) + { + pRes0 = (unsigned *)Vec_PtrEntry( vInfoCis, i ); + for ( w = 0; w < p->nWords; w++ ) + pRes0[w] = Gia_ManRandom( 0 ); + } + for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) + { + pRes0 = (unsigned *)Vec_PtrEntry( vInfoCis, Gia_ManPiNum(p->pAig) + i ); + pRes1 = (unsigned *)Vec_PtrEntry( vInfoCos, Gia_ManPoNum(p->pAig) + i ); + for ( w = 0; w < p->nWords; w++ ) + pRes0[w] = pRes1[w]; + } + } + else + { + for ( i = 0; i < Gia_ManCiNum(p->pAig); i++ ) + { + pRes0 = (unsigned *)Vec_PtrEntry( vInfoCis, i ); + for ( w = 0; w < p->nWords; w++ ) + pRes0[w] = Gia_ManRandom( 0 ); + } + } +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the bug is found.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManSimClassesPrepare( Cec_ManSim_t * p, int LevelMax ) +{ + Gia_Obj_t * pObj; + int i; + assert( p->pAig->pReprs == NULL ); + // allocate representation + p->pAig->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p->pAig) ); + p->pAig->pNexts = ABC_CALLOC( int, Gia_ManObjNum(p->pAig) ); + // create references + Gia_ManSetRefs( p->pAig ); + // set starting representative of internal nodes to be constant 0 + if ( p->pPars->fLatchCorr ) + Gia_ManForEachObj( p->pAig, pObj, i ) + Gia_ObjSetRepr( p->pAig, i, GIA_VOID ); + else if ( LevelMax == -1 ) + Gia_ManForEachObj( p->pAig, pObj, i ) + Gia_ObjSetRepr( p->pAig, i, Gia_ObjIsAnd(pObj) ? 0 : GIA_VOID ); + else + { + Gia_ManLevelNum( p->pAig ); + Gia_ManForEachObj( p->pAig, pObj, i ) + Gia_ObjSetRepr( p->pAig, i, (Gia_ObjIsAnd(pObj) && Gia_ObjLevel(p->pAig,pObj) <= LevelMax) ? 0 : GIA_VOID ); + Vec_IntFreeP( &p->pAig->vLevels ); + } + // if sequential simulation, set starting representative of ROs to be constant 0 + if ( p->pPars->fSeqSimulate ) + Gia_ManForEachRo( p->pAig, pObj, i ) + if ( pObj->Value ) + Gia_ObjSetRepr( p->pAig, Gia_ObjId(p->pAig, pObj), 0 ); + // perform simulation + p->nWords = 1; + do { + if ( p->pPars->fVerbose ) + Gia_ManEquivPrintClasses( p->pAig, 0, Cec_MemUsage(p) ); + for ( i = 0; i < 4; i++ ) + { + Cec_ManSimCreateInfo( p, p->vCiSimInfo, p->vCoSimInfo ); + if ( Cec_ManSimSimulateRound( p, p->vCiSimInfo, p->vCoSimInfo ) ) + return 1; + } + p->nWords = 2 * p->nWords + 1; + } + while ( p->nWords <= p->pPars->nWords ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the bug is found.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManSimClassesRefine( Cec_ManSim_t * p ) +{ + int i; + Gia_ManSetRefs( p->pAig ); + p->nWords = p->pPars->nWords; + for ( i = 0; i < p->pPars->nRounds; i++ ) + { + if ( (i % (p->pPars->nRounds / 5)) == 0 && p->pPars->fVerbose ) + Gia_ManEquivPrintClasses( p->pAig, 0, Cec_MemUsage(p) ); + Cec_ManSimCreateInfo( p, p->vCiSimInfo, p->vCoSimInfo ); + if ( Cec_ManSimSimulateRound( p, p->vCiSimInfo, p->vCoSimInfo ) ) + return 1; + } + if ( p->pPars->fVerbose ) + Gia_ManEquivPrintClasses( p->pAig, 0, Cec_MemUsage(p) ); + return 0; +} +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/cec/cecCore.c b/src/proof/cec/cecCore.c new file mode 100644 index 00000000..bf41304b --- /dev/null +++ b/src/proof/cec/cecCore.c @@ -0,0 +1,542 @@ +/**CFile**************************************************************** + + FileName [cecCore.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinational equivalence checking.] + + Synopsis [Core procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cecCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cecInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [This procedure sets default parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManSatSetDefaultParams( Cec_ParSat_t * p ) +{ + memset( p, 0, sizeof(Cec_ParSat_t) ); + p->nBTLimit = 100; // conflict limit at a node + p->nSatVarMax = 2000; // the max number of SAT variables + p->nCallsRecycle = 200; // calls to perform before recycling SAT solver + p->fNonChrono = 0; // use non-chronological backtracling (for circuit SAT only) + p->fPolarFlip = 1; // flops polarity of variables + p->fCheckMiter = 0; // the circuit is the miter +// p->fFirstStop = 0; // stop on the first sat output + p->fLearnCls = 0; // perform clause learning + p->fVerbose = 0; // verbose stats +} + +/**Function************ ************************************************* + + Synopsis [This procedure sets default parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManSimSetDefaultParams( Cec_ParSim_t * p ) +{ + memset( p, 0, sizeof(Cec_ParSim_t) ); + p->nWords = 31; // the number of simulation words + p->nFrames = 100; // the number of simulation frames + p->nRounds = 20; // the max number of simulation rounds + p->nNonRefines = 3; // the max number of rounds without refinement + p->TimeLimit = 0; // the runtime limit in seconds + p->fCheckMiter = 0; // the circuit is the miter +// p->fFirstStop = 0; // stop on the first sat output + p->fDualOut = 0; // miter with separate outputs + p->fConstCorr = 0; // consider only constants + p->fSeqSimulate = 0; // performs sequential simulation + p->fVeryVerbose = 0; // verbose stats + p->fVerbose = 0; // verbose stats +} + +/**Function************ ************************************************* + + Synopsis [This procedure sets default parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManSmfSetDefaultParams( Cec_ParSmf_t * p ) +{ + memset( p, 0, sizeof(Cec_ParSmf_t) ); + p->nWords = 31; // the number of simulation words + p->nRounds = 200; // the number of simulation rounds + p->nFrames = 200; // the max number of time frames + p->nNonRefines = 3; // the max number of rounds without refinement + p->nMinOutputs = 0; // the min outputs to accumulate + p->nBTLimit = 100; // conflict limit at a node + p->TimeLimit = 0; // the runtime limit in seconds + p->fDualOut = 0; // miter with separate outputs + p->fCheckMiter = 0; // the circuit is the miter +// p->fFirstStop = 0; // stop on the first sat output + p->fVerbose = 0; // verbose stats +} + +/**Function************ ************************************************* + + Synopsis [This procedure sets default parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManFraSetDefaultParams( Cec_ParFra_t * p ) +{ + memset( p, 0, sizeof(Cec_ParFra_t) ); + p->nWords = 15; // the number of simulation words + p->nRounds = 15; // the number of simulation rounds + p->TimeLimit = 0; // the runtime limit in seconds + p->nItersMax = 10; // the maximum number of iterations of SAT sweeping + p->nBTLimit = 100; // conflict limit at a node + p->nLevelMax = 0; // restriction on the level of nodes to be swept + p->nDepthMax = 1; // the depth in terms of steps of speculative reduction + p->fRewriting = 0; // enables AIG rewriting + p->fCheckMiter = 0; // the circuit is the miter +// p->fFirstStop = 0; // stop on the first sat output + p->fDualOut = 0; // miter with separate outputs + p->fColorDiff = 0; // miter with separate outputs + p->fSatSweeping = 0; // enable SAT sweeping + p->fVeryVerbose = 0; // verbose stats + p->fVerbose = 0; // verbose stats + p->iOutFail = -1; // the failed output +} + +/**Function************************************************************* + + Synopsis [This procedure sets default parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManCecSetDefaultParams( Cec_ParCec_t * p ) +{ + memset( p, 0, sizeof(Cec_ParCec_t) ); + p->nBTLimit = 1000; // conflict limit at a node + p->TimeLimit = 0; // the runtime limit in seconds +// p->fFirstStop = 0; // stop on the first sat output + p->fUseSmartCnf = 0; // use smart CNF computation + p->fRewriting = 0; // enables AIG rewriting + p->fVeryVerbose = 0; // verbose stats + p->fVerbose = 0; // verbose stats + p->iOutFail = -1; // the number of failed output +} + +/**Function************************************************************* + + Synopsis [This procedure sets default parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManCorSetDefaultParams( Cec_ParCor_t * p ) +{ + memset( p, 0, sizeof(Cec_ParCor_t) ); + p->nWords = 15; // the number of simulation words + p->nRounds = 15; // the number of simulation rounds + p->nFrames = 1; // the number of time frames + p->nBTLimit = 100; // conflict limit at a node + p->nLevelMax = -1; // (scorr only) the max number of levels + p->nStepsMax = -1; // (scorr only) the max number of induction steps + p->fLatchCorr = 0; // consider only latch outputs + p->fConstCorr = 0; // consider only constants + p->fUseRings = 1; // combine classes into rings + p->fUseCSat = 1; // use circuit-based solver +// p->fFirstStop = 0; // stop on the first sat output + p->fUseSmartCnf = 0; // use smart CNF computation + p->fVeryVerbose = 0; // verbose stats + p->fVerbose = 0; // verbose stats +} + +/**Function************************************************************* + + Synopsis [This procedure sets default parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManChcSetDefaultParams( Cec_ParChc_t * p ) +{ + memset( p, 0, sizeof(Cec_ParChc_t) ); + p->nWords = 15; // the number of simulation words + p->nRounds = 15; // the number of simulation rounds + p->nBTLimit = 1000; // conflict limit at a node + p->fUseRings = 1; // use rings + p->fUseCSat = 0; // use circuit-based solver + p->fVeryVerbose = 0; // verbose stats + p->fVerbose = 0; // verbose stats +} + +/**Function************************************************************* + + Synopsis [Core procedure for SAT sweeping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Cec_ManSatSolving( Gia_Man_t * pAig, Cec_ParSat_t * pPars ) +{ + Gia_Man_t * pNew; + Cec_ManPat_t * pPat; + pPat = Cec_ManPatStart(); + Cec_ManSatSolve( pPat, pAig, pPars ); +// pNew = Gia_ManDupDfsSkip( pAig ); + pNew = Gia_ManDup( pAig ); + Cec_ManPatStop( pPat ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Core procedure for simulation.] + + Description [Returns 1 if refinement has happened.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManSimulationOne( Gia_Man_t * pAig, Cec_ParSim_t * pPars ) +{ + Cec_ManSim_t * pSim; + int RetValue = 0, clkTotal = clock(); + pSim = Cec_ManSimStart( pAig, pPars ); + if ( (pAig->pReprs == NULL && (RetValue = Cec_ManSimClassesPrepare( pSim, -1 ))) || + (RetValue == 0 && (RetValue = Cec_ManSimClassesRefine( pSim ))) ) + Abc_Print( 1, "The number of failed outputs of the miter = %6d. (Words = %4d. Frames = %4d.)\n", + pSim->nOuts, pPars->nWords, pPars->nFrames ); + if ( pPars->fVerbose ) + Abc_PrintTime( 1, "Time", clock() - clkTotal ); + Cec_ManSimStop( pSim ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Core procedure for simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManSimulation( Gia_Man_t * pAig, Cec_ParSim_t * pPars ) +{ + int r, nLitsOld, nLitsNew, nCountNoRef = 0, fStop = 0; + Gia_ManRandom( 1 ); + if ( pPars->fSeqSimulate ) + Abc_Print( 1, "Performing rounds of random simulation of %d frames with %d words.\n", + pPars->nRounds, pPars->nFrames, pPars->nWords ); + nLitsOld = Gia_ManEquivCountLits( pAig ); + for ( r = 0; r < pPars->nRounds; r++ ) + { + if ( Cec_ManSimulationOne( pAig, pPars ) ) + { + fStop = 1; + break; + } + // decide when to stop + nLitsNew = Gia_ManEquivCountLits( pAig ); + if ( nLitsOld == 0 || nLitsOld > nLitsNew ) + { + nLitsOld = nLitsNew; + nCountNoRef = 0; + } + else if ( ++nCountNoRef == pPars->nNonRefines ) + { + r++; + break; + } + assert( nLitsOld == nLitsNew ); + } +// if ( pPars->fVerbose ) + if ( r == pPars->nRounds || fStop ) + Abc_Print( 1, "Random simulation is stopped after %d rounds.\n", r ); + else + Abc_Print( 1, "Random simulation saturated after %d rounds.\n", r ); + if ( pPars->fCheckMiter ) + { + int nNonConsts = Cec_ManCountNonConstOutputs( pAig ); + if ( nNonConsts ) + Abc_Print( 1, "The number of POs that are not const-0 candidates = %d.\n", nNonConsts ); + } +} + +/**Function************************************************************* + + Synopsis [Core procedure for SAT sweeping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Cec_ManSatSweeping( Gia_Man_t * pAig, Cec_ParFra_t * pPars ) +{ + int fOutputResult = 0; + Cec_ParSat_t ParsSat, * pParsSat = &ParsSat; + Cec_ParSim_t ParsSim, * pParsSim = &ParsSim; + Gia_Man_t * pIni, * pSrm, * pTemp; + Cec_ManFra_t * p; + Cec_ManSim_t * pSim; + Cec_ManPat_t * pPat; + int i, fTimeOut = 0, nMatches = 0, clk, clk2; + double clkTotal = clock(); + + // duplicate AIG and transfer equivalence classes + Gia_ManRandom( 1 ); + pIni = Gia_ManDup(pAig); + pIni->pReprs = pAig->pReprs; pAig->pReprs = NULL; + pIni->pNexts = pAig->pNexts; pAig->pNexts = NULL; + + // prepare the managers + // SAT sweeping + p = Cec_ManFraStart( pIni, pPars ); + if ( pPars->fDualOut ) + pPars->fColorDiff = 1; + // simulation + Cec_ManSimSetDefaultParams( pParsSim ); + pParsSim->nWords = pPars->nWords; + pParsSim->nFrames = pPars->nRounds; + pParsSim->fCheckMiter = pPars->fCheckMiter; + pParsSim->fDualOut = pPars->fDualOut; + pParsSim->fVerbose = pPars->fVerbose; + pSim = Cec_ManSimStart( p->pAig, pParsSim ); + // SAT solving + Cec_ManSatSetDefaultParams( pParsSat ); + pParsSat->nBTLimit = pPars->nBTLimit; + pParsSat->fVerbose = pPars->fVeryVerbose; + // simulation patterns + pPat = Cec_ManPatStart(); + pPat->fVerbose = pPars->fVeryVerbose; + + // start equivalence classes +clk = clock(); + if ( p->pAig->pReprs == NULL ) + { + if ( Cec_ManSimClassesPrepare(pSim, -1) || Cec_ManSimClassesRefine(pSim) ) + { + Gia_ManStop( p->pAig ); + p->pAig = NULL; + goto finalize; + } + } +p->timeSim += clock() - clk; + // perform solving + for ( i = 1; i <= pPars->nItersMax; i++ ) + { + clk2 = clock(); + nMatches = 0; + if ( pPars->fDualOut ) + { + nMatches = Gia_ManEquivSetColors( p->pAig, pPars->fVeryVerbose ); +// p->pAig->pIso = Cec_ManDetectIsomorphism( p->pAig ); +// Gia_ManEquivTransform( p->pAig, 1 ); + } + pSrm = Cec_ManFraSpecReduction( p ); + +// Gia_WriteAiger( pSrm, "gia_srm.aig", 0, 0 ); + + if ( pPars->fVeryVerbose ) + Gia_ManPrintStats( pSrm, 0 ); + if ( Gia_ManCoNum(pSrm) == 0 ) + { + Gia_ManStop( pSrm ); + if ( p->pPars->fVerbose ) + Abc_Print( 1, "Considered all available candidate equivalences.\n" ); + if ( pPars->fDualOut && Gia_ManAndNum(p->pAig) > 0 ) + { + if ( pPars->fColorDiff ) + { + if ( p->pPars->fVerbose ) + Abc_Print( 1, "Switching into reduced mode.\n" ); + pPars->fColorDiff = 0; + } + else + { + if ( p->pPars->fVerbose ) + Abc_Print( 1, "Switching into normal mode.\n" ); + pPars->fDualOut = 0; + } + continue; + } + break; + } +clk = clock(); + Cec_ManSatSolve( pPat, pSrm, pParsSat ); +p->timeSat += clock() - clk; + if ( Cec_ManFraClassesUpdate( p, pSim, pPat, pSrm ) ) + { + Gia_ManStop( pSrm ); + Gia_ManStop( p->pAig ); + p->pAig = NULL; + goto finalize; + } + Gia_ManStop( pSrm ); + + // update the manager + pSim->pAig = p->pAig = Gia_ManEquivReduceAndRemap( pTemp = p->pAig, 0, pParsSim->fDualOut ); + if ( p->pAig == NULL ) + { + p->pAig = pTemp; + break; + } + Gia_ManStop( pTemp ); + if ( p->pPars->fVerbose ) + { + Abc_Print( 1, "%3d : P =%7d. D =%7d. F =%6d. M = %7d. And =%8d. ", + i, p->nAllProved, p->nAllDisproved, p->nAllFailed, nMatches, Gia_ManAndNum(p->pAig) ); + Abc_PrintTime( 1, "Time", clock() - clk2 ); + } + if ( Gia_ManAndNum(p->pAig) == 0 ) + { + if ( p->pPars->fVerbose ) + Abc_Print( 1, "Network after reduction is empty.\n" ); + break; + } + // check resource limits + if ( p->pPars->TimeLimit && ((double)clock() - clkTotal)/CLOCKS_PER_SEC >= p->pPars->TimeLimit ) + { + fTimeOut = 1; + break; + } +// if ( p->nAllFailed && !p->nAllProved && !p->nAllDisproved ) + if ( p->nAllFailed > p->nAllProved + p->nAllDisproved ) + { + if ( pParsSat->nBTLimit >= 10001 ) + break; + if ( pPars->fSatSweeping ) + { + if ( p->pPars->fVerbose ) + Abc_Print( 1, "Exceeded the limit on the number of conflicts (%d).\n", pParsSat->nBTLimit ); + break; + } + pParsSat->nBTLimit *= 10; + if ( p->pPars->fVerbose ) + { + if ( p->pPars->fVerbose ) + Abc_Print( 1, "Increasing conflict limit to %d.\n", pParsSat->nBTLimit ); + if ( fOutputResult ) + { + Gia_WriteAiger( p->pAig, "gia_cec_temp.aig", 0, 0 ); + Abc_Print( 1,"The result is written into file \"%s\".\n", "gia_cec_temp.aig" ); + } + } + } + if ( pPars->fDualOut && pPars->fColorDiff && (Gia_ManAndNum(p->pAig) < 100000 || p->nAllProved + p->nAllDisproved < 10) ) + { + if ( p->pPars->fVerbose ) + Abc_Print( 1, "Switching into reduced mode.\n" ); + pPars->fColorDiff = 0; + } +// if ( pPars->fDualOut && Gia_ManAndNum(p->pAig) < 20000 ) + else if ( pPars->fDualOut && (Gia_ManAndNum(p->pAig) < 20000 || p->nAllProved + p->nAllDisproved < 10) ) + { + if ( p->pPars->fVerbose ) + Abc_Print( 1, "Switching into normal mode.\n" ); + pPars->fColorDiff = 0; + pPars->fDualOut = 0; + } + } +finalize: + if ( p->pPars->fVerbose && p->pAig ) + { + Abc_Print( 1, "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n", + Gia_ManAndNum(pAig), Gia_ManAndNum(p->pAig), + 100.0*(Gia_ManAndNum(pAig)-Gia_ManAndNum(p->pAig))/(Gia_ManAndNum(pAig)?Gia_ManAndNum(pAig):1), + Gia_ManRegNum(pAig), Gia_ManRegNum(p->pAig), + 100.0*(Gia_ManRegNum(pAig)-Gia_ManRegNum(p->pAig))/(Gia_ManRegNum(pAig)?Gia_ManRegNum(pAig):1) ); + Abc_PrintTimeP( 1, "Sim ", p->timeSim, clock() - (int)clkTotal ); + Abc_PrintTimeP( 1, "Sat ", p->timeSat-pPat->timeTotalSave, clock() - (int)clkTotal ); + Abc_PrintTimeP( 1, "Pat ", p->timePat+pPat->timeTotalSave, clock() - (int)clkTotal ); + Abc_PrintTime( 1, "Time", (int)(clock() - clkTotal) ); + } + + pTemp = p->pAig; p->pAig = NULL; + if ( pTemp == NULL && pSim->iOut >= 0 ) + { + Abc_Print( 1, "Disproved at least one output of the miter (zero-based number %d).\n", pSim->iOut ); + pPars->iOutFail = pSim->iOut; + } + else if ( pSim->pCexes ) + Abc_Print( 1, "Disproved %d outputs of the miter.\n", pSim->nOuts ); + if ( fTimeOut ) + Abc_Print( 1, "Timed out after %d seconds.\n", (int)((double)clock() - clkTotal)/CLOCKS_PER_SEC ); + + pAig->pCexComb = pSim->pCexComb; pSim->pCexComb = NULL; + Cec_ManSimStop( pSim ); + Cec_ManPatStop( pPat ); + Cec_ManFraStop( p ); + return pTemp; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/cec/cecCorr.c b/src/proof/cec/cecCorr.c new file mode 100644 index 00000000..6f3ce785 --- /dev/null +++ b/src/proof/cec/cecCorr.c @@ -0,0 +1,1137 @@ +/**CFile**************************************************************** + + FileName [cecCorr.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinational equivalence checking.] + + Synopsis [Latch/signal correspondence computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cecCorr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cecInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Gia_ManCorrSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes the real value of the literal w/o spec reduction.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_ManCorrSpecReal( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix ) +{ + if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ManCorrSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj), f, nPrefix ); + Gia_ManCorrSpecReduce_rec( pNew, p, Gia_ObjFanin1(pObj), f, nPrefix ); + return Gia_ManHashAnd( pNew, Gia_ObjFanin0CopyF(p, f, pObj), Gia_ObjFanin1CopyF(p, f, pObj) ); + } + if ( f == 0 ) + { + assert( Gia_ObjIsRo(p, pObj) ); + return Gia_ObjCopyF(p, f, pObj); + } + assert( f && Gia_ObjIsRo(p, pObj) ); + pObj = Gia_ObjRoToRi( p, pObj ); + Gia_ManCorrSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj), f-1, nPrefix ); + return Gia_ObjFanin0CopyF( p, f-1, pObj ); +} + +/**Function************************************************************* + + Synopsis [Recursively performs speculative reduction for the object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCorrSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix ) +{ + Gia_Obj_t * pRepr; + int iLitNew; + if ( ~Gia_ObjCopyF(p, f, pObj) ) + return; + if ( f >= nPrefix && (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) + { + Gia_ManCorrSpecReduce_rec( pNew, p, pRepr, f, nPrefix ); + iLitNew = Abc_LitNotCond( Gia_ObjCopyF(p, f, pRepr), Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); + Gia_ObjSetCopyF( p, f, pObj, iLitNew ); + return; + } + assert( Gia_ObjIsCand(pObj) ); + iLitNew = Gia_ManCorrSpecReal( pNew, p, pObj, f, nPrefix ); + Gia_ObjSetCopyF( p, f, pObj, iLitNew ); +} + +/**Function************************************************************* + + Synopsis [Derives SRM for signal correspondence.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManCorrSpecReduce( Gia_Man_t * p, int nFrames, int fScorr, Vec_Int_t ** pvOutputs, int fRings ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pRepr; + Vec_Int_t * vXorLits; + int f, i, iPrev, iObj, iPrevNew, iObjNew; + assert( nFrames > 0 ); + assert( Gia_ManRegNum(p) > 0 ); + assert( p->pReprs != NULL ); + p->pCopies = ABC_FALLOC( int, (nFrames+fScorr)*Gia_ManObjNum(p) ); + Gia_ManSetPhase( p ); + pNew = Gia_ManStart( nFrames * Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManHashAlloc( pNew ); + Gia_ObjSetCopyF( p, 0, Gia_ManConst0(p), 0 ); + Gia_ManForEachRo( p, pObj, i ) + Gia_ObjSetCopyF( p, 0, pObj, Gia_ManAppendCi(pNew) ); + Gia_ManForEachRo( p, pObj, i ) + if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) + Gia_ObjSetCopyF( p, 0, pObj, Gia_ObjCopyF(p, 0, pRepr) ); + for ( f = 0; f < nFrames+fScorr; f++ ) + { + Gia_ObjSetCopyF( p, f, Gia_ManConst0(p), 0 ); + Gia_ManForEachPi( p, pObj, i ) + Gia_ObjSetCopyF( p, f, pObj, Gia_ManAppendCi(pNew) ); + } + *pvOutputs = Vec_IntAlloc( 1000 ); + vXorLits = Vec_IntAlloc( 1000 ); + if ( fRings ) + { + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsConst( p, i ) ) + { + iObjNew = Gia_ManCorrSpecReal( pNew, p, pObj, nFrames, 0 ); + iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ); + if ( iObjNew != 0 ) + { + Vec_IntPush( *pvOutputs, 0 ); + Vec_IntPush( *pvOutputs, i ); + Vec_IntPush( vXorLits, iObjNew ); + } + } + else if ( Gia_ObjIsHead( p, i ) ) + { + iPrev = i; + Gia_ClassForEachObj1( p, i, iObj ) + { + iPrevNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iPrev), nFrames, 0 ); + iObjNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iObj), nFrames, 0 ); + iPrevNew = Abc_LitNotCond( iPrevNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) ); + iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) ); + if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 ) + { + Vec_IntPush( *pvOutputs, iPrev ); + Vec_IntPush( *pvOutputs, iObj ); + Vec_IntPush( vXorLits, Gia_ManHashAnd(pNew, iPrevNew, Abc_LitNot(iObjNew)) ); + } + iPrev = iObj; + } + iObj = i; + iPrevNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iPrev), nFrames, 0 ); + iObjNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iObj), nFrames, 0 ); + iPrevNew = Abc_LitNotCond( iPrevNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) ); + iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) ); + if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 ) + { + Vec_IntPush( *pvOutputs, iPrev ); + Vec_IntPush( *pvOutputs, iObj ); + Vec_IntPush( vXorLits, Gia_ManHashAnd(pNew, iPrevNew, Abc_LitNot(iObjNew)) ); + } + } + } + } + else + { + Gia_ManForEachObj1( p, pObj, i ) + { + pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); + if ( pRepr == NULL ) + continue; + iPrevNew = Gia_ObjIsConst(p, i)? 0 : Gia_ManCorrSpecReal( pNew, p, pRepr, nFrames, 0 ); + iObjNew = Gia_ManCorrSpecReal( pNew, p, pObj, nFrames, 0 ); + iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); + if ( iPrevNew != iObjNew ) + { + Vec_IntPush( *pvOutputs, Gia_ObjId(p, pRepr) ); + Vec_IntPush( *pvOutputs, Gia_ObjId(p, pObj) ); + Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, iPrevNew, iObjNew) ); + } + } + } + Vec_IntForEachEntry( vXorLits, iObjNew, i ) + Gia_ManAppendCo( pNew, iObjNew ); + Vec_IntFree( vXorLits ); + Gia_ManHashStop( pNew ); + ABC_FREE( p->pCopies ); +//Abc_Print( 1, "Before sweeping = %d\n", Gia_ManAndNum(pNew) ); + pNew = Gia_ManCleanup( pTemp = pNew ); +//Abc_Print( 1, "After sweeping = %d\n", Gia_ManAndNum(pNew) ); + Gia_ManStop( pTemp ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Derives SRM for signal correspondence.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManCorrSpecReduceInit( Gia_Man_t * p, int nFrames, int nPrefix, int fScorr, Vec_Int_t ** pvOutputs, int fRings ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pRepr; + Vec_Int_t * vXorLits; + int f, i, iPrevNew, iObjNew; + assert( (!fScorr && nFrames > 1) || (fScorr && nFrames > 0) || nPrefix ); + assert( Gia_ManRegNum(p) > 0 ); + assert( p->pReprs != NULL ); + p->pCopies = ABC_FALLOC( int, (nFrames+nPrefix+fScorr)*Gia_ManObjNum(p) ); + Gia_ManSetPhase( p ); + pNew = Gia_ManStart( (nFrames+nPrefix) * Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachRo( p, pObj, i ) + { + Gia_ManAppendCi(pNew); + Gia_ObjSetCopyF( p, 0, pObj, 0 ); + } + for ( f = 0; f < nFrames+nPrefix+fScorr; f++ ) + { + Gia_ObjSetCopyF( p, f, Gia_ManConst0(p), 0 ); + Gia_ManForEachPi( p, pObj, i ) + Gia_ObjSetCopyF( p, f, pObj, Gia_ManAppendCi(pNew) ); + } + *pvOutputs = Vec_IntAlloc( 1000 ); + vXorLits = Vec_IntAlloc( 1000 ); + for ( f = nPrefix; f < nFrames+nPrefix; f++ ) + { + Gia_ManForEachObj1( p, pObj, i ) + { + pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); + if ( pRepr == NULL ) + continue; + iPrevNew = Gia_ObjIsConst(p, i)? 0 : Gia_ManCorrSpecReal( pNew, p, pRepr, f, nPrefix ); + iObjNew = Gia_ManCorrSpecReal( pNew, p, pObj, f, nPrefix ); + iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); + if ( iPrevNew != iObjNew ) + { + Vec_IntPush( *pvOutputs, Gia_ObjId(p, pRepr) ); + Vec_IntPush( *pvOutputs, Gia_ObjId(p, pObj) ); + Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, iPrevNew, iObjNew) ); + } + } + } + Vec_IntForEachEntry( vXorLits, iObjNew, i ) + Gia_ManAppendCo( pNew, iObjNew ); + Vec_IntFree( vXorLits ); + Gia_ManHashStop( pNew ); + ABC_FREE( p->pCopies ); +//Abc_Print( 1, "Before sweeping = %d\n", Gia_ManAndNum(pNew) ); + pNew = Gia_ManCleanup( pTemp = pNew ); +//Abc_Print( 1, "After sweeping = %d\n", Gia_ManAndNum(pNew) ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Initializes simulation info for lcorr/scorr counter-examples.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManStartSimInfo( Vec_Ptr_t * vInfo, int nFlops ) +{ + unsigned * pInfo; + int k, w, nWords; + nWords = Vec_PtrReadWordsSimInfo( vInfo ); + assert( nFlops <= Vec_PtrSize(vInfo) ); + for ( k = 0; k < nFlops; k++ ) + { + pInfo = (unsigned *)Vec_PtrEntry( vInfo, k ); + for ( w = 0; w < nWords; w++ ) + pInfo[w] = 0; + } + for ( k = nFlops; k < Vec_PtrSize(vInfo); k++ ) + { + pInfo = (unsigned *)Vec_PtrEntry( vInfo, k ); + for ( w = 0; w < nWords; w++ ) + pInfo[w] = Gia_ManRandom( 0 ); + } +} + +/**Function************************************************************* + + Synopsis [Remaps simulation info from SRM to the original AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCorrRemapSimInfo( Gia_Man_t * p, Vec_Ptr_t * vInfo ) +{ + Gia_Obj_t * pObj, * pRepr; + unsigned * pInfoObj, * pInfoRepr; + int i, w, nWords; + nWords = Vec_PtrReadWordsSimInfo( vInfo ); + Gia_ManForEachRo( p, pObj, i ) + { + // skip ROs without representatives + pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); + if ( pRepr == NULL || Gia_ObjFailed(p, Gia_ObjId(p,pObj)) ) + continue; + pInfoObj = (unsigned *)Vec_PtrEntry( vInfo, i ); + for ( w = 0; w < nWords; w++ ) + assert( pInfoObj[w] == 0 ); + // skip ROs with constant representatives + if ( Gia_ObjIsConst0(pRepr) ) + continue; + assert( Gia_ObjIsRo(p, pRepr) ); +// Abc_Print( 1, "%d -> %d ", i, Gia_ObjId(p, pRepr) ); + // transfer info from the representative + pInfoRepr = (unsigned *)Vec_PtrEntry( vInfo, Gia_ObjCioId(pRepr) - Gia_ManPiNum(p) ); + for ( w = 0; w < nWords; w++ ) + pInfoObj[w] = pInfoRepr[w]; + } +// Abc_Print( 1, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Collects information about remapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManCorrCreateRemapping( Gia_Man_t * p ) +{ + Vec_Int_t * vPairs; + Gia_Obj_t * pObj, * pRepr; + int i; + vPairs = Vec_IntAlloc( 100 ); + Gia_ManForEachRo( p, pObj, i ) + { + // skip ROs without representatives + pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); + if ( pRepr == NULL || Gia_ObjIsConst0(pRepr) || Gia_ObjFailed(p, Gia_ObjId(p,pObj)) ) +// if ( pRepr == NULL || Gia_ObjIsConst0(pRepr) || Gia_ObjIsFailedPair(p, Gia_ObjId(p, pRepr), Gia_ObjId(p, pObj)) ) + continue; + assert( Gia_ObjIsRo(p, pRepr) ); +// Abc_Print( 1, "%d -> %d ", Gia_ObjId(p,pObj), Gia_ObjId(p, pRepr) ); + // remember the pair + Vec_IntPush( vPairs, Gia_ObjCioId(pRepr) - Gia_ManPiNum(p) ); + Vec_IntPush( vPairs, i ); + } + return vPairs; +} + +/**Function************************************************************* + + Synopsis [Remaps simulation info from SRM to the original AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCorrPerformRemapping( Vec_Int_t * vPairs, Vec_Ptr_t * vInfo ) +{ + unsigned * pInfoObj, * pInfoRepr; + int w, i, iObj, iRepr, nWords; + nWords = Vec_PtrReadWordsSimInfo( vInfo ); + Vec_IntForEachEntry( vPairs, iRepr, i ) + { + iObj = Vec_IntEntry( vPairs, ++i ); + pInfoObj = (unsigned *)Vec_PtrEntry( vInfo, iObj ); + pInfoRepr = (unsigned *)Vec_PtrEntry( vInfo, iRepr ); + for ( w = 0; w < nWords; w++ ) + { + assert( pInfoObj[w] == 0 ); + pInfoObj[w] = pInfoRepr[w]; + } + } +} + +/**Function************************************************************* + + Synopsis [Packs one counter-examples into the array of simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +*************************************`**********************************/ +int Cec_ManLoadCounterExamplesTry( Vec_Ptr_t * vInfo, Vec_Ptr_t * vPres, int iBit, int * pLits, int nLits ) +{ + unsigned * pInfo, * pPres; + int i; + for ( i = 0; i < nLits; i++ ) + { + pInfo = (unsigned *)Vec_PtrEntry(vInfo, Abc_Lit2Var(pLits[i])); + pPres = (unsigned *)Vec_PtrEntry(vPres, Abc_Lit2Var(pLits[i])); + if ( Abc_InfoHasBit( pPres, iBit ) && + Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(pLits[i]) ) + return 0; + } + for ( i = 0; i < nLits; i++ ) + { + pInfo = (unsigned *)Vec_PtrEntry(vInfo, Abc_Lit2Var(pLits[i])); + pPres = (unsigned *)Vec_PtrEntry(vPres, Abc_Lit2Var(pLits[i])); + Abc_InfoSetBit( pPres, iBit ); + if ( Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(pLits[i]) ) + Abc_InfoXorBit( pInfo, iBit ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Performs bitpacking of counter-examples.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManLoadCounterExamples( Vec_Ptr_t * vInfo, Vec_Int_t * vCexStore, int iStart ) +{ + Vec_Int_t * vPat; + Vec_Ptr_t * vPres; + int nWords = Vec_PtrReadWordsSimInfo(vInfo); + int nBits = 32 * nWords; + int k, nSize, iBit = 1, kMax = 0; + vPat = Vec_IntAlloc( 100 ); + vPres = Vec_PtrAllocSimInfo( Vec_PtrSize(vInfo), nWords ); + Vec_PtrCleanSimInfo( vPres, 0, nWords ); + while ( iStart < Vec_IntSize(vCexStore) ) + { + // skip the output number + iStart++; + // get the number of items + nSize = Vec_IntEntry( vCexStore, iStart++ ); + if ( nSize <= 0 ) + continue; + // extract pattern + Vec_IntClear( vPat ); + for ( k = 0; k < nSize; k++ ) + Vec_IntPush( vPat, Vec_IntEntry( vCexStore, iStart++ ) ); + // add pattern to storage + for ( k = 1; k < nBits; k++ ) + if ( Cec_ManLoadCounterExamplesTry( vInfo, vPres, k, (int *)Vec_IntArray(vPat), Vec_IntSize(vPat) ) ) + break; + kMax = Abc_MaxInt( kMax, k ); + if ( k == nBits-1 ) + break; + } + Vec_PtrFree( vPres ); + Vec_IntFree( vPat ); + return iStart; +} + +/**Function************************************************************* + + Synopsis [Performs bitpacking of counter-examples.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManLoadCounterExamples2( Vec_Ptr_t * vInfo, Vec_Int_t * vCexStore, int iStart ) +{ + unsigned * pInfo; + int nBits = 32 * Vec_PtrReadWordsSimInfo(vInfo); + int k, iLit, nLits, Out, iBit = 1; + while ( iStart < Vec_IntSize(vCexStore) ) + { + // skip the output number +// iStart++; + Out = Vec_IntEntry( vCexStore, iStart++ ); +// Abc_Print( 1, "iBit = %d. Out = %d.\n", iBit, Out ); + // get the number of items + nLits = Vec_IntEntry( vCexStore, iStart++ ); + if ( nLits <= 0 ) + continue; + // add pattern to storage + for ( k = 0; k < nLits; k++ ) + { + iLit = Vec_IntEntry( vCexStore, iStart++ ); + pInfo = (unsigned *)Vec_PtrEntry( vInfo, Abc_Lit2Var(iLit) ); + if ( Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(iLit) ) + Abc_InfoXorBit( pInfo, iBit ); + } + if ( ++iBit == nBits ) + break; + } +// Abc_Print( 1, "added %d bits\n", iBit-1 ); + return iStart; +} + +/**Function************************************************************* + + Synopsis [Resimulates counter-examples derived by the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManResimulateCounterExamples( Cec_ManSim_t * pSim, Vec_Int_t * vCexStore, int nFrames ) +{ + Vec_Int_t * vPairs; + Vec_Ptr_t * vSimInfo; + int RetValue = 0, iStart = 0; + vPairs = Gia_ManCorrCreateRemapping( pSim->pAig ); + Gia_ManSetRefs( pSim->pAig ); +// pSim->pPars->nWords = 63; + pSim->pPars->nFrames = nFrames; + vSimInfo = Vec_PtrAllocSimInfo( Gia_ManRegNum(pSim->pAig) + Gia_ManPiNum(pSim->pAig) * nFrames, pSim->pPars->nWords ); + while ( iStart < Vec_IntSize(vCexStore) ) + { + Cec_ManStartSimInfo( vSimInfo, Gia_ManRegNum(pSim->pAig) ); + iStart = Cec_ManLoadCounterExamples( vSimInfo, vCexStore, iStart ); +// iStart = Cec_ManLoadCounterExamples2( vSimInfo, vCexStore, iStart ); +// Gia_ManCorrRemapSimInfo( pSim->pAig, vSimInfo ); + Gia_ManCorrPerformRemapping( vPairs, vSimInfo ); + RetValue |= Cec_ManSeqResimulate( pSim, vSimInfo ); +// Cec_ManSeqResimulateInfo( pSim->pAig, vSimInfo, NULL ); + } +//Gia_ManEquivPrintOne( pSim->pAig, 85, 0 ); + assert( iStart == Vec_IntSize(vCexStore) ); + Vec_PtrFree( vSimInfo ); + Vec_IntFree( vPairs ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Resimulates counter-examples derived by the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManResimulateCounterExamplesComb( Cec_ManSim_t * pSim, Vec_Int_t * vCexStore ) +{ + Vec_Ptr_t * vSimInfo; + int RetValue = 0, iStart = 0; + Gia_ManSetRefs( pSim->pAig ); + pSim->pPars->nFrames = 1; + vSimInfo = Vec_PtrAllocSimInfo( Gia_ManCiNum(pSim->pAig), pSim->pPars->nWords ); + while ( iStart < Vec_IntSize(vCexStore) ) + { + Cec_ManStartSimInfo( vSimInfo, 0 ); + iStart = Cec_ManLoadCounterExamples( vSimInfo, vCexStore, iStart ); + RetValue |= Cec_ManSeqResimulate( pSim, vSimInfo ); + } + assert( iStart == Vec_IntSize(vCexStore) ); + Vec_PtrFree( vSimInfo ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Updates equivalence classes by marking those that timed out.] + + Description [Returns 1 if all ndoes are proved.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCheckRefinements( Gia_Man_t * p, Vec_Str_t * vStatus, Vec_Int_t * vOutputs, Cec_ManSim_t * pSim, int fRings ) +{ + int i, status, iRepr, iObj; + int Counter = 0; + assert( 2 * Vec_StrSize(vStatus) == Vec_IntSize(vOutputs) ); + Vec_StrForEachEntry( vStatus, status, i ) + { + iRepr = Vec_IntEntry( vOutputs, 2*i ); + iObj = Vec_IntEntry( vOutputs, 2*i+1 ); + if ( status == 1 ) + continue; + if ( status == 0 ) + { + if ( Gia_ObjHasSameRepr(p, iRepr, iObj) ) + Counter++; +// if ( Gia_ObjHasSameRepr(p, iRepr, iObj) ) +// Abc_Print( 1, "Gia_ManCheckRefinements(): Disproved equivalence (%d,%d) is not refined!\n", iRepr, iObj ); +// if ( Gia_ObjHasSameRepr(p, iRepr, iObj) ) +// Cec_ManSimClassRemoveOne( pSim, iObj ); + continue; + } + if ( status == -1 ) + { +// if ( !Gia_ObjFailed( p, iObj ) ) +// Abc_Print( 1, "Gia_ManCheckRefinements(): Failed equivalence is not marked as failed!\n" ); +// Gia_ObjSetFailed( p, iRepr ); +// Gia_ObjSetFailed( p, iObj ); +// if ( fRings ) +// Cec_ManSimClassRemoveOne( pSim, iRepr ); + Cec_ManSimClassRemoveOne( pSim, iObj ); + continue; + } + } +// if ( Counter ) +// Abc_Print( 1, "Gia_ManCheckRefinements(): Could not refine %d nodes.\n", Counter ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Duplicates the AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCorrReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + Gia_Obj_t * pRepr; + if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) + { + Gia_ManCorrReduce_rec( pNew, p, pRepr ); + pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); + return; + } + if ( ~pObj->Value ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManCorrReduce_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManCorrReduce_rec( pNew, p, Gia_ObjFanin1(pObj) ); + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Reduces AIG using equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManCorrReduce( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + Gia_ManSetPhase( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManCorrReduce_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Prints statistics during solving.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManRefinedClassPrintStats( Gia_Man_t * p, Vec_Str_t * vStatus, int iIter, int Time ) +{ + int nLits, CounterX = 0, Counter0 = 0, Counter = 0; + int i, Entry, nProve = 0, nDispr = 0, nFail = 0; + for ( i = 1; i < Gia_ManObjNum(p); i++ ) + { + if ( Gia_ObjIsNone(p, i) ) + CounterX++; + else if ( Gia_ObjIsConst(p, i) ) + Counter0++; + else if ( Gia_ObjIsHead(p, i) ) + Counter++; + } + CounterX -= Gia_ManCoNum(p); + nLits = Gia_ManCiNum(p) + Gia_ManAndNum(p) - Counter - CounterX; + if ( iIter == -1 ) + Abc_Print( 1, "BMC : " ); + else + Abc_Print( 1, "%3d : ", iIter ); + Abc_Print( 1, "c =%8d cl =%7d lit =%8d ", Counter0, Counter, nLits ); + if ( vStatus ) + Vec_StrForEachEntry( vStatus, Entry, i ) + { + if ( Entry == 1 ) + nProve++; + else if ( Entry == 0 ) + nDispr++; + else if ( Entry == -1 ) + nFail++; + } + Abc_Print( 1, "p =%6d d =%6d f =%6d ", nProve, nDispr, nFail ); + Abc_PrintTime( 1, "T", Time ); +} + +/**Function************************************************************* + + Synopsis [Runs BMC for the equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManLSCorrespondenceBmc( Gia_Man_t * pAig, Cec_ParCor_t * pPars, int nPrefs ) +{ + Cec_ParSim_t ParsSim, * pParsSim = &ParsSim; + Cec_ParSat_t ParsSat, * pParsSat = &ParsSat; + Vec_Str_t * vStatus; + Vec_Int_t * vOutputs; + Vec_Int_t * vCexStore; + Cec_ManSim_t * pSim; + Gia_Man_t * pSrm; + int fChanges, RetValue; + // prepare simulation manager + Cec_ManSimSetDefaultParams( pParsSim ); + pParsSim->nWords = pPars->nWords; + pParsSim->nFrames = pPars->nRounds; + pParsSim->fVerbose = pPars->fVerbose; + pParsSim->fLatchCorr = pPars->fLatchCorr; + pParsSim->fSeqSimulate = 1; + pSim = Cec_ManSimStart( pAig, pParsSim ); + // prepare SAT solving + Cec_ManSatSetDefaultParams( pParsSat ); + pParsSat->nBTLimit = pPars->nBTLimit; + pParsSat->fVerbose = pPars->fVerbose; + fChanges = 1; + while ( fChanges ) + { + int clkBmc = clock(); + fChanges = 0; + pSrm = Gia_ManCorrSpecReduceInit( pAig, pPars->nFrames, nPrefs, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings ); + if ( Gia_ManPoNum(pSrm) == 0 ) + { + Gia_ManStop( pSrm ); + Vec_IntFree( vOutputs ); + break; + } + pParsSat->nBTLimit *= 10; + if ( pPars->fUseCSat ) + vCexStore = Tas_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0 ); + else + vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus ); + // refine classes with these counter-examples + if ( Vec_IntSize(vCexStore) ) + { + RetValue = Cec_ManResimulateCounterExamples( pSim, vCexStore, pPars->nFrames + 1 + nPrefs ); + Gia_ManCheckRefinements( pAig, vStatus, vOutputs, pSim, pPars->fUseRings ); + fChanges = 1; + } + if ( pPars->fVerbose ) + Cec_ManRefinedClassPrintStats( pAig, vStatus, -1, clock() - clkBmc ); + // recycle + Vec_IntFree( vCexStore ); + Vec_StrFree( vStatus ); + Gia_ManStop( pSrm ); + Vec_IntFree( vOutputs ); + } + Cec_ManSimStop( pSim ); +} + +/**Function************************************************************* + + Synopsis [Internal procedure for register correspondence.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars ) +{ + int nIterMax = 100000; + int nAddFrames = 1; // additional timeframes to simulate + int fRunBmcFirst = 1; + Vec_Str_t * vStatus; + Vec_Int_t * vOutputs; + Vec_Int_t * vCexStore; + Cec_ParSim_t ParsSim, * pParsSim = &ParsSim; + Cec_ParSat_t ParsSat, * pParsSat = &ParsSat; + Cec_ManSim_t * pSim; + Gia_Man_t * pSrm; + int r, RetValue, clkTotal = clock(); + int clkSat = 0, clkSim = 0, clkSrm = 0; + int clk2, clk = clock(); + if ( Gia_ManRegNum(pAig) == 0 ) + { + Abc_Print( 1, "Cec_ManLatchCorrespondence(): Not a sequential AIG.\n" ); + return 0; + } + Gia_ManRandom( 1 ); + // prepare simulation manager + Cec_ManSimSetDefaultParams( pParsSim ); + pParsSim->nWords = pPars->nWords; + pParsSim->nFrames = pPars->nFrames; + pParsSim->fVerbose = pPars->fVerbose; + pParsSim->fLatchCorr = pPars->fLatchCorr; + pParsSim->fConstCorr = pPars->fConstCorr; + pParsSim->fSeqSimulate = 1; + // create equivalence classes of registers + pSim = Cec_ManSimStart( pAig, pParsSim ); + if ( pAig->pReprs == NULL ) + { + Cec_ManSimClassesPrepare( pSim, pPars->nLevelMax ); + Cec_ManSimClassesRefine( pSim ); + } + // prepare SAT solving + Cec_ManSatSetDefaultParams( pParsSat ); + pParsSat->nBTLimit = pPars->nBTLimit; + pParsSat->fVerbose = pPars->fVerbose; + if ( pPars->fVerbose ) + { + Abc_Print( 1, "Obj = %7d. And = %7d. Conf = %5d. Fr = %d. Lcorr = %d. Ring = %d. CSat = %d.\n", + Gia_ManObjNum(pAig), Gia_ManAndNum(pAig), + pPars->nBTLimit, pPars->nFrames, pPars->fLatchCorr, pPars->fUseRings, pPars->fUseCSat ); + Cec_ManRefinedClassPrintStats( pAig, NULL, 0, clock() - clk ); + } + // check the base case + if ( fRunBmcFirst && (!pPars->fLatchCorr || pPars->nFrames > 1) ) + Cec_ManLSCorrespondenceBmc( pAig, pPars, 0 ); + if ( pPars->pFunc ) + { + ((int (*)(void *))pPars->pFunc)( pPars->pData ); + ((int (*)(void *))pPars->pFunc)( pPars->pData ); + } + if ( pPars->nStepsMax == 0 ) + { + Abc_Print( 1, "Stopped signal correspondence after BMC.\n" ); + Cec_ManSimStop( pSim ); + return 1; + } + // perform refinement of equivalence classes + for ( r = 0; r < nIterMax; r++ ) + { + if ( pPars->nStepsMax == r ) + { + Cec_ManSimStop( pSim ); + Abc_Print( 1, "Stopped signal correspondence after %d refiment iterations.\n", r ); + return 1; + } + clk = clock(); + // perform speculative reduction + clk2 = clock(); + pSrm = Gia_ManCorrSpecReduce( pAig, pPars->nFrames, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings ); + assert( Gia_ManRegNum(pSrm) == 0 && Gia_ManPiNum(pSrm) == Gia_ManRegNum(pAig)+(pPars->nFrames+!pPars->fLatchCorr)*Gia_ManPiNum(pAig) ); + clkSrm += clock() - clk2; + if ( Gia_ManCoNum(pSrm) == 0 ) + { + Vec_IntFree( vOutputs ); + Gia_ManStop( pSrm ); + break; + } +//Gia_DumpAiger( pSrm, "corrsrm", r, 2 ); + // found counter-examples to speculation + clk2 = clock(); + if ( pPars->fUseCSat ) + vCexStore = Cbs_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0 ); + else + vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus ); + Gia_ManStop( pSrm ); + clkSat += clock() - clk2; + if ( Vec_IntSize(vCexStore) == 0 ) + { + Vec_IntFree( vCexStore ); + Vec_StrFree( vStatus ); + Vec_IntFree( vOutputs ); + break; + } + // refine classes with these counter-examples + clk2 = clock(); + RetValue = Cec_ManResimulateCounterExamples( pSim, vCexStore, pPars->nFrames + 1 + nAddFrames ); + Vec_IntFree( vCexStore ); + clkSim += clock() - clk2; + Gia_ManCheckRefinements( pAig, vStatus, vOutputs, pSim, pPars->fUseRings ); + if ( pPars->fVerbose ) + Cec_ManRefinedClassPrintStats( pAig, vStatus, r+1, clock() - clk ); + Vec_StrFree( vStatus ); + Vec_IntFree( vOutputs ); +//Gia_ManEquivPrintClasses( pAig, 1, 0 ); + if ( pPars->pFunc ) + ((int (*)(void *))pPars->pFunc)( pPars->pData ); + } + if ( pPars->fVerbose ) + Cec_ManRefinedClassPrintStats( pAig, NULL, r+1, clock() - clk ); + // check the overflow + if ( r == nIterMax ) + Abc_Print( 1, "The refinement was not finished. The result may be incorrect.\n" ); + Cec_ManSimStop( pSim ); + // check the base case + if ( !fRunBmcFirst && (!pPars->fLatchCorr || pPars->nFrames > 1) ) + Cec_ManLSCorrespondenceBmc( pAig, pPars, 0 ); + clkTotal = clock() - clkTotal; + // report the results + if ( pPars->fVerbose ) + { + ABC_PRTP( "Srm ", clkSrm, clkTotal ); + ABC_PRTP( "Sat ", clkSat, clkTotal ); + ABC_PRTP( "Sim ", clkSim, clkTotal ); + ABC_PRTP( "Other", clkTotal-clkSat-clkSrm-clkSim, clkTotal ); + Abc_PrintTime( 1, "TOTAL", clkTotal ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes new initial state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Cec_ManComputeInitState( Gia_Man_t * pAig, int nFrames ) +{ + Gia_Obj_t * pObj, * pObjRo, * pObjRi; + unsigned * pInitState; + int i, f; + Gia_ManRandom( 1 ); +// Abc_Print( 1, "Simulating %d timeframes.\n", nFrames ); + Gia_ManForEachRo( pAig, pObj, i ) + pObj->fMark1 = 0; + for ( f = 0; f < nFrames; f++ ) + { + Gia_ManConst0(pAig)->fMark1 = 0; + Gia_ManForEachPi( pAig, pObj, i ) + pObj->fMark1 = Gia_ManRandom(0) & 1; + Gia_ManForEachAnd( pAig, pObj, i ) + pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) & + (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj)); + Gia_ManForEachRi( pAig, pObj, i ) + pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)); + Gia_ManForEachRiRo( pAig, pObjRi, pObjRo, i ) + pObjRo->fMark1 = pObjRi->fMark1; + } + pInitState = ABC_CALLOC( unsigned, Abc_BitWordNum(Gia_ManRegNum(pAig)) ); + Gia_ManForEachRo( pAig, pObj, i ) + { + if ( pObj->fMark1 ) + Abc_InfoSetBit( pInitState, i ); +// Abc_Print( 1, "%d", pObj->fMark1 ); + } +// Abc_Print( 1, "\n" ); + Gia_ManCleanMark1( pAig ); + return pInitState; +} + +/**Function************************************************************* + + Synopsis [Prints flop equivalences.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManPrintFlopEquivs( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj, * pRepr; + int i; + assert( p->vNamesIn != NULL ); + Gia_ManForEachRo( p, pObj, i ) + { + if ( Gia_ObjIsConst(p, Gia_ObjId(p, pObj)) ) + Abc_Print( 1, "Original flop %s is proved equivalent to constant.\n", Vec_PtrEntry(p->vNamesIn, Gia_ObjCioId(pObj)) ); + else if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) + { + if ( Gia_ObjIsCi(pRepr) ) + Abc_Print( 1, "Original flop %s is proved equivalent to flop %s.\n", + Vec_PtrEntry( p->vNamesIn, Gia_ObjCioId(pObj) ), + Vec_PtrEntry( p->vNamesIn, Gia_ObjCioId(pRepr) ) ); + else + Abc_Print( 1, "Original flop %s is proved equivalent to internal node %d.\n", + Vec_PtrEntry( p->vNamesIn, Gia_ObjCioId(pObj) ), Gia_ObjId(p, pRepr) ); + } + } +} + + +/**Function************************************************************* + + Synopsis [Top-level procedure for register correspondence.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Cec_ManLSCorrespondence( Gia_Man_t * pAig, Cec_ParCor_t * pPars ) +{ + Gia_Man_t * pNew, * pTemp; + unsigned * pInitState; + int RetValue; + ABC_FREE( pAig->pReprs ); + ABC_FREE( pAig->pNexts ); + if ( pPars->nPrefix == 0 ) + RetValue = Cec_ManLSCorrespondenceClasses( pAig, pPars ); + else + { + // compute the cycles AIG + pInitState = Cec_ManComputeInitState( pAig, pPars->nPrefix ); + pTemp = Gia_ManDupFlip( pAig, (int *)pInitState ); + ABC_FREE( pInitState ); + // compute classes of this AIG + RetValue = Cec_ManLSCorrespondenceClasses( pTemp, pPars ); + // transfer the class info + pAig->pReprs = pTemp->pReprs; pTemp->pReprs = NULL; + pAig->pNexts = pTemp->pNexts; pTemp->pNexts = NULL; + // perform additional BMC + pPars->fUseCSat = 0; + pPars->nBTLimit = Abc_MaxInt( pPars->nBTLimit, 1000 ); + Cec_ManLSCorrespondenceBmc( pAig, pPars, pPars->nPrefix ); +/* + // transfer the class info back + pTemp->pReprs = pAig->pReprs; pAig->pReprs = NULL; + pTemp->pNexts = pAig->pNexts; pAig->pNexts = NULL; + // continue refining + RetValue = Cec_ManLSCorrespondenceClasses( pTemp, pPars ); + // transfer the class info + pAig->pReprs = pTemp->pReprs; pTemp->pReprs = NULL; + pAig->pNexts = pTemp->pNexts; pTemp->pNexts = NULL; +*/ + Gia_ManStop( pTemp ); + } + // derive reduced AIG + if ( pPars->fMakeChoices ) + { + pNew = Gia_ManEquivToChoices( pAig, 1 ); + Gia_ManHasChoices( pNew ); + } + else + { +// Gia_ManEquivImprove( pAig ); + pNew = Gia_ManCorrReduce( pAig ); + pNew = Gia_ManSeqCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + //Gia_WriteAiger( pNew, "reduced.aig", 0, 0 ); + } + // report the results + if ( pPars->fVerbose ) + { + Abc_Print( 1, "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n", + Gia_ManAndNum(pAig), Gia_ManAndNum(pNew), + 100.0*(Gia_ManAndNum(pAig)-Gia_ManAndNum(pNew))/(Gia_ManAndNum(pAig)?Gia_ManAndNum(pAig):1), + Gia_ManRegNum(pAig), Gia_ManRegNum(pNew), + 100.0*(Gia_ManRegNum(pAig)-Gia_ManRegNum(pNew))/(Gia_ManRegNum(pAig)?Gia_ManRegNum(pAig):1) ); + } + if ( pPars->nPrefix && (Gia_ManAndNum(pNew) < Gia_ManAndNum(pAig) || Gia_ManRegNum(pNew) < Gia_ManRegNum(pAig)) ) + Abc_Print( 1, "The reduced AIG was produced using %d-th invariants and will not verify.\n", pPars->nPrefix ); + // print verbose info about equivalences + if ( pPars->fVerboseFlops ) + { + if ( pAig->vNamesIn == NULL ) + Abc_Print( 1, "Flop output names are not available. Use command \"&get -n\".\n" ); + else + Cec_ManPrintFlopEquivs( pAig ); + } + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/cec/cecCorr_updated.c b/src/proof/cec/cecCorr_updated.c new file mode 100644 index 00000000..1db30705 --- /dev/null +++ b/src/proof/cec/cecCorr_updated.c @@ -0,0 +1,1027 @@ +/**CFile**************************************************************** + + FileName [cecCorr.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinational equivalence checking.] + + Synopsis [Latch/signal correspondence computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cecCorr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cecInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Gia_ManCorrSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes the real value of the literal w/o spec reduction.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_ManCorrSpecReal( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix ) +{ + if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ManCorrSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj), f, nPrefix ); + Gia_ManCorrSpecReduce_rec( pNew, p, Gia_ObjFanin1(pObj), f, nPrefix ); + return Gia_ManHashAnd( pNew, Gia_ObjFanin0CopyF(p, f, pObj), Gia_ObjFanin1CopyF(p, f, pObj) ); + } + if ( f == 0 ) + { + assert( Gia_ObjIsRo(p, pObj) ); + return Gia_ObjCopyF(p, f, pObj); + } + assert( f && Gia_ObjIsRo(p, pObj) ); + pObj = Gia_ObjRoToRi( p, pObj ); + Gia_ManCorrSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj), f-1, nPrefix ); + return Gia_ObjFanin0CopyF( p, f-1, pObj ); +} + +/**Function************************************************************* + + Synopsis [Recursively performs speculative reduction for the object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCorrSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix ) +{ + Gia_Obj_t * pRepr; + int iLitNew; + if ( ~Gia_ObjCopyF(p, f, pObj) ) + return; + if ( f >= nPrefix && (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) + { + Gia_ManCorrSpecReduce_rec( pNew, p, pRepr, f, nPrefix ); + iLitNew = Gia_LitNotCond( Gia_ObjCopyF(p, f, pRepr), Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); + Gia_ObjSetCopyF( p, f, pObj, iLitNew ); + return; + } + assert( Gia_ObjIsCand(pObj) ); + iLitNew = Gia_ManCorrSpecReal( pNew, p, pObj, f, nPrefix ); + Gia_ObjSetCopyF( p, f, pObj, iLitNew ); +} + +/**Function************************************************************* + + Synopsis [Derives SRM for signal correspondence.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManCorrSpecReduce( Gia_Man_t * p, int nFrames, int fScorr, Vec_Int_t ** pvOutputs, int fRings ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pRepr; + Vec_Int_t * vXorLits; + int f, i, iPrev, iObj, iPrevNew, iObjNew; + assert( nFrames > 0 ); + assert( Gia_ManRegNum(p) > 0 ); + assert( p->pReprs != NULL ); + p->pCopies = ABC_FALLOC( int, (nFrames+fScorr)*Gia_ManObjNum(p) ); + Gia_ManSetPhase( p ); + pNew = Gia_ManStart( nFrames * Gia_ManObjNum(p) ); + pNew->pName = Gia_UtilStrsav( p->pName ); + Gia_ManHashAlloc( pNew ); + Gia_ObjSetCopyF( p, 0, Gia_ManConst0(p), 0 ); + Gia_ManForEachRo( p, pObj, i ) + Gia_ObjSetCopyF( p, 0, pObj, Gia_ManAppendCi(pNew) ); + Gia_ManForEachRo( p, pObj, i ) + if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) + Gia_ObjSetCopyF( p, 0, pObj, Gia_ObjCopyF(p, 0, pRepr) ); + for ( f = 0; f < nFrames+fScorr; f++ ) + { + Gia_ObjSetCopyF( p, f, Gia_ManConst0(p), 0 ); + Gia_ManForEachPi( p, pObj, i ) + Gia_ObjSetCopyF( p, f, pObj, Gia_ManAppendCi(pNew) ); + } + *pvOutputs = Vec_IntAlloc( 1000 ); + vXorLits = Vec_IntAlloc( 1000 ); + if ( fRings ) + { + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsConst( p, i ) ) + { + iObjNew = Gia_ManCorrSpecReal( pNew, p, pObj, nFrames, 0 ); + iObjNew = Gia_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ); + if ( iObjNew != 0 ) + { + Vec_IntPush( *pvOutputs, 0 ); + Vec_IntPush( *pvOutputs, i ); + Vec_IntPush( vXorLits, iObjNew ); + } + } + else if ( Gia_ObjIsHead( p, i ) ) + { + iPrev = i; + Gia_ClassForEachObj1( p, i, iObj ) + { + iPrevNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iPrev), nFrames, 0 ); + iObjNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iObj), nFrames, 0 ); + iPrevNew = Gia_LitNotCond( iPrevNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) ); + iObjNew = Gia_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) ); + if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 ) + { + Vec_IntPush( *pvOutputs, iPrev ); + Vec_IntPush( *pvOutputs, iObj ); + Vec_IntPush( vXorLits, Gia_ManHashAnd(pNew, iPrevNew, Gia_LitNot(iObjNew)) ); + } + iPrev = iObj; + } + iObj = i; + iPrevNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iPrev), nFrames, 0 ); + iObjNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iObj), nFrames, 0 ); + iPrevNew = Gia_LitNotCond( iPrevNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) ); + iObjNew = Gia_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) ); + if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 ) + { + Vec_IntPush( *pvOutputs, iPrev ); + Vec_IntPush( *pvOutputs, iObj ); + Vec_IntPush( vXorLits, Gia_ManHashAnd(pNew, iPrevNew, Gia_LitNot(iObjNew)) ); + } + } + } + } + else + { + Gia_ManForEachObj1( p, pObj, i ) + { + pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); + if ( pRepr == NULL ) + continue; + iPrevNew = Gia_ObjIsConst(p, i)? 0 : Gia_ManCorrSpecReal( pNew, p, pRepr, nFrames, 0 ); + iObjNew = Gia_ManCorrSpecReal( pNew, p, pObj, nFrames, 0 ); + iObjNew = Gia_LitNotCond( iObjNew, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); + if ( iPrevNew != iObjNew ) + { + Vec_IntPush( *pvOutputs, Gia_ObjId(p, pRepr) ); + Vec_IntPush( *pvOutputs, Gia_ObjId(p, pObj) ); + Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, iPrevNew, iObjNew) ); + } + } + } + Vec_IntForEachEntry( vXorLits, iObjNew, i ) + Gia_ManAppendCo( pNew, iObjNew ); + Vec_IntFree( vXorLits ); + Gia_ManHashStop( pNew ); + ABC_FREE( p->pCopies ); +//printf( "Before sweeping = %d\n", Gia_ManAndNum(pNew) ); + pNew = Gia_ManCleanup( pTemp = pNew ); +//printf( "After sweeping = %d\n", Gia_ManAndNum(pNew) ); + Gia_ManStop( pTemp ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Derives SRM for signal correspondence.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManCorrSpecReduceInit( Gia_Man_t * p, int nFrames, int nPrefix, int fScorr, Vec_Int_t ** pvOutputs, int fRings ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pRepr; + Vec_Int_t * vXorLits; + int f, i, iPrevNew, iObjNew; + assert( (!fScorr && nFrames > 1) || (fScorr && nFrames > 0) || nPrefix ); + assert( Gia_ManRegNum(p) > 0 ); + assert( p->pReprs != NULL ); + p->pCopies = ABC_FALLOC( int, (nFrames+nPrefix+fScorr)*Gia_ManObjNum(p) ); + Gia_ManSetPhase( p ); + pNew = Gia_ManStart( (nFrames+nPrefix) * Gia_ManObjNum(p) ); + pNew->pName = Gia_UtilStrsav( p->pName ); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachRo( p, pObj, i ) + { + Gia_ManAppendCi(pNew); + Gia_ObjSetCopyF( p, 0, pObj, 0 ); + } + for ( f = 0; f < nFrames+nPrefix+fScorr; f++ ) + { + Gia_ObjSetCopyF( p, f, Gia_ManConst0(p), 0 ); + Gia_ManForEachPi( p, pObj, i ) + Gia_ObjSetCopyF( p, f, pObj, Gia_ManAppendCi(pNew) ); + } + *pvOutputs = Vec_IntAlloc( 1000 ); + vXorLits = Vec_IntAlloc( 1000 ); + for ( f = nPrefix; f < nFrames+nPrefix; f++ ) + { + Gia_ManForEachObj1( p, pObj, i ) + { + pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); + if ( pRepr == NULL ) + continue; + iPrevNew = Gia_ObjIsConst(p, i)? 0 : Gia_ManCorrSpecReal( pNew, p, pRepr, f, nPrefix ); + iObjNew = Gia_ManCorrSpecReal( pNew, p, pObj, f, nPrefix ); + iObjNew = Gia_LitNotCond( iObjNew, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); + if ( iPrevNew != iObjNew ) + { + Vec_IntPush( *pvOutputs, Gia_ObjId(p, pRepr) ); + Vec_IntPush( *pvOutputs, Gia_ObjId(p, pObj) ); + Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, iPrevNew, iObjNew) ); + } + } + } + Vec_IntForEachEntry( vXorLits, iObjNew, i ) + Gia_ManAppendCo( pNew, iObjNew ); + Vec_IntFree( vXorLits ); + Gia_ManHashStop( pNew ); + ABC_FREE( p->pCopies ); +//printf( "Before sweeping = %d\n", Gia_ManAndNum(pNew) ); + pNew = Gia_ManCleanup( pTemp = pNew ); +//printf( "After sweeping = %d\n", Gia_ManAndNum(pNew) ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Initializes simulation info for lcorr/scorr counter-examples.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManStartSimInfo( Vec_Ptr_t * vInfo, int nFlops, int * pInitState ) +{ + unsigned * pInfo; + int k, w, nWords; + nWords = Vec_PtrReadWordsSimInfo( vInfo ); + assert( nFlops <= Vec_PtrSize(vInfo) ); + for ( k = 0; k < nFlops; k++ ) + { + pInfo = Vec_PtrEntry( vInfo, k ); + if ( pInitState && Gia_InfoHasBit(pInitState, k) ) + { + for ( w = 0; w < nWords; w++ ) + pInfo[w] = ~0; +// pInfo[0] <<= 1; + } + else + { + for ( w = 0; w < nWords; w++ ) + pInfo[w] = 0; + } + } + for ( k = nFlops; k < Vec_PtrSize(vInfo); k++ ) + { + pInfo = Vec_PtrEntry( vInfo, k ); + for ( w = 0; w < nWords; w++ ) + pInfo[w] = Gia_ManRandom( 0 ); + } +} + +/**Function************************************************************* + + Synopsis [Remaps simulation info from SRM to the original AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCorrRemapSimInfo( Gia_Man_t * p, Vec_Ptr_t * vInfo ) +{ + Gia_Obj_t * pObj, * pRepr; + unsigned * pInfoObj, * pInfoRepr; + int i, w, nWords; + nWords = Vec_PtrReadWordsSimInfo( vInfo ); + Gia_ManForEachRo( p, pObj, i ) + { + // skip ROs without representatives + pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); + if ( pRepr == NULL || Gia_ObjFailed(p, Gia_ObjId(p,pObj)) ) + continue; + pInfoObj = Vec_PtrEntry( vInfo, i ); + for ( w = 0; w < nWords; w++ ) + assert( pInfoObj[w] == 0 ); + // skip ROs with constant representatives + if ( Gia_ObjIsConst0(pRepr) ) + continue; + assert( Gia_ObjIsRo(p, pRepr) ); +// printf( "%d -> %d ", i, Gia_ObjId(p, pRepr) ); + // transfer info from the representative + pInfoRepr = Vec_PtrEntry( vInfo, Gia_ObjCioId(pRepr) - Gia_ManPiNum(p) ); + for ( w = 0; w < nWords; w++ ) + pInfoObj[w] = pInfoRepr[w]; + } +// printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Collects information about remapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManCorrCreateRemapping( Gia_Man_t * p ) +{ + Vec_Int_t * vPairs; + Gia_Obj_t * pObj, * pRepr; + int i; + vPairs = Vec_IntAlloc( 100 ); + Gia_ManForEachRo( p, pObj, i ) + { + // skip ROs without representatives + pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); + if ( pRepr == NULL || Gia_ObjIsConst0(pRepr) || Gia_ObjFailed(p, Gia_ObjId(p,pObj)) ) +// if ( pRepr == NULL || Gia_ObjIsConst0(pRepr) || Gia_ObjIsFailedPair(p, Gia_ObjId(p, pRepr), Gia_ObjId(p, pObj)) ) + continue; + assert( Gia_ObjIsRo(p, pRepr) ); +// printf( "%d -> %d ", Gia_ObjId(p,pObj), Gia_ObjId(p, pRepr) ); + // remember the pair + Vec_IntPush( vPairs, Gia_ObjCioId(pRepr) - Gia_ManPiNum(p) ); + Vec_IntPush( vPairs, i ); + } + return vPairs; +} + +/**Function************************************************************* + + Synopsis [Remaps simulation info from SRM to the original AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCorrPerformRemapping( Vec_Int_t * vPairs, Vec_Ptr_t * vInfo, int * pInitState ) +{ + unsigned * pInfoObj, * pInfoRepr; + int w, i, iObj, iRepr, nWords; + nWords = Vec_PtrReadWordsSimInfo( vInfo ); + Vec_IntForEachEntry( vPairs, iRepr, i ) + { + iObj = Vec_IntEntry( vPairs, ++i ); + pInfoObj = Vec_PtrEntry( vInfo, iObj ); + pInfoRepr = Vec_PtrEntry( vInfo, iRepr ); + for ( w = 0; w < nWords; w++ ) + { + assert( pInitState || pInfoObj[w] == 0 ); + pInfoObj[w] = pInfoRepr[w]; + } + } +} + +/**Function************************************************************* + + Synopsis [Packs one counter-examples into the array of simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +*************************************`**********************************/ +int Cec_ManLoadCounterExamplesTry( Vec_Ptr_t * vInfo, Vec_Ptr_t * vPres, int iBit, int * pLits, int nLits ) +{ + unsigned * pInfo, * pPres; + int i; + for ( i = 0; i < nLits; i++ ) + { + pInfo = Vec_PtrEntry(vInfo, Gia_Lit2Var(pLits[i])); + pPres = Vec_PtrEntry(vPres, Gia_Lit2Var(pLits[i])); + if ( Gia_InfoHasBit( pPres, iBit ) && + Gia_InfoHasBit( pInfo, iBit ) == Gia_LitIsCompl(pLits[i]) ) + return 0; + } + for ( i = 0; i < nLits; i++ ) + { + pInfo = Vec_PtrEntry(vInfo, Gia_Lit2Var(pLits[i])); + pPres = Vec_PtrEntry(vPres, Gia_Lit2Var(pLits[i])); + Gia_InfoSetBit( pPres, iBit ); + if ( Gia_InfoHasBit( pInfo, iBit ) == Gia_LitIsCompl(pLits[i]) ) + Gia_InfoXorBit( pInfo, iBit ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Performs bitpacking of counter-examples.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManLoadCounterExamples( Vec_Ptr_t * vInfo, Vec_Int_t * vCexStore, int iStart ) +{ + Vec_Int_t * vPat; + Vec_Ptr_t * vPres; + int nWords = Vec_PtrReadWordsSimInfo(vInfo); + int nBits = 32 * nWords; + int k, nSize, iBit = 1, kMax = 0; + vPat = Vec_IntAlloc( 100 ); + vPres = Vec_PtrAllocSimInfo( Vec_PtrSize(vInfo), nWords ); + Vec_PtrCleanSimInfo( vPres, 0, nWords ); + while ( iStart < Vec_IntSize(vCexStore) ) + { + // skip the output number + iStart++; + // get the number of items + nSize = Vec_IntEntry( vCexStore, iStart++ ); + if ( nSize <= 0 ) + continue; + // extract pattern + Vec_IntClear( vPat ); + for ( k = 0; k < nSize; k++ ) + Vec_IntPush( vPat, Vec_IntEntry( vCexStore, iStart++ ) ); + // add pattern to storage + for ( k = 1; k < nBits; k++ ) + if ( Cec_ManLoadCounterExamplesTry( vInfo, vPres, k, (int *)Vec_IntArray(vPat), Vec_IntSize(vPat) ) ) + break; + kMax = Abc_MaxInt( kMax, k ); + if ( k == nBits-1 ) + break; + } + Vec_PtrFree( vPres ); + Vec_IntFree( vPat ); + return iStart; +} + +/**Function************************************************************* + + Synopsis [Performs bitpacking of counter-examples.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManLoadCounterExamples2( Vec_Ptr_t * vInfo, Vec_Int_t * vCexStore, int iStart ) +{ + unsigned * pInfo; + int nBits = 32 * Vec_PtrReadWordsSimInfo(vInfo); + int k, iLit, nLits, Out, iBit = 1; + while ( iStart < Vec_IntSize(vCexStore) ) + { + // skip the output number +// iStart++; + Out = Vec_IntEntry( vCexStore, iStart++ ); +// printf( "iBit = %d. Out = %d.\n", iBit, Out ); + // get the number of items + nLits = Vec_IntEntry( vCexStore, iStart++ ); + if ( nLits <= 0 ) + continue; + // add pattern to storage + for ( k = 0; k < nLits; k++ ) + { + iLit = Vec_IntEntry( vCexStore, iStart++ ); + pInfo = Vec_PtrEntry( vInfo, Gia_Lit2Var(iLit) ); + if ( Gia_InfoHasBit( pInfo, iBit ) == Gia_LitIsCompl(iLit) ) + Gia_InfoXorBit( pInfo, iBit ); + } + if ( ++iBit == nBits ) + break; + } +// printf( "added %d bits\n", iBit-1 ); + return iStart; +} + +/**Function************************************************************* + + Synopsis [Resimulates counter-examples derived by the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManResimulateCounterExamples( Cec_ManSim_t * pSim, Vec_Int_t * vCexStore, int nFrames, int * pInitState ) +{ + Vec_Int_t * vPairs; + Vec_Ptr_t * vSimInfo; + int RetValue = 0, iStart = 0; + vPairs = Gia_ManCorrCreateRemapping( pSim->pAig ); + Gia_ManSetRefs( pSim->pAig ); +// pSim->pPars->nWords = 63; + pSim->pPars->nRounds = nFrames; + vSimInfo = Vec_PtrAllocSimInfo( Gia_ManRegNum(pSim->pAig) + Gia_ManPiNum(pSim->pAig) * nFrames, pSim->pPars->nWords ); + while ( iStart < Vec_IntSize(vCexStore) ) + { + Cec_ManStartSimInfo( vSimInfo, Gia_ManRegNum(pSim->pAig), pInitState ); + iStart = Cec_ManLoadCounterExamples( vSimInfo, vCexStore, iStart ); +// iStart = Cec_ManLoadCounterExamples2( vSimInfo, vCexStore, iStart ); +// Gia_ManCorrRemapSimInfo( pSim->pAig, vSimInfo ); + Gia_ManCorrPerformRemapping( vPairs, vSimInfo, pInitState ); + RetValue |= Cec_ManSeqResimulate( pSim, vSimInfo ); +// Cec_ManSeqResimulateInfo( pSim->pAig, vSimInfo, NULL ); + } +//Gia_ManEquivPrintOne( pSim->pAig, 85, 0 ); + assert( iStart == Vec_IntSize(vCexStore) ); + Vec_PtrFree( vSimInfo ); + Vec_IntFree( vPairs ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Resimulates counter-examples derived by the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManResimulateCounterExamplesComb( Cec_ManSim_t * pSim, Vec_Int_t * vCexStore ) +{ + Vec_Ptr_t * vSimInfo; + int RetValue = 0, iStart = 0; + Gia_ManSetRefs( pSim->pAig ); + pSim->pPars->nRounds = 1; + vSimInfo = Vec_PtrAllocSimInfo( Gia_ManCiNum(pSim->pAig), pSim->pPars->nWords ); + while ( iStart < Vec_IntSize(vCexStore) ) + { + Cec_ManStartSimInfo( vSimInfo, 0, NULL ); + iStart = Cec_ManLoadCounterExamples( vSimInfo, vCexStore, iStart ); + RetValue |= Cec_ManSeqResimulate( pSim, vSimInfo ); + } + assert( iStart == Vec_IntSize(vCexStore) ); + Vec_PtrFree( vSimInfo ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Updates equivalence classes by marking those that timed out.] + + Description [Returns 1 if all ndoes are proved.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCheckRefinements( Gia_Man_t * p, Vec_Str_t * vStatus, Vec_Int_t * vOutputs, Cec_ManSim_t * pSim, int fRings ) +{ + int i, status, iRepr, iObj; + int Counter = 0; + assert( 2 * Vec_StrSize(vStatus) == Vec_IntSize(vOutputs) ); + Vec_StrForEachEntry( vStatus, status, i ) + { + iRepr = Vec_IntEntry( vOutputs, 2*i ); + iObj = Vec_IntEntry( vOutputs, 2*i+1 ); + if ( status == 1 ) + continue; + if ( status == 0 ) + { + if ( Gia_ObjHasSameRepr(p, iRepr, iObj) ) + Counter++; +// if ( Gia_ObjHasSameRepr(p, iRepr, iObj) ) +// printf( "Gia_ManCheckRefinements(): Disproved equivalence (%d,%d) is not refined!\n", iRepr, iObj ); +// if ( Gia_ObjHasSameRepr(p, iRepr, iObj) ) +// Cec_ManSimClassRemoveOne( pSim, iObj ); + continue; + } + if ( status == -1 ) + { +// if ( !Gia_ObjFailed( p, iObj ) ) +// printf( "Gia_ManCheckRefinements(): Failed equivalence is not marked as failed!\n" ); +// Gia_ObjSetFailed( p, iRepr ); +// Gia_ObjSetFailed( p, iObj ); +// if ( fRings ) +// Cec_ManSimClassRemoveOne( pSim, iRepr ); + Cec_ManSimClassRemoveOne( pSim, iObj ); + continue; + } + } +// if ( Counter ) +// printf( "Gia_ManCheckRefinements(): Could not refine %d nodes.\n", Counter ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Duplicates the AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCorrReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + Gia_Obj_t * pRepr; + if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) + { + Gia_ManCorrReduce_rec( pNew, p, pRepr ); + pObj->Value = Gia_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); + return; + } + if ( ~pObj->Value ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManCorrReduce_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManCorrReduce_rec( pNew, p, Gia_ObjFanin1(pObj) ); + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Reduces AIG using equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManCorrReduce( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + Gia_ManSetPhase( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Gia_UtilStrsav( p->pName ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManCorrReduce_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Prints statistics during solving.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManRefinedClassPrintStats( Gia_Man_t * p, Vec_Str_t * vStatus, int iIter, int Time ) +{ + int nLits, CounterX = 0, Counter0 = 0, Counter = 0; + int i, Entry, nProve = 0, nDispr = 0, nFail = 0; + for ( i = 1; i < Gia_ManObjNum(p); i++ ) + { + if ( Gia_ObjIsNone(p, i) ) + CounterX++; + else if ( Gia_ObjIsConst(p, i) ) + Counter0++; + else if ( Gia_ObjIsHead(p, i) ) + Counter++; + } + CounterX -= Gia_ManCoNum(p); + nLits = Gia_ManCiNum(p) + Gia_ManAndNum(p) - Counter - CounterX; + if ( iIter == -1 ) + printf( "BMC : " ); + else + printf( "%3d : ", iIter ); + printf( "c =%8d cl =%7d lit =%8d ", Counter0, Counter, nLits ); + if ( vStatus ) + Vec_StrForEachEntry( vStatus, Entry, i ) + { + if ( Entry == 1 ) + nProve++; + else if ( Entry == 0 ) + nDispr++; + else if ( Entry == -1 ) + nFail++; + } + printf( "p =%6d d =%6d f =%6d ", nProve, nDispr, nFail ); + ABC_PRT( "T", Time ); +} + +/**Function************************************************************* + + Synopsis [Computes new initial state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Cec_ManComputeInitState( Gia_Man_t * pAig, int nFrames ) +{ + Gia_Obj_t * pObj, * pObjRo, * pObjRi; + unsigned * pInitState; + int i, f; + printf( "Simulating %d timeframes.\n", nFrames ); + Gia_ManForEachRo( pAig, pObj, i ) + pObj->fMark1 = 0; + for ( f = 0; f < nFrames; f++ ) + { + Gia_ManConst0(pAig)->fMark1 = 0; + Gia_ManForEachPi( pAig, pObj, i ) + pObj->fMark1 = Gia_ManRandom(0) & 1; +// pObj->fMark1 = 1; + Gia_ManForEachAnd( pAig, pObj, i ) + pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) & + (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj)); + Gia_ManForEachRi( pAig, pObj, i ) + pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)); + Gia_ManForEachRiRo( pAig, pObjRi, pObjRo, i ) + pObjRo->fMark1 = pObjRi->fMark1; + } + pInitState = ABC_CALLOC( unsigned, Gia_BitWordNum(Gia_ManRegNum(pAig)) ); + Gia_ManForEachRo( pAig, pObj, i ) + { + if ( pObj->fMark1 ) + Gia_InfoSetBit( pInitState, i ); +// printf( "%d", pObj->fMark1 ); + } +// printf( "\n" ); + Gia_ManCleanMark1( pAig ); + return pInitState; +} + +/**Function************************************************************* + + Synopsis [Internal procedure for register correspondence.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars ) +{ + int nIterMax = 100000; + int nAddFrames = 1; // additional timeframes to simulate + Vec_Str_t * vStatus; + Vec_Int_t * vOutputs; + Vec_Int_t * vCexStore; + Cec_ParSim_t ParsSim, * pParsSim = &ParsSim; + Cec_ParSat_t ParsSat, * pParsSat = &ParsSat; + Cec_ManSim_t * pSim; + Gia_Man_t * pSrm; + unsigned * pInitState = NULL; + int r, RetValue, clkTotal = clock(); + int clkSat = 0, clkSim = 0, clkSrm = 0; + int clk2, clk = clock(); + ABC_FREE( pAig->pReprs ); + ABC_FREE( pAig->pNexts ); + if ( Gia_ManRegNum(pAig) == 0 ) + { + printf( "Cec_ManLatchCorrespondence(): Not a sequential AIG.\n" ); + return 0; + } + Gia_ManRandom( 1 ); + // derive initial state for resimulation + if ( pPars->nPrefix ) +// pInitState = Cec_ManComputeInitState( pAig, 5+(1<<20)/Gia_ManAndNum(pAig) ); + pInitState = Cec_ManComputeInitState( pAig, 100 ); + // prepare simulation manager + Cec_ManSimSetDefaultParams( pParsSim ); + pParsSim->nWords = pPars->nWords; + pParsSim->nRounds = pPars->nRounds; + pParsSim->fVerbose = pPars->fVerbose; + pParsSim->fLatchCorr = pPars->fLatchCorr; + pParsSim->fSeqSimulate = 1; + // create equivalence classes of registers + pSim = Cec_ManSimStart( pAig, pParsSim, pInitState ); + Cec_ManSimClassesPrepare( pSim ); + Cec_ManSimClassesRefine( pSim ); + // prepare SAT solving + Cec_ManSatSetDefaultParams( pParsSat ); + pParsSat->nBTLimit = pPars->nBTLimit; + pParsSat->fVerbose = pPars->fVerbose; + if ( pPars->fVerbose ) + { + printf( "Obj = %7d. And = %7d. Conf = %5d. Fr = %d. Lcorr = %d. Ring = %d. CSat = %d.\n", + Gia_ManObjNum(pAig), Gia_ManAndNum(pAig), + pPars->nBTLimit, pPars->nFrames, pPars->fLatchCorr, pPars->fUseRings, pPars->fUseCSat ); + Cec_ManRefinedClassPrintStats( pAig, NULL, 0, clock() - clk ); + } + // perform refinement of equivalence classes + for ( r = 0; r < nIterMax; r++ ) + { + clk = clock(); + // perform speculative reduction + clk2 = clock(); + pSrm = Gia_ManCorrSpecReduce( pAig, pPars->nFrames, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings ); + assert( Gia_ManRegNum(pSrm) == 0 && Gia_ManPiNum(pSrm) == Gia_ManRegNum(pAig)+(pPars->nFrames+!pPars->fLatchCorr)*Gia_ManPiNum(pAig) ); + clkSrm += clock() - clk2; + if ( Gia_ManCoNum(pSrm) == 0 ) + { + Vec_IntFree( vOutputs ); + Gia_ManStop( pSrm ); + break; + } +//Gia_DumpAiger( pSrm, "corrsrm", r, 2 ); + // found counter-examples to speculation + clk2 = clock(); + if ( pPars->fUseCSat ) + vCexStore = Cbs_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0 ); + else + vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus ); + Gia_ManStop( pSrm ); + clkSat += clock() - clk2; + if ( Vec_IntSize(vCexStore) == 0 ) + { + Vec_IntFree( vCexStore ); + Vec_StrFree( vStatus ); + Vec_IntFree( vOutputs ); + break; + } + // refine classes with these counter-examples + clk2 = clock(); + RetValue = Cec_ManResimulateCounterExamples( pSim, vCexStore, pPars->nFrames + 1 + nAddFrames, pInitState ); + Vec_IntFree( vCexStore ); + clkSim += clock() - clk2; + Gia_ManCheckRefinements( pAig, vStatus, vOutputs, pSim, pPars->fUseRings ); + if ( pPars->fVerbose ) + Cec_ManRefinedClassPrintStats( pAig, vStatus, r+1, clock() - clk ); + Vec_StrFree( vStatus ); + Vec_IntFree( vOutputs ); +//Gia_ManEquivPrintClasses( pAig, 1, 0 ); + } + ABC_FREE( pInitState ); + // check the base case + if ( (!pPars->fLatchCorr || pPars->nFrames > 1) || pPars->nPrefix ) + { + int fChanges = 1; + while ( fChanges ) + { + int clkBmc = clock(); + fChanges = 0; + pSrm = Gia_ManCorrSpecReduceInit( pAig, pPars->nFrames, pPars->nPrefix, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings ); + if ( Gia_ManPoNum(pSrm) == 0 ) + { + Gia_ManStop( pSrm ); + Vec_IntFree( vOutputs ); + break; + } + pParsSat->nBTLimit *= 10; + if ( pPars->nPrefix ) + { + pParsSat->nBTLimit = 10000; + vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus ); + } + else if ( pPars->fUseCSat ) + vCexStore = Cbs_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0 ); + else + vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus ); + // refine classes with these counter-examples + if ( Vec_IntSize(vCexStore) ) + { + clk2 = clock(); + RetValue = Cec_ManResimulateCounterExamples( pSim, vCexStore, pPars->nFrames + 1 + nAddFrames + pPars->nPrefix, NULL ); + clkSim += clock() - clk2; + Gia_ManCheckRefinements( pAig, vStatus, vOutputs, pSim, pPars->fUseRings ); + fChanges = 1; + } + if ( pPars->fVerbose ) + Cec_ManRefinedClassPrintStats( pAig, vStatus, -1, clock() - clkBmc ); + // recycle + Vec_IntFree( vCexStore ); + Vec_StrFree( vStatus ); + Gia_ManStop( pSrm ); + Vec_IntFree( vOutputs ); + } + } + else + { + if ( pPars->fVerbose ) + Cec_ManRefinedClassPrintStats( pAig, NULL, r+1, clock() - clk ); + } + // check the overflow + if ( r == nIterMax ) + printf( "The refinement was not finished. The result may be incorrect.\n" ); + Cec_ManSimStop( pSim ); + clkTotal = clock() - clkTotal; + // report the results + if ( pPars->fVerbose ) + { + ABC_PRTP( "Srm ", clkSrm, clkTotal ); + ABC_PRTP( "Sat ", clkSat, clkTotal ); + ABC_PRTP( "Sim ", clkSim, clkTotal ); + ABC_PRTP( "Other", clkTotal-clkSat-clkSrm-clkSim, clkTotal ); + ABC_PRT( "TOTAL", clkTotal ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Top-level procedure for register correspondence.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Cec_ManLSCorrespondence( Gia_Man_t * pAig, Cec_ParCor_t * pPars ) +{ + Gia_Man_t * pNew, * pTemp; + int RetValue; + RetValue = Cec_ManLSCorrespondenceClasses( pAig, pPars ); + // derive reduced AIG + if ( pPars->fMakeChoices ) + { + pNew = Gia_ManEquivToChoices( pAig, 1 ); + Gia_ManHasChoices( pNew ); + } + else + { + Gia_ManEquivImprove( pAig ); + pNew = Gia_ManCorrReduce( pAig ); + pNew = Gia_ManSeqCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + //Gia_WriteAiger( pNew, "reduced.aig", 0, 0 ); + } + // report the results + if ( pPars->fVerbose ) + { + printf( "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n", + Gia_ManAndNum(pAig), Gia_ManAndNum(pNew), + 100.0*(Gia_ManAndNum(pAig)-Gia_ManAndNum(pNew))/(Gia_ManAndNum(pAig)?Gia_ManAndNum(pAig):1), + Gia_ManRegNum(pAig), Gia_ManRegNum(pNew), + 100.0*(Gia_ManRegNum(pAig)-Gia_ManRegNum(pNew))/(Gia_ManRegNum(pAig)?Gia_ManRegNum(pAig):1) ); + } + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/cec/cecInt.h b/src/proof/cec/cecInt.h new file mode 100644 index 00000000..371dedda --- /dev/null +++ b/src/proof/cec/cecInt.h @@ -0,0 +1,225 @@ +/**CFile**************************************************************** + + FileName [cecInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinational equivalence checking.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cecInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__cec__cecInt_h +#define ABC__aig__cec__cecInt_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "src/sat/bsat/satSolver.h" +#include "src/misc/bar/bar.h" +#include "src/aig/gia/gia.h" +#include "cec.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +// simulation pattern manager +typedef struct Cec_ManPat_t_ Cec_ManPat_t; +struct Cec_ManPat_t_ +{ + Vec_Int_t * vPattern1; // pattern in terms of primary inputs + Vec_Int_t * vPattern2; // pattern in terms of primary inputs + Vec_Str_t * vStorage; // storage for compressed patterns + int iStart; // position in the array where recent patterns begin + int nPats; // total number of recent patterns + int nPatsAll; // total number of all patterns + int nPatLits; // total number of literals in recent patterns + int nPatLitsAll; // total number of literals in all patterns + int nPatLitsMin; // total number of literals in minimized recent patterns + int nPatLitsMinAll; // total number of literals in minimized all patterns + int nSeries; // simulation series + int fVerbose; // verbose stats + // runtime statistics + int timeFind; // detecting the pattern + int timeShrink; // minimizing the pattern + int timeVerify; // verifying the result of minimisation + int timeSort; // sorting literals + int timePack; // packing into sim info structures + int timeTotal; // total runtime + int timeTotalSave; // total runtime for saving +}; + +// SAT solving manager +typedef struct Cec_ManSat_t_ Cec_ManSat_t; +struct Cec_ManSat_t_ +{ + // parameters + Cec_ParSat_t * pPars; + // AIGs used in the package + Gia_Man_t * pAig; // the AIG whose outputs are considered + Vec_Int_t * vStatus; // status for each output + // SAT solving + sat_solver * pSat; // recyclable SAT solver + int nSatVars; // the counter of SAT variables + int * pSatVars; // mapping of each node into its SAT var + Vec_Ptr_t * vUsedNodes; // nodes whose SAT vars are assigned + int nRecycles; // the number of times SAT solver was recycled + int nCallsSince; // the number of calls since the last recycle + Vec_Ptr_t * vFanins; // fanins of the CNF node + // counter-examples + Vec_Int_t * vCex; // the latest counter-example + Vec_Int_t * vVisits; // temporary array for visited nodes + // SAT calls statistics + int nSatUnsat; // the number of proofs + int nSatSat; // the number of failure + int nSatUndec; // the number of timeouts + int nSatTotal; // the number of calls + int nCexLits; + // conflicts + int nConfUnsat; // conflicts in unsat problems + int nConfSat; // conflicts in sat problems + int nConfUndec; // conflicts in undec problems + // runtime stats + int timeSatUnsat; // unsat + int timeSatSat; // sat + int timeSatUndec; // undecided + int timeTotal; // total runtime +}; + +// combinational simulation manager +typedef struct Cec_ManSim_t_ Cec_ManSim_t; +struct Cec_ManSim_t_ +{ + // parameters + Gia_Man_t * pAig; // the AIG to be used for simulation + Cec_ParSim_t * pPars; // simulation parameters + int nWords; // the number of simulation words + // recycable memory + int * pSimInfo; // simulation information offsets + unsigned * pMems; // allocated simulaton memory + int nWordsAlloc; // the number of allocated entries + int nMems; // the number of used entries + int nMemsMax; // the max number of used entries + int MemFree; // next free entry + int nWordsOld; // the number of simulation words after previous relink + // internal simulation info + Vec_Ptr_t * vCiSimInfo; // CI simulation info + Vec_Ptr_t * vCoSimInfo; // CO simulation info + // counter examples + void ** pCexes; // counter-examples for each output + int iOut; // first failed output + int nOuts; // the number of failed outputs + Abc_Cex_t * pCexComb; // counter-example for the first failed output + Abc_Cex_t * pBestState; // the state that led to most of the refinements + // scoring simulation patterns + int * pScores; // counters of refinement for each pattern + // temporaries + Vec_Int_t * vClassOld; // old class numbers + Vec_Int_t * vClassNew; // new class numbers + Vec_Int_t * vClassTemp; // temporary storage + Vec_Int_t * vRefinedC; // refined const reprs +}; + +// combinational simulation manager +typedef struct Cec_ManFra_t_ Cec_ManFra_t; +struct Cec_ManFra_t_ +{ + // parameters + Gia_Man_t * pAig; // the AIG to be used for simulation + Cec_ParFra_t * pPars; // SAT sweeping parameters + // simulation patterns + Vec_Int_t * vXorNodes; // nodes used in speculative reduction + int nAllProved; // total number of proved nodes + int nAllDisproved; // total number of disproved nodes + int nAllFailed; // total number of failed nodes + // runtime stats + int timeSim; // unsat + int timePat; // unsat + int timeSat; // sat + int timeTotal; // total runtime +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== cecCorr.c ============================================================*/ +extern void Cec_ManRefinedClassPrintStats( Gia_Man_t * p, Vec_Str_t * vStatus, int iIter, int Time ); +/*=== cecClass.c ============================================================*/ +extern int Cec_ManSimClassRemoveOne( Cec_ManSim_t * p, int i ); +extern int Cec_ManSimClassesPrepare( Cec_ManSim_t * p, int LevelMax ); +extern int Cec_ManSimClassesRefine( Cec_ManSim_t * p ); +extern int Cec_ManSimSimulateRound( Cec_ManSim_t * p, Vec_Ptr_t * vInfoCis, Vec_Ptr_t * vInfoCos ); +/*=== cecIso.c ============================================================*/ +extern int * Cec_ManDetectIsomorphism( Gia_Man_t * p ); +/*=== cecMan.c ============================================================*/ +extern Cec_ManSat_t * Cec_ManSatCreate( Gia_Man_t * pAig, Cec_ParSat_t * pPars ); +extern void Cec_ManSatPrintStats( Cec_ManSat_t * p ); +extern void Cec_ManSatStop( Cec_ManSat_t * p ); +extern Cec_ManPat_t * Cec_ManPatStart(); +extern void Cec_ManPatPrintStats( Cec_ManPat_t * p ); +extern void Cec_ManPatStop( Cec_ManPat_t * p ); +extern Cec_ManSim_t * Cec_ManSimStart( Gia_Man_t * pAig, Cec_ParSim_t * pPars ); +extern void Cec_ManSimStop( Cec_ManSim_t * p ); +extern Cec_ManFra_t * Cec_ManFraStart( Gia_Man_t * pAig, Cec_ParFra_t * pPars ); +extern void Cec_ManFraStop( Cec_ManFra_t * p ); +/*=== cecPat.c ============================================================*/ +extern void Cec_ManPatSavePattern( Cec_ManPat_t * pPat, Cec_ManSat_t * p, Gia_Obj_t * pObj ); +extern Vec_Ptr_t * Cec_ManPatCollectPatterns( Cec_ManPat_t * pMan, int nInputs, int nWords ); +extern Vec_Ptr_t * Cec_ManPatPackPatterns( Vec_Int_t * vCexStore, int nInputs, int nRegs, int nWordsInit ); +/*=== cecSeq.c ============================================================*/ +extern int Cec_ManSeqResimulate( Cec_ManSim_t * p, Vec_Ptr_t * vInfo ); +extern int Cec_ManSeqResimulateInfo( Gia_Man_t * pAig, Vec_Ptr_t * vSimInfo, Abc_Cex_t * pBestState, int fCheckMiter ); +extern void Cec_ManSeqDeriveInfoInitRandom( Vec_Ptr_t * vInfo, Gia_Man_t * pAig, Abc_Cex_t * pCex ); +extern int Cec_ManCountNonConstOutputs( Gia_Man_t * pAig ); +extern int Cec_ManCheckNonTrivialCands( Gia_Man_t * pAig ); +/*=== cecSolve.c ============================================================*/ +extern int Cec_ObjSatVarValue( Cec_ManSat_t * p, Gia_Obj_t * pObj ); +extern void Cec_ManSatSolve( Cec_ManPat_t * pPat, Gia_Man_t * pAig, Cec_ParSat_t * pPars ); +extern Vec_Str_t * Cec_ManSatSolveSeq( Vec_Ptr_t * vPatts, Gia_Man_t * pAig, Cec_ParSat_t * pPars, int nRegs, int * pnPats ); +extern Vec_Int_t * Cec_ManSatSolveMiter( Gia_Man_t * pAig, Cec_ParSat_t * pPars, Vec_Str_t ** pvStatus ); +extern int Cec_ManSatCheckNode( Cec_ManSat_t * p, Gia_Obj_t * pObj ); +extern int Cec_ManSatCheckNodeTwo( Cec_ManSat_t * p, Gia_Obj_t * pObj1, Gia_Obj_t * pObj2 ); +extern void Cec_ManSavePattern( Cec_ManSat_t * p, Gia_Obj_t * pObj1, Gia_Obj_t * pObj2 ); +extern Vec_Int_t * Cec_ManSatReadCex( Cec_ManSat_t * p ); +/*=== ceFraeep.c ============================================================*/ +extern Gia_Man_t * Cec_ManFraSpecReduction( Cec_ManFra_t * p ); +extern int Cec_ManFraClassesUpdate( Cec_ManFra_t * p, Cec_ManSim_t * pSim, Cec_ManPat_t * pPat, Gia_Man_t * pNew ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/proof/cec/cecIso.c b/src/proof/cec/cecIso.c new file mode 100644 index 00000000..f1ca2ff7 --- /dev/null +++ b/src/proof/cec/cecIso.c @@ -0,0 +1,375 @@ +/**CFile**************************************************************** + + FileName [cecIso.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinational equivalence checking.] + + Synopsis [Detection of structural isomorphism.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cecIso.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cecInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline unsigned * Cec_ManIsoInfo( unsigned * pStore, int nWords, int Id ) { return pStore + nWords * Id; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes simulation info for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManIsoSimulate( Gia_Obj_t * pObj, int Id, unsigned * pStore, int nWords ) +{ + unsigned * pInfo = Cec_ManIsoInfo( pStore, nWords, Id ); + unsigned * pInfo0 = Cec_ManIsoInfo( pStore, nWords, Gia_ObjFaninId0(pObj, Id) ); + unsigned * pInfo1 = Cec_ManIsoInfo( pStore, nWords, Gia_ObjFaninId1(pObj, Id) ); + int w; + if ( Gia_ObjFaninC0(pObj) ) + { + if ( Gia_ObjFaninC1(pObj) ) + for ( w = 0; w < nWords; w++ ) + pInfo[w] = ~(pInfo0[w] | pInfo1[w]); + else + for ( w = 0; w < nWords; w++ ) + pInfo[w] = ~pInfo0[w] & pInfo1[w]; + } + else + { + if ( Gia_ObjFaninC1(pObj) ) + for ( w = 0; w < nWords; w++ ) + pInfo[w] = pInfo0[w] & ~pInfo1[w]; + else + for ( w = 0; w < nWords; w++ ) + pInfo[w] = pInfo0[w] & pInfo1[w]; + } +} + +/**Function************************************************************* + + Synopsis [Copies simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManIsoCopy( int IdDest, int IdSour, unsigned * pStore, int nWords ) +{ + unsigned * pInfo0 = Cec_ManIsoInfo( pStore, nWords, IdDest ); + unsigned * pInfo1 = Cec_ManIsoInfo( pStore, nWords, IdSour ); + int w; + for ( w = 0; w < nWords; w++ ) + pInfo0[w] = pInfo1[w]; +} + +/**Function************************************************************* + + Synopsis [Compares simulation info of two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_ManIsoEqual( int Id0, int Id1, unsigned * pStore, int nWords ) +{ + unsigned * pInfo0 = Cec_ManIsoInfo( pStore, nWords, Id0 ); + unsigned * pInfo1 = Cec_ManIsoInfo( pStore, nWords, Id1 ); + int w; + for ( w = 0; w < nWords; w++ ) + if ( pInfo0[w] != pInfo1[w] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Generates random simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManIsoRandom( int Id, unsigned * pStore, int nWords ) +{ + unsigned * pInfo0 = Cec_ManIsoInfo( pStore, nWords, Id ); + int w; + for ( w = 0; w < nWords; w++ ) + pInfo0[w] = Gia_ManRandom( 0 ); +} + +/**Function************************************************************* + + Synopsis [Computes hash key of the simuation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_ManIsoHashKey( int Id, unsigned * pStore, int nWords, int nTableSize ) +{ + static int s_Primes[16] = { + 1291, 1699, 1999, 2357, 2953, 3313, 3907, 4177, + 4831, 5147, 5647, 6343, 6899, 7103, 7873, 8147 }; + unsigned * pInfo0 = Cec_ManIsoInfo( pStore, nWords, Id ); + unsigned uHash = 0; + int i; + for ( i = 0; i < nWords; i++ ) + uHash ^= pInfo0[i] * s_Primes[i & 0xf]; + return (int)(uHash % nTableSize); + +} + +/**Function************************************************************* + + Synopsis [Adds node to the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManIsoTableAdd( Gia_Man_t * p, int Id, unsigned * pStore, int nWords, int * pTable, int nTableSize ) +{ + Gia_Obj_t * pTemp; + int Key, Ent, Counter = 0, Color = Gia_ObjColors( p, Id ); + assert( Color == 1 || Color == 2 ); + Key = Gia_ManIsoHashKey( Id, pStore, nWords, nTableSize ); + for ( Ent = pTable[Key], pTemp = (Ent ? Gia_ManObj(p, Ent) : NULL); pTemp; + Ent = pTemp->Value, pTemp = (Ent ? Gia_ManObj(p, Ent) : NULL) ) + { + if ( Gia_ObjColors( p, Ent ) != Color ) + continue; + if ( !Gia_ManIsoEqual( Id, Ent, pStore, nWords ) ) + continue; + // found node with the same color and signature - mark it and do not add new node + pTemp->fMark0 = 1; + return; + } + // did not find the node with the same color and signature - add new node + pTemp = Gia_ManObj( p, Id ); + assert( pTemp->Value == 0 ); + assert( pTemp->fMark0 == 0 ); + pTemp->Value = pTable[Key]; + pTable[Key] = Id; +} + +/**Function************************************************************* + + Synopsis [Extracts equivalence class candidates from one bin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_ManIsoExtractClasses( Gia_Man_t * p, int Bin, unsigned * pStore, int nWords, Vec_Int_t * vNodesA, Vec_Int_t * vNodesB ) +{ + Gia_Obj_t * pTemp; + int Ent; + Vec_IntClear( vNodesA ); + Vec_IntClear( vNodesB ); + for ( Ent = Bin, pTemp = (Ent ? Gia_ManObj(p, Ent) : NULL); pTemp; + Ent = pTemp->Value, pTemp = (Ent ? Gia_ManObj(p, Ent) : NULL) ) + { + if ( pTemp->fMark0 ) + { + pTemp->fMark0 = 0; + continue; + } + if ( Gia_ObjColors( p, Ent ) == 1 ) + Vec_IntPush( vNodesA, Ent ); + else + Vec_IntPush( vNodesB, Ent ); + } + return Vec_IntSize(vNodesA) > 0 && Vec_IntSize(vNodesB) > 0; +} + +/**Function************************************************************* + + Synopsis [Matches nodes in the extacted classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManIsoMatchNodes( int * pIso, unsigned * pStore, int nWords, Vec_Int_t * vNodesA, Vec_Int_t * vNodesB ) +{ + int k0, k1, IdA, IdB; + Vec_IntForEachEntry( vNodesA, IdA, k0 ) + Vec_IntForEachEntry( vNodesB, IdB, k1 ) + { + if ( Gia_ManIsoEqual( IdA, IdB, pStore, nWords ) ) + { + assert( pIso[IdA] == 0 ); + assert( pIso[IdB] == 0 ); + assert( IdA != IdB ); + pIso[IdA] = IdB; + pIso[IdB] = IdA; + continue; + } + } +} + +/**Function************************************************************* + + Synopsis [Transforms iso into equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManTransformClasses( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + assert( p->pReprs && p->pNexts && p->pIso ); + memset( p->pReprs, 0, sizeof(int) * Gia_ManObjNum(p) ); + memset( p->pNexts, 0, sizeof(int) * Gia_ManObjNum(p) ); + Gia_ManForEachObj( p, pObj, i ) + { + p->pReprs[i].iRepr = GIA_VOID; + if ( p->pIso[i] && p->pIso[i] < i ) + { + p->pReprs[i].iRepr = p->pIso[i]; + p->pNexts[p->pIso[i]] = i; + } + } +} + +/**Function************************************************************* + + Synopsis [Finds node correspondences in the miter.] + + Description [Assumes that the colors are assigned.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Cec_ManDetectIsomorphism( Gia_Man_t * p ) +{ + int nWords = 2; + Gia_Obj_t * pObj; + Vec_Int_t * vNodesA, * vNodesB; + unsigned * pStore, Counter; + int i, * pIso, * pTable, nTableSize; + // start equivalence classes + pIso = ABC_CALLOC( int, Gia_ManObjNum(p) ); + Gia_ManForEachObj( p, pObj, i ) + { + if ( Gia_ObjIsCo(pObj) ) + { + assert( Gia_ObjColors(p, i) == 0 ); + continue; + } + assert( Gia_ObjColors(p, i) ); + if ( Gia_ObjColors(p, i) == 3 ) + pIso[i] = i; + } + // start simulation info + pStore = ABC_ALLOC( unsigned, Gia_ManObjNum(p) * nWords ); + // simulate and create table + nTableSize = Abc_PrimeCudd( 100 + Gia_ManObjNum(p)/2 ); + pTable = ABC_CALLOC( int, nTableSize ); + Gia_ManCleanValue( p ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsCo(pObj) ) + continue; + if ( pIso[i] == 0 ) // simulate + Gia_ManIsoSimulate( pObj, i, pStore, nWords ); + else if ( pIso[i] < i ) // copy + Gia_ManIsoCopy( i, pIso[i], pStore, nWords ); + else // generate + Gia_ManIsoRandom( i, pStore, nWords ); + if ( pIso[i] == 0 ) + Gia_ManIsoTableAdd( p, i, pStore, nWords, pTable, nTableSize ); + } + // create equivalence classes + vNodesA = Vec_IntAlloc( 100 ); + vNodesB = Vec_IntAlloc( 100 ); + for ( i = 0; i < nTableSize; i++ ) + if ( Gia_ManIsoExtractClasses( p, pTable[i], pStore, nWords, vNodesA, vNodesB ) ) + Gia_ManIsoMatchNodes( pIso, pStore, nWords, vNodesA, vNodesB ); + Vec_IntFree( vNodesA ); + Vec_IntFree( vNodesB ); + // collect info + Counter = 0; + Gia_ManForEachObj1( p, pObj, i ) + { + Counter += (pIso[i] && pIso[i] < i); +/* + if ( pIso[i] && pIso[i] < i ) + { + if ( (Gia_ObjIsHead(p,pIso[i]) && Gia_ObjRepr(p,i)==pIso[i]) || + (Gia_ObjIsClass(p,pIso[i]) && Gia_ObjRepr(p,i)==Gia_ObjRepr(p,pIso[i])) ) + Abc_Print( 1, "1" ); + else + Abc_Print( 1, "0" ); + } +*/ + } + Abc_Print( 1, "Computed %d pairs of structurally equivalent nodes.\n", Counter ); +// p->pIso = pIso; +// Cec_ManTransformClasses( p ); + + ABC_FREE( pTable ); + ABC_FREE( pStore ); + return pIso; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/cec/cecMan.c b/src/proof/cec/cecMan.c new file mode 100644 index 00000000..f03ec701 --- /dev/null +++ b/src/proof/cec/cecMan.c @@ -0,0 +1,297 @@ +/**CFile**************************************************************** + + FileName [cecMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinational equivalence checking.] + + Synopsis [Manager procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cecMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cecInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cec_ManSat_t * Cec_ManSatCreate( Gia_Man_t * pAig, Cec_ParSat_t * pPars ) +{ + Cec_ManSat_t * p; + // create interpolation manager + p = ABC_ALLOC( Cec_ManSat_t, 1 ); + memset( p, 0, sizeof(Cec_ManSat_t) ); + p->pPars = pPars; + p->pAig = pAig; + // SAT solving + p->nSatVars = 1; + p->pSatVars = ABC_CALLOC( int, Gia_ManObjNum(pAig) ); + p->vUsedNodes = Vec_PtrAlloc( 1000 ); + p->vFanins = Vec_PtrAlloc( 100 ); + p->vCex = Vec_IntAlloc( 100 ); + p->vVisits = Vec_IntAlloc( 100 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Prints statistics of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManSatPrintStats( Cec_ManSat_t * p ) +{ + Abc_Print( 1, "CO = %8d ", Gia_ManCoNum(p->pAig) ); + Abc_Print( 1, "AND = %8d ", Gia_ManAndNum(p->pAig) ); + Abc_Print( 1, "Conf = %5d ", p->pPars->nBTLimit ); + Abc_Print( 1, "MinVar = %5d ", p->pPars->nSatVarMax ); + Abc_Print( 1, "MinCalls = %5d\n", p->pPars->nCallsRecycle ); + Abc_Print( 1, "Unsat calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatUnsat, p->nSatTotal? 100.0*p->nSatUnsat/p->nSatTotal : 0.0, p->nSatUnsat? 1.0*p->nConfUnsat/p->nSatUnsat :0.0 ); + Abc_PrintTimeP( 1, "Time", p->timeSatUnsat, p->timeTotal ); + Abc_Print( 1, "Sat calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatSat, p->nSatTotal? 100.0*p->nSatSat/p->nSatTotal : 0.0, p->nSatSat? 1.0*p->nConfSat/p->nSatSat : 0.0 ); + Abc_PrintTimeP( 1, "Time", p->timeSatSat, p->timeTotal ); + Abc_Print( 1, "Undef calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatUndec, p->nSatTotal? 100.0*p->nSatUndec/p->nSatTotal : 0.0, p->nSatUndec? 1.0*p->nConfUndec/p->nSatUndec : 0.0 ); + Abc_PrintTimeP( 1, "Time", p->timeSatUndec, p->timeTotal ); + Abc_PrintTime( 1, "Total time", p->timeTotal ); +} + +/**Function************************************************************* + + Synopsis [Frees the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManSatStop( Cec_ManSat_t * p ) +{ + if ( p->pSat ) + sat_solver_delete( p->pSat ); + Vec_IntFree( p->vCex ); + Vec_IntFree( p->vVisits ); + Vec_PtrFree( p->vUsedNodes ); + Vec_PtrFree( p->vFanins ); + ABC_FREE( p->pSatVars ); + ABC_FREE( p ); +} + + + +/**Function************************************************************* + + Synopsis [Creates AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cec_ManPat_t * Cec_ManPatStart() +{ + Cec_ManPat_t * p; + p = ABC_CALLOC( Cec_ManPat_t, 1 ); + p->vStorage = Vec_StrAlloc( 1<<20 ); + p->vPattern1 = Vec_IntAlloc( 1000 ); + p->vPattern2 = Vec_IntAlloc( 1000 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Creates AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManPatPrintStats( Cec_ManPat_t * p ) +{ + Abc_Print( 1, "Latest: P = %8d. L = %10d. Lm = %10d. Ave = %6.1f. MEM =%6.2f Mb\n", + p->nPats, p->nPatLits, p->nPatLitsMin, 1.0 * p->nPatLitsMin/p->nPats, + 1.0*(Vec_StrSize(p->vStorage)-p->iStart)/(1<<20) ); + Abc_Print( 1, "Total: P = %8d. L = %10d. Lm = %10d. Ave = %6.1f. MEM =%6.2f Mb\n", + p->nPatsAll, p->nPatLitsAll, p->nPatLitsMinAll, 1.0 * p->nPatLitsMinAll/p->nPatsAll, + 1.0*Vec_StrSize(p->vStorage)/(1<<20) ); + Abc_PrintTimeP( 1, "Finding ", p->timeFind, p->timeTotal ); + Abc_PrintTimeP( 1, "Shrinking", p->timeShrink, p->timeTotal ); + Abc_PrintTimeP( 1, "Verifying", p->timeVerify, p->timeTotal ); + Abc_PrintTimeP( 1, "Sorting ", p->timeSort, p->timeTotal ); + Abc_PrintTimeP( 1, "Packing ", p->timePack, p->timeTotal ); + Abc_PrintTime( 1, "TOTAL ", p->timeTotal ); +} + +/**Function************************************************************* + + Synopsis [Deletes AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManPatStop( Cec_ManPat_t * p ) +{ + Vec_StrFree( p->vStorage ); + Vec_IntFree( p->vPattern1 ); + Vec_IntFree( p->vPattern2 ); + ABC_FREE( p ); +} + + + +/**Function************************************************************* + + Synopsis [Creates AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cec_ManSim_t * Cec_ManSimStart( Gia_Man_t * pAig, Cec_ParSim_t * pPars ) +{ + Cec_ManSim_t * p; + p = ABC_ALLOC( Cec_ManSim_t, 1 ); + memset( p, 0, sizeof(Cec_ManSim_t) ); + p->pAig = pAig; + p->pPars = pPars; + p->nWords = pPars->nWords; + p->pSimInfo = ABC_CALLOC( int, Gia_ManObjNum(pAig) ); + p->vClassOld = Vec_IntAlloc( 1000 ); + p->vClassNew = Vec_IntAlloc( 1000 ); + p->vClassTemp = Vec_IntAlloc( 1000 ); + p->vRefinedC = Vec_IntAlloc( 10000 ); + p->vCiSimInfo = Vec_PtrAllocSimInfo( Gia_ManCiNum(p->pAig), pPars->nWords ); + if ( pPars->fCheckMiter || Gia_ManRegNum(p->pAig) ) + { + p->vCoSimInfo = Vec_PtrAllocSimInfo( Gia_ManCoNum(p->pAig), pPars->nWords ); + Vec_PtrCleanSimInfo( p->vCoSimInfo, 0, pPars->nWords ); + } + p->iOut = -1; + return p; +} + +/**Function************************************************************* + + Synopsis [Deletes AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManSimStop( Cec_ManSim_t * p ) +{ + Vec_IntFree( p->vClassOld ); + Vec_IntFree( p->vClassNew ); + Vec_IntFree( p->vClassTemp ); + Vec_IntFree( p->vRefinedC ); + if ( p->vCiSimInfo ) + Vec_PtrFree( p->vCiSimInfo ); + if ( p->vCoSimInfo ) + Vec_PtrFree( p->vCoSimInfo ); + ABC_FREE( p->pScores ); + ABC_FREE( p->pCexComb ); + ABC_FREE( p->pCexes ); + ABC_FREE( p->pMems ); + ABC_FREE( p->pSimInfo ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [Creates AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cec_ManFra_t * Cec_ManFraStart( Gia_Man_t * pAig, Cec_ParFra_t * pPars ) +{ + Cec_ManFra_t * p; + p = ABC_ALLOC( Cec_ManFra_t, 1 ); + memset( p, 0, sizeof(Cec_ManFra_t) ); + p->pAig = pAig; + p->pPars = pPars; + p->vXorNodes = Vec_IntAlloc( 1000 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Deletes AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManFraStop( Cec_ManFra_t * p ) +{ + Vec_IntFree( p->vXorNodes ); + ABC_FREE( p ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/cec/cecPat.c b/src/proof/cec/cecPat.c new file mode 100644 index 00000000..cb1dae46 --- /dev/null +++ b/src/proof/cec/cecPat.c @@ -0,0 +1,569 @@ +/**CFile**************************************************************** + + FileName [cecPat.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinational equivalence checking.] + + Synopsis [Simulation pattern manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cecPat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cecInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cec_ManPatStoreNum( Cec_ManPat_t * p, int Num ) +{ + unsigned x = (unsigned)Num; + assert( Num >= 0 ); + while ( x & ~0x7f ) + { + Vec_StrPush( p->vStorage, (char)((x & 0x7f) | 0x80) ); + x >>= 7; + } + Vec_StrPush( p->vStorage, (char)x ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cec_ManPatRestoreNum( Cec_ManPat_t * p ) +{ + int ch, i, x = 0; + for ( i = 0; (ch = Vec_StrEntry(p->vStorage, p->iStart++)) & 0x80; i++ ) + x |= (ch & 0x7f) << (7 * i); + return x | (ch << (7 * i)); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cec_ManPatStore( Cec_ManPat_t * p, Vec_Int_t * vPat ) +{ + int i, Number, NumberPrev; + assert( Vec_IntSize(vPat) > 0 ); + Cec_ManPatStoreNum( p, Vec_IntSize(vPat) ); + NumberPrev = Vec_IntEntry( vPat, 0 ); + Cec_ManPatStoreNum( p, NumberPrev ); + Vec_IntForEachEntryStart( vPat, Number, i, 1 ) + { + assert( NumberPrev < Number ); + Cec_ManPatStoreNum( p, Number - NumberPrev ); + NumberPrev = Number; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cec_ManPatRestore( Cec_ManPat_t * p, Vec_Int_t * vPat ) +{ + int i, Size, Number; + Vec_IntClear( vPat ); + Size = Cec_ManPatRestoreNum( p ); + Number = Cec_ManPatRestoreNum( p ); + Vec_IntPush( vPat, Number ); + for ( i = 1; i < Size; i++ ) + { + Number += Cec_ManPatRestoreNum( p ); + Vec_IntPush( vPat, Number ); + } + assert( Vec_IntSize(vPat) == Size ); +} + + +/**Function************************************************************* + + Synopsis [Derives satisfying assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManPatComputePattern_rec( Cec_ManSat_t * pSat, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + int Counter = 0; + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return 0; + Gia_ObjSetTravIdCurrent(p, pObj); + if ( Gia_ObjIsCi(pObj) ) + { + pObj->fMark1 = Cec_ObjSatVarValue( pSat, pObj ); + return 1; + } + assert( Gia_ObjIsAnd(pObj) ); + Counter += Cec_ManPatComputePattern_rec( pSat, p, Gia_ObjFanin0(pObj) ); + Counter += Cec_ManPatComputePattern_rec( pSat, p, Gia_ObjFanin1(pObj) ); + pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) & + (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj)); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Derives satisfying assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManPatComputePattern1_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vPat ) +{ + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return; + Gia_ObjSetTravIdCurrent(p, pObj); + if ( Gia_ObjIsCi(pObj) ) + { + Vec_IntPush( vPat, Abc_Var2Lit( Gia_ObjCioId(pObj), pObj->fMark1==0 ) ); + return; + } + assert( Gia_ObjIsAnd(pObj) ); + if ( pObj->fMark1 == 1 ) + { + Cec_ManPatComputePattern1_rec( p, Gia_ObjFanin0(pObj), vPat ); + Cec_ManPatComputePattern1_rec( p, Gia_ObjFanin1(pObj), vPat ); + } + else + { + assert( (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) == 0 || + (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj)) == 0 ); + if ( (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) == 0 ) + Cec_ManPatComputePattern1_rec( p, Gia_ObjFanin0(pObj), vPat ); + else + Cec_ManPatComputePattern1_rec( p, Gia_ObjFanin1(pObj), vPat ); + } +} + +/**Function************************************************************* + + Synopsis [Derives satisfying assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManPatComputePattern2_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vPat ) +{ + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return; + Gia_ObjSetTravIdCurrent(p, pObj); + if ( Gia_ObjIsCi(pObj) ) + { + Vec_IntPush( vPat, Abc_Var2Lit( Gia_ObjCioId(pObj), pObj->fMark1==0 ) ); + return; + } + assert( Gia_ObjIsAnd(pObj) ); + if ( pObj->fMark1 == 1 ) + { + Cec_ManPatComputePattern2_rec( p, Gia_ObjFanin0(pObj), vPat ); + Cec_ManPatComputePattern2_rec( p, Gia_ObjFanin1(pObj), vPat ); + } + else + { + assert( (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) == 0 || + (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj)) == 0 ); + if ( (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj)) == 0 ) + Cec_ManPatComputePattern2_rec( p, Gia_ObjFanin1(pObj), vPat ); + else + Cec_ManPatComputePattern2_rec( p, Gia_ObjFanin0(pObj), vPat ); + } +} + +/**Function************************************************************* + + Synopsis [Derives satisfying assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManPatComputePattern3_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + int Value0, Value1, Value; + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return (pObj->fMark1 << 1) | pObj->fMark0; + Gia_ObjSetTravIdCurrent(p, pObj); + if ( Gia_ObjIsCi(pObj) ) + { + pObj->fMark0 = 1; + pObj->fMark1 = 1; + return GIA_UND; + } + assert( Gia_ObjIsAnd(pObj) ); + Value0 = Cec_ManPatComputePattern3_rec( p, Gia_ObjFanin0(pObj) ); + Value1 = Cec_ManPatComputePattern3_rec( p, Gia_ObjFanin1(pObj) ); + Value = Gia_XsimAndCond( Value0, Gia_ObjFaninC0(pObj), Value1, Gia_ObjFaninC1(pObj) ); + pObj->fMark0 = (Value & 1); + pObj->fMark1 = ((Value >> 1) & 1); + return Value; +} + +/**Function************************************************************* + + Synopsis [Derives satisfying assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManPatVerifyPattern( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vPat ) +{ + Gia_Obj_t * pTemp; + int i, Value; + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vPat, Value, i ) + { + pTemp = Gia_ManCi( p, Abc_Lit2Var(Value) ); +// assert( Abc_LitIsCompl(Value) != (int)pTemp->fMark1 ); + if ( pTemp->fMark1 ) + { + pTemp->fMark0 = 0; + pTemp->fMark1 = 1; + } + else + { + pTemp->fMark0 = 1; + pTemp->fMark1 = 0; + } + Gia_ObjSetTravIdCurrent( p, pTemp ); + } + Value = Cec_ManPatComputePattern3_rec( p, Gia_ObjFanin0(pObj) ); + Value = Gia_XsimNotCond( Value, Gia_ObjFaninC0(pObj) ); + if ( Value != GIA_ONE ) + Abc_Print( 1, "Cec_ManPatVerifyPattern(): Verification failed.\n" ); + assert( Value == GIA_ONE ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManPatComputePattern4_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return; + Gia_ObjSetTravIdCurrent(p, pObj); + pObj->fMark0 = 0; + if ( Gia_ObjIsCi(pObj) ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Cec_ManPatComputePattern4_rec( p, Gia_ObjFanin0(pObj) ); + Cec_ManPatComputePattern4_rec( p, Gia_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManPatCleanMark0( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + assert( Gia_ObjIsCo(pObj) ); + Gia_ManIncrementTravId( p ); + Cec_ManPatComputePattern4_rec( p, Gia_ObjFanin0(pObj) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManPatSavePattern( Cec_ManPat_t * pMan, Cec_ManSat_t * p, Gia_Obj_t * pObj ) +{ + Vec_Int_t * vPat; + int nPatLits, clk, clkTotal = clock(); + assert( Gia_ObjIsCo(pObj) ); + pMan->nPats++; + pMan->nPatsAll++; + // compute values in the cone of influence +clk = clock(); + Gia_ManIncrementTravId( p->pAig ); + nPatLits = Cec_ManPatComputePattern_rec( p, p->pAig, Gia_ObjFanin0(pObj) ); + assert( (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) == 1 ); + pMan->nPatLits += nPatLits; + pMan->nPatLitsAll += nPatLits; +pMan->timeFind += clock() - clk; + // compute sensitizing path +clk = clock(); + Vec_IntClear( pMan->vPattern1 ); + Gia_ManIncrementTravId( p->pAig ); + Cec_ManPatComputePattern1_rec( p->pAig, Gia_ObjFanin0(pObj), pMan->vPattern1 ); + // compute sensitizing path + Vec_IntClear( pMan->vPattern2 ); + Gia_ManIncrementTravId( p->pAig ); + Cec_ManPatComputePattern2_rec( p->pAig, Gia_ObjFanin0(pObj), pMan->vPattern2 ); + // compare patterns + vPat = Vec_IntSize(pMan->vPattern1) < Vec_IntSize(pMan->vPattern2) ? pMan->vPattern1 : pMan->vPattern2; + pMan->nPatLitsMin += Vec_IntSize(vPat); + pMan->nPatLitsMinAll += Vec_IntSize(vPat); +pMan->timeShrink += clock() - clk; + // verify pattern using ternary simulation +clk = clock(); + Cec_ManPatVerifyPattern( p->pAig, pObj, vPat ); +pMan->timeVerify += clock() - clk; + // sort pattern +clk = clock(); + Vec_IntSort( vPat, 0 ); +pMan->timeSort += clock() - clk; + // save pattern + Cec_ManPatStore( pMan, vPat ); + pMan->timeTotal += clock() - clkTotal; +} + +/**Function************************************************************* + + Synopsis [Packs patterns into array of simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +*************************************`**********************************/ +int Cec_ManPatCollectTry( Vec_Ptr_t * vInfo, Vec_Ptr_t * vPres, int iBit, int * pLits, int nLits ) +{ + unsigned * pInfo, * pPres; + int i; + for ( i = 0; i < nLits; i++ ) + { + pInfo = (unsigned *)Vec_PtrEntry(vInfo, Abc_Lit2Var(pLits[i])); + pPres = (unsigned *)Vec_PtrEntry(vPres, Abc_Lit2Var(pLits[i])); + if ( Abc_InfoHasBit( pPres, iBit ) && + Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(pLits[i]) ) + return 0; + } + for ( i = 0; i < nLits; i++ ) + { + pInfo = (unsigned *)Vec_PtrEntry(vInfo, Abc_Lit2Var(pLits[i])); + pPres = (unsigned *)Vec_PtrEntry(vPres, Abc_Lit2Var(pLits[i])); + Abc_InfoSetBit( pPres, iBit ); + if ( Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(pLits[i]) ) + Abc_InfoXorBit( pInfo, iBit ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Packs patterns into array of simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Cec_ManPatCollectPatterns( Cec_ManPat_t * pMan, int nInputs, int nWordsInit ) +{ + Vec_Int_t * vPat = pMan->vPattern1; + Vec_Ptr_t * vInfo, * vPres; + int k, kMax = -1, nPatterns = 0; + int iStartOld = pMan->iStart; + int nWords = nWordsInit; + int nBits = 32 * nWords; + int clk = clock(); + vInfo = Vec_PtrAllocSimInfo( nInputs, nWords ); + Gia_ManRandomInfo( vInfo, 0, 0, nWords ); + vPres = Vec_PtrAllocSimInfo( nInputs, nWords ); + Vec_PtrCleanSimInfo( vPres, 0, nWords ); + while ( pMan->iStart < Vec_StrSize(pMan->vStorage) ) + { + nPatterns++; + Cec_ManPatRestore( pMan, vPat ); + for ( k = 1; k < nBits; k++, k += ((k % (32 * nWordsInit)) == 0) ) + if ( Cec_ManPatCollectTry( vInfo, vPres, k, (int *)Vec_IntArray(vPat), Vec_IntSize(vPat) ) ) + break; + kMax = Abc_MaxInt( kMax, k ); + if ( k == nBits-1 ) + { + Vec_PtrReallocSimInfo( vInfo ); + Gia_ManRandomInfo( vInfo, 0, nWords, 2*nWords ); + Vec_PtrReallocSimInfo( vPres ); + Vec_PtrCleanSimInfo( vPres, nWords, 2*nWords ); + nWords *= 2; + nBits *= 2; + } + } + Vec_PtrFree( vPres ); + pMan->nSeries = Vec_PtrReadWordsSimInfo(vInfo) / nWordsInit; + pMan->timePack += clock() - clk; + pMan->timeTotal += clock() - clk; + pMan->iStart = iStartOld; + if ( pMan->fVerbose ) + { + Abc_Print( 1, "Total = %5d. Max used = %5d. Full = %5d. Series = %d. ", + nPatterns, kMax, nWordsInit*32, pMan->nSeries ); + ABC_PRT( "Time", clock() - clk ); + Cec_ManPatPrintStats( pMan ); + } + return vInfo; +} + + +/**Function************************************************************* + + Synopsis [Packs patterns into array of simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Cec_ManPatPackPatterns( Vec_Int_t * vCexStore, int nInputs, int nRegs, int nWordsInit ) +{ + Vec_Int_t * vPat; + Vec_Ptr_t * vInfo, * vPres; + int k, nSize, iStart, kMax = 0, nPatterns = 0; + int nWords = nWordsInit; + int nBits = 32 * nWords; +// int RetValue; + assert( nRegs <= nInputs ); + vPat = Vec_IntAlloc( 100 ); + + vInfo = Vec_PtrAllocSimInfo( nInputs, nWords ); + Vec_PtrCleanSimInfo( vInfo, 0, nWords ); + Gia_ManRandomInfo( vInfo, nRegs, 0, nWords ); + + vPres = Vec_PtrAllocSimInfo( nInputs, nWords ); + Vec_PtrCleanSimInfo( vPres, 0, nWords ); + iStart = 0; + while ( iStart < Vec_IntSize(vCexStore) ) + { + nPatterns++; + // skip the output number + iStart++; + // get the number of items + nSize = Vec_IntEntry( vCexStore, iStart++ ); + if ( nSize <= 0 ) + continue; + // extract pattern + Vec_IntClear( vPat ); + for ( k = 0; k < nSize; k++ ) + Vec_IntPush( vPat, Vec_IntEntry( vCexStore, iStart++ ) ); + // add pattern to storage + for ( k = 1; k < nBits; k++, k += ((k % (32 * nWordsInit)) == 0) ) + if ( Cec_ManPatCollectTry( vInfo, vPres, k, (int *)Vec_IntArray(vPat), Vec_IntSize(vPat) ) ) + break; + +// k = kMax + 1; +// RetValue = Cec_ManPatCollectTry( vInfo, vPres, k, (int *)Vec_IntArray(vPat), Vec_IntSize(vPat) ); +// assert( RetValue == 1 ); + + kMax = Abc_MaxInt( kMax, k ); + if ( k == nBits-1 ) + { + Vec_PtrReallocSimInfo( vInfo ); + Vec_PtrCleanSimInfo( vInfo, nWords, 2*nWords ); + Gia_ManRandomInfo( vInfo, nRegs, nWords, 2*nWords ); + + Vec_PtrReallocSimInfo( vPres ); + Vec_PtrCleanSimInfo( vPres, nWords, 2*nWords ); + nWords *= 2; + nBits *= 2; + } + } +// Abc_Print( 1, "packed %d patterns into %d vectors (out of %d)\n", nPatterns, kMax, nBits ); + Vec_PtrFree( vPres ); + Vec_IntFree( vPat ); + return vInfo; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/cec/cecSeq.c b/src/proof/cec/cecSeq.c new file mode 100644 index 00000000..21ed8656 --- /dev/null +++ b/src/proof/cec/cecSeq.c @@ -0,0 +1,448 @@ +/**CFile**************************************************************** + + FileName [cecSeq.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinational equivalence checking.] + + Synopsis [Refinement of sequential equivalence classes.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cecSeq.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cecInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Sets register values from the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManSeqDeriveInfoFromCex( Vec_Ptr_t * vInfo, Gia_Man_t * pAig, Abc_Cex_t * pCex ) +{ + unsigned * pInfo; + int k, i, w, nWords; + assert( pCex->nBits == pCex->nRegs + pCex->nPis * (pCex->iFrame + 1) ); + assert( pCex->nBits - pCex->nRegs + Gia_ManRegNum(pAig) <= Vec_PtrSize(vInfo) ); + nWords = Vec_PtrReadWordsSimInfo( vInfo ); +/* + // user register values + assert( pCex->nRegs == Gia_ManRegNum(pAig) ); + for ( k = 0; k < pCex->nRegs; k++ ) + { + pInfo = (unsigned *)Vec_PtrEntry( vInfo, k ); + for ( w = 0; w < nWords; w++ ) + pInfo[w] = Abc_InfoHasBit( pCex->pData, k )? ~0 : 0; + } +*/ + // print warning about register values + for ( k = 0; k < pCex->nRegs; k++ ) + if ( Abc_InfoHasBit( pCex->pData, k ) ) + break; + if ( k < pCex->nRegs ) + Abc_Print( 0, "The CEX has flop values different from 0, but they are currently not used by \"resim\".\n" ); + + // assign zero register values + for ( k = 0; k < Gia_ManRegNum(pAig); k++ ) + { + pInfo = (unsigned *)Vec_PtrEntry( vInfo, k ); + for ( w = 0; w < nWords; w++ ) + pInfo[w] = 0; + } + for ( i = pCex->nRegs; i < pCex->nBits; i++ ) + { + pInfo = (unsigned *)Vec_PtrEntry( vInfo, k++ ); + for ( w = 0; w < nWords; w++ ) + pInfo[w] = Gia_ManRandom(0); + // set simulation pattern and make sure it is second (first will be erased during simulation) + pInfo[0] = (pInfo[0] << 1) | Abc_InfoHasBit( pCex->pData, i ); + pInfo[0] <<= 1; + } + for ( ; k < Vec_PtrSize(vInfo); k++ ) + { + pInfo = (unsigned *)Vec_PtrEntry( vInfo, k ); + for ( w = 0; w < nWords; w++ ) + pInfo[w] = Gia_ManRandom(0); + } +} + +/**Function************************************************************* + + Synopsis [Sets register values from the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManSeqDeriveInfoInitRandom( Vec_Ptr_t * vInfo, Gia_Man_t * pAig, Abc_Cex_t * pCex ) +{ + unsigned * pInfo; + int k, w, nWords; + nWords = Vec_PtrReadWordsSimInfo( vInfo ); + assert( pCex == NULL || Gia_ManRegNum(pAig) == pCex->nRegs ); + assert( Gia_ManRegNum(pAig) <= Vec_PtrSize(vInfo) ); + for ( k = 0; k < Gia_ManRegNum(pAig); k++ ) + { + pInfo = (unsigned *)Vec_PtrEntry( vInfo, k ); + for ( w = 0; w < nWords; w++ ) + pInfo[w] = (pCex && Abc_InfoHasBit(pCex->pData, k))? ~0 : 0; + } + + for ( ; k < Vec_PtrSize(vInfo); k++ ) + { + pInfo = (unsigned *)Vec_PtrEntry( vInfo, k ); + for ( w = 0; w < nWords; w++ ) + pInfo[w] = Gia_ManRandom( 0 ); + } +} + +/**Function************************************************************* + + Synopsis [Resimulates the classes using sequential simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManSeqResimulate( Cec_ManSim_t * p, Vec_Ptr_t * vInfo ) +{ + unsigned * pInfo0, * pInfo1; + int f, i, k, w; +// assert( Gia_ManRegNum(p->pAig) > 0 ); + assert( Vec_PtrSize(vInfo) == Gia_ManRegNum(p->pAig) + Gia_ManPiNum(p->pAig) * p->pPars->nFrames ); + for ( k = 0; k < Gia_ManRegNum(p->pAig); k++ ) + { + pInfo0 = (unsigned *)Vec_PtrEntry( vInfo, k ); + pInfo1 = (unsigned *)Vec_PtrEntry( p->vCoSimInfo, Gia_ManPoNum(p->pAig) + k ); + for ( w = 0; w < p->nWords; w++ ) + pInfo1[w] = pInfo0[w]; + } + for ( f = 0; f < p->pPars->nFrames; f++ ) + { + for ( i = 0; i < Gia_ManPiNum(p->pAig); i++ ) + { + pInfo0 = (unsigned *)Vec_PtrEntry( vInfo, k++ ); + pInfo1 = (unsigned *)Vec_PtrEntry( p->vCiSimInfo, i ); + for ( w = 0; w < p->nWords; w++ ) + pInfo1[w] = pInfo0[w]; + } + for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) + { + pInfo0 = (unsigned *)Vec_PtrEntry( p->vCoSimInfo, Gia_ManPoNum(p->pAig) + i ); + pInfo1 = (unsigned *)Vec_PtrEntry( p->vCiSimInfo, Gia_ManPiNum(p->pAig) + i ); + for ( w = 0; w < p->nWords; w++ ) + pInfo1[w] = pInfo0[w]; + } + if ( Cec_ManSimSimulateRound( p, p->vCiSimInfo, p->vCoSimInfo ) ) + return 1; + } + assert( k == Vec_PtrSize(vInfo) ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Resimulates information to refine equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManSeqResimulateInfo( Gia_Man_t * pAig, Vec_Ptr_t * vSimInfo, Abc_Cex_t * pBestState, int fCheckMiter ) +{ + Cec_ParSim_t ParsSim, * pParsSim = &ParsSim; + Cec_ManSim_t * pSim; + int RetValue, clkTotal = clock(); + assert( (Vec_PtrSize(vSimInfo) - Gia_ManRegNum(pAig)) % Gia_ManPiNum(pAig) == 0 ); + Cec_ManSimSetDefaultParams( pParsSim ); + pParsSim->nFrames = (Vec_PtrSize(vSimInfo) - Gia_ManRegNum(pAig)) / Gia_ManPiNum(pAig); + pParsSim->nWords = Vec_PtrReadWordsSimInfo( vSimInfo ); + pParsSim->fCheckMiter = fCheckMiter; + Gia_ManSetRefs( pAig ); + pSim = Cec_ManSimStart( pAig, pParsSim ); + if ( pBestState ) + pSim->pBestState = pBestState; + RetValue = Cec_ManSeqResimulate( pSim, vSimInfo ); + pSim->pBestState = NULL; + Cec_ManSimStop( pSim ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Resimuates one counter-example to refine equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManSeqResimulateCounter( Gia_Man_t * pAig, Cec_ParSim_t * pPars, Abc_Cex_t * pCex ) +{ + Vec_Ptr_t * vSimInfo; + int RetValue, clkTotal = clock(); + if ( pCex == NULL ) + { + Abc_Print( 1, "Cec_ManSeqResimulateCounter(): Counter-example is not available.\n" ); + return -1; + } + if ( pAig->pReprs == NULL ) + { + Abc_Print( 1, "Cec_ManSeqResimulateCounter(): Equivalence classes are not available.\n" ); + return -1; + } + if ( Gia_ManRegNum(pAig) == 0 ) + { + Abc_Print( 1, "Cec_ManSeqResimulateCounter(): Not a sequential AIG.\n" ); + return -1; + } +// if ( Gia_ManRegNum(pAig) != pCex->nRegs || Gia_ManPiNum(pAig) != pCex->nPis ) + if ( Gia_ManPiNum(pAig) != pCex->nPis ) + { + Abc_Print( 1, "Cec_ManSeqResimulateCounter(): The number of PIs in the AIG and the counter-example differ.\n" ); + return -1; + } + if ( pPars->fVerbose ) + Abc_Print( 1, "Resimulating %d timeframes.\n", pPars->nFrames + pCex->iFrame + 1 ); + Gia_ManRandom( 1 ); + vSimInfo = Vec_PtrAllocSimInfo( Gia_ManRegNum(pAig) + + Gia_ManPiNum(pAig) * (pPars->nFrames + pCex->iFrame + 1), 1 ); + Cec_ManSeqDeriveInfoFromCex( vSimInfo, pAig, pCex ); + if ( pPars->fVerbose ) + Gia_ManEquivPrintClasses( pAig, 0, 0 ); + RetValue = Cec_ManSeqResimulateInfo( pAig, vSimInfo, NULL, pPars->fCheckMiter ); + if ( pPars->fVerbose ) + Gia_ManEquivPrintClasses( pAig, 0, 0 ); + Vec_PtrFree( vSimInfo ); + if ( pPars->fVerbose ) + ABC_PRT( "Time", clock() - clkTotal ); +// if ( RetValue && pPars->fCheckMiter ) +// Abc_Print( 1, "Cec_ManSeqResimulateCounter(): An output of the miter is asserted!\n" ); + return RetValue; +} + + +/**Function************************************************************* + + Synopsis [Returns the number of POs that are not const0 cands.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManCountNonConstOutputs( Gia_Man_t * pAig ) +{ + Gia_Obj_t * pObj; + int i, Counter = 0; + if ( pAig->pReprs == NULL ) + return -1; + Gia_ManForEachPo( pAig, pObj, i ) + if ( !Gia_ObjIsConst( pAig, Gia_ObjFaninId0p(pAig, pObj) ) ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns the number of POs that are not const0 cands.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManCheckNonTrivialCands( Gia_Man_t * pAig ) +{ + Gia_Obj_t * pObj; + int i, RetValue = 0; + if ( pAig->pReprs == NULL ) + return 0; + // label internal nodes driving POs + Gia_ManForEachPo( pAig, pObj, i ) + Gia_ObjFanin0(pObj)->fMark0 = 1; + // check if there are non-labled equivs + Gia_ManForEachObj( pAig, pObj, i ) + if ( Gia_ObjIsCand(pObj) && !pObj->fMark0 && Gia_ObjRepr(pAig, i) != GIA_VOID ) + { + RetValue = 1; + break; + } + // clean internal nodes driving POs + Gia_ManForEachPo( pAig, pObj, i ) + Gia_ObjFanin0(pObj)->fMark0 = 0; + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Performs semiformal refinement of equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManSeqSemiformal( Gia_Man_t * pAig, Cec_ParSmf_t * pPars ) +{ + int nAddFrames = 16; // additional timeframes to simulate + int nCountNoRef = 0; + int nFramesReal; + Cec_ParSat_t ParsSat, * pParsSat = &ParsSat; + Vec_Ptr_t * vSimInfo; + Vec_Str_t * vStatus; + Abc_Cex_t * pState; + Gia_Man_t * pSrm, * pReduce, * pAux; + int r, nPats, RetValue = 0; + if ( pAig->pReprs == NULL ) + { + Abc_Print( 1, "Cec_ManSeqSemiformal(): Equivalence classes are not available.\n" ); + return -1; + } + if ( Gia_ManRegNum(pAig) == 0 ) + { + Abc_Print( 1, "Cec_ManSeqSemiformal(): Not a sequential AIG.\n" ); + return -1; + } + Gia_ManRandom( 1 ); + // prepare starting pattern + pState = Abc_CexAlloc( Gia_ManRegNum(pAig), 0, 0 ); + pState->iFrame = -1; + pState->iPo = -1; + // prepare SAT solving + Cec_ManSatSetDefaultParams( pParsSat ); + pParsSat->nBTLimit = pPars->nBTLimit; + pParsSat->fVerbose = pPars->fVerbose; + if ( pParsSat->fVerbose ) + { + Abc_Print( 1, "Starting: " ); + Gia_ManEquivPrintClasses( pAig, 0, 0 ); + } + // perform the given number of BMC rounds + Gia_ManCleanMark0( pAig ); + for ( r = 0; r < pPars->nRounds; r++ ) + { + if ( !Cec_ManCheckNonTrivialCands(pAig) ) + { + Abc_Print( 1, "Cec_ManSeqSemiformal: There are only trivial equiv candidates left (PO drivers). Quitting.\n" ); + break; + } +// Abc_CexPrint( pState ); + // derive speculatively reduced model +// pSrm = Gia_ManSpecReduceInit( pAig, pState, pPars->nFrames, pPars->fDualOut ); + pSrm = Gia_ManSpecReduceInitFrames( pAig, pState, pPars->nFrames, &nFramesReal, pPars->fDualOut, pPars->nMinOutputs ); + if ( pSrm == NULL ) + { + Abc_Print( 1, "Quitting refinement because miter could not be unrolled.\n" ); + break; + } + assert( Gia_ManRegNum(pSrm) == 0 && Gia_ManPiNum(pSrm) == (Gia_ManPiNum(pAig) * nFramesReal) ); + if ( pPars->fVerbose ) + Abc_Print( 1, "Unrolled for %d frames.\n", nFramesReal ); + // allocate room for simulation info + vSimInfo = Vec_PtrAllocSimInfo( Gia_ManRegNum(pAig) + + Gia_ManPiNum(pAig) * (nFramesReal + nAddFrames), pPars->nWords ); + Cec_ManSeqDeriveInfoInitRandom( vSimInfo, pAig, pState ); + // fill in simulation info with counter-examples + vStatus = Cec_ManSatSolveSeq( vSimInfo, pSrm, pParsSat, Gia_ManRegNum(pAig), &nPats ); + Vec_StrFree( vStatus ); + Gia_ManStop( pSrm ); + // resimulate and refine the classes + RetValue = Cec_ManSeqResimulateInfo( pAig, vSimInfo, pState, pPars->fCheckMiter ); + Vec_PtrFree( vSimInfo ); + assert( pState->iPo >= 0 ); // hit counter + pState->iPo = -1; + if ( pPars->fVerbose ) + { + Abc_Print( 1, "BMC = %3d ", nPats ); + Gia_ManEquivPrintClasses( pAig, 0, 0 ); + } + + // write equivalence classes + Gia_WriteAiger( pAig, "gore.aig", 0, 0 ); + // reduce the model + pReduce = Gia_ManSpecReduce( pAig, 0, 0, 1, 0, 0 ); + if ( pReduce ) + { + pReduce = Gia_ManSeqStructSweep( pAux = pReduce, 1, 1, 0 ); + Gia_ManStop( pAux ); + Gia_WriteAiger( pReduce, "gsrm.aig", 0, 0 ); +// Abc_Print( 1, "Speculatively reduced model was written into file \"%s\".\n", "gsrm.aig" ); +// Gia_ManPrintStatsShort( pReduce ); + Gia_ManStop( pReduce ); + } + + if ( RetValue ) + { + Abc_Print( 1, "Cec_ManSeqSemiformal(): An output of the miter is asserted. Refinement stopped.\n" ); + break; + } + // decide when to stop + if ( nPats > 0 ) + nCountNoRef = 0; + else if ( ++nCountNoRef == pPars->nNonRefines ) + break; + } + ABC_FREE( pState ); + if ( pPars->fCheckMiter ) + { + int nNonConsts = Cec_ManCountNonConstOutputs( pAig ); + if ( nNonConsts ) + Abc_Print( 1, "The number of POs that are not const-0 candidates = %d.\n", nNonConsts ); + } + return RetValue; +} + +//&r s13207.aig; &ps; ≡ &ps; &semi -R 2 -vm +//&r bug/50/temp.aig; &ps; &equiv -smv; &semi -v +//r mentor/1_05c.blif; st; &get; &ps; &equiv -smv; &semi -mv +//&r bug/50/hdl1.aig; &ps; &equiv -smv; &semi -mv; &srm; &r gsrm.aig; &ps + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/cec/cecSim.c b/src/proof/cec/cecSim.c new file mode 100644 index 00000000..92f8fc2e --- /dev/null +++ b/src/proof/cec/cecSim.c @@ -0,0 +1,53 @@ +/**CFile**************************************************************** + + FileName [cecSim.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinational equivalence checking.] + + Synopsis [Simulation manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cecSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cecInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/cec/cecSolve.c b/src/proof/cec/cecSolve.c new file mode 100644 index 00000000..bd7202e4 --- /dev/null +++ b/src/proof/cec/cecSolve.c @@ -0,0 +1,1023 @@ +/**CFile**************************************************************** + + FileName [cecSolve.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinational equivalence checking.] + + Synopsis [Performs one round of SAT solving.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cecSolve.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cecInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Cec_ObjSatNum( Cec_ManSat_t * p, Gia_Obj_t * pObj ) { return p->pSatVars[Gia_ObjId(p->pAig,pObj)]; } +static inline void Cec_ObjSetSatNum( Cec_ManSat_t * p, Gia_Obj_t * pObj, int Num ) { p->pSatVars[Gia_ObjId(p->pAig,pObj)] = Num; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns value of the SAT variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ObjSatVarValue( Cec_ManSat_t * p, Gia_Obj_t * pObj ) +{ + return sat_solver_var_value( p->pSat, Cec_ObjSatNum(p, pObj) ); +} + +/**Function************************************************************* + + Synopsis [Addes clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_AddClausesMux( Cec_ManSat_t * p, Gia_Obj_t * pNode ) +{ + Gia_Obj_t * pNodeI, * pNodeT, * pNodeE; + int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE; + + assert( !Gia_IsComplement( pNode ) ); + assert( Gia_ObjIsMuxType( pNode ) ); + // get nodes (I = if, T = then, E = else) + pNodeI = Gia_ObjRecognizeMux( pNode, &pNodeT, &pNodeE ); + // get the variable numbers + VarF = Cec_ObjSatNum(p,pNode); + VarI = Cec_ObjSatNum(p,pNodeI); + VarT = Cec_ObjSatNum(p,Gia_Regular(pNodeT)); + VarE = Cec_ObjSatNum(p,Gia_Regular(pNodeE)); + // get the complementation flags + fCompT = Gia_IsComplement(pNodeT); + fCompE = Gia_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); + if ( p->pPars->fPolarFlip ) + { + if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Gia_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + 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); + if ( p->pPars->fPolarFlip ) + { + if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Gia_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + 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); + if ( p->pPars->fPolarFlip ) + { + if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + 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); + if ( p->pPars->fPolarFlip ) + { + if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + 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); + if ( p->pPars->fPolarFlip ) + { + if ( Gia_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + 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); + if ( p->pPars->fPolarFlip ) + { + if ( Gia_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); +} + +/**Function************************************************************* + + Synopsis [Addes clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_AddClausesSuper( Cec_ManSat_t * p, Gia_Obj_t * pNode, Vec_Ptr_t * vSuper ) +{ + Gia_Obj_t * pFanin; + int * pLits, nLits, RetValue, i; + assert( !Gia_IsComplement(pNode) ); + assert( Gia_ObjIsAnd( pNode ) ); + // create storage for literals + nLits = Vec_PtrSize(vSuper) + 1; + pLits = ABC_ALLOC( int, nLits ); + // suppose AND-gate is A & B = C + // add !A => !C or A + !C + Vec_PtrForEachEntry( Gia_Obj_t *, vSuper, pFanin, i ) + { + pLits[0] = toLitCond(Cec_ObjSatNum(p,Gia_Regular(pFanin)), Gia_IsComplement(pFanin)); + pLits[1] = toLitCond(Cec_ObjSatNum(p,pNode), 1); + if ( p->pPars->fPolarFlip ) + { + if ( Gia_Regular(pFanin)->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( pNode->fPhase ) pLits[1] = lit_neg( pLits[1] ); + } + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); + assert( RetValue ); + } + // add A & B => C or !A + !B + C + Vec_PtrForEachEntry( Gia_Obj_t *, vSuper, pFanin, i ) + { + pLits[i] = toLitCond(Cec_ObjSatNum(p,Gia_Regular(pFanin)), !Gia_IsComplement(pFanin)); + if ( p->pPars->fPolarFlip ) + { + if ( Gia_Regular(pFanin)->fPhase ) pLits[i] = lit_neg( pLits[i] ); + } + } + pLits[nLits-1] = toLitCond(Cec_ObjSatNum(p,pNode), 0); + if ( p->pPars->fPolarFlip ) + { + if ( pNode->fPhase ) pLits[nLits-1] = lit_neg( pLits[nLits-1] ); + } + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits ); + assert( RetValue ); + ABC_FREE( pLits ); +} + +/**Function************************************************************* + + Synopsis [Collects the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_CollectSuper_rec( Gia_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes ) +{ + // if the new node is complemented or a PI, another gate begins + if ( Gia_IsComplement(pObj) || Gia_ObjIsCi(pObj) || + (!fFirst && Gia_ObjValue(pObj) > 1) || + (fUseMuxes && Gia_ObjIsMuxType(pObj)) ) + { + Vec_PtrPushUnique( vSuper, pObj ); + return; + } + // go through the branches + Cec_CollectSuper_rec( Gia_ObjChild0(pObj), vSuper, 0, fUseMuxes ); + Cec_CollectSuper_rec( Gia_ObjChild1(pObj), vSuper, 0, fUseMuxes ); +} + +/**Function************************************************************* + + Synopsis [Collects the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_CollectSuper( Gia_Obj_t * pObj, int fUseMuxes, Vec_Ptr_t * vSuper ) +{ + assert( !Gia_IsComplement(pObj) ); + assert( !Gia_ObjIsCi(pObj) ); + Vec_PtrClear( vSuper ); + Cec_CollectSuper_rec( pObj, vSuper, 1, fUseMuxes ); +} + +/**Function************************************************************* + + Synopsis [Updates the solver clause database.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ObjAddToFrontier( Cec_ManSat_t * p, Gia_Obj_t * pObj, Vec_Ptr_t * vFrontier ) +{ + assert( !Gia_IsComplement(pObj) ); + if ( Cec_ObjSatNum(p,pObj) ) + return; + assert( Cec_ObjSatNum(p,pObj) == 0 ); + if ( Gia_ObjIsConst0(pObj) ) + return; + Vec_PtrPush( p->vUsedNodes, pObj ); + Cec_ObjSetSatNum( p, pObj, p->nSatVars++ ); + if ( Gia_ObjIsAnd(pObj) ) + Vec_PtrPush( vFrontier, pObj ); +} + +/**Function************************************************************* + + Synopsis [Updates the solver clause database.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_CnfNodeAddToSolver( Cec_ManSat_t * p, Gia_Obj_t * pObj ) +{ + Vec_Ptr_t * vFrontier; + Gia_Obj_t * pNode, * pFanin; + int i, k, fUseMuxes = 1; + // quit if CNF is ready + if ( Cec_ObjSatNum(p,pObj) ) + return; + if ( Gia_ObjIsCi(pObj) ) + { + Vec_PtrPush( p->vUsedNodes, pObj ); + Cec_ObjSetSatNum( p, pObj, p->nSatVars++ ); + sat_solver_setnvars( p->pSat, p->nSatVars ); + return; + } + assert( Gia_ObjIsAnd(pObj) ); + // start the frontier + vFrontier = Vec_PtrAlloc( 100 ); + Cec_ObjAddToFrontier( p, pObj, vFrontier ); + // explore nodes in the frontier + Vec_PtrForEachEntry( Gia_Obj_t *, vFrontier, pNode, i ) + { + // create the supergate + assert( Cec_ObjSatNum(p,pNode) ); + if ( fUseMuxes && Gia_ObjIsMuxType(pNode) ) + { + Vec_PtrClear( p->vFanins ); + Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin0( Gia_ObjFanin0(pNode) ) ); + Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin0( Gia_ObjFanin1(pNode) ) ); + Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin1( Gia_ObjFanin0(pNode) ) ); + Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin1( Gia_ObjFanin1(pNode) ) ); + Vec_PtrForEachEntry( Gia_Obj_t *, p->vFanins, pFanin, k ) + Cec_ObjAddToFrontier( p, Gia_Regular(pFanin), vFrontier ); + Cec_AddClausesMux( p, pNode ); + } + else + { + Cec_CollectSuper( pNode, fUseMuxes, p->vFanins ); + Vec_PtrForEachEntry( Gia_Obj_t *, p->vFanins, pFanin, k ) + Cec_ObjAddToFrontier( p, Gia_Regular(pFanin), vFrontier ); + Cec_AddClausesSuper( p, pNode, p->vFanins ); + } + assert( Vec_PtrSize(p->vFanins) > 1 ); + } + Vec_PtrFree( vFrontier ); +} + + +/**Function************************************************************* + + Synopsis [Recycles the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManSatSolverRecycle( Cec_ManSat_t * p ) +{ + int Lit; + if ( p->pSat ) + { + Gia_Obj_t * pObj; + int i; + Vec_PtrForEachEntry( Gia_Obj_t *, p->vUsedNodes, pObj, i ) + Cec_ObjSetSatNum( p, pObj, 0 ); + Vec_PtrClear( p->vUsedNodes ); +// memset( p->pSatVars, 0, sizeof(int) * Gia_ManObjNumMax(p->pAigTotal) ); + sat_solver_delete( p->pSat ); + } + p->pSat = sat_solver_new(); + p->pSat->factors = ABC_CALLOC( double, 1 ); + sat_solver_setnvars( p->pSat, 1000 ); + // var 0 is not used + // var 1 is reserved for const0 node - add the clause + p->nSatVars = 1; +// p->nSatVars = 0; + Lit = toLitCond( p->nSatVars, 1 ); + if ( p->pPars->fPolarFlip ) + Lit = lit_neg( Lit ); + sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ); + Cec_ObjSetSatNum( p, Gia_ManConst0(p->pAig), p->nSatVars++ ); + + p->nRecycles++; + p->nCallsSince = 0; +} + +/**Function************************************************************* + + Synopsis [Sets variable activities in the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_SetActivityFactors_rec( Cec_ManSat_t * p, Gia_Obj_t * pObj, int LevelMin, int LevelMax ) +{ + float dActConeBumpMax = 20.0; + int iVar; + // skip visited variables + if ( Gia_ObjIsTravIdCurrent(p->pAig, pObj) ) + return; + Gia_ObjSetTravIdCurrent(p->pAig, pObj); + // add the PI to the list + if ( Gia_ObjLevel(p->pAig, pObj) <= LevelMin || Gia_ObjIsCi(pObj) ) + return; + // set the factor of this variable + // (LevelMax-LevelMin) / (pObj->Level-LevelMin) = p->pPars->dActConeBumpMax / ThisBump + if ( (iVar = Cec_ObjSatNum(p,pObj)) ) + { + p->pSat->factors[iVar] = dActConeBumpMax * (Gia_ObjLevel(p->pAig, pObj) - LevelMin)/(LevelMax - LevelMin); + veci_push(&p->pSat->act_vars, iVar); + } + // explore the fanins + Cec_SetActivityFactors_rec( p, Gia_ObjFanin0(pObj), LevelMin, LevelMax ); + Cec_SetActivityFactors_rec( p, Gia_ObjFanin1(pObj), LevelMin, LevelMax ); +} + +/**Function************************************************************* + + Synopsis [Sets variable activities in the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_SetActivityFactors( Cec_ManSat_t * p, Gia_Obj_t * pObj ) +{ + float dActConeRatio = 0.5; + int LevelMin, LevelMax; + // reset the active variables + veci_resize(&p->pSat->act_vars, 0); + // prepare for traversal + Gia_ManIncrementTravId( p->pAig ); + // determine the min and max level to visit + assert( dActConeRatio > 0 && dActConeRatio < 1 ); + LevelMax = Gia_ObjLevel(p->pAig,pObj); + LevelMin = (int)(LevelMax * (1.0 - dActConeRatio)); + // traverse + Cec_SetActivityFactors_rec( p, pObj, LevelMin, LevelMax ); +//Cec_PrintActivity( p ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Runs equivalence test for the two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManSatCheckNode( Cec_ManSat_t * p, Gia_Obj_t * pObj ) +{ + Gia_Obj_t * pObjR = Gia_Regular(pObj); + int nBTLimit = p->pPars->nBTLimit; + int Lit, RetValue, status, clk, clk2, nConflicts; + + if ( pObj == Gia_ManConst0(p->pAig) ) + return 1; + if ( pObj == Gia_ManConst1(p->pAig) ) + { + assert( 0 ); + return 0; + } + + p->nCallsSince++; // experiment with this!!! + p->nSatTotal++; + + // check if SAT solver needs recycling + if ( p->pSat == NULL || + (p->pPars->nSatVarMax && + p->nSatVars > p->pPars->nSatVarMax && + p->nCallsSince > p->pPars->nCallsRecycle) ) + Cec_ManSatSolverRecycle( p ); + + // if the nodes do not have SAT variables, allocate them +clk2 = clock(); + Cec_CnfNodeAddToSolver( p, pObjR ); +//ABC_PRT( "cnf", clock() - clk2 ); +//Abc_Print( 1, "%d \n", p->pSat->size ); + +clk2 = clock(); +// Cec_SetActivityFactors( p, pObjR ); +//ABC_PRT( "act", clock() - clk2 ); + + // propage unit clauses + if ( p->pSat->qtail != p->pSat->qhead ) + { + status = sat_solver_simplify(p->pSat); + assert( status != 0 ); + assert( p->pSat->qtail == p->pSat->qhead ); + } + + // solve under assumptions + // A = 1; B = 0 OR A = 1; B = 1 + Lit = toLitCond( Cec_ObjSatNum(p,pObjR), Gia_IsComplement(pObj) ); + if ( p->pPars->fPolarFlip ) + { + if ( pObjR->fPhase ) Lit = lit_neg( Lit ); + } +//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 ); +clk = clock(); + nConflicts = p->pSat->stats.conflicts; + +clk2 = clock(); + RetValue = sat_solver_solve( p->pSat, &Lit, &Lit + 1, + (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); +//ABC_PRT( "sat", clock() - clk2 ); + + if ( RetValue == l_False ) + { +p->timeSatUnsat += clock() - clk; + Lit = lit_neg( Lit ); + RetValue = sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ); + assert( RetValue ); + p->nSatUnsat++; + p->nConfUnsat += p->pSat->stats.conflicts - nConflicts; +//Abc_Print( 1, "UNSAT after %d conflicts\n", p->pSat->stats.conflicts - nConflicts ); + return 1; + } + else if ( RetValue == l_True ) + { +p->timeSatSat += clock() - clk; + p->nSatSat++; + p->nConfSat += p->pSat->stats.conflicts - nConflicts; +//Abc_Print( 1, "SAT after %d conflicts\n", p->pSat->stats.conflicts - nConflicts ); + return 0; + } + else // if ( RetValue == l_Undef ) + { +p->timeSatUndec += clock() - clk; + p->nSatUndec++; + p->nConfUndec += p->pSat->stats.conflicts - nConflicts; +//Abc_Print( 1, "UNDEC after %d conflicts\n", p->pSat->stats.conflicts - nConflicts ); + return -1; + } +} + +/**Function************************************************************* + + Synopsis [Runs equivalence test for the two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManSatCheckNodeTwo( Cec_ManSat_t * p, Gia_Obj_t * pObj1, Gia_Obj_t * pObj2 ) +{ + Gia_Obj_t * pObjR1 = Gia_Regular(pObj1); + Gia_Obj_t * pObjR2 = Gia_Regular(pObj2); + int nBTLimit = p->pPars->nBTLimit; + int Lits[2], RetValue, status, clk, clk2, nConflicts; + + if ( pObj1 == Gia_ManConst0(p->pAig) || pObj2 == Gia_ManConst0(p->pAig) || pObj1 == Gia_Not(pObj2) ) + return 1; + if ( pObj1 == Gia_ManConst1(p->pAig) && (pObj2 == NULL || pObj2 == Gia_ManConst1(p->pAig)) ) + { + assert( 0 ); + return 0; + } + + p->nCallsSince++; // experiment with this!!! + p->nSatTotal++; + + // check if SAT solver needs recycling + if ( p->pSat == NULL || + (p->pPars->nSatVarMax && + p->nSatVars > p->pPars->nSatVarMax && + p->nCallsSince > p->pPars->nCallsRecycle) ) + Cec_ManSatSolverRecycle( p ); + + // if the nodes do not have SAT variables, allocate them +clk2 = clock(); + Cec_CnfNodeAddToSolver( p, pObjR1 ); + Cec_CnfNodeAddToSolver( p, pObjR2 ); +//ABC_PRT( "cnf", clock() - clk2 ); +//Abc_Print( 1, "%d \n", p->pSat->size ); + +clk2 = clock(); +// Cec_SetActivityFactors( p, pObjR1 ); +// Cec_SetActivityFactors( p, pObjR2 ); +//ABC_PRT( "act", clock() - clk2 ); + + // propage unit clauses + if ( p->pSat->qtail != p->pSat->qhead ) + { + status = sat_solver_simplify(p->pSat); + assert( status != 0 ); + assert( p->pSat->qtail == p->pSat->qhead ); + } + + // solve under assumptions + // A = 1; B = 0 OR A = 1; B = 1 + Lits[0] = toLitCond( Cec_ObjSatNum(p,pObjR1), Gia_IsComplement(pObj1) ); + Lits[1] = toLitCond( Cec_ObjSatNum(p,pObjR2), Gia_IsComplement(pObj2) ); + if ( p->pPars->fPolarFlip ) + { + if ( pObjR1->fPhase ) Lits[0] = lit_neg( Lits[0] ); + if ( pObjR2->fPhase ) Lits[1] = lit_neg( Lits[1] ); + } +//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 ); +clk = clock(); + nConflicts = p->pSat->stats.conflicts; + +clk2 = clock(); + RetValue = sat_solver_solve( p->pSat, Lits, Lits + 2, + (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); +//ABC_PRT( "sat", clock() - clk2 ); + + if ( RetValue == l_False ) + { +p->timeSatUnsat += clock() - clk; + Lits[0] = lit_neg( Lits[0] ); + Lits[1] = lit_neg( Lits[1] ); + RetValue = sat_solver_addclause( p->pSat, Lits, Lits + 2 ); + assert( RetValue ); + p->nSatUnsat++; + p->nConfUnsat += p->pSat->stats.conflicts - nConflicts; +//Abc_Print( 1, "UNSAT after %d conflicts\n", p->pSat->stats.conflicts - nConflicts ); + return 1; + } + else if ( RetValue == l_True ) + { +p->timeSatSat += clock() - clk; + p->nSatSat++; + p->nConfSat += p->pSat->stats.conflicts - nConflicts; +//Abc_Print( 1, "SAT after %d conflicts\n", p->pSat->stats.conflicts - nConflicts ); + return 0; + } + else // if ( RetValue == l_Undef ) + { +p->timeSatUndec += clock() - clk; + p->nSatUndec++; + p->nConfUndec += p->pSat->stats.conflicts - nConflicts; +//Abc_Print( 1, "UNDEC after %d conflicts\n", p->pSat->stats.conflicts - nConflicts ); + return -1; + } +} + + +/**Function************************************************************* + + Synopsis [Performs one round of solving for the POs of the AIG.] + + Description [Labels the nodes that have been proved (pObj->fMark1) + and returns the set of satisfying assignments.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManSatSolve( Cec_ManPat_t * pPat, Gia_Man_t * pAig, Cec_ParSat_t * pPars ) +{ + Bar_Progress_t * pProgress = NULL; + Cec_ManSat_t * p; + Gia_Obj_t * pObj; + int i, status, clk = clock(), clk2; + // reset the manager + if ( pPat ) + { + pPat->iStart = Vec_StrSize(pPat->vStorage); + pPat->nPats = 0; + pPat->nPatLits = 0; + pPat->nPatLitsMin = 0; + } + Gia_ManSetPhase( pAig ); + Gia_ManLevelNum( pAig ); + Gia_ManIncrementTravId( pAig ); + p = Cec_ManSatCreate( pAig, pPars ); + pProgress = Bar_ProgressStart( stdout, Gia_ManPoNum(pAig) ); + Gia_ManForEachCo( pAig, pObj, i ) + { + if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) + { + pObj->fMark0 = 0; + pObj->fMark1 = 1; + continue; + } + Bar_ProgressUpdate( pProgress, i, "SAT..." ); +clk2 = clock(); + status = Cec_ManSatCheckNode( p, Gia_ObjChild0(pObj) ); + pObj->fMark0 = (status == 0); + pObj->fMark1 = (status == 1); +/* + if ( status == -1 ) + { + Gia_Man_t * pTemp = Gia_ManDupDfsCone( pAig, pObj ); + Gia_WriteAiger( pTemp, "gia_hard.aig", 0, 0 ); + Gia_ManStop( pTemp ); + Abc_Print( 1, "Dumping hard cone into file \"%s\".\n", "gia_hard.aig" ); + } +*/ + if ( status != 0 ) + continue; + // save the pattern + if ( pPat ) + { + int clk3 = clock(); + Cec_ManPatSavePattern( pPat, p, pObj ); + pPat->timeTotalSave += clock() - clk3; + } + // quit if one of them is solved + if ( pPars->fCheckMiter ) + break; + } + p->timeTotal = clock() - clk; + Bar_ProgressStop( pProgress ); + if ( pPars->fVerbose ) + Cec_ManSatPrintStats( p ); + Cec_ManSatStop( p ); +} + + + +/**Function************************************************************* + + Synopsis [Returns the pattern stored.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Cec_ManSatReadCex( Cec_ManSat_t * pSat ) +{ + return pSat->vCex; +} + +/**Function************************************************************* + + Synopsis [Save values in the cone of influence.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManSatSolveSeq_rec( Cec_ManSat_t * pSat, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Ptr_t * vInfo, int iPat, int nRegs ) +{ + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return; + Gia_ObjSetTravIdCurrent(p, pObj); + if ( Gia_ObjIsCi(pObj) ) + { + unsigned * pInfo = (unsigned *)Vec_PtrEntry( vInfo, nRegs + Gia_ObjCioId(pObj) ); + if ( Cec_ObjSatVarValue( pSat, pObj ) != Abc_InfoHasBit( pInfo, iPat ) ) + Abc_InfoXorBit( pInfo, iPat ); + pSat->nCexLits++; +// Vec_IntPush( pSat->vCex, Abc_Var2Lit( Gia_ObjCioId(pObj), !Cec_ObjSatVarValue(pSat, pObj) ) ); + return; + } + assert( Gia_ObjIsAnd(pObj) ); + Cec_ManSatSolveSeq_rec( pSat, p, Gia_ObjFanin0(pObj), vInfo, iPat, nRegs ); + Cec_ManSatSolveSeq_rec( pSat, p, Gia_ObjFanin1(pObj), vInfo, iPat, nRegs ); +} + +/**Function************************************************************* + + Synopsis [Performs one round of solving for the POs of the AIG.] + + Description [Labels the nodes that have been proved (pObj->fMark1) + and returns the set of satisfying assignments.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Str_t * Cec_ManSatSolveSeq( Vec_Ptr_t * vPatts, Gia_Man_t * pAig, Cec_ParSat_t * pPars, int nRegs, int * pnPats ) +{ + Bar_Progress_t * pProgress = NULL; + Vec_Str_t * vStatus; + Cec_ManSat_t * p; + Gia_Obj_t * pObj; + int iPat = 0, nPatsInit, nPats; + int i, status, clk = clock(); + nPatsInit = nPats = 32 * Vec_PtrReadWordsSimInfo(vPatts); + Gia_ManSetPhase( pAig ); + Gia_ManLevelNum( pAig ); + Gia_ManIncrementTravId( pAig ); + p = Cec_ManSatCreate( pAig, pPars ); + vStatus = Vec_StrAlloc( Gia_ManPoNum(pAig) ); + pProgress = Bar_ProgressStart( stdout, Gia_ManPoNum(pAig) ); + Gia_ManForEachCo( pAig, pObj, i ) + { + Bar_ProgressUpdate( pProgress, i, "SAT..." ); + if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) + { + if ( Gia_ObjFaninC0(pObj) ) + { +// Abc_Print( 1, "Constant 1 output of SRM!!!\n" ); + Vec_StrPush( vStatus, 0 ); + } + else + { +// Abc_Print( 1, "Constant 0 output of SRM!!!\n" ); + Vec_StrPush( vStatus, 1 ); + } + continue; + } + status = Cec_ManSatCheckNode( p, Gia_ObjChild0(pObj) ); +//Abc_Print( 1, "output %d status = %d\n", i, status ); + Vec_StrPush( vStatus, (char)status ); + if ( status != 0 ) + continue; + // resize storage + if ( iPat == nPats ) + { + int nWords = Vec_PtrReadWordsSimInfo(vPatts); + Vec_PtrReallocSimInfo( vPatts ); + Vec_PtrCleanSimInfo( vPatts, nWords, 2*nWords ); + nPats = 32 * Vec_PtrReadWordsSimInfo(vPatts); + } + if ( iPat % nPatsInit == 0 ) + iPat++; + // save the pattern + Gia_ManIncrementTravId( pAig ); +// Vec_IntClear( p->vCex ); + Cec_ManSatSolveSeq_rec( p, pAig, Gia_ObjFanin0(pObj), vPatts, iPat++, nRegs ); +// Gia_SatVerifyPattern( pAig, pObj, p->vCex, p->vVisits ); +// Cec_ManSatAddToStore( p->vCexStore, p->vCex ); +// if ( iPat == nPats ) +// break; + // quit if one of them is solved +// if ( pPars->fFirstStop ) +// break; +// if ( iPat == 32 * 15 * 16 - 1 ) +// break; + } + p->timeTotal = clock() - clk; + Bar_ProgressStop( pProgress ); + if ( pPars->fVerbose ) + Cec_ManSatPrintStats( p ); +// Abc_Print( 1, "Total number of cex literals = %d. (Ave = %d)\n", p->nCexLits, p->nCexLits/p->nSatSat ); + Cec_ManSatStop( p ); + if ( pnPats ) + *pnPats = iPat-1; + return vStatus; +} + + +/**Function************************************************************* + + Synopsis [Save values in the cone of influence.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out ) +{ + int i, Entry; + Vec_IntPush( vCexStore, Out ); + if ( vCex == NULL ) // timeout + { + Vec_IntPush( vCexStore, -1 ); + return; + } + // write the counter-example + Vec_IntPush( vCexStore, Vec_IntSize(vCex) ); + Vec_IntForEachEntry( vCex, Entry, i ) + Vec_IntPush( vCexStore, Entry ); +} + +/**Function************************************************************* + + Synopsis [Save values in the cone of influence.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManSatSolveMiter_rec( Cec_ManSat_t * pSat, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return; + Gia_ObjSetTravIdCurrent(p, pObj); + if ( Gia_ObjIsCi(pObj) ) + { + pSat->nCexLits++; + Vec_IntPush( pSat->vCex, Abc_Var2Lit( Gia_ObjCioId(pObj), !Cec_ObjSatVarValue(pSat, pObj) ) ); + return; + } + assert( Gia_ObjIsAnd(pObj) ); + Cec_ManSatSolveMiter_rec( pSat, p, Gia_ObjFanin0(pObj) ); + Cec_ManSatSolveMiter_rec( pSat, p, Gia_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Save patterns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManSavePattern( Cec_ManSat_t * p, Gia_Obj_t * pObj1, Gia_Obj_t * pObj2 ) +{ + Vec_IntClear( p->vCex ); + Gia_ManIncrementTravId( p->pAig ); + Cec_ManSatSolveMiter_rec( p, p->pAig, Gia_Regular(pObj1) ); + if ( pObj2 ) + Cec_ManSatSolveMiter_rec( p, p->pAig, Gia_Regular(pObj2) ); +} + +/**Function************************************************************* + + Synopsis [Performs one round of solving for the POs of the AIG.] + + Description [Labels the nodes that have been proved (pObj->fMark1) + and returns the set of satisfying assignments.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Cec_ManSatSolveMiter( Gia_Man_t * pAig, Cec_ParSat_t * pPars, Vec_Str_t ** pvStatus ) +{ + Bar_Progress_t * pProgress = NULL; + Vec_Int_t * vCexStore; + Vec_Str_t * vStatus; + Cec_ManSat_t * p; + Gia_Obj_t * pObj; + int i, status, clk = clock(); + // prepare AIG + Gia_ManSetPhase( pAig ); + Gia_ManLevelNum( pAig ); + Gia_ManIncrementTravId( pAig ); + // create resulting data-structures + vStatus = Vec_StrAlloc( Gia_ManPoNum(pAig) ); + vCexStore = Vec_IntAlloc( 10000 ); + // perform solving + p = Cec_ManSatCreate( pAig, pPars ); + pProgress = Bar_ProgressStart( stdout, Gia_ManPoNum(pAig) ); + Gia_ManForEachCo( pAig, pObj, i ) + { + Vec_IntClear( p->vCex ); + Bar_ProgressUpdate( pProgress, i, "SAT..." ); + if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) + { + if ( Gia_ObjFaninC0(pObj) ) + { +// Abc_Print( 1, "Constant 1 output of SRM!!!\n" ); + Cec_ManSatAddToStore( vCexStore, p->vCex, i ); // trivial counter-example + Vec_StrPush( vStatus, 0 ); + } + else + { +// Abc_Print( 1, "Constant 0 output of SRM!!!\n" ); + Vec_StrPush( vStatus, 1 ); + } + continue; + } + status = Cec_ManSatCheckNode( p, Gia_ObjChild0(pObj) ); + Vec_StrPush( vStatus, (char)status ); + if ( status == -1 ) + { + Cec_ManSatAddToStore( vCexStore, NULL, i ); // timeout + continue; + } + if ( status == 1 ) + continue; + assert( status == 0 ); + // save the pattern +// Gia_ManIncrementTravId( pAig ); +// Cec_ManSatSolveMiter_rec( p, pAig, Gia_ObjFanin0(pObj) ); + Cec_ManSavePattern( p, Gia_ObjFanin0(pObj), NULL ); +// Gia_SatVerifyPattern( pAig, pObj, p->vCex, p->vVisits ); + Cec_ManSatAddToStore( vCexStore, p->vCex, i ); + } + p->timeTotal = clock() - clk; + Bar_ProgressStop( pProgress ); +// if ( pPars->fVerbose ) +// Cec_ManSatPrintStats( p ); + Cec_ManSatStop( p ); + *pvStatus = vStatus; + return vCexStore; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/cec/cecSweep.c b/src/proof/cec/cecSweep.c new file mode 100644 index 00000000..4523810e --- /dev/null +++ b/src/proof/cec/cecSweep.c @@ -0,0 +1,299 @@ +/**CFile**************************************************************** + + FileName [cecSweep.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinational equivalence checking.] + + Synopsis [SAT sweeping manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cecSweep.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cecInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs limited speculative reduction.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Cec_ManFraSpecReduction( Cec_ManFra_t * p ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pRepr = NULL; + int iRes0, iRes1, iRepr, iNode, iMiter; + int i, fCompl, * piCopies, * pDepths; + Gia_ManSetPhase( p->pAig ); + Vec_IntClear( p->vXorNodes ); + if ( p->pPars->nLevelMax ) + Gia_ManLevelNum( p->pAig ); + pNew = Gia_ManStart( Gia_ManObjNum(p->pAig) ); + pNew->pName = Abc_UtilStrsav( p->pAig->pName ); + Gia_ManHashAlloc( pNew ); + piCopies = ABC_FALLOC( int, Gia_ManObjNum(p->pAig) ); + pDepths = ABC_CALLOC( int, Gia_ManObjNum(p->pAig) ); + piCopies[0] = 0; + Gia_ManForEachObj1( p->pAig, pObj, i ) + { + if ( Gia_ObjIsCi(pObj) ) + { + piCopies[i] = Gia_ManAppendCi( pNew ); + continue; + } + if ( Gia_ObjIsCo(pObj) ) + continue; + if ( piCopies[Gia_ObjFaninId0(pObj,i)] == -1 || + piCopies[Gia_ObjFaninId1(pObj,i)] == -1 ) + continue; + iRes0 = Abc_LitNotCond( piCopies[Gia_ObjFaninId0(pObj,i)], Gia_ObjFaninC0(pObj) ); + iRes1 = Abc_LitNotCond( piCopies[Gia_ObjFaninId1(pObj,i)], Gia_ObjFaninC1(pObj) ); + iNode = piCopies[i] = Gia_ManHashAnd( pNew, iRes0, iRes1 ); + pDepths[i] = Abc_MaxInt( pDepths[Gia_ObjFaninId0(pObj,i)], pDepths[Gia_ObjFaninId1(pObj,i)] ); + if ( Gia_ObjRepr(p->pAig, i) == GIA_VOID || Gia_ObjFailed(p->pAig, i) ) + continue; + assert( Gia_ObjRepr(p->pAig, i) < i ); + iRepr = piCopies[Gia_ObjRepr(p->pAig, i)]; + if ( iRepr == -1 ) + continue; + if ( Abc_LitRegular(iNode) == Abc_LitRegular(iRepr) ) + continue; + if ( p->pPars->nLevelMax && + (Gia_ObjLevel(p->pAig, pObj) > p->pPars->nLevelMax || + Gia_ObjLevel(p->pAig, pRepr) > p->pPars->nLevelMax) ) + continue; + if ( p->pPars->fDualOut ) + { +// if ( i % 1000 == 0 && Gia_ObjRepr(p->pAig, i) ) +// Gia_ManEquivPrintOne( p->pAig, Gia_ObjRepr(p->pAig, i), 0 ); + if ( p->pPars->fColorDiff ) + { + if ( !Gia_ObjDiffColors( p->pAig, Gia_ObjRepr(p->pAig, i), i ) ) + continue; + } + else + { + if ( !Gia_ObjDiffColors2( p->pAig, Gia_ObjRepr(p->pAig, i), i ) ) + continue; + } + } + pRepr = Gia_ManObj( p->pAig, Gia_ObjRepr(p->pAig, i) ); + fCompl = Gia_ObjPhaseReal(pObj) ^ Gia_ObjPhaseReal(pRepr); + piCopies[i] = Abc_LitNotCond( iRepr, fCompl ); + if ( Gia_ObjProved(p->pAig, i) ) + continue; + // produce speculative miter + iMiter = Gia_ManHashXor( pNew, iNode, piCopies[i] ); + Gia_ManAppendCo( pNew, iMiter ); + Vec_IntPush( p->vXorNodes, Gia_ObjRepr(p->pAig, i) ); + Vec_IntPush( p->vXorNodes, i ); + // add to the depth of this node + pDepths[i] = 1 + Abc_MaxInt( pDepths[i], pDepths[Gia_ObjRepr(p->pAig, i)] ); + if ( p->pPars->nDepthMax && pDepths[i] >= p->pPars->nDepthMax ) + piCopies[i] = -1; + } + ABC_FREE( piCopies ); + ABC_FREE( pDepths ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, 0 ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManFraClassesUpdate_rec( Gia_Obj_t * pObj ) +{ + int Result; + if ( pObj->fMark0 ) + return 1; + if ( Gia_ObjIsCi(pObj) || Gia_ObjIsConst0(pObj) ) + return 0; + Result = (Cec_ManFraClassesUpdate_rec( Gia_ObjFanin0(pObj) ) | + Cec_ManFraClassesUpdate_rec( Gia_ObjFanin1(pObj) )); + return pObj->fMark0 = Result; +} + +/**Function************************************************************* + + Synopsis [Creates simulation info for this round.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManFraCreateInfo( Cec_ManSim_t * p, Vec_Ptr_t * vCiInfo, Vec_Ptr_t * vInfo, int nSeries ) +{ + unsigned * pRes0, * pRes1; + int i, w; + for ( i = 0; i < Gia_ManCiNum(p->pAig); i++ ) + { + pRes0 = (unsigned *)Vec_PtrEntry( vCiInfo, i ); + pRes1 = (unsigned *)Vec_PtrEntry( vInfo, i ); + pRes1 += p->nWords * nSeries; + for ( w = 0; w < p->nWords; w++ ) + pRes0[w] = pRes1[w]; + } +} + +/**Function************************************************************* + + Synopsis [Updates equivalence classes using the patterns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManFraClassesUpdate( Cec_ManFra_t * p, Cec_ManSim_t * pSim, Cec_ManPat_t * pPat, Gia_Man_t * pNew ) +{ + Vec_Ptr_t * vInfo; + Gia_Obj_t * pObj, * pObjOld, * pReprOld; + int i, k, iRepr, iNode, clk; +clk = clock(); + vInfo = Cec_ManPatCollectPatterns( pPat, Gia_ManCiNum(p->pAig), pSim->nWords ); +p->timePat += clock() - clk; +clk = clock(); + if ( vInfo != NULL ) + { + Gia_ManSetRefs( p->pAig ); + for ( i = 0; i < pPat->nSeries; i++ ) + { + Cec_ManFraCreateInfo( pSim, pSim->vCiSimInfo, vInfo, i ); + if ( Cec_ManSimSimulateRound( pSim, pSim->vCiSimInfo, pSim->vCoSimInfo ) ) + { + Vec_PtrFree( vInfo ); + return 1; + } + } + Vec_PtrFree( vInfo ); + } +p->timeSim += clock() - clk; + assert( Vec_IntSize(p->vXorNodes) == 2*Gia_ManCoNum(pNew) ); + // mark the transitive fanout of failed nodes + if ( p->pPars->nDepthMax != 1 ) + { + Gia_ManCleanMark0( p->pAig ); + Gia_ManCleanMark1( p->pAig ); + Gia_ManForEachCo( pNew, pObj, k ) + { + iRepr = Vec_IntEntry( p->vXorNodes, 2*k ); + iNode = Vec_IntEntry( p->vXorNodes, 2*k+1 ); + if ( pObj->fMark0 == 0 && pObj->fMark1 == 1 ) // proved + continue; +// Gia_ManObj(p->pAig, iRepr)->fMark0 = 1; + Gia_ManObj(p->pAig, iNode)->fMark0 = 1; + } + // mark the nodes reachable through the failed nodes + Gia_ManForEachAnd( p->pAig, pObjOld, k ) + pObjOld->fMark0 |= (Gia_ObjFanin0(pObjOld)->fMark0 | Gia_ObjFanin1(pObjOld)->fMark0); + // unmark the disproved nodes + Gia_ManForEachCo( pNew, pObj, k ) + { + iRepr = Vec_IntEntry( p->vXorNodes, 2*k ); + iNode = Vec_IntEntry( p->vXorNodes, 2*k+1 ); + if ( pObj->fMark0 == 0 && pObj->fMark1 == 1 ) // proved + continue; + pObjOld = Gia_ManObj(p->pAig, iNode); + assert( pObjOld->fMark0 == 1 ); + if ( Gia_ObjFanin0(pObjOld)->fMark0 == 0 && Gia_ObjFanin1(pObjOld)->fMark0 == 0 ) + pObjOld->fMark1 = 1; + } + // clean marks + Gia_ManForEachAnd( p->pAig, pObjOld, k ) + if ( pObjOld->fMark1 ) + { + pObjOld->fMark0 = 0; + pObjOld->fMark1 = 0; + } + } + // set the results + p->nAllProved = p->nAllDisproved = p->nAllFailed = 0; + Gia_ManForEachCo( pNew, pObj, k ) + { + iRepr = Vec_IntEntry( p->vXorNodes, 2*k ); + iNode = Vec_IntEntry( p->vXorNodes, 2*k+1 ); + pReprOld = Gia_ManObj(p->pAig, iRepr); + pObjOld = Gia_ManObj(p->pAig, iNode); + if ( pObj->fMark1 ) + { // proved + assert( pObj->fMark0 == 0 ); + assert( !Gia_ObjProved(p->pAig, iNode) ); + if ( pReprOld->fMark0 == 0 && pObjOld->fMark0 == 0 ) +// if ( pObjOld->fMark0 == 0 ) + { + assert( iRepr == Gia_ObjRepr(p->pAig, iNode) ); + Gia_ObjSetProved( p->pAig, iNode ); + p->nAllProved++; + } + } + else if ( pObj->fMark0 ) + { // disproved + assert( pObj->fMark1 == 0 ); + if ( pReprOld->fMark0 == 0 && pObjOld->fMark0 == 0 ) +// if ( pObjOld->fMark0 == 0 ) + { + if ( iRepr == Gia_ObjRepr(p->pAig, iNode) ) + Abc_Print( 1, "Cec_ManFraClassesUpdate(): Error! Node is not refined!\n" ); + p->nAllDisproved++; + } + } + else + { // failed + assert( pObj->fMark0 == 0 ); + assert( pObj->fMark1 == 0 ); + assert( !Gia_ObjFailed(p->pAig, iNode) ); + assert( !Gia_ObjProved(p->pAig, iNode) ); + Gia_ObjSetFailed( p->pAig, iNode ); + p->nAllFailed++; + } + } + return 0; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/cec/cecSynth.c b/src/proof/cec/cecSynth.c new file mode 100644 index 00000000..21470dd4 --- /dev/null +++ b/src/proof/cec/cecSynth.c @@ -0,0 +1,380 @@ +/**CFile**************************************************************** + + FileName [cecSynth.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinational equivalence checking.] + + Synopsis [Partitioned sequential synthesis.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cecSynth.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cecInt.h" +#include "src/aig/gia/giaAig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Populate sequential synthesis parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_SeqSynthesisSetDefaultParams( Cec_ParSeq_t * p ) +{ + memset( p, 0, sizeof(Cec_ParSeq_t) ); + p->fUseLcorr = 0; // enables latch correspondence + p->fUseScorr = 0; // enables signal correspondence + p->nBTLimit = 1000; // (scorr/lcorr) conflict limit at a node + p->nFrames = 1; // (scorr only) the number of timeframes + p->nLevelMax = -1; // (scorr only) the max number of levels + p->fConsts = 1; // (scl only) merging constants + p->fEquivs = 1; // (scl only) merging equivalences + p->fUseMiniSat = 0; // enables MiniSat in lcorr/scorr + p->nMinDomSize = 100; // the size of minimum clock domain + p->fVeryVerbose = 0; // verbose stats + p->fVerbose = 0; // verbose stats +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_SeqReadMinDomSize( Cec_ParSeq_t * p ) +{ + return p->nMinDomSize; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_SeqReadVerbose( Cec_ParSeq_t * p ) +{ + return p->fVerbose; +} + +/**Function************************************************************* + + Synopsis [Computes partitioning of registers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManRegCreatePart( Gia_Man_t * p, Vec_Int_t * vPart, int * pnCountPis, int * pnCountRegs, int ** ppMapBack ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + Vec_Int_t * vNodes, * vRoots; + int i, iOut, nCountPis, nCountRegs; + int * pMapBack; + // collect/mark nodes/PIs in the DFS order from the roots + Gia_ManIncrementTravId( p ); + vRoots = Vec_IntAlloc( Vec_IntSize(vPart) ); + Vec_IntForEachEntry( vPart, iOut, i ) + Vec_IntPush( vRoots, Gia_ObjId(p, Gia_ManCo(p, Gia_ManPoNum(p)+iOut)) ); + vNodes = Gia_ManCollectNodesCis( p, Vec_IntArray(vRoots), Vec_IntSize(vRoots) ); + Vec_IntFree( vRoots ); + // unmark register outputs + Vec_IntForEachEntry( vPart, iOut, i ) + Gia_ObjSetTravIdPrevious( p, Gia_ManCi(p, Gia_ManPiNum(p)+iOut) ); + // count pure PIs + nCountPis = nCountRegs = 0; + Gia_ManForEachPi( p, pObj, i ) + nCountPis += Gia_ObjIsTravIdCurrent(p, pObj); + // count outputs of other registers + Gia_ManForEachRo( p, pObj, i ) + nCountRegs += Gia_ObjIsTravIdCurrent(p, pObj); // should be !Gia_... ??? + if ( pnCountPis ) + *pnCountPis = nCountPis; + if ( pnCountRegs ) + *pnCountRegs = nCountRegs; + // clean old manager + Gia_ManFillValue(p); + Gia_ManConst0(p)->Value = 0; + // create the new manager + pNew = Gia_ManStart( Vec_IntSize(vNodes) ); + // create the PIs + Gia_ManForEachCi( p, pObj, i ) + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + pObj->Value = Gia_ManAppendCi(pNew); + // add variables for the register outputs + // create fake POs to hold the register outputs + Vec_IntForEachEntry( vPart, iOut, i ) + { + pObj = Gia_ManCi(p, Gia_ManPiNum(p)+iOut); + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManAppendCo( pNew, pObj->Value ); + Gia_ObjSetTravIdCurrent( p, pObj ); // added + } + // create the nodes + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + // add real POs for the registers + Vec_IntForEachEntry( vPart, iOut, i ) + { + pObj = Gia_ManCo( p, Gia_ManPoNum(p)+iOut ); + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Gia_ManSetRegNum( pNew, Vec_IntSize(vPart) ); + // create map + if ( ppMapBack ) + { + pMapBack = ABC_FALLOC( int, Gia_ManObjNum(pNew) ); + // map constant nodes + pMapBack[0] = 0; + // logic cones of register outputs + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + { +// pObjNew = Aig_Regular(pObj->pData); +// pMapBack[pObjNew->Id] = pObj->Id; + assert( Abc_Lit2Var(Gia_ObjValue(pObj)) >= 0 ); + assert( Abc_Lit2Var(Gia_ObjValue(pObj)) < Gia_ManObjNum(pNew) ); + pMapBack[ Abc_Lit2Var(Gia_ObjValue(pObj)) ] = Gia_ObjId(p, pObj); + } + // map register outputs + Vec_IntForEachEntry( vPart, iOut, i ) + { + pObj = Gia_ManCi(p, Gia_ManPiNum(p)+iOut); +// pObjNew = pObj->pData; +// pMapBack[pObjNew->Id] = pObj->Id; + assert( Abc_Lit2Var(Gia_ObjValue(pObj)) >= 0 ); + assert( Abc_Lit2Var(Gia_ObjValue(pObj)) < Gia_ManObjNum(pNew) ); + pMapBack[ Abc_Lit2Var(Gia_ObjValue(pObj)) ] = Gia_ObjId(p, pObj); + } + *ppMapBack = pMapBack; + } + Vec_IntFree( vNodes ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Transfers the classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_TransferMappedClasses( Gia_Man_t * pPart, int * pMapBack, int * pReprs ) +{ + Gia_Obj_t * pObj; + int i, Id1, Id2, nClasses; + if ( pPart->pReprs == NULL ) + return 0; + nClasses = 0; + Gia_ManForEachObj( pPart, pObj, i ) + { + if ( Gia_ObjRepr(pPart, i) == GIA_VOID ) + continue; + assert( i < Gia_ManObjNum(pPart) ); + assert( Gia_ObjRepr(pPart, i) < Gia_ManObjNum(pPart) ); + Id1 = pMapBack[ i ]; + Id2 = pMapBack[ Gia_ObjRepr(pPart, i) ]; + if ( Id1 == Id2 ) + continue; + if ( Id1 < Id2 ) + pReprs[Id2] = Id1; + else + pReprs[Id1] = Id2; + nClasses++; + } + return nClasses; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManFindRepr_rec( int * pReprs, int Id ) +{ + if ( pReprs[Id] == 0 ) + return 0; + if ( pReprs[Id] == ~0 ) + return Id; + return Gia_ManFindRepr_rec( pReprs, pReprs[Id] ); +} + +/**Function************************************************************* + + Synopsis [Normalizes equivalences.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManNormalizeEquivalences( Gia_Man_t * p, int * pReprs ) +{ + int i, iRepr; + assert( p->pReprs == NULL ); + assert( p->pNexts == NULL ); + p->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + Gia_ObjSetRepr( p, i, GIA_VOID ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + { + if ( pReprs[i] == ~0 ) + continue; + iRepr = Gia_ManFindRepr_rec( pReprs, i ); + Gia_ObjSetRepr( p, i, iRepr ); + } + p->pNexts = Gia_ManDeriveNexts( p ); +} + +/**Function************************************************************* + + Synopsis [Partitioned sequential synthesis.] + + Description [Returns AIG annotated with equivalence classes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_SequentialSynthesisPart( Gia_Man_t * p, Cec_ParSeq_t * pPars ) +{ + int fPrintParts = 0; + char Buffer[100]; + Gia_Man_t * pTemp; + Vec_Ptr_t * vParts = (Vec_Ptr_t *)p->vClockDoms; + Vec_Int_t * vPart; + int * pMapBack, * pReprs; + int i, nCountPis, nCountRegs; + int nClasses, clk = clock(); + + // save parameters + if ( fPrintParts ) + { + // print partitions + Abc_Print( 1, "The following clock domains are used:\n" ); + Vec_PtrForEachEntry( Vec_Int_t *, vParts, vPart, i ) + { + pTemp = Gia_ManRegCreatePart( p, vPart, &nCountPis, &nCountRegs, NULL ); + sprintf( Buffer, "part%03d.aig", i ); + Gia_WriteAiger( pTemp, Buffer, 0, 0 ); + Abc_Print( 1, "part%03d.aig : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d.\n", + i, Vec_IntSize(vPart), Gia_ManCiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Gia_ManAndNum(pTemp) ); + Gia_ManStop( pTemp ); + } + } + + // perform sequential synthesis for clock domains + pReprs = ABC_FALLOC( int, Gia_ManObjNum(p) ); + Vec_PtrForEachEntry( Vec_Int_t *, vParts, vPart, i ) + { + pTemp = Gia_ManRegCreatePart( p, vPart, &nCountPis, &nCountRegs, &pMapBack ); + if ( nCountPis > 0 ) + { + if ( pPars->fUseScorr ) + { + Cec_ParCor_t CorPars, * pCorPars = &CorPars; + Cec_ManCorSetDefaultParams( pCorPars ); + pCorPars->nBTLimit = pPars->nBTLimit; + pCorPars->nLevelMax = pPars->nLevelMax; + pCorPars->fVerbose = pPars->fVeryVerbose; + pCorPars->fUseCSat = 1; + Cec_ManLSCorrespondenceClasses( pTemp, pCorPars ); + } + else if ( pPars->fUseLcorr ) + { + Cec_ParCor_t CorPars, * pCorPars = &CorPars; + Cec_ManCorSetDefaultParams( pCorPars ); + pCorPars->fLatchCorr = 1; + pCorPars->nBTLimit = pPars->nBTLimit; + pCorPars->fVerbose = pPars->fVeryVerbose; + pCorPars->fUseCSat = 1; + Cec_ManLSCorrespondenceClasses( pTemp, pCorPars ); + } + else + { +// pNew = Gia_ManSeqStructSweep( pTemp, pPars->fConsts, pPars->fEquivs, pPars->fVerbose ); +// Gia_ManStop( pNew ); + Gia_ManSeqCleanupClasses( pTemp, pPars->fConsts, pPars->fEquivs, pPars->fVerbose ); + } +//Abc_Print( 1, "Part equivalences = %d.\n", Gia_ManEquivCountLitsAll(pTemp) ); + nClasses = Gia_TransferMappedClasses( pTemp, pMapBack, pReprs ); + if ( pPars->fVerbose ) + { + Abc_Print( 1, "%3d : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d. Cl = %5d.\n", + i, Vec_IntSize(vPart), Gia_ManCiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Gia_ManAndNum(pTemp), nClasses ); + } + } + Gia_ManStop( pTemp ); + ABC_FREE( pMapBack ); + } + + // generate resulting equivalences + Gia_ManNormalizeEquivalences( p, pReprs ); +//Abc_Print( 1, "Total equivalences = %d.\n", Gia_ManEquivCountLitsAll(p) ); + ABC_FREE( pReprs ); + if ( pPars->fVerbose ) + { + Abc_PrintTime( 1, "Total time", clock() - clk ); + } + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/cec/module.make b/src/proof/cec/module.make new file mode 100644 index 00000000..bac6e9bc --- /dev/null +++ b/src/proof/cec/module.make @@ -0,0 +1,13 @@ +SRC += src/proof/cec/cecCec.c \ + src/proof/cec/cecChoice.c \ + src/proof/cec/cecClass.c \ + src/proof/cec/cecCore.c \ + src/proof/cec/cecCorr.c \ + src/proof/cec/cecIso.c \ + src/proof/cec/cecMan.c \ + src/proof/cec/cecPat.c \ + src/proof/cec/cecSeq.c \ + src/proof/cec/cecSim.c \ + src/proof/cec/cecSolve.c \ + src/proof/cec/cecSynth.c \ + src/proof/cec/cecSweep.c diff --git a/src/proof/dch/dch.h b/src/proof/dch/dch.h new file mode 100644 index 00000000..731eb776 --- /dev/null +++ b/src/proof/dch/dch.h @@ -0,0 +1,90 @@ +/**CFile**************************************************************** + + FileName [dch.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Choice computation for tech-mapping.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 29, 2008.] + + Revision [$Id: dch.h,v 1.00 2008/07/29 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__dch__dch_h +#define ABC__aig__dch__dch_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +// choicing parameters +typedef struct Dch_Pars_t_ Dch_Pars_t; +struct Dch_Pars_t_ +{ + int nWords; // the number of simulation words + int nBTLimit; // conflict limit at a node + int nSatVarMax; // the max number of SAT variables + int fSynthesis; // set to 1 to perform synthesis + int fPolarFlip; // uses polarity adjustment + int fSimulateTfo; // uses simulation of TFO classes + int fPower; // uses power-aware rewriting + int fUseGia; // uses GIA package + int fUseCSat; // uses circuit-based solver + int fLightSynth; // uses lighter version of synthesis + int fVerbose; // verbose stats + int timeSynth; // synthesis runtime + int nNodesAhead; // the lookahead in terms of nodes + int nCallsRecycle; // calls to perform before recycling SAT solver +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== dchAig.c ==========================================================*/ +extern Aig_Man_t * Dch_DeriveTotalAig( Vec_Ptr_t * vAigs ); +/*=== dchCore.c ==========================================================*/ +extern void Dch_ManSetDefaultParams( Dch_Pars_t * p ); +extern int Dch_ManReadVerbose( Dch_Pars_t * p ); +extern Aig_Man_t * Dch_ComputeChoices( Aig_Man_t * pAig, Dch_Pars_t * pPars ); +extern void Dch_ComputeEquivalences( Aig_Man_t * pAig, Dch_Pars_t * pPars ); +/*=== dchScript.c ==========================================================*/ +extern Aig_Man_t * Dar_ManChoiceNew( Aig_Man_t * pAig, Dch_Pars_t * pPars ); + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/proof/dch/dchAig.c b/src/proof/dch/dchAig.c new file mode 100644 index 00000000..91a00c63 --- /dev/null +++ b/src/proof/dch/dchAig.c @@ -0,0 +1,119 @@ +/**CFile**************************************************************** + + FileName [dchAig.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Choice computation for tech-mapping.] + + Synopsis [AIG manipulation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 29, 2008.] + + Revision [$Id: dchAig.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "dchInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Derives the cumulative AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_DeriveTotalAig_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + if ( pObj->pData ) + return; + Dch_DeriveTotalAig_rec( p, Aig_ObjFanin0(pObj) ); + Dch_DeriveTotalAig_rec( p, Aig_ObjFanin1(pObj) ); + pObj->pData = Aig_And( p, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Derives the cumulative AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Dch_DeriveTotalAig( Vec_Ptr_t * vAigs ) +{ + Aig_Man_t * pAig, * pAig2, * pAigTotal; + Aig_Obj_t * pObj, * pObjPi, * pObjPo; + int i, k, nNodes; + assert( Vec_PtrSize(vAigs) > 0 ); + // make sure they have the same number of PIs/POs + nNodes = 0; + pAig = (Aig_Man_t *)Vec_PtrEntry( vAigs, 0 ); + Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig2, i ) + { + assert( Aig_ManPiNum(pAig) == Aig_ManPiNum(pAig2) ); + assert( Aig_ManPoNum(pAig) == Aig_ManPoNum(pAig2) ); + nNodes += Aig_ManNodeNum(pAig2); + Aig_ManCleanData( pAig2 ); + } + // map constant nodes + pAigTotal = Aig_ManStart( nNodes ); + Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig2, k ) + Aig_ManConst1(pAig2)->pData = Aig_ManConst1(pAigTotal); + // map primary inputs + Aig_ManForEachPi( pAig, pObj, i ) + { + pObjPi = Aig_ObjCreatePi( pAigTotal ); + Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig2, k ) + Aig_ManPi( pAig2, i )->pData = pObjPi; + } + // construct the AIG in the order of POs + Aig_ManForEachPo( pAig, pObj, i ) + { + Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig2, k ) + { + pObjPo = Aig_ManPo( pAig2, i ); + Dch_DeriveTotalAig_rec( pAigTotal, Aig_ObjFanin0(pObjPo) ); + } + Aig_ObjCreatePo( pAigTotal, Aig_ObjChild0Copy(pObj) ); + } +/* + // mark the cone of the first AIG + Aig_ManIncrementTravId( pAigTotal ); + Aig_ManForEachObj( pAig, pObj, i ) + if ( pObj->pData ) + Aig_ObjSetTravIdCurrent( pAigTotal, pObj->pData ); +*/ + // cleanup should not be done + return pAigTotal; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/dch/dchChoice.c b/src/proof/dch/dchChoice.c new file mode 100644 index 00000000..1772f8aa --- /dev/null +++ b/src/proof/dch/dchChoice.c @@ -0,0 +1,508 @@ +/**CFile**************************************************************** + + FileName [dchChoice.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Choice computation for tech-mapping.] + + Synopsis [Contrustion of choices.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 29, 2008.] + + Revision [$Id: dchChoice.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "dchInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Counts the number of representatives.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dch_DeriveChoiceCountReprs( Aig_Man_t * pAig ) +{ + Aig_Obj_t * pObj, * pRepr; + int i, nReprs = 0; + Aig_ManForEachObj( pAig, pObj, i ) + { + pRepr = Aig_ObjRepr( pAig, pObj ); + if ( pRepr == NULL ) + continue; + assert( pRepr->Id < pObj->Id ); + nReprs++; + } + return nReprs; +} + +/**Function************************************************************* + + Synopsis [Counts the number of equivalences.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dch_DeriveChoiceCountEquivs( Aig_Man_t * pAig ) +{ + Aig_Obj_t * pObj, * pTemp, * pPrev; + int i, nEquivs = 0, Counter = 0; + Aig_ManForEachObj( pAig, pObj, i ) + { + if ( !Aig_ObjIsChoice(pAig, pObj) ) + continue; + for ( pPrev = pObj, pTemp = Aig_ObjEquiv(pAig, pObj); pTemp; + pPrev = pTemp, pTemp = Aig_ObjEquiv(pAig, pTemp) ) + { + if ( pTemp->nRefs > 0 ) + { + // remove referenced node from equivalence class + assert( pAig->pEquivs[pPrev->Id] == pTemp ); + pAig->pEquivs[pPrev->Id] = pAig->pEquivs[pTemp->Id]; + pAig->pEquivs[pTemp->Id] = NULL; + // how about the need to continue iterating over the list? + // pPrev = pTemp ??? + Counter++; + } + nEquivs++; + } + } +// printf( "Removed %d classes.\n", Counter ); + + if ( Counter ) + Dch_DeriveChoiceCountEquivs( pAig ); +// if ( Counter ) +// printf( "Removed %d equiv nodes because of non-zero ref counter.\n", Counter ); + return nEquivs; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the choice node of pRepr is in the TFI of pObj.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dch_ObjCheckTfi_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + // check the trivial cases + if ( pObj == NULL ) + return 0; + if ( Aig_ObjIsPi(pObj) ) + return 0; + if ( pObj->fMarkA ) + return 1; + // skip the visited node + if ( Aig_ObjIsTravIdCurrent( p, pObj ) ) + return 0; + Aig_ObjSetTravIdCurrent( p, pObj ); + // check the children + if ( Dch_ObjCheckTfi_rec( p, Aig_ObjFanin0(pObj) ) ) + return 1; + if ( Dch_ObjCheckTfi_rec( p, Aig_ObjFanin1(pObj) ) ) + return 1; + // check equivalent nodes + return Dch_ObjCheckTfi_rec( p, Aig_ObjEquiv(p, pObj) ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the choice node of pRepr is in the TFI of pObj.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dch_ObjCheckTfi( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr ) +{ + Aig_Obj_t * pTemp; + int RetValue; + assert( !Aig_IsComplement(pObj) ); + assert( !Aig_IsComplement(pRepr) ); + // mark nodes of the choice node + for ( pTemp = pRepr; pTemp; pTemp = Aig_ObjEquiv(p, pTemp) ) + pTemp->fMarkA = 1; + // traverse the new node + Aig_ManIncrementTravId( p ); + RetValue = Dch_ObjCheckTfi_rec( p, pObj ); + // unmark nodes of the choice node + for ( pTemp = pRepr; pTemp; pTemp = Aig_ObjEquiv(p, pTemp) ) + pTemp->fMarkA = 0; + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Returns representatives of fanin in approapriate polarity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Aig_Obj_t * Aig_ObjGetRepr( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pRepr; + if ( (pRepr = Aig_ObjRepr(p, Aig_Regular(pObj))) ) + return Aig_NotCond( pRepr, Aig_Regular(pObj)->fPhase ^ pRepr->fPhase ^ Aig_IsComplement(pObj) ); + return pObj; +} + +static inline Aig_Obj_t * Aig_ObjChild0CopyRepr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_ObjGetRepr( p, Aig_ObjChild0Copy(pObj) ); } +static inline Aig_Obj_t * Aig_ObjChild1CopyRepr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_ObjGetRepr( p, Aig_ObjChild1Copy(pObj) ); } + +/**Function************************************************************* + + Synopsis [Derives the AIG with choices from representatives.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_DeriveChoiceAigNode( Aig_Man_t * pAigNew, Aig_Man_t * pAigOld, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pRepr, * pObjNew, * pReprNew; + // get the new node + pObj->pData = Aig_And( pAigNew, + Aig_ObjChild0CopyRepr(pAigNew, pObj), + Aig_ObjChild1CopyRepr(pAigNew, pObj) ); + pRepr = Aig_ObjRepr( pAigOld, pObj ); + if ( pRepr == NULL ) + return; + // get the corresponding new nodes + pObjNew = Aig_Regular((Aig_Obj_t *)pObj->pData); + pReprNew = Aig_Regular((Aig_Obj_t *)pRepr->pData); + if ( pObjNew == pReprNew ) + return; + // skip the earlier nodes + if ( pReprNew->Id > pObjNew->Id ) + return; + assert( pReprNew->Id < pObjNew->Id ); + // set the representatives + Aig_ObjSetRepr( pAigNew, pObjNew, pReprNew ); + // skip used nodes + if ( pObjNew->nRefs > 0 ) + return; + assert( pObjNew->nRefs == 0 ); + // update new nodes of the object + if ( !Aig_ObjIsNode(pRepr) ) + return; + // skip choices with combinational loops + if ( Dch_ObjCheckTfi( pAigNew, pObjNew, pReprNew ) ) + return; + // add choice + pAigNew->pEquivs[pObjNew->Id] = pAigNew->pEquivs[pReprNew->Id]; + pAigNew->pEquivs[pReprNew->Id] = pObjNew; +} + +/**Function************************************************************* + + Synopsis [Derives the AIG with choices from representatives.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Dch_DeriveChoiceAig_old( Aig_Man_t * pAig ) +{ + Aig_Man_t * pChoices, * pTemp; + Aig_Obj_t * pObj; + int i; + // start recording equivalences + pChoices = Aig_ManStart( Aig_ManObjNumMax(pAig) ); + pChoices->pEquivs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) ); + pChoices->pReprs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) ); + // map constants and PIs + Aig_ManCleanData( pAig ); + Aig_ManConst1(pAig)->pData = Aig_ManConst1(pChoices); + Aig_ManForEachPi( pAig, pObj, i ) + pObj->pData = Aig_ObjCreatePi( pChoices ); + // construct choices for the internal nodes + assert( pAig->pReprs != NULL ); + Aig_ManForEachNode( pAig, pObj, i ) + Dch_DeriveChoiceAigNode( pChoices, pAig, pObj ); + Aig_ManForEachPo( pAig, pObj, i ) + Aig_ObjCreatePo( pChoices, Aig_ObjChild0CopyRepr(pChoices, pObj) ); + Dch_DeriveChoiceCountEquivs( pChoices ); + // there is no need for cleanup + ABC_FREE( pChoices->pReprs ); + pChoices = Aig_ManDupDfs( pTemp = pChoices ); + Aig_ManStop( pTemp ); + return pChoices; +} + + + + +/**Function************************************************************* + + Synopsis [Checks for combinational loops in the AIG.] + + Description [Returns 1 if combinational loop is detected.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManCheckAcyclic_rec( Aig_Man_t * p, Aig_Obj_t * pNode, int fVerbose ) +{ + Aig_Obj_t * pFanin; + int fAcyclic; + if ( Aig_ObjIsPi(pNode) || Aig_ObjIsConst1(pNode) ) + return 1; + assert( Aig_ObjIsNode(pNode) ); + // make sure the node is not visited + assert( !Aig_ObjIsTravIdPrevious(p, pNode) ); + // check if the node is part of the combinational loop + if ( Aig_ObjIsTravIdCurrent(p, pNode) ) + { + if ( fVerbose ) + Abc_Print( 1, "Network \"%s\" contains combinational loop!\n", p->pSpec? p->pSpec : NULL ); + if ( fVerbose ) + Abc_Print( 1, "Node \"%d\" is encountered twice on the following path to the COs:\n", Aig_ObjId(pNode) ); + return 0; + } + // mark this node as a node on the current path + Aig_ObjSetTravIdCurrent( p, pNode ); + + // visit the transitive fanin + pFanin = Aig_ObjFanin0(pNode); + // check if the fanin is visited + if ( !Aig_ObjIsTravIdPrevious(p, pFanin) ) + { + // traverse the fanin's cone searching for the loop + if ( !(fAcyclic = Aig_ManCheckAcyclic_rec(p, pFanin, fVerbose)) ) + { + // return as soon as the loop is detected + if ( fVerbose ) + Abc_Print( 1, " %d ->", Aig_ObjId(pFanin) ); + return 0; + } + } + + // visit the transitive fanin + pFanin = Aig_ObjFanin1(pNode); + // check if the fanin is visited + if ( !Aig_ObjIsTravIdPrevious(p, pFanin) ) + { + // traverse the fanin's cone searching for the loop + if ( !(fAcyclic = Aig_ManCheckAcyclic_rec(p, pFanin, fVerbose)) ) + { + // return as soon as the loop is detected + if ( fVerbose ) + Abc_Print( 1, " %d ->", Aig_ObjId(pFanin) ); + return 0; + } + } + + // visit choices + if ( Aig_ObjRepr(p, pNode) == NULL && Aig_ObjEquiv(p, pNode) != NULL ) + { + for ( pFanin = Aig_ObjEquiv(p, pNode); pFanin; pFanin = Aig_ObjEquiv(p, pFanin) ) + { + // check if the fanin is visited + if ( Aig_ObjIsTravIdPrevious(p, pFanin) ) + continue; + // traverse the fanin's cone searching for the loop + if ( (fAcyclic = Aig_ManCheckAcyclic_rec(p, pFanin, fVerbose)) ) + continue; + // return as soon as the loop is detected + if ( fVerbose ) + Abc_Print( 1, " %d", Aig_ObjId(pFanin) ); + if ( fVerbose ) + Abc_Print( 1, " (choice of %d) -> ", Aig_ObjId(pNode) ); + return 0; + } + } + // mark this node as a visited node + Aig_ObjSetTravIdPrevious( p, pNode ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Checks for combinational loops in the AIG.] + + Description [Returns 1 if there is no combinational loops.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManCheckAcyclic( Aig_Man_t * p, int fVerbose ) +{ + Aig_Obj_t * pNode; + int fAcyclic; + int i; + // set the traversal ID for this DFS ordering + Aig_ManIncrementTravId( p ); + Aig_ManIncrementTravId( p ); + // 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; + Aig_ManForEachPo( p, pNode, i ) + { + pNode = Aig_ObjFanin0(pNode); + if ( Aig_ObjIsTravIdPrevious(p, pNode) ) + continue; + // traverse the output logic cone + if ( (fAcyclic = Aig_ManCheckAcyclic_rec(p, pNode, fVerbose)) ) + continue; + // stop as soon as the first loop is detected + if ( fVerbose ) + Abc_Print( 1, " CO %d\n", i ); + break; + } + return fAcyclic; +} + +/**Function************************************************************* + + Synopsis [Removes combinational loop.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManFixLoopProblem( Aig_Man_t * p, int fVerbose ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0, Counter2 = 0; + Aig_ManForEachObj( p, pObj, i ) + { + if ( !Aig_ObjIsTravIdCurrent(p, pObj) ) + continue; + Counter2++; + if ( Aig_ObjRepr(p, pObj) == NULL && Aig_ObjEquiv(p, pObj) != NULL ) + { + Aig_ObjSetEquiv(p, pObj, NULL); + Counter++; + } + } + if ( fVerbose ) + Abc_Print( 1, "Fixed %d choice nodes on the path with %d objects.\n", Counter, Counter2 ); +} + + +/**Function************************************************************* + + Synopsis [Derives the AIG with choices from representatives.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Dch_DeriveChoiceAigInt( Aig_Man_t * pAig ) +{ + Aig_Man_t * pChoices; + Aig_Obj_t * pObj; + int i; + // start recording equivalences + pChoices = Aig_ManStart( Aig_ManObjNumMax(pAig) ); + pChoices->pEquivs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) ); + pChoices->pReprs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) ); + // map constants and PIs + Aig_ManCleanData( pAig ); + Aig_ManConst1(pAig)->pData = Aig_ManConst1(pChoices); + Aig_ManForEachPi( pAig, pObj, i ) + pObj->pData = Aig_ObjCreatePi( pChoices ); + // construct choices for the internal nodes + assert( pAig->pReprs != NULL ); + Aig_ManForEachNode( pAig, pObj, i ) + Dch_DeriveChoiceAigNode( pChoices, pAig, pObj ); + Aig_ManForEachPo( pAig, pObj, i ) + Aig_ObjCreatePo( pChoices, Aig_ObjChild0CopyRepr(pChoices, pObj) ); + Dch_DeriveChoiceCountEquivs( pChoices ); + Aig_ManSetRegNum( pChoices, Aig_ManRegNum(pAig) ); + return pChoices; +} + +/**Function************************************************************* + + Synopsis [Derives the AIG with choices from representatives.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Dch_DeriveChoiceAig( Aig_Man_t * pAig ) +{ + extern int Aig_ManCheckAcyclic( Aig_Man_t * pAig, int fVerbose ); + Aig_Man_t * pChoices, * pTemp; + int fVerbose = 0; + pChoices = Dch_DeriveChoiceAigInt( pAig ); +// pChoices = Dch_DeriveChoiceAigInt( pTemp = pChoices ); +// Aig_ManStop( pTemp ); + // there is no need for cleanup + ABC_FREE( pChoices->pReprs ); + while ( !Aig_ManCheckAcyclic( pChoices, fVerbose ) ) + { + if ( fVerbose ) + Abc_Print( 1, "There is a loop!\n" ); + Aig_ManFixLoopProblem( pChoices, fVerbose ); + } + pChoices = Aig_ManDupDfs( pTemp = pChoices ); + Aig_ManStop( pTemp ); + return pChoices; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/dch/dchClass.c b/src/proof/dch/dchClass.c new file mode 100644 index 00000000..24476309 --- /dev/null +++ b/src/proof/dch/dchClass.c @@ -0,0 +1,611 @@ +/**CFile**************************************************************** + + FileName [dchClass.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Choice computation for tech-mapping.] + + Synopsis [Representation of candidate equivalence classes.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 29, 2008.] + + Revision [$Id: dchClass.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "dchInt.h" + +ABC_NAMESPACE_IMPL_START + + +/* + 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 topo order of their representatives. +*/ + +// internal representation of candidate equivalence classes +struct Dch_Cla_t_ +{ + // class information + Aig_Man_t * pAig; // original AIG manager + Aig_Obj_t *** pId2Class; // non-const classes by ID of repr node + int * pClassSizes; // sizes of each equivalence class + // statistics + int nClasses; // the total number of non-const classes + int nCands1; // the total number of const candidates + int nLits; // the number of literals in all classes + // memory + Aig_Obj_t ** pMemClasses; // memory allocated for equivalence classes + Aig_Obj_t ** pMemClassesFree; // memory allocated for equivalence classes to be used + // temporary data + Vec_Ptr_t * vClassOld; // old equivalence class after splitting + Vec_Ptr_t * vClassNew; // new equivalence class(es) after splitting + // procedures used for class refinement + void * pManData; + unsigned (*pFuncNodeHash) (void *,Aig_Obj_t *); // returns hash key of the node + int (*pFuncNodeIsConst) (void *,Aig_Obj_t *); // returns 1 if the node is a constant + int (*pFuncNodesAreEqual) (void *,Aig_Obj_t *, Aig_Obj_t *); // returns 1 if nodes are equal up to a complement +}; + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline Aig_Obj_t * Dch_ObjNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj ) { return ppNexts[pObj->Id]; } +static inline void Dch_ObjSetNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { ppNexts[pObj->Id] = pNext; } + +// iterator through the equivalence classes +#define Dch_ManForEachClass( p, ppClass, i ) \ + for ( i = 0; i < Aig_ManObjNumMax(p->pAig); i++ ) \ + if ( ((ppClass) = p->pId2Class[i]) == NULL ) {} else +// iterator through the nodes in one class +#define Dch_ClassForEachNode( p, pRepr, pNode, i ) \ + for ( i = 0; i < p->pClassSizes[pRepr->Id]; i++ ) \ + if ( ((pNode) = p->pId2Class[pRepr->Id][i]) == NULL ) {} else + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates one equivalence class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Dch_ObjAddClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, Aig_Obj_t ** pClass, int nSize ) +{ + assert( p->pId2Class[pRepr->Id] == NULL ); + p->pId2Class[pRepr->Id] = pClass; + assert( p->pClassSizes[pRepr->Id] == 0 ); + assert( nSize > 1 ); + p->pClassSizes[pRepr->Id] = nSize; + p->nClasses++; + p->nLits += nSize - 1; +} + +/**Function************************************************************* + + Synopsis [Removes one equivalence class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Aig_Obj_t ** Dch_ObjRemoveClass( Dch_Cla_t * p, Aig_Obj_t * pRepr ) +{ + Aig_Obj_t ** pClass = p->pId2Class[pRepr->Id]; + int nSize; + assert( pClass != NULL ); + p->pId2Class[pRepr->Id] = NULL; + nSize = p->pClassSizes[pRepr->Id]; + assert( nSize > 1 ); + p->nClasses--; + p->nLits -= nSize - 1; + p->pClassSizes[pRepr->Id] = 0; + return pClass; +} + +/**Function************************************************************* + + Synopsis [Starts representation of equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dch_Cla_t * Dch_ClassesStart( Aig_Man_t * pAig ) +{ + Dch_Cla_t * p; + p = ABC_ALLOC( Dch_Cla_t, 1 ); + memset( p, 0, sizeof(Dch_Cla_t) ); + p->pAig = pAig; + p->pId2Class = ABC_CALLOC( Aig_Obj_t **, Aig_ManObjNumMax(pAig) ); + p->pClassSizes = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); + p->vClassOld = Vec_PtrAlloc( 100 ); + p->vClassNew = Vec_PtrAlloc( 100 ); + assert( pAig->pReprs == NULL ); + Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) ); + return p; +} + +/**Function************************************************************* + + Synopsis [Starts representation of equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_ClassesSetData( Dch_Cla_t * p, void * pManData, + unsigned (*pFuncNodeHash)(void *,Aig_Obj_t *), // returns hash key of the node + int (*pFuncNodeIsConst)(void *,Aig_Obj_t *), // returns 1 if the node is a constant + int (*pFuncNodesAreEqual)(void *,Aig_Obj_t *, Aig_Obj_t *) ) // returns 1 if nodes are equal up to a complement +{ + p->pManData = pManData; + p->pFuncNodeHash = pFuncNodeHash; + p->pFuncNodeIsConst = pFuncNodeIsConst; + p->pFuncNodesAreEqual = pFuncNodesAreEqual; +} + +/**Function************************************************************* + + Synopsis [Stop representation of equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_ClassesStop( Dch_Cla_t * p ) +{ + if ( p->vClassNew ) Vec_PtrFree( p->vClassNew ); + if ( p->vClassOld ) Vec_PtrFree( p->vClassOld ); + ABC_FREE( p->pId2Class ); + ABC_FREE( p->pClassSizes ); + ABC_FREE( p->pMemClasses ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Stop representation of equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dch_ClassesLitNum( Dch_Cla_t * p ) +{ + return p->nLits; +} + +/**Function************************************************************* + + Synopsis [Stop representation of equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t ** Dch_ClassesReadClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, int * pnSize ) +{ + assert( p->pId2Class[pRepr->Id] != NULL ); + assert( p->pClassSizes[pRepr->Id] > 1 ); + *pnSize = p->pClassSizes[pRepr->Id]; + return p->pId2Class[pRepr->Id]; +} + +/**Function************************************************************* + + Synopsis [Checks candidate equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_ClassesCheck( Dch_Cla_t * p ) +{ + Aig_Obj_t * pObj, * pPrev, ** ppClass; + int i, k, nLits, nClasses, nCands1; + nClasses = nLits = 0; + Dch_ManForEachClass( p, ppClass, k ) + { + pPrev = NULL; + Dch_ClassForEachNode( p, ppClass[0], pObj, i ) + { + if ( i == 0 ) + assert( Aig_ObjRepr(p->pAig, pObj) == NULL ); + else + { + assert( Aig_ObjRepr(p->pAig, pObj) == ppClass[0] ); + assert( pPrev->Id < pObj->Id ); + nLits++; + } + pPrev = pObj; + } + nClasses++; + } + nCands1 = 0; + Aig_ManForEachObj( p->pAig, pObj, i ) + nCands1 += Dch_ObjIsConst1Cand( p->pAig, pObj ); + assert( p->nLits == nLits ); + assert( p->nCands1 == nCands1 ); + assert( p->nClasses == nClasses ); +} + +/**Function************************************************************* + + Synopsis [Prints simulation classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_ClassesPrintOne( Dch_Cla_t * p, Aig_Obj_t * pRepr ) +{ + Aig_Obj_t * pObj; + int i; + Abc_Print( 1, "{ " ); + Dch_ClassForEachNode( p, pRepr, pObj, i ) + Abc_Print( 1, "%d(%d,%d) ", pObj->Id, pObj->Level, Aig_SupportSize(p->pAig,pObj) ); + Abc_Print( 1, "}\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints simulation classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_ClassesPrint( Dch_Cla_t * p, int fVeryVerbose ) +{ + Aig_Obj_t ** ppClass; + Aig_Obj_t * pObj; + int i; + Abc_Print( 1, "Equivalence classes: Const1 = %5d. Class = %5d. Lit = %5d.\n", + p->nCands1, p->nClasses, p->nLits ); + if ( !fVeryVerbose ) + return; + Abc_Print( 1, "Constants { " ); + Aig_ManForEachObj( p->pAig, pObj, i ) + if ( Dch_ObjIsConst1Cand( p->pAig, pObj ) ) + Abc_Print( 1, "%d(%d,%d) ", pObj->Id, pObj->Level, Aig_SupportSize(p->pAig,pObj) ); + Abc_Print( 1, "}\n" ); + Dch_ManForEachClass( p, ppClass, i ) + { + Abc_Print( 1, "%3d (%3d) : ", i, p->pClassSizes[i] ); + Dch_ClassesPrintOne( p, ppClass[0] ); + } + Abc_Print( 1, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Creates initial simulation classes.] + + Description [Assumes that simulation info is assigned.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_ClassesPrepare( Dch_Cla_t * p, int fLatchCorr, int nMaxLevs ) +{ + Aig_Obj_t ** ppTable, ** ppNexts, ** ppClassNew; + Aig_Obj_t * pObj, * pTemp, * pRepr; + int i, k, nTableSize, nNodes, iEntry, nEntries, nEntries2; + + // allocate the hash table hashing simulation info into nodes + nTableSize = Abc_PrimeCudd( Aig_ManObjNumMax(p->pAig)/4 ); + ppTable = ABC_CALLOC( Aig_Obj_t *, nTableSize ); + ppNexts = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) ); + + // add all the nodes to the hash table + nEntries = 0; + 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; + } + // check if the node belongs to the class of constant 1 + if ( p->pFuncNodeIsConst( p->pManData, pObj ) ) + { + Dch_ObjSetConst1Cand( p->pAig, pObj ); + p->nCands1++; + continue; + } + // hash the node by its simulation info + iEntry = p->pFuncNodeHash( p->pManData, pObj ) % nTableSize; + // add the node to the class + if ( ppTable[iEntry] == NULL ) + ppTable[iEntry] = pObj; + else + { + // set the representative of this node + pRepr = ppTable[iEntry]; + Aig_ObjSetRepr( p->pAig, pObj, pRepr ); + // add node to the table + if ( Dch_ObjNext( ppNexts, pRepr ) == NULL ) + { // this will be the second entry + p->pClassSizes[pRepr->Id]++; + nEntries++; + } + // add the entry to the list + Dch_ObjSetNext( ppNexts, pObj, Dch_ObjNext( ppNexts, pRepr ) ); + Dch_ObjSetNext( ppNexts, pRepr, pObj ); + p->pClassSizes[pRepr->Id]++; + nEntries++; + } + } + + // allocate room for classes + p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, nEntries + p->nCands1 ); + p->pMemClassesFree = p->pMemClasses + nEntries; + + // copy the entries into storage in the topological order + nEntries2 = 0; + Aig_ManForEachObj( p->pAig, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) ) + continue; + nNodes = p->pClassSizes[pObj->Id]; + // skip the nodes that are not representatives of non-trivial classes + if ( nNodes == 0 ) + continue; + assert( nNodes > 1 ); + // add the nodes to the class in the topological order + ppClassNew = p->pMemClasses + nEntries2; + ppClassNew[0] = pObj; + for ( pTemp = Dch_ObjNext(ppNexts, pObj), k = 1; pTemp; + pTemp = Dch_ObjNext(ppNexts, pTemp), k++ ) + { + ppClassNew[nNodes-k] = pTemp; + } + // add the class of nodes + p->pClassSizes[pObj->Id] = 0; + Dch_ObjAddClass( p, pObj, ppClassNew, nNodes ); + // increment the number of entries + nEntries2 += nNodes; + } + assert( nEntries == nEntries2 ); + ABC_FREE( ppTable ); + ABC_FREE( ppNexts ); + // now it is time to refine the classes + Dch_ClassesRefine( p ); + Dch_ClassesCheck( p ); +} + +/**Function************************************************************* + + Synopsis [Iteratively refines the classes after simulation.] + + Description [Returns the number of refinements performed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dch_ClassesRefineOneClass( Dch_Cla_t * p, Aig_Obj_t * pReprOld, int fRecursive ) +{ + Aig_Obj_t ** pClassOld, ** pClassNew; + Aig_Obj_t * pObj, * pReprNew; + int i; + + // split the class + Vec_PtrClear( p->vClassOld ); + Vec_PtrClear( p->vClassNew ); + Dch_ClassForEachNode( p, pReprOld, pObj, i ) + if ( p->pFuncNodesAreEqual(p->pManData, pReprOld, pObj) ) + Vec_PtrPush( p->vClassOld, pObj ); + else + Vec_PtrPush( p->vClassNew, pObj ); + // check if splitting happened + if ( Vec_PtrSize(p->vClassNew) == 0 ) + return 0; + + // get the new representative + pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 ); + assert( Vec_PtrSize(p->vClassOld) > 0 ); + assert( Vec_PtrSize(p->vClassNew) > 0 ); + + // create old class + pClassOld = Dch_ObjRemoveClass( p, pReprOld ); + Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassOld, pObj, i ) + { + pClassOld[i] = pObj; + Aig_ObjSetRepr( p->pAig, pObj, i? pReprOld : NULL ); + } + // create new class + pClassNew = pClassOld + i; + Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i ) + { + pClassNew[i] = pObj; + Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL ); + } + + // put classes back + if ( Vec_PtrSize(p->vClassOld) > 1 ) + Dch_ObjAddClass( p, pReprOld, pClassOld, Vec_PtrSize(p->vClassOld) ); + if ( Vec_PtrSize(p->vClassNew) > 1 ) + Dch_ObjAddClass( p, pReprNew, pClassNew, Vec_PtrSize(p->vClassNew) ); + + // check if the class should be recursively refined + if ( fRecursive && Vec_PtrSize(p->vClassNew) > 1 ) + return 1 + Dch_ClassesRefineOneClass( p, pReprNew, 1 ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Refines the classes after simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dch_ClassesRefine( Dch_Cla_t * p ) +{ + Aig_Obj_t ** ppClass; + int i, nRefis = 0; + Dch_ManForEachClass( p, ppClass, i ) + nRefis += Dch_ClassesRefineOneClass( p, ppClass[0], 0 ); + return nRefis; +} + + +/**Function************************************************************* + + Synopsis [Returns equivalence class of the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_ClassesCollectOneClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, Vec_Ptr_t * vRoots ) +{ + Aig_Obj_t * pObj; + int i; + Vec_PtrClear( vRoots ); + Dch_ClassForEachNode( p, pRepr, pObj, i ) + Vec_PtrPush( vRoots, pObj ); + assert( Vec_PtrSize(vRoots) > 1 ); +} + +/**Function************************************************************* + + Synopsis [Returns equivalence class of the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_ClassesCollectConst1Group( Dch_Cla_t * p, Aig_Obj_t * pObj, int nNodes, Vec_Ptr_t * vRoots ) +{ + int i, Limit; + Vec_PtrClear( vRoots ); + Limit = Abc_MinInt( pObj->Id + nNodes, Aig_ManObjNumMax(p->pAig) ); + for ( i = pObj->Id; i < Limit; i++ ) + { + pObj = Aig_ManObj( p->pAig, i ); + if ( pObj && Dch_ObjIsConst1Cand( p->pAig, pObj ) ) + Vec_PtrPush( vRoots, pObj ); + } +} + +/**Function************************************************************* + + Synopsis [Refine the group of constant 1 nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dch_ClassesRefineConst1Group( Dch_Cla_t * p, Vec_Ptr_t * vRoots, int fRecursive ) +{ + Aig_Obj_t * pObj, * pReprNew, ** ppClassNew; + int i; + if ( Vec_PtrSize(vRoots) == 0 ) + return 0; + // collect the nodes to be refined + Vec_PtrClear( p->vClassNew ); + Vec_PtrForEachEntry( Aig_Obj_t *, vRoots, pObj, i ) + if ( !p->pFuncNodeIsConst( p->pManData, pObj ) ) + Vec_PtrPush( p->vClassNew, pObj ); + // check if there is a new class + if ( Vec_PtrSize(p->vClassNew) == 0 ) + return 0; + p->nCands1 -= Vec_PtrSize(p->vClassNew); + pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 ); + Aig_ObjSetRepr( p->pAig, pReprNew, NULL ); + if ( Vec_PtrSize(p->vClassNew) == 1 ) + return 1; + // create a new class composed of these nodes + ppClassNew = p->pMemClassesFree; + p->pMemClassesFree += Vec_PtrSize(p->vClassNew); + Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i ) + { + ppClassNew[i] = pObj; + Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL ); + } + Dch_ObjAddClass( p, pReprNew, ppClassNew, Vec_PtrSize(p->vClassNew) ); + // refine them recursively + if ( fRecursive ) + return 1 + Dch_ClassesRefineOneClass( p, pReprNew, 1 ); + return 1; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/dch/dchCnf.c b/src/proof/dch/dchCnf.c new file mode 100644 index 00000000..4175a123 --- /dev/null +++ b/src/proof/dch/dchCnf.c @@ -0,0 +1,334 @@ +/**CFile**************************************************************** + + FileName [dchCnf.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Choice computation for tech-mapping.] + + Synopsis [Computation of CNF.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 29, 2008.] + + Revision [$Id: dchCnf.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "dchInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Addes clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_AddClausesMux( Dch_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 = Dch_ObjSatNum(p,pNode); + VarI = Dch_ObjSatNum(p,pNodeI); + VarT = Dch_ObjSatNum(p,Aig_Regular(pNodeT)); + VarE = Dch_ObjSatNum(p,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); + if ( p->pPars->fPolarFlip ) + { + if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Aig_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + 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); + if ( p->pPars->fPolarFlip ) + { + if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Aig_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + 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); + if ( p->pPars->fPolarFlip ) + { + if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + 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); + if ( p->pPars->fPolarFlip ) + { + if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + 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); + if ( p->pPars->fPolarFlip ) + { + if ( Aig_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + 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); + if ( p->pPars->fPolarFlip ) + { + if ( Aig_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); +} + +/**Function************************************************************* + + Synopsis [Addes clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_AddClausesSuper( Dch_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 = ABC_ALLOC( int, nLits ); + // suppose AND-gate is A & B = C + // add !A => !C or A + !C + Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i ) + { + pLits[0] = toLitCond(Dch_ObjSatNum(p,Aig_Regular(pFanin)), Aig_IsComplement(pFanin)); + pLits[1] = toLitCond(Dch_ObjSatNum(p,pNode), 1); + if ( p->pPars->fPolarFlip ) + { + if ( Aig_Regular(pFanin)->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( pNode->fPhase ) pLits[1] = lit_neg( pLits[1] ); + } + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); + assert( RetValue ); + } + // add A & B => C or !A + !B + C + Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i ) + { + pLits[i] = toLitCond(Dch_ObjSatNum(p,Aig_Regular(pFanin)), !Aig_IsComplement(pFanin)); + if ( p->pPars->fPolarFlip ) + { + if ( Aig_Regular(pFanin)->fPhase ) pLits[i] = lit_neg( pLits[i] ); + } + } + pLits[nLits-1] = toLitCond(Dch_ObjSatNum(p,pNode), 0); + if ( p->pPars->fPolarFlip ) + { + if ( pNode->fPhase ) pLits[nLits-1] = lit_neg( pLits[nLits-1] ); + } + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits ); + assert( RetValue ); + ABC_FREE( pLits ); +} + +/**Function************************************************************* + + Synopsis [Collects the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_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 + Dch_CollectSuper_rec( Aig_ObjChild0(pObj), vSuper, 0, fUseMuxes ); + Dch_CollectSuper_rec( Aig_ObjChild1(pObj), vSuper, 0, fUseMuxes ); +} + +/**Function************************************************************* + + Synopsis [Collects the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_CollectSuper( Aig_Obj_t * pObj, int fUseMuxes, Vec_Ptr_t * vSuper ) +{ + assert( !Aig_IsComplement(pObj) ); + assert( !Aig_ObjIsPi(pObj) ); + Vec_PtrClear( vSuper ); + Dch_CollectSuper_rec( pObj, vSuper, 1, fUseMuxes ); +} + +/**Function************************************************************* + + Synopsis [Updates the solver clause database.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_ObjAddToFrontier( Dch_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vFrontier ) +{ + assert( !Aig_IsComplement(pObj) ); + if ( Dch_ObjSatNum(p,pObj) ) + return; + assert( Dch_ObjSatNum(p,pObj) == 0 ); + if ( Aig_ObjIsConst1(pObj) ) + return; + Vec_PtrPush( p->vUsedNodes, pObj ); + Dch_ObjSetSatNum( p, pObj, p->nSatVars++ ); + if ( Aig_ObjIsNode(pObj) ) + Vec_PtrPush( vFrontier, pObj ); +} + +/**Function************************************************************* + + Synopsis [Updates the solver clause database.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_CnfNodeAddToSolver( Dch_Man_t * p, Aig_Obj_t * pObj ) +{ + Vec_Ptr_t * vFrontier; + Aig_Obj_t * pNode, * pFanin; + int i, k, fUseMuxes = 1; + // quit if CNF is ready + if ( Dch_ObjSatNum(p,pObj) ) + return; + // start the frontier + vFrontier = Vec_PtrAlloc( 100 ); + Dch_ObjAddToFrontier( p, pObj, vFrontier ); + // explore nodes in the frontier + Vec_PtrForEachEntry( Aig_Obj_t *, vFrontier, pNode, i ) + { + // create the supergate + assert( Dch_ObjSatNum(p,pNode) ); + if ( fUseMuxes && Aig_ObjIsMuxType(pNode) ) + { + Vec_PtrClear( p->vFanins ); + Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin0( Aig_ObjFanin0(pNode) ) ); + Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin0( Aig_ObjFanin1(pNode) ) ); + Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin1( Aig_ObjFanin0(pNode) ) ); + Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin1( Aig_ObjFanin1(pNode) ) ); + Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanins, pFanin, k ) + Dch_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier ); + Dch_AddClausesMux( p, pNode ); + } + else + { + Dch_CollectSuper( pNode, fUseMuxes, p->vFanins ); + Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanins, pFanin, k ) + Dch_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier ); + Dch_AddClausesSuper( p, pNode, p->vFanins ); + } + assert( Vec_PtrSize(p->vFanins) > 1 ); + } + Vec_PtrFree( vFrontier ); +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/dch/dchCore.c b/src/proof/dch/dchCore.c new file mode 100644 index 00000000..bc78682b --- /dev/null +++ b/src/proof/dch/dchCore.c @@ -0,0 +1,158 @@ +/**CFile**************************************************************** + + FileName [dchCore.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Choice computation for tech-mapping.] + + Synopsis [The core procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 29, 2008.] + + Revision [$Id: dchCore.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "dchInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [This procedure sets default parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_ManSetDefaultParams( Dch_Pars_t * p ) +{ + memset( p, 0, sizeof(Dch_Pars_t) ); + p->nWords = 8; // the number of simulation words + p->nBTLimit = 1000; // conflict limit at a node + p->nSatVarMax = 5000; // the max number of SAT variables + p->fSynthesis = 1; // derives three snapshots + p->fPolarFlip = 1; // uses polarity adjustment + p->fSimulateTfo = 1; // simulate TFO + p->fPower = 0; // power-aware rewriting + p->fLightSynth = 0; // uses lighter version of synthesis + p->fVerbose = 0; // verbose stats + p->nNodesAhead = 1000; // the lookahead in terms of nodes + p->nCallsRecycle = 100; // calls to perform before recycling SAT solver +} + +/**Function************************************************************* + + Synopsis [Returns verbose parameter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dch_ManReadVerbose( Dch_Pars_t * p ) +{ + return p->fVerbose; +} + +/**Function************************************************************* + + Synopsis [Performs computation of AIGs with choices.] + + Description [Takes several AIGs and performs choicing.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Dch_ComputeChoices( Aig_Man_t * pAig, Dch_Pars_t * pPars ) +{ + Dch_Man_t * p; + Aig_Man_t * pResult; + int clk, clkTotal = clock(); + // reset random numbers + Aig_ManRandom(1); + // start the choicing manager + p = Dch_ManCreate( pAig, pPars ); + // compute candidate equivalence classes +clk = clock(); + p->ppClasses = Dch_CreateCandEquivClasses( pAig, pPars->nWords, pPars->fVerbose ); +p->timeSimInit = clock() - clk; +// Dch_ClassesPrint( p->ppClasses, 0 ); + p->nLits = Dch_ClassesLitNum( p->ppClasses ); + // perform SAT sweeping + Dch_ManSweep( p ); + // free memory ahead of time +p->timeTotal = clock() - clkTotal; + Dch_ManStop( p ); + // create choices + ABC_FREE( pAig->pTable ); + pResult = Dch_DeriveChoiceAig( pAig ); + // count the number of representatives + if ( pPars->fVerbose ) + Abc_Print( 1, "STATS: Reprs = %6d. Equivs = %6d. Choices = %6d.\n", + Dch_DeriveChoiceCountReprs( pAig ), + Dch_DeriveChoiceCountEquivs( pResult ), + Aig_ManChoiceNum( pResult ) ); + return pResult; +} + +/**Function************************************************************* + + Synopsis [Performs computation of AIGs with choices.] + + Description [Takes several AIGs and performs choicing.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_ComputeEquivalences( Aig_Man_t * pAig, Dch_Pars_t * pPars ) +{ + Dch_Man_t * p; + int clk, clkTotal = clock(); + // reset random numbers + Aig_ManRandom(1); + // start the choicing manager + p = Dch_ManCreate( pAig, pPars ); + // compute candidate equivalence classes +clk = clock(); + p->ppClasses = Dch_CreateCandEquivClasses( pAig, pPars->nWords, pPars->fVerbose ); +p->timeSimInit = clock() - clk; +// Dch_ClassesPrint( p->ppClasses, 0 ); + p->nLits = Dch_ClassesLitNum( p->ppClasses ); + // perform SAT sweeping + Dch_ManSweep( p ); + // free memory ahead of time +p->timeTotal = clock() - clkTotal; + Dch_ManStop( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/dch/dchInt.h b/src/proof/dch/dchInt.h new file mode 100644 index 00000000..c9f2f4f6 --- /dev/null +++ b/src/proof/dch/dchInt.h @@ -0,0 +1,170 @@ +/**CFile**************************************************************** + + FileName [dchInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Choice computation for tech-mapping.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 29, 2008.] + + Revision [$Id: dchInt.h,v 1.00 2008/07/29 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__dch__dchInt_h +#define ABC__aig__dch__dchInt_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "src/aig/aig/aig.h" +#include "src/sat/bsat/satSolver.h" +#include "dch.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +// equivalence classes +typedef struct Dch_Cla_t_ Dch_Cla_t; + +// choicing manager +typedef struct Dch_Man_t_ Dch_Man_t; +struct Dch_Man_t_ +{ + // parameters + Dch_Pars_t * pPars; // choicing parameters + // AIGs used in the package +// Vec_Ptr_t * vAigs; // user-given AIGs + Aig_Man_t * pAigTotal; // intermediate AIG + Aig_Man_t * pAigFraig; // final AIG + // equivalence classes + Dch_Cla_t * ppClasses; // equivalence classes of nodes + Aig_Obj_t ** pReprsProved; // equivalences proved + // SAT solving + sat_solver * pSat; // recyclable SAT solver + int nSatVars; // the counter of SAT variables + int * pSatVars; // mapping of each node into its SAT var + Vec_Ptr_t * vUsedNodes; // nodes whose SAT vars are assigned + int nRecycles; // the number of times SAT solver was recycled + int nCallsSince; // the number of calls since the last recycle + Vec_Ptr_t * vFanins; // fanins of the CNF node + Vec_Ptr_t * vSimRoots; // the roots of cand const 1 nodes to simulate + Vec_Ptr_t * vSimClasses; // the roots of cand equiv classes to simulate + // solver cone size + int nConeThis; + int nConeMax; + // SAT calls statistics + int nSatCalls; // the number of SAT calls + int nSatProof; // the number of proofs + int nSatFailsReal; // the number of timeouts + int nSatCallsUnsat; // the number of unsat SAT calls + int nSatCallsSat; // the number of sat SAT calls + // choice node statistics + int nLits; // the number of lits in the cand equiv classes + int nReprs; // the number of proved equivalent pairs + int nEquivs; // the number of final equivalences + int nChoices; // the number of final choice nodes + // runtime stats + int timeSimInit; // simulation and class computation + int timeSimSat; // simulation of the counter-examples + int timeSat; // solving SAT + int timeSatSat; // sat + int timeSatUnsat; // unsat + int timeSatUndec; // undecided + int timeChoice; // choice computation + int timeOther; // other runtime + int timeTotal; // total runtime +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Dch_ObjSatNum( Dch_Man_t * p, Aig_Obj_t * pObj ) { return p->pSatVars[pObj->Id]; } +static inline void Dch_ObjSetSatNum( Dch_Man_t * p, Aig_Obj_t * pObj, int Num ) { p->pSatVars[pObj->Id] = Num; } + +static inline Aig_Obj_t * Dch_ObjFraig( Aig_Obj_t * pObj ) { return (Aig_Obj_t *)pObj->pData; } +static inline void Dch_ObjSetFraig( Aig_Obj_t * pObj, Aig_Obj_t * pNode ) { pObj->pData = pNode; } + +static inline int Dch_ObjIsConst1Cand( Aig_Man_t * pAig, Aig_Obj_t * pObj ) +{ + return Aig_ObjRepr(pAig, pObj) == Aig_ManConst1(pAig); +} +static inline void Dch_ObjSetConst1Cand( Aig_Man_t * pAig, Aig_Obj_t * pObj ) +{ + assert( !Dch_ObjIsConst1Cand( pAig, pObj ) ); + Aig_ObjSetRepr( pAig, pObj, Aig_ManConst1(pAig) ); +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== dchAig.c ===================================================*/ +/*=== dchChoice.c ===================================================*/ +extern int Dch_DeriveChoiceCountReprs( Aig_Man_t * pAig ); +extern int Dch_DeriveChoiceCountEquivs( Aig_Man_t * pAig ); +extern Aig_Man_t * Dch_DeriveChoiceAig( Aig_Man_t * pAig ); +/*=== dchClass.c =================================================*/ +extern Dch_Cla_t * Dch_ClassesStart( Aig_Man_t * pAig ); +extern void Dch_ClassesSetData( Dch_Cla_t * p, void * pManData, + unsigned (*pFuncNodeHash)(void *,Aig_Obj_t *), + int (*pFuncNodeIsConst)(void *,Aig_Obj_t *), + int (*pFuncNodesAreEqual)(void *,Aig_Obj_t *, Aig_Obj_t *) ); +extern void Dch_ClassesStop( Dch_Cla_t * p ); +extern int Dch_ClassesLitNum( Dch_Cla_t * p ); +extern Aig_Obj_t ** Dch_ClassesReadClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, int * pnSize ); +extern void Dch_ClassesPrint( Dch_Cla_t * p, int fVeryVerbose ); +extern void Dch_ClassesPrepare( Dch_Cla_t * p, int fLatchCorr, int nMaxLevs ); +extern int Dch_ClassesRefine( Dch_Cla_t * p ); +extern int Dch_ClassesRefineOneClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, int fRecursive ); +extern void Dch_ClassesCollectOneClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, Vec_Ptr_t * vRoots ); +extern void Dch_ClassesCollectConst1Group( Dch_Cla_t * p, Aig_Obj_t * pObj, int nNodes, Vec_Ptr_t * vRoots ); +extern int Dch_ClassesRefineConst1Group( Dch_Cla_t * p, Vec_Ptr_t * vRoots, int fRecursive ); +/*=== dchCnf.c ===================================================*/ +extern void Dch_CnfNodeAddToSolver( Dch_Man_t * p, Aig_Obj_t * pObj ); +/*=== dchMan.c ===================================================*/ +extern Dch_Man_t * Dch_ManCreate( Aig_Man_t * pAig, Dch_Pars_t * pPars ); +extern void Dch_ManStop( Dch_Man_t * p ); +extern void Dch_ManSatSolverRecycle( Dch_Man_t * p ); +/*=== dchSat.c ===================================================*/ +extern int Dch_NodesAreEquiv( Dch_Man_t * p, Aig_Obj_t * pObj1, Aig_Obj_t * pObj2 ); +/*=== dchSim.c ===================================================*/ +extern Dch_Cla_t * Dch_CreateCandEquivClasses( Aig_Man_t * pAig, int nWords, int fVerbose ); +/*=== dchSimSat.c ===================================================*/ +extern void Dch_ManResimulateCex( Dch_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr ); +extern void Dch_ManResimulateCex2( Dch_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr ); +/*=== dchSweep.c ===================================================*/ +extern void Dch_ManSweep( Dch_Man_t * p ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/proof/dch/dchMan.c b/src/proof/dch/dchMan.c new file mode 100644 index 00000000..dc856309 --- /dev/null +++ b/src/proof/dch/dchMan.c @@ -0,0 +1,191 @@ +/**CFile**************************************************************** + + FileName [dchMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Choice computation for tech-mapping.] + + Synopsis [Calls to the SAT solver.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 29, 2008.] + + Revision [$Id: dchMan.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "dchInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dch_Man_t * Dch_ManCreate( Aig_Man_t * pAig, Dch_Pars_t * pPars ) +{ + Dch_Man_t * p; + // create interpolation manager + p = ABC_ALLOC( Dch_Man_t, 1 ); + memset( p, 0, sizeof(Dch_Man_t) ); + p->pPars = pPars; + p->pAigTotal = pAig; //Dch_DeriveTotalAig( vAigs ); + Aig_ManFanoutStart( p->pAigTotal ); + // SAT solving + p->nSatVars = 1; + p->pSatVars = ABC_CALLOC( int, Aig_ManObjNumMax(p->pAigTotal) ); + p->vUsedNodes = Vec_PtrAlloc( 1000 ); + p->vFanins = Vec_PtrAlloc( 100 ); + p->vSimRoots = Vec_PtrAlloc( 1000 ); + p->vSimClasses = Vec_PtrAlloc( 1000 ); + // equivalences proved + p->pReprsProved = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAigTotal) ); + return p; +} + +/**Function************************************************************* + + Synopsis [Prints stats of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_ManPrintStats( Dch_Man_t * p ) +{ + int nNodeNum = Aig_ManNodeNum(p->pAigTotal) / 3; + Abc_Print( 1, "Parameters: Sim words = %d. Conf limit = %d. SAT var max = %d.\n", + p->pPars->nWords, p->pPars->nBTLimit, p->pPars->nSatVarMax ); + Abc_Print( 1, "AIG nodes : Total = %6d. Dangling = %6d. Main = %6d. (%6.2f %%)\n", + Aig_ManNodeNum(p->pAigTotal), + Aig_ManNodeNum(p->pAigTotal)-nNodeNum, + nNodeNum, + 100.0 * nNodeNum/Aig_ManNodeNum(p->pAigTotal) ); + Abc_Print( 1, "SAT solver: Vars = %d. Max cone = %d. Recycles = %d.\n", + p->nSatVars, p->nConeMax, p->nRecycles ); + Abc_Print( 1, "SAT calls : All = %6d. Unsat = %6d. Sat = %6d. Fail = %6d.\n", + p->nSatCalls, p->nSatCalls-p->nSatCallsSat-p->nSatFailsReal, + p->nSatCallsSat, p->nSatFailsReal ); + Abc_Print( 1, "Choices : Lits = %6d. Reprs = %5d. Equivs = %5d. Choices = %5d.\n", + p->nLits, p->nReprs, p->nEquivs, p->nChoices ); + Abc_Print( 1, "Choicing runtime statistics:\n" ); + p->timeOther = p->timeTotal-p->timeSimInit-p->timeSimSat-p->timeSat-p->timeChoice; + Abc_PrintTimeP( 1, "Sim init ", p->timeSimInit, p->timeTotal ); + Abc_PrintTimeP( 1, "Sim SAT ", p->timeSimSat, p->timeTotal ); + Abc_PrintTimeP( 1, "SAT solving", p->timeSat, p->timeTotal ); + Abc_PrintTimeP( 1, " sat ", p->timeSatSat, p->timeTotal ); + Abc_PrintTimeP( 1, " unsat ", p->timeSatUnsat, p->timeTotal ); + Abc_PrintTimeP( 1, " undecided", p->timeSatUndec, p->timeTotal ); + Abc_PrintTimeP( 1, "Choice ", p->timeChoice, p->timeTotal ); + Abc_PrintTimeP( 1, "Other ", p->timeOther, p->timeTotal ); + Abc_PrintTimeP( 1, "TOTAL ", p->timeTotal, p->timeTotal ); + if ( p->pPars->timeSynth ) + { + Abc_PrintTime( 1, "Synthesis ", p->pPars->timeSynth ); + } +} + +/**Function************************************************************* + + Synopsis [Frees the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_ManStop( Dch_Man_t * p ) +{ + Aig_ManFanoutStop( p->pAigTotal ); + if ( p->pPars->fVerbose ) + Dch_ManPrintStats( p ); + if ( p->pAigFraig ) + Aig_ManStop( p->pAigFraig ); + if ( p->ppClasses ) + Dch_ClassesStop( p->ppClasses ); + if ( p->pSat ) + sat_solver_delete( p->pSat ); + Vec_PtrFree( p->vUsedNodes ); + Vec_PtrFree( p->vFanins ); + Vec_PtrFree( p->vSimRoots ); + Vec_PtrFree( p->vSimClasses ); + ABC_FREE( p->pReprsProved ); + ABC_FREE( p->pSatVars ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Recycles the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_ManSatSolverRecycle( Dch_Man_t * p ) +{ + int Lit; + if ( p->pSat ) + { + Aig_Obj_t * pObj; + int i; + Vec_PtrForEachEntry( Aig_Obj_t *, p->vUsedNodes, pObj, i ) + Dch_ObjSetSatNum( p, pObj, 0 ); + Vec_PtrClear( p->vUsedNodes ); +// memset( p->pSatVars, 0, sizeof(int) * Aig_ManObjNumMax(p->pAigTotal) ); + sat_solver_delete( p->pSat ); + } + p->pSat = sat_solver_new(); + sat_solver_setnvars( p->pSat, 1000 ); + // var 0 is not used + // var 1 is reserved for const1 node - add the clause + p->nSatVars = 1; +// p->nSatVars = 0; + Lit = toLit( p->nSatVars ); + if ( p->pPars->fPolarFlip ) + Lit = lit_neg( Lit ); + sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ); + Dch_ObjSetSatNum( p, Aig_ManConst1(p->pAigFraig), p->nSatVars++ ); + + p->nRecycles++; + p->nCallsSince = 0; +} + + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/dch/dchSat.c b/src/proof/dch/dchSat.c new file mode 100644 index 00000000..f5e346ef --- /dev/null +++ b/src/proof/dch/dchSat.c @@ -0,0 +1,166 @@ +/**CFile**************************************************************** + + FileName [dchSat.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Choice computation for tech-mapping.] + + Synopsis [Calls to the SAT solver.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 29, 2008.] + + Revision [$Id: dchSat.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "dchInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Runs equivalence test for the two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dch_NodesAreEquiv( Dch_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ) +{ + int nBTLimit = p->pPars->nBTLimit; + int pLits[2], RetValue, RetValue1, status, clk; + p->nSatCalls++; + + // sanity checks + assert( !Aig_IsComplement(pNew) ); + assert( !Aig_IsComplement(pOld) ); + assert( pNew != pOld ); + + p->nCallsSince++; // experiment with this!!! + + // check if SAT solver needs recycling + if ( p->pSat == NULL || + (p->pPars->nSatVarMax && + p->nSatVars > p->pPars->nSatVarMax && + p->nCallsSince > p->pPars->nCallsRecycle) ) + Dch_ManSatSolverRecycle( p ); + + // if the nodes do not have SAT variables, allocate them + Dch_CnfNodeAddToSolver( p, pOld ); + Dch_CnfNodeAddToSolver( p, pNew ); + + // propage unit clauses + if ( p->pSat->qtail != p->pSat->qhead ) + { + status = sat_solver_simplify(p->pSat); + assert( status != 0 ); + assert( p->pSat->qtail == p->pSat->qhead ); + } + + // solve under assumptions + // A = 1; B = 0 OR A = 1; B = 1 + pLits[0] = toLitCond( Dch_ObjSatNum(p,pOld), 0 ); + pLits[1] = toLitCond( Dch_ObjSatNum(p,pNew), pOld->fPhase == pNew->fPhase ); + if ( p->pPars->fPolarFlip ) + { + if ( pOld->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( pNew->fPhase ) pLits[1] = lit_neg( pLits[1] ); + } +//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 ); +clk = clock(); + RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, + (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); +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; + p->nSatCallsSat++; + return 0; + } + else // if ( RetValue1 == l_Undef ) + { +p->timeSatUndec += clock() - clk; + p->nSatFailsReal++; + return -1; + } + + // if the old node was constant 0, we already know the answer + if ( pOld == Aig_ManConst1(p->pAigFraig) ) + { + p->nSatProof++; + return 1; + } + + // solve under assumptions + // A = 0; B = 1 OR A = 0; B = 0 + pLits[0] = toLitCond( Dch_ObjSatNum(p,pOld), 1 ); + pLits[1] = toLitCond( Dch_ObjSatNum(p,pNew), pOld->fPhase ^ pNew->fPhase ); + if ( p->pPars->fPolarFlip ) + { + if ( pOld->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( pNew->fPhase ) pLits[1] = lit_neg( pLits[1] ); + } +clk = clock(); + RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, + (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); +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; + p->nSatCallsSat++; + return 0; + } + else // if ( RetValue1 == l_Undef ) + { +p->timeSatUndec += clock() - clk; + p->nSatFailsReal++; + return -1; + } + // return SAT proof + p->nSatProof++; + return 1; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/dch/dchSim.c b/src/proof/dch/dchSim.c new file mode 100644 index 00000000..b2d24761 --- /dev/null +++ b/src/proof/dch/dchSim.c @@ -0,0 +1,297 @@ +/**CFile**************************************************************** + + FileName [dchSim.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Choice computation for tech-mapping.] + + Synopsis [Performs random simulation at the beginning.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 29, 2008.] + + Revision [$Id: dchSim.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "dchInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline unsigned * Dch_ObjSim( Vec_Ptr_t * vSims, Aig_Obj_t * pObj ) +{ + return (unsigned *)Vec_PtrEntry( vSims, pObj->Id ); +} +static inline unsigned Dch_ObjRandomSim() +{ + return Aig_ManRandom(0); +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns 1 if the node appears to be constant 1 candidate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dch_NodeIsConstCex( void * p, Aig_Obj_t * pObj ) +{ + return pObj->fPhase == pObj->fMarkB; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the nodes appear equal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dch_NodesAreEqualCex( void * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) +{ + return (pObj0->fPhase == pObj1->fPhase) == (pObj0->fMarkB == pObj1->fMarkB); +} + +/**Function************************************************************* + + Synopsis [Computes hash value of the node using its simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Dch_NodeHash( void * p, Aig_Obj_t * pObj ) +{ + Vec_Ptr_t * vSims = (Vec_Ptr_t *)p; + 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 * pSim; + unsigned uHash; + int k, nWords; + nWords = (unsigned *)Vec_PtrEntry(vSims, 1) - (unsigned *)Vec_PtrEntry(vSims, 0); + uHash = 0; + pSim = Dch_ObjSim( vSims, pObj ); + if ( pObj->fPhase ) + { + for ( k = 0; k < nWords; k++ ) + uHash ^= ~pSim[k] * s_FPrimes[k & 0x7F]; + } + else + { + for ( k = 0; k < nWords; k++ ) + uHash ^= pSim[k] * s_FPrimes[k & 0x7F]; + } + return uHash; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if simulation info is composed of all zeros.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dch_NodeIsConst( void * p, Aig_Obj_t * pObj ) +{ + Vec_Ptr_t * vSims = (Vec_Ptr_t *)p; + unsigned * pSim; + int k, nWords; + nWords = (unsigned *)Vec_PtrEntry(vSims, 1) - (unsigned *)Vec_PtrEntry(vSims, 0); + pSim = Dch_ObjSim( vSims, pObj ); + if ( pObj->fPhase ) + { + for ( k = 0; k < nWords; k++ ) + if ( ~pSim[k] ) + return 0; + } + else + { + for ( k = 0; k < nWords; k++ ) + if ( pSim[k] ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if simulation infos are equal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dch_NodesAreEqual( void * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) +{ + Vec_Ptr_t * vSims = (Vec_Ptr_t *)p; + unsigned * pSim0, * pSim1; + int k, nWords; + nWords = (unsigned *)Vec_PtrEntry(vSims, 1) - (unsigned *)Vec_PtrEntry(vSims, 0); + pSim0 = Dch_ObjSim( vSims, pObj0 ); + pSim1 = Dch_ObjSim( vSims, pObj1 ); + if ( pObj0->fPhase != pObj1->fPhase ) + { + for ( k = 0; k < nWords; k++ ) + if ( pSim0[k] != ~pSim1[k] ) + return 0; + } + else + { + for ( k = 0; k < nWords; k++ ) + if ( pSim0[k] != pSim1[k] ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Perform random simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_PerformRandomSimulation( Aig_Man_t * pAig, Vec_Ptr_t * vSims ) +{ + unsigned * pSim, * pSim0, * pSim1; + Aig_Obj_t * pObj; + int i, k, nWords; + nWords = (unsigned *)Vec_PtrEntry(vSims, 1) - (unsigned *)Vec_PtrEntry(vSims, 0); + + // assign const 1 sim info + pObj = Aig_ManConst1(pAig); + pSim = Dch_ObjSim( vSims, pObj ); + memset( pSim, 0xff, sizeof(unsigned) * nWords ); + + // assign primary input random sim info + Aig_ManForEachPi( pAig, pObj, i ) + { + pSim = Dch_ObjSim( vSims, pObj ); + for ( k = 0; k < nWords; k++ ) + pSim[k] = Dch_ObjRandomSim(); + pSim[0] <<= 1; + } + + // simulate AIG in the topological order + Aig_ManForEachNode( pAig, pObj, i ) + { + pSim0 = Dch_ObjSim( vSims, Aig_ObjFanin0(pObj) ); + pSim1 = Dch_ObjSim( vSims, Aig_ObjFanin1(pObj) ); + pSim = Dch_ObjSim( vSims, pObj ); + + if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) // both are compls + { + for ( k = 0; k < nWords; k++ ) + pSim[k] = ~pSim0[k] & ~pSim1[k]; + } + else if ( Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) ) // first one is compl + { + for ( k = 0; k < nWords; k++ ) + pSim[k] = ~pSim0[k] & pSim1[k]; + } + else if ( !Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) // second one is compl + { + for ( k = 0; k < nWords; k++ ) + pSim[k] = pSim0[k] & ~pSim1[k]; + } + else // if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) // none is compl + { + for ( k = 0; k < nWords; k++ ) + pSim[k] = pSim0[k] & pSim1[k]; + } + } + // get simulation information for primary outputs +} + +/**Function************************************************************* + + Synopsis [Derives candidate equivalence classes of AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dch_Cla_t * Dch_CreateCandEquivClasses( Aig_Man_t * pAig, int nWords, int fVerbose ) +{ + Dch_Cla_t * pClasses; + Vec_Ptr_t * vSims; + int i; + // allocate simulation information + vSims = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(pAig), nWords ); + // run random simulation from the primary inputs + Dch_PerformRandomSimulation( pAig, vSims ); + // start storage for equivalence classes + pClasses = Dch_ClassesStart( pAig ); + Dch_ClassesSetData( pClasses, vSims, Dch_NodeHash, Dch_NodeIsConst, Dch_NodesAreEqual ); + // hash nodes by sim info + Dch_ClassesPrepare( pClasses, 0, 0 ); + // iterate random simulation + for ( i = 0; i < 7; i++ ) + { + Dch_PerformRandomSimulation( pAig, vSims ); + Dch_ClassesRefine( pClasses ); + } + // clean up and return + Vec_PtrFree( vSims ); + // prepare class refinement procedures + Dch_ClassesSetData( pClasses, NULL, NULL, Dch_NodeIsConstCex, Dch_NodesAreEqualCex ); + return pClasses; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/dch/dchSimSat.c b/src/proof/dch/dchSimSat.c new file mode 100644 index 00000000..808e754a --- /dev/null +++ b/src/proof/dch/dchSimSat.c @@ -0,0 +1,258 @@ +/**CFile**************************************************************** + + FileName [dchSimSat.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Choice computation for tech-mapping.] + + Synopsis [Performs resimulation using counter-examples.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 29, 2008.] + + Revision [$Id: dchSimSat.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "dchInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Collects internal nodes in the reverse DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_ManCollectTfoCands_rec( Dch_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pFanout, * pRepr; + int iFanout = -1, i; + assert( !Aig_IsComplement(pObj) ); + if ( Aig_ObjIsTravIdCurrent(p->pAigTotal, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p->pAigTotal, pObj); + // traverse the fanouts + Aig_ObjForEachFanout( p->pAigTotal, pObj, pFanout, iFanout, i ) + Dch_ManCollectTfoCands_rec( p, pFanout ); + // check if the given node has a representative + pRepr = Aig_ObjRepr( p->pAigTotal, pObj ); + if ( pRepr == NULL ) + return; + // pRepr is the constant 1 node + if ( pRepr == Aig_ManConst1(p->pAigTotal) ) + { + Vec_PtrPush( p->vSimRoots, pObj ); + return; + } + // pRepr is the representative of an equivalence class + if ( pRepr->fMarkA ) + return; + pRepr->fMarkA = 1; + Vec_PtrPush( p->vSimClasses, pRepr ); +} + +/**Function************************************************************* + + Synopsis [Collect equivalence classes and const1 cands in the TFO.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_ManCollectTfoCands( Dch_Man_t * p, Aig_Obj_t * pObj1, Aig_Obj_t * pObj2 ) +{ + Aig_Obj_t * pObj; + int i; + Vec_PtrClear( p->vSimRoots ); + Vec_PtrClear( p->vSimClasses ); + Aig_ManIncrementTravId( p->pAigTotal ); + Aig_ObjSetTravIdCurrent( p->pAigTotal, Aig_ManConst1(p->pAigTotal) ); + Dch_ManCollectTfoCands_rec( p, pObj1 ); + Dch_ManCollectTfoCands_rec( p, pObj2 ); + Vec_PtrSort( p->vSimRoots, (int (*)(void))Aig_ObjCompareIdIncrease ); + Vec_PtrSort( p->vSimClasses, (int (*)(void))Aig_ObjCompareIdIncrease ); + Vec_PtrForEachEntry( Aig_Obj_t *, p->vSimClasses, pObj, i ) + pObj->fMarkA = 0; +} + +/**Function************************************************************* + + Synopsis [Resimulates the cone of influence of the solved nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_ManResimulateSolved_rec( Dch_Man_t * p, Aig_Obj_t * pObj ) +{ + if ( Aig_ObjIsTravIdCurrent(p->pAigTotal, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p->pAigTotal, pObj); + if ( Aig_ObjIsPi(pObj) ) + { + Aig_Obj_t * pObjFraig; + int nVarNum; + pObjFraig = Dch_ObjFraig( pObj ); + assert( !Aig_IsComplement(pObjFraig) ); + nVarNum = Dch_ObjSatNum( p, pObjFraig ); + // get the value from the SAT solver + // (account for the fact that some vars may be minimized away) + pObj->fMarkB = !nVarNum? 0 : sat_solver_var_value( p->pSat, nVarNum ); +// pObj->fMarkB = !nVarNum? Aig_ManRandom(0) & 1 : sat_solver_var_value( p->pSat, nVarNum ); + return; + } + Dch_ManResimulateSolved_rec( p, Aig_ObjFanin0(pObj) ); + Dch_ManResimulateSolved_rec( p, Aig_ObjFanin1(pObj) ); + pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ) + & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) ); + // count the cone size + if ( Dch_ObjSatNum( p, Aig_Regular(Dch_ObjFraig(pObj)) ) > 0 ) + p->nConeThis++; +} + +/**Function************************************************************* + + Synopsis [Resimulates the cone of influence of the other nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_ManResimulateOther_rec( Dch_Man_t * p, Aig_Obj_t * pObj ) +{ + if ( Aig_ObjIsTravIdCurrent(p->pAigTotal, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p->pAigTotal, pObj); + if ( Aig_ObjIsPi(pObj) ) + { + // set random value + pObj->fMarkB = Aig_ManRandom(0) & 1; + return; + } + Dch_ManResimulateOther_rec( p, Aig_ObjFanin0(pObj) ); + Dch_ManResimulateOther_rec( p, Aig_ObjFanin1(pObj) ); + pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ) + & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Handle the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_ManResimulateCex( Dch_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr ) +{ + Aig_Obj_t * pRoot, ** ppClass; + int i, k, nSize, RetValue1, RetValue2, clk = clock(); + // get the equivalence classes + Dch_ManCollectTfoCands( p, pObj, pRepr ); + // resimulate the cone of influence of the solved nodes + p->nConeThis = 0; + Aig_ManIncrementTravId( p->pAigTotal ); + Aig_ObjSetTravIdCurrent( p->pAigTotal, Aig_ManConst1(p->pAigTotal) ); + Dch_ManResimulateSolved_rec( p, pObj ); + Dch_ManResimulateSolved_rec( p, pRepr ); + p->nConeMax = Abc_MaxInt( p->nConeMax, p->nConeThis ); + // resimulate the cone of influence of the other nodes + Vec_PtrForEachEntry( Aig_Obj_t *, p->vSimRoots, pRoot, i ) + Dch_ManResimulateOther_rec( p, pRoot ); + // refine these nodes + RetValue1 = Dch_ClassesRefineConst1Group( p->ppClasses, p->vSimRoots, 0 ); + // resimulate the cone of influence of the cand classes + RetValue2 = 0; + Vec_PtrForEachEntry( Aig_Obj_t *, p->vSimClasses, pRoot, i ) + { + ppClass = Dch_ClassesReadClass( p->ppClasses, pRoot, &nSize ); + for ( k = 0; k < nSize; k++ ) + Dch_ManResimulateOther_rec( p, ppClass[k] ); + // refine this class + RetValue2 += Dch_ClassesRefineOneClass( p->ppClasses, pRoot, 0 ); + } + // make sure refinement happened + if ( Aig_ObjIsConst1(pRepr) ) + assert( RetValue1 ); + else + assert( RetValue2 ); +p->timeSimSat += clock() - clk; +} + +/**Function************************************************************* + + Synopsis [Handle the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_ManResimulateCex2( Dch_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr ) +{ + Aig_Obj_t * pRoot; + int i, RetValue, clk = clock(); + // get the equivalence class + if ( Dch_ObjIsConst1Cand(p->pAigTotal, pObj) ) + Dch_ClassesCollectConst1Group( p->ppClasses, pObj, 500, p->vSimRoots ); + else + Dch_ClassesCollectOneClass( p->ppClasses, pRepr, p->vSimRoots ); + // resimulate the cone of influence of the solved nodes + p->nConeThis = 0; + Aig_ManIncrementTravId( p->pAigTotal ); + Aig_ObjSetTravIdCurrent( p->pAigTotal, Aig_ManConst1(p->pAigTotal) ); + Dch_ManResimulateSolved_rec( p, pObj ); + Dch_ManResimulateSolved_rec( p, pRepr ); + p->nConeMax = Abc_MaxInt( p->nConeMax, p->nConeThis ); + // resimulate the cone of influence of the other nodes + Vec_PtrForEachEntry( Aig_Obj_t *, p->vSimRoots, pRoot, i ) + Dch_ManResimulateOther_rec( p, pRoot ); + // refine this class + if ( Dch_ObjIsConst1Cand(p->pAigTotal, pObj) ) + RetValue = Dch_ClassesRefineConst1Group( p->ppClasses, p->vSimRoots, 0 ); + else + RetValue = Dch_ClassesRefineOneClass( p->ppClasses, pRepr, 0 ); + assert( RetValue ); +p->timeSimSat += clock() - clk; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/dch/dchSweep.c b/src/proof/dch/dchSweep.c new file mode 100644 index 00000000..a1c4f79b --- /dev/null +++ b/src/proof/dch/dchSweep.c @@ -0,0 +1,146 @@ +/**CFile**************************************************************** + + FileName [dchSweep.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Choice computation for tech-mapping.] + + Synopsis [One round of SAT sweeping.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 29, 2008.] + + Revision [$Id: dchSweep.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "dchInt.h" +#include "src/misc/bar/bar.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline Aig_Obj_t * Dch_ObjChild0Fra( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Dch_ObjFraig(Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj)) : NULL; } +static inline Aig_Obj_t * Dch_ObjChild1Fra( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Dch_ObjFraig(Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj)) : NULL; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs fraiging for one node.] + + Description [Returns the fraiged node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_ManSweepNode( Dch_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pObjRepr, * pObjFraig, * pObjFraig2, * pObjReprFraig; + int RetValue; + // get representative of this class + pObjRepr = Aig_ObjRepr( p->pAigTotal, pObj ); + if ( pObjRepr == NULL ) + return; + // get the fraiged node + pObjFraig = Dch_ObjFraig( pObj ); + if ( pObjFraig == NULL ) + return; + // get the fraiged representative + pObjReprFraig = Dch_ObjFraig( pObjRepr ); + if ( pObjReprFraig == NULL ) + return; + // if the fraiged nodes are the same, return + if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) ) + { + // remember the proved equivalence + p->pReprsProved[ pObj->Id ] = pObjRepr; + return; + } + assert( Aig_Regular(pObjFraig) != Aig_ManConst1(p->pAigFraig) ); + RetValue = Dch_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) ); + if ( RetValue == -1 ) // timed out + { + Dch_ObjSetFraig( pObj, NULL ); + return; + } + if ( RetValue == 1 ) // proved equivalent + { + pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase ); + Dch_ObjSetFraig( pObj, pObjFraig2 ); + // remember the proved equivalence + p->pReprsProved[ pObj->Id ] = pObjRepr; + return; + } + // disproved the equivalence + if ( p->pPars->fSimulateTfo ) + Dch_ManResimulateCex( p, pObj, pObjRepr ); + else + Dch_ManResimulateCex2( p, pObj, pObjRepr ); + assert( Aig_ObjRepr( p->pAigTotal, pObj ) != pObjRepr ); +} + +/**Function************************************************************* + + Synopsis [Performs fraiging for the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dch_ManSweep( Dch_Man_t * p ) +{ + Bar_Progress_t * pProgress = NULL; + Aig_Obj_t * pObj, * pObjNew; + int i; + // map constants and PIs + p->pAigFraig = Aig_ManStart( Aig_ManObjNumMax(p->pAigTotal) ); + Aig_ManCleanData( p->pAigTotal ); + Aig_ManConst1(p->pAigTotal)->pData = Aig_ManConst1(p->pAigFraig); + Aig_ManForEachPi( p->pAigTotal, pObj, i ) + pObj->pData = Aig_ObjCreatePi( p->pAigFraig ); + // sweep internal nodes + pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAigTotal) ); + Aig_ManForEachNode( p->pAigTotal, pObj, i ) + { + Bar_ProgressUpdate( pProgress, i, NULL ); + if ( Dch_ObjFraig(Aig_ObjFanin0(pObj)) == NULL || + Dch_ObjFraig(Aig_ObjFanin1(pObj)) == NULL ) + continue; + pObjNew = Aig_And( p->pAigFraig, Dch_ObjChild0Fra(pObj), Dch_ObjChild1Fra(pObj) ); + if ( pObjNew == NULL ) + continue; + Dch_ObjSetFraig( pObj, pObjNew ); + Dch_ManSweepNode( p, pObj ); + } + Bar_ProgressStop( pProgress ); + // update the representatives of the nodes (makes classes invalid) + ABC_FREE( p->pAigTotal->pReprs ); + p->pAigTotal->pReprs = p->pReprsProved; + p->pReprsProved = NULL; + // clean the mark + Aig_ManCleanMarkB( p->pAigTotal ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/dch/module.make b/src/proof/dch/module.make new file mode 100644 index 00000000..11163cef --- /dev/null +++ b/src/proof/dch/module.make @@ -0,0 +1,10 @@ +SRC += src/proof/dch/dchAig.c \ + src/proof/dch/dchChoice.c \ + src/proof/dch/dchClass.c \ + src/proof/dch/dchCnf.c \ + src/proof/dch/dchCore.c \ + src/proof/dch/dchMan.c \ + src/proof/dch/dchSat.c \ + src/proof/dch/dchSim.c \ + src/proof/dch/dchSimSat.c \ + src/proof/dch/dchSweep.c diff --git a/src/proof/fra/fra.h b/src/proof/fra/fra.h new file mode 100644 index 00000000..3e50ff57 --- /dev/null +++ b/src/proof/fra/fra.h @@ -0,0 +1,389 @@ +/**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 ABC__aig__fra__fra_h +#define ABC__aig__fra__fra_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + +#include "src/misc/vec/vec.h" +#include "src/aig/aig/aig.h" +#include "src/opt/dar/dar.h" +#include "src/sat/bsat/satSolver.h" +#include "src/aig/ioa/ioa.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Fra_Par_t_ Fra_Par_t; +typedef struct Fra_Ssw_t_ Fra_Ssw_t; +typedef struct Fra_Sec_t_ Fra_Sec_t; +typedef struct Fra_Man_t_ Fra_Man_t; +typedef struct Fra_Cla_t_ Fra_Cla_t; +typedef struct Fra_Sml_t_ Fra_Sml_t; +typedef struct Fra_Bmc_t_ Fra_Bmc_t; + +// FRAIG parameters +struct Fra_Par_t_ +{ + int nSimWords; // the number of words in the simulation info + double dSimSatur; // the ratio of refined classes when saturation is reached + int fPatScores; // enables simulation pattern scoring + int MaxScore; // max score after which resimulation is used + double dActConeRatio; // the ratio of cone to be bumped + double dActConeBumpMax; // the largest bump in activity + int fChoicing; // enables choicing + int fSpeculate; // use speculative reduction + int fProve; // prove the miter outputs + int fVerbose; // verbose output + int fDoSparse; // skip sparse functions + int fConeBias; // bias variables in the cone (good for unsat runs) + int nBTLimitNode; // conflict limit at a node + int nBTLimitMiter; // conflict limit at an output + int nLevelMax; // the max level to consider seriously + 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 fUse1Hot; // use one-hotness conditions + int fWriteImps; // record implications + int fDontShowBar; // does not show progressbar during fraiging +}; + +// seq SAT sweeping parameters +struct Fra_Ssw_t_ +{ + int nPartSize; // size of the partition + int nOverSize; // size of the overlap between partitions + int nFramesP; // number of frames in the prefix + int nFramesK; // number of frames for induction (1=simple) + int nMaxImps; // max implications to consider + int nMaxLevs; // max levels to consider + int nMinDomSize; // min clock domain considered for optimization + int fUseImps; // use implications + int fRewrite; // enable rewriting of the specualatively reduced model + int fFraiging; // enable comb SAT sweeping as preprocessing + int fLatchCorr; // perform register correspondence + int fWriteImps; // write implications into a file + int fUse1Hot; // use one-hotness constraints + int fVerbose; // enable verbose output + int fSilent; // disable any output + int nIters; // the number of iterations performed + float TimeLimit; // the runtime budget for this call +}; + +// SEC parametesr +struct Fra_Sec_t_ +{ + int fTryComb; // try CEC call as a preprocessing step + int fTryBmc; // try BMC call as a preprocessing step + int nFramesMax; // the max number of frames used for induction + int nBTLimit; // the conflict limit at a node + int nBTLimitGlobal; // the global conflict limit + int nBTLimitInter; // the conflict limit for interpolation + int nBddVarsMax; // the state space limit for BDD reachability + int nBddMax; // the max number of BDD nodes + int nBddIterMax; // the limit on the number of BDD iterations + int nPdrTimeout; // the timeout for PDR in the end + int fPhaseAbstract; // enables phase abstraction + int fRetimeFirst; // enables most-forward retiming at the beginning + int fRetimeRegs; // enables min-register retiming at the beginning + int fFraiging; // enables fraiging at the beginning + int fInduction; // enable the use of induction + int fInterpolation; // enables interpolation + int fInterSeparate; // enables interpolation for each outputs separately + int fReachability; // enables BDD based reachability + int fReorderImage; // enables BDD reordering during image computation + int fStopOnFirstFail; // enables stopping after first output of a miter has failed to prove + int fUseNewProver; // the new prover + int fUsePdr; // the PDR + int fSilent; // disables all output + int fVerbose; // enables verbose reporting of statistics + int fVeryVerbose; // enables very verbose reporting + int TimeLimit; // enables the timeout + int fReadUnsolved; // inserts the unsolved model back + int nSMnumber; // the number of model written + // internal parameters + int fRecursive; // set to 1 when SEC is called recursively + int fReportSolution; // enables report solution in a special form +}; + +// FRAIG equivalence classes +struct Fra_Cla_t_ +{ + Aig_Man_t * pAig; // the original AIG manager + Aig_Obj_t ** pMemRepr; // pointers to representatives of each node + Vec_Ptr_t * vClasses; // equivalence classes + Vec_Ptr_t * vClasses1; // equivalence class of Const1 node + Vec_Ptr_t * vClassesTemp; // temporary storage for new classes + Aig_Obj_t ** pMemClasses; // memory allocated for equivalence classes + Aig_Obj_t ** pMemClassesFree; // memory allocated for equivalence classes to be used + Vec_Ptr_t * vClassOld; // old equivalence class after splitting + Vec_Ptr_t * vClassNew; // new equivalence class(es) after splitting + int nPairs; // the number of pairs of nodes + int fRefinement; // set to 1 when refinement has happened + Vec_Int_t * vImps; // implications + // procedures used for class refinement + int (*pFuncNodeHash) (Aig_Obj_t *, int); // returns has key of the node + int (*pFuncNodeIsConst) (Aig_Obj_t *); // returns 1 if the node is a constant + int (*pFuncNodesAreEqual)(Aig_Obj_t *, Aig_Obj_t *); // returns 1 if nodes are equal up to a complement +}; + +// simulation manager +struct Fra_Sml_t_ +{ + Aig_Man_t * pAig; // the original AIG manager + int nPref; // the number of times frames in the prefix + int nFrames; // the number of times frames + int nWordsFrame; // the number of words in each time frame + int nWordsTotal; // the total number of words at a node + int nWordsPref; // the number of word in the prefix + int fNonConstOut; // have seen a non-const-0 output during simulation + int nSimRounds; // statistics + int timeSim; // statistics + unsigned pData[0]; // simulation data for the nodes +}; + +// FRAIG manager +struct Fra_Man_t_ +{ + // high-level data + Fra_Par_t * pPars; // parameters governing fraiging + // AIG managers + Aig_Man_t * pManAig; // the starting AIG manager + Aig_Man_t * pManFraig; // the final AIG manager + // mapping AIG into FRAIG + int nFramesAll; // the number of timeframes used + Aig_Obj_t ** pMemFraig; // memory allocated for points to the fraig nodes + int nSizeAlloc; // allocated size of the arrays for timeframe nodes + // equivalence classes + Fra_Cla_t * pCla; // representation of (candidate) equivalent nodes + // simulation info + Fra_Sml_t * pSml; // simulation manager + // bounded model checking manager + Fra_Bmc_t * pBmc; + // counter example storage + int nPatWords; // the number of words in the counter example + unsigned * pPatWords; // the counter example + Vec_Int_t * vCex; + // one-hotness conditions + Vec_Int_t * vOneHots; + // 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 + ABC_INT64_T nBTLimitGlobal; // resource limit + ABC_INT64_T 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 Aig_ManRandom(0); } + +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, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int fFlipBits, int fAndOuts, int fNewSolver, int fVerbose ); +extern int Fra_FraigCec( Aig_Man_t ** ppAig, int nConfLimit, int fVerbose ); +extern int Fra_FraigCecPartitioned( Aig_Man_t * pMan1, Aig_Man_t * pMan2, int nConfLimit, int nPartSize, int fSmart, 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, int nLevelMax ); +extern Aig_Man_t * Fra_FraigEquivence( Aig_Man_t * pManAig, int nConfMax, int fProve ); +/*=== fraHot.c ========================================================*/ +extern Vec_Int_t * Fra_OneHotCompute( Fra_Man_t * p, Fra_Sml_t * pSim ); +extern void Fra_OneHotAssume( Fra_Man_t * p, Vec_Int_t * vOneHots ); +extern void Fra_OneHotCheck( Fra_Man_t * p, Vec_Int_t * vOneHots ); +extern int Fra_OneHotRefineUsingCex( Fra_Man_t * p, Vec_Int_t * vOneHots ); +extern int Fra_OneHotCount( Fra_Man_t * p, Vec_Int_t * vOneHots ); +extern void Fra_OneHotEstimateCoverage( Fra_Man_t * p, Vec_Int_t * vOneHots ); +extern Aig_Man_t * Fra_OneHotCreateExdc( Fra_Man_t * p, Vec_Int_t * vOneHots ); +extern void Fra_OneHotAddKnownConstraint( Fra_Man_t * p, Vec_Ptr_t * vOnehots ); +/*=== 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, Fra_Ssw_t * pPars ); +/*=== fraIndVer.c =====================================================*/ +extern int Fra_InvariantVerify( Aig_Man_t * p, int nFrames, Vec_Int_t * vClauses, Vec_Int_t * vLits ); +/*=== fraLcr.c ========================================================*/ +extern Aig_Man_t * Fra_FraigLatchCorrespondence( Aig_Man_t * pAig, int nFramesP, int nConfMax, int fProve, int fVerbose, int * pnIter, float TimeLimit ); +/*=== 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_NodesAreClause( 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 void Fra_SecSetDefaultParams( Fra_Sec_t * p ); +extern int Fra_FraigSec( Aig_Man_t * p, Fra_Sec_t * pParSec, Aig_Man_t ** ppResult ); +/*=== 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_SmlNodeCountOnes( Fra_Sml_t * p, Aig_Obj_t * pObj ); +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, int fCheckMiter ); +extern Fra_Sml_t * Fra_SmlSimulateComb( Aig_Man_t * pAig, int nWords ); +extern Abc_Cex_t * Fra_SmlGetCounterExample( Fra_Sml_t * p ); +extern Abc_Cex_t * Fra_SmlCopyCounterExample( Aig_Man_t * pAig, Aig_Man_t * pFrames, int * pModel ); + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/proof/fra/fraBmc.c b/src/proof/fra/fraBmc.c new file mode 100644 index 00000000..7b4db3de --- /dev/null +++ b/src/proof/fra/fraBmc.c @@ -0,0 +1,451 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 = (Fra_Man_t *)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 = (Fra_Man_t *)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 = ABC_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 = ABC_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 ); + ABC_FREE( p->pObjToFrames ); + ABC_FREE( p->pObjToFraig ); + ABC_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 = Abc_UtilStrsav( p->pAig->pName ); + pAigFrames->pSpec = Abc_UtilStrsav( p->pAig->pSpec ); + // 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 = ABC_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) ); + } + ABC_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) ); + ABC_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 clk, iOutput; + // derive and fraig the frames + clk = clock(); + pBmc = Fra_BmcStart( pAig, 0, nFrames ); + pTemp = Fra_LcrAigPrepare( pAig ); + pTemp->pBmc = pBmc; + pBmc->pAigFrames = Fra_BmcFrames( pBmc, 1 ); + if ( fVerbose ) + { + printf( "AIG: PI/PO/Reg = %d/%d/%d. Node = %6d. Lev = %5d.\n", + Aig_ManPiNum(pAig)-Aig_ManRegNum(pAig), Aig_ManPoNum(pAig)-Aig_ManRegNum(pAig), Aig_ManRegNum(pAig), + Aig_ManNodeNum(pAig), Aig_ManLevelNum(pAig) ); + printf( "Time-frames (%d): PI/PO = %d/%d. Node = %6d. Lev = %5d. ", + nFrames, Aig_ManPiNum(pBmc->pAigFrames), Aig_ManPoNum(pBmc->pAigFrames), + Aig_ManNodeNum(pBmc->pAigFrames), Aig_ManLevelNum(pBmc->pAigFrames) ); + ABC_PRT( "Time", clock() - clk ); + } + if ( fRewrite ) + { + clk = clock(); + pBmc->pAigFrames = Dar_ManRwsat( pAigTemp = pBmc->pAigFrames, 1, 0 ); + Aig_ManStop( pAigTemp ); + if ( fVerbose ) + { + printf( "Time-frames after rewriting: Node = %6d. Lev = %5d. ", + Aig_ManNodeNum(pBmc->pAigFrames), Aig_ManLevelNum(pBmc->pAigFrames) ); + ABC_PRT( "Time", clock() - clk ); + } + } + clk = clock(); + iOutput = Fra_FraigMiterAssertedOutput( pBmc->pAigFrames ); + if ( iOutput >= 0 ) + pAig->pSeqModel = Abc_CexMakeTriv( Aig_ManRegNum(pAig), Aig_ManPiNum(pAig)-Aig_ManRegNum(pAig), Aig_ManPoNum(pAig)-Aig_ManRegNum(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, (int *)pBmc->pAigFraig->pData ); + ABC_FREE( pBmc->pAigFraig->pData ); + } + else if ( iOutput >= 0 ) + pAig->pSeqModel = Abc_CexMakeTriv( Aig_ManRegNum(pAig), Aig_ManPiNum(pAig)-Aig_ManRegNum(pAig), Aig_ManPoNum(pAig)-Aig_ManRegNum(pAig), iOutput ); + } + if ( fVerbose ) + { + printf( "Fraiged init frames: Node = %6d. Lev = %5d. ", + pBmc->pAigFraig? Aig_ManNodeNum(pBmc->pAigFraig) : -1, + pBmc->pAigFraig? Aig_ManLevelNum(pBmc->pAigFraig) : -1 ); + ABC_PRT( "Time", clock() - clk ); + } + Fra_BmcStop( pBmc ); + ABC_FREE( pTemp ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fra/fraCec.c b/src/proof/fra/fraCec.c new file mode 100644 index 00000000..ac11b0bb --- /dev/null +++ b/src/proof/fra/fraCec.c @@ -0,0 +1,516 @@ +/**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 "src/sat/cnf/cnf.h" +#include "src/sat/bsat/satSolver2.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_FraigSat( Aig_Man_t * pMan, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int fFlipBits, int fAndOuts, int fNewSolver, int fVerbose ) +{ + if ( fNewSolver ) + { + extern void * Cnf_DataWriteIntoSolver2( Cnf_Dat_t * p, int nFrames, int fInit ); + extern int Cnf_DataWriteOrClause2( void * pSat, Cnf_Dat_t * pCnf ); + + sat_solver2 * pSat; + Cnf_Dat_t * pCnf; + int status, RetValue, clk = clock(); + Vec_Int_t * vCiIds; + + assert( Aig_ManRegNum(pMan) == 0 ); + pMan->pData = NULL; + + // derive CNF + pCnf = Cnf_Derive( pMan, Aig_ManPoNum(pMan) ); + // pCnf = Cnf_DeriveSimple( pMan, Aig_ManPoNum(pMan) ); + + if ( fFlipBits ) + Cnf_DataTranformPolarity( pCnf, 0 ); + + // convert into SAT solver + pSat = (sat_solver2 *)Cnf_DataWriteIntoSolver2( pCnf, 1, 0 ); + if ( pSat == NULL ) + { + Cnf_DataFree( pCnf ); + return 1; + } + + + if ( fAndOuts ) + { + // assert each output independently + if ( !Cnf_DataWriteAndClauses( pSat, pCnf ) ) + { + sat_solver2_delete( pSat ); + Cnf_DataFree( pCnf ); + return 1; + } + } + else + { + // add the OR clause for the outputs + if ( !Cnf_DataWriteOrClause2( pSat, pCnf ) ) + { + sat_solver2_delete( pSat ); + Cnf_DataFree( pCnf ); + return 1; + } + } + vCiIds = Cnf_DataCollectPiSatNums( pCnf, pMan ); + Cnf_DataFree( pCnf ); + + + printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver2_nvars(pSat), sat_solver2_nclauses(pSat) ); + ABC_PRT( "Time", clock() - clk ); + + // simplify the problem + clk = clock(); + status = sat_solver2_simplify(pSat); +// printf( "Simplified the problem to %d variables and %d clauses. ", sat_solver2_nvars(pSat), sat_solver2_nclauses(pSat) ); +// ABC_PRT( "Time", clock() - clk ); + if ( status == 0 ) + { + Vec_IntFree( vCiIds ); + sat_solver2_delete( pSat ); + // printf( "The problem is UNSATISFIABLE after simplification.\n" ); + return 1; + } + + // solve the miter + clk = clock(); + if ( fVerbose ) + pSat->verbosity = 1; + status = sat_solver2_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, (ABC_INT64_T)0, (ABC_INT64_T)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 ); + + // Abc_Print( 1, "The number of conflicts = %6d. ", (int)pSat->stats.conflicts ); + // Abc_PrintTime( 1, "Solving time", clock() - clk ); + + // if the problem is SAT, get the counterexample + if ( status == l_True ) + { + pMan->pData = Sat_Solver2GetModel( pSat, vCiIds->pArray, vCiIds->nSize ); + } + // free the sat_solver2 + if ( fVerbose ) + Sat_Solver2PrintStats( stdout, pSat ); + //sat_solver2_store_write( pSat, "trace.cnf" ); + //sat_solver2_store_free( pSat ); + sat_solver2_delete( pSat ); + Vec_IntFree( vCiIds ); + return RetValue; + } + else + { + sat_solver * pSat; + Cnf_Dat_t * pCnf; + int status, RetValue, clk = clock(); + Vec_Int_t * vCiIds; + + assert( Aig_ManRegNum(pMan) == 0 ); + pMan->pData = NULL; + + // derive CNF + pCnf = Cnf_Derive( pMan, Aig_ManPoNum(pMan) ); + // pCnf = Cnf_DeriveSimple( pMan, Aig_ManPoNum(pMan) ); + + if ( fFlipBits ) + Cnf_DataTranformPolarity( pCnf, 0 ); + + // convert into SAT solver + pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + if ( pSat == NULL ) + { + Cnf_DataFree( pCnf ); + return 1; + } + + + if ( fAndOuts ) + { + // assert each output independently + if ( !Cnf_DataWriteAndClauses( pSat, pCnf ) ) + { + sat_solver_delete( pSat ); + Cnf_DataFree( pCnf ); + return 1; + } + } + else + { + // add the OR clause for the outputs + if ( !Cnf_DataWriteOrClause( pSat, pCnf ) ) + { + sat_solver_delete( pSat ); + Cnf_DataFree( pCnf ); + return 1; + } + } + vCiIds = Cnf_DataCollectPiSatNums( pCnf, pMan ); + Cnf_DataFree( pCnf ); + + + // printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) ); + // ABC_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) ); + // ABC_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, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, (ABC_INT64_T)0, (ABC_INT64_T)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 ); + + // Abc_Print( 1, "The number of conflicts = %6d. ", (int)pSat->stats.conflicts ); + // Abc_PrintTime( 1, "Solving time", clock() - clk ); + + // 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 nConfLimit, int fVerbose ) +{ + int nBTLimitStart = 300; // starting SAT run + int nBTLimitFirst = 2; // first fraiging iteration + int nBTLimitLast = nConfLimit; // 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 ) + { + pAig->pData = ABC_ALLOC( int, Aig_ManPiNum(pAig) ); + memset( pAig->pData, 0, sizeof(int) * Aig_ManPiNum(pAig) ); + return RetValue; + } + + // if SAT only, solve without iteration +clk = clock(); + RetValue = Fra_FraigSat( pAig, (ABC_INT64_T)2*nBTLimitStart, (ABC_INT64_T)0, 1, 0, 0, 0 ); + if ( fVerbose ) + { + printf( "Initial SAT: Nodes = %6d. ", Aig_ManNodeNum(pAig) ); +ABC_PRT( "Time", clock() - clk ); + } + if ( RetValue >= 0 ) + return RetValue; + + // duplicate the AIG +clk = clock(); + pAig = Dar_ManRwsat( pTemp = pAig, 1, 0 ); + Aig_ManStop( pTemp ); + if ( fVerbose ) + { + printf( "Rewriting: Nodes = %6d. ", Aig_ManNodeNum(pAig) ); +ABC_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) ); +ABC_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) ); +ABC_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, (ABC_INT64_T)nBTLimitLast, (ABC_INT64_T)0, 1, 0, 0, 0 ); + if ( fVerbose ) + { + printf( "Final SAT: Nodes = %6d. ", Aig_ManNodeNum(pAig) ); +ABC_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 nConfLimit, int nPartSize, int fSmart, int fVerbose ) +{ + Aig_Man_t * pAig; + Vec_Ptr_t * vParts; + int i, RetValue = 1, nOutputs; + // create partitions + vParts = Aig_ManMiterPartitioned( pMan1, pMan2, nPartSize, fSmart ); + // solve the partitions + nOutputs = -1; + Vec_PtrForEachEntry( Aig_Man_t *, 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) ); + fflush( stdout ); + } + RetValue = Fra_FraigMiterStatus( pAig ); + if ( RetValue == 1 ) + continue; + if ( RetValue == 0 ) + break; + RetValue = Fra_FraigCec( &pAig, nConfLimit, 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( Aig_Man_t *, vParts, pAig, i ) + Aig_ManStop( pAig ); + Vec_PtrFree( vParts ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_FraigCecTop( Aig_Man_t * pMan1, Aig_Man_t * pMan2, int nConfLimit, int nPartSize, int fSmart, int fVerbose ) +{ + Aig_Man_t * pTemp; + //Abc_NtkDarCec( pNtk1, pNtk2, fPartition, fVerbose ); + int RetValue, clkTotal = clock(); + + if ( Aig_ManPiNum(pMan1) != Aig_ManPiNum(pMan1) ) + { + printf( "Abc_CommandAbc8Cec(): Miters have different number of PIs.\n" ); + return 0; + } + if ( Aig_ManPoNum(pMan1) != Aig_ManPoNum(pMan1) ) + { + printf( "Abc_CommandAbc8Cec(): Miters have different number of POs.\n" ); + return 0; + } + assert( Aig_ManPiNum(pMan1) == Aig_ManPiNum(pMan1) ); + assert( Aig_ManPoNum(pMan1) == Aig_ManPoNum(pMan1) ); + + // make sure that the first miter has more nodes + if ( Aig_ManNodeNum(pMan1) < Aig_ManNodeNum(pMan2) ) + { + pTemp = pMan1; + pMan1 = pMan2; + pMan2 = pTemp; + } + assert( Aig_ManNodeNum(pMan1) >= Aig_ManNodeNum(pMan2) ); + + if ( nPartSize ) + RetValue = Fra_FraigCecPartitioned( pMan1, pMan2, nConfLimit, nPartSize, fSmart, fVerbose ); + else // no partitioning + RetValue = Fra_FraigCecPartitioned( pMan1, pMan2, nConfLimit, Aig_ManPoNum(pMan1), 0, fVerbose ); + + // report the miter + if ( RetValue == 1 ) + { + printf( "Networks are equivalent. " ); +ABC_PRT( "Time", clock() - clkTotal ); + } + else if ( RetValue == 0 ) + { + printf( "Networks are NOT EQUIVALENT. " ); +ABC_PRT( "Time", clock() - clkTotal ); + } + else + { + printf( "Networks are UNDECIDED. " ); +ABC_PRT( "Time", clock() - clkTotal ); + } + fflush( stdout ); + return RetValue; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fra/fraClass.c b/src/proof/fra/fraClass.c new file mode 100644 index 00000000..67351f6d --- /dev/null +++ b/src/proof/fra/fraClass.c @@ -0,0 +1,862 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +/* + 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 = ABC_ALLOC( Fra_Cla_t, 1 ); + memset( p, 0, sizeof(Fra_Cla_t) ); + p->pAig = pAig; + p->pMemRepr = ABC_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 ) +{ + ABC_FREE( p->pMemClasses ); + ABC_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 ); + ABC_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( Aig_Obj_t *, 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( Aig_Obj_t **, 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( Aig_Obj_t **, 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( Fra_Cla_t * p, 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,%d) ", pTemp->Id, pTemp->Level, Aig_SupportSize(p->pAig,pTemp) ); + 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( Aig_Obj_t *, p->vClasses1, pObj, i ) + assert( Fra_ClassObjRepr(pObj) == Aig_ManConst1(p->pAig) ); + printf( "Constants { " ); + Vec_PtrForEachEntry( Aig_Obj_t *, p->vClasses1, pObj, i ) + printf( "%d(%d,%d) ", pObj->Id, pObj->Level, Aig_SupportSize(p->pAig,pObj) ); + printf( "}\n" ); + Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, pClass, i ) + { + printf( "%3d (%3d) : ", i, Fra_ClassCount(pClass) ); + Fra_PrintClass( p, 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 = Abc_PrimeCudd( Aig_ManObjNumMax(p->pAig) ); + ppTable = ABC_FALLOC( Aig_Obj_t *, nTableSize ); + ppNexts = ABC_FALLOC( 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 = ABC_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; + } + ABC_FREE( ppTable ); + ABC_FREE( ppNexts ); + // now it is time to refine the classes + Fra_ClassesRefine( p ); +// Fra_ClassesPrint( p, 0 ); +} + +/**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( Aig_Obj_t *, p->vClassOld, pObj, i ) + printf( "%d,", pObj->Id ); + printf( ") + (" ); + Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i ) + printf( "%d,", pObj->Id ); + printf( ")\n" ); +*/ + // put the nodes back into the class memory + Vec_PtrForEachEntry( Aig_Obj_t *, 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( Aig_Obj_t *, 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 = (Aig_Obj_t **)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( Aig_Obj_t **, 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( Aig_Obj_t *, 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( Aig_Obj_t *, p->vClassNew, pObj, i ) + printf( " %d", pObj->Id ); + printf( " }\n" ); +*/ + if ( Vec_PtrSize(p->vClassNew) == 1 ) + { + Fra_ClassObjSetRepr( (Aig_Obj_t *)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( Aig_Obj_t *, 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 = ABC_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 = ABC_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 = ABC_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 = Abc_MaxInt( 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( Aig_Obj_t *, 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( Aig_Obj_t **, 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( Aig_Obj_t **, 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) ); + ABC_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( Aig_Obj_t **, p->vClasses, pClass, i ) + { + // collect support sizes and find the min-support node + cMinSupp = -1; + pNodeMin = NULL; + nSuppSizeMin = ABC_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 = Abc_UtilStrsav( p->pAig->pName ); + pManFraig->pSpec = Abc_UtilStrsav( p->pAig->pSpec ); + // allocate place for the node mapping + ppEquivs = ABC_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 = ABC_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++] ); + } + ABC_FREE( pLatches ); + ABC_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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fra/fraClau.c b/src/proof/fra/fraClau.c new file mode 100644 index 00000000..fb87550d --- /dev/null +++ b/src/proof/fra/fraClau.c @@ -0,0 +1,763 @@ +/**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 "src/sat/cnf/cnf.h" +#include "src/sat/bsat/satSolver.h" + +ABC_NAMESPACE_IMPL_START + + +/* + 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 = ABC_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 ) +{ + ABC_FREE( p->pMapCsMainToCsTest ); + ABC_FREE( p->pMapCsTestToCsMain ); + ABC_FREE( p->pMapCsTestToNsTest ); + ABC_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 ); + ABC_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 = ABC_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 = (sat_solver *)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 = (sat_solver *)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 = (sat_solver *)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, (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)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), + (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)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; + // 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), + (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fra/fraClaus.c b/src/proof/fra/fraClaus.c new file mode 100644 index 00000000..e71219b5 --- /dev/null +++ b/src/proof/fra/fraClaus.c @@ -0,0 +1,1875 @@ +/**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 "src/sat/cnf/cnf.h" +#include "src/sat/bsat/satSolver.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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; + // 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, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)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 = ABC_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, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + ABC_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, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)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 = ABC_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 ); + } + ABC_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; +/* + // add the property + { + Aig_Obj_t * pObj; + int Lits[1]; + pObj = Aig_ManPo( p->pAig, 0 ); + Lits[0] = toLitCond( p->pCnf->pVarNums[pObj->Id], 1 ); + Vec_IntPush( p->vLits, Lits[0] ); + Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) ); + Vec_IntPush( p->vCosts, CostMax ); + nCountConst++; +// printf( "Added the target property to the set of clauses to be inductively checked.\n" ); + } +*/ + + 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 ); + Aig_ManRandom(1); + pSeq = Fra_SmlSimulateSeq( p->pAig, 0, p->nPref + p->nSimFrames, p->nSimWords/p->nSimFrames, 1 ); + if ( p->fTarget && pSeq->fNonConstOut ) + { + printf( "Property failed after sequential simulation!\n" ); + Fra_SmlStop( pSeq ); + return 0; + } +if ( p->fVerbose ) +{ +ABC_PRT( "Sim-seq", clock() - clk ); +} + + +clk = clock(); + if ( fRefs ) + { + Fra_ClausCollectLatchClauses( p, pSeq ); +if ( p->fVerbose ) +{ +ABC_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 ) +{ +ABC_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 ) +{ +ABC_PRT( "Infoseq", clock() - clk ); +} + Fra_SmlStop( pSeq ); + + // perform combinational simulation +clk = clock(); +// srand( 0xAABBAABB ); + Aig_ManRandom(1); + pComb = Fra_SmlSimulateComb( p->pAig, p->nSimWords + p->nSimWordsPref ); +if ( p->fVerbose ) +{ +ABC_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 ) +{ +ABC_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 ); + Aig_ManRandom(1); + pSeq = Fra_SmlSimulateSeq( p->pAig, 0, p->nPref + p->nSimFrames, p->nSimWords/p->nSimFrames, 1 ); + if ( p->fTarget && pSeq->fNonConstOut ) + { + printf( "Property failed after sequential simulation!\n" ); + Fra_SmlStop( pSeq ); + return 0; + } +if ( p->fVerbose ) +{ +//ABC_PRT( "Sim-seq", clock() - clk ); +} + + // perform combinational simulation +clk = clock(); +// srand( 0xAABBAABB ); + Aig_ManRandom(1); + pComb = Fra_SmlSimulateComb( p->pAig, p->nSimWords + p->nSimWordsPref ); +if ( p->fVerbose ) +{ +//ABC_PRT( "Sim-cmb", clock() - clk ); +} + + +clk = clock(); + if ( fRefs ) + { + Fra_ClausCollectLatchClauses( p, pSeq ); +if ( p->fVerbose ) +{ +//ABC_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 ) +{ +//ABC_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 ); + ABC_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; + int End = -1; // Suppress "might be used uninitialized" + int * pStart; + // reset the solver + if ( p->pSatMain ) sat_solver_delete( p->pSatMain ); + p->pSatMain = (sat_solver *)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, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)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, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)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( Abc_InfoHasBit( (unsigned *)Vec_PtrEntry(p->vCexes, i), p->nCexes ) == 0 ); + Abc_InfoSetBit( (unsigned *)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] = (unsigned *)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 & Abc_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 = (sat_solver *)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, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)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 ); + Fra_ClausSimInfoRecord( p, (int*)p->pSatMain->model + 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 = ABC_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 ); + ABC_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 [Writes the clauses into an AIGER file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Fra_ClausGetLiteral( Clu_Man_t * p, int * pVar2Id, int Lit ) +{ + Aig_Obj_t * pLiteral; + int NodeId = pVar2Id[ lit_var(Lit) ]; + assert( NodeId >= 0 ); + pLiteral = (Aig_Obj_t *)Aig_ManObj( p->pAig, NodeId )->pData; + return Aig_NotCond( pLiteral, lit_sign(Lit) ); +} + +/**Function************************************************************* + + Synopsis [Writes the clauses into an AIGER file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ClausWriteIndClauses( Clu_Man_t * p ) +{ + extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact ); + Aig_Man_t * pNew; + Aig_Obj_t * pClause, * pLiteral; + char * pName; + int * pStart, * pVar2Id; + int Beg, End, i, k; + // create mapping from SAT vars to node IDs + pVar2Id = ABC_ALLOC( int, p->pCnf->nVars ); + memset( pVar2Id, 0xFF, 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; + } + // start the manager + pNew = Aig_ManDupWithoutPos( p->pAig ); + // add the clauses + Beg = 0; + pStart = Vec_IntArray( p->vLitsProven ); + Vec_IntForEachEntry( p->vClausesProven, End, i ) + { + pClause = Fra_ClausGetLiteral( p, pVar2Id, pStart[Beg] ); + for ( k = Beg + 1; k < End; k++ ) + { + pLiteral = Fra_ClausGetLiteral( p, pVar2Id, pStart[k] ); + pClause = Aig_Or( pNew, pClause, pLiteral ); + } + Aig_ObjCreatePo( pNew, pClause ); + Beg = End; + } + ABC_FREE( pVar2Id ); + Aig_ManCleanup( pNew ); + pName = Ioa_FileNameGenericAppend( p->pAig->pName, "_care.aig" ); + printf( "Care one-hotness clauses will be written into file \"%s\".\n", pName ); + Ioa_WriteAiger( pNew, pName, 0, 1 ); + Aig_ManStop( pNew ); +} + +/**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 ); + Aig_ManRandom(1); + pComb = Fra_SmlSimulateComb( p->pAig, nCombSimWords ); + // create mapping from SAT vars to node IDs + pVar2Id = ABC_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 ); + ABC_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 ); + ABC_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" ); +//ABC_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 ) +{ +//ABC_PRT( "CNF ", clock() - clk ); +} + + // check BMC +clk = clock(); + p->pSatBmc = (sat_solver *)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 ) +{ +//ABC_PRT( "SAT-bmc", clock() - clk ); +} + + // start the SAT solver +clk = clock(); + p->pSatMain = (sat_solver *)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 ) + { +// ABC_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; + + //ABC_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 ); + ABC_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" ); + ABC_PRT( "Time", clock() - clk ); + } + clk = clock(); + } + // add proved clauses to storage + Fra_ClausAddToStorage( p ); + // report the results + 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. " ); + ABC_PRT( "Time ", clock() - clkTotal ); + if ( !p->fFail ) + break; + } + else + { + printf( "Finished proving inductive clauses. " ); + ABC_PRT( "Time ", clock() - clkTotal ); + } + } + + // verify the computed interpolant + Fra_InvariantVerify( pAig, nFrames, p->vClausesProven, p->vLitsProven ); +// printf( "THIS COMMAND IS KNOWN TO HAVE A BUG!\n" ); + +// if ( !p->fTarget && p->fVerbose ) + if ( p->fVerbose ) + { + Fra_ClausPrintIndClauses( p ); + Fra_ClausEstimateCoverage( p ); + } + + if ( !p->fTarget ) + { + Fra_ClausWriteIndClauses( 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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fra/fraCnf.c b/src/proof/fra/fraCnf.c new file mode 100644 index 00000000..5021e750 --- /dev/null +++ b/src/proof/fra/fraCnf.c @@ -0,0 +1,289 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 = ABC_ALLOC( int, nLits ); + // suppose AND-gate is A & B = C + // add !A => !C or A + !C + Vec_PtrForEachEntry( Aig_Obj_t *, 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( Aig_Obj_t *, 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 ); + ABC_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( Aig_Obj_t *, 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( Aig_Obj_t *, vFanins, pFanin, k ) + Fra_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier ); + Fra_AddClausesMux( p, pNode ); + } + else + { + vFanins = Fra_CollectSuper( pNode, fUseMuxes ); + Vec_PtrForEachEntry( Aig_Obj_t *, 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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fra/fraCore.c b/src/proof/fra/fraCore.c new file mode 100644 index 00000000..d3b60ab7 --- /dev/null +++ b/src/proof/fra/fraCore.c @@ -0,0 +1,490 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 refinement 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 is a primary input + if ( Aig_ObjIsPi(Aig_Regular(pChild)) && Aig_ObjPioNum(Aig_Regular(pChild)) < p->nTruePis ) + { + 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, NULL, NULL ); + 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( Aig_Obj_t *, p->pCla->vClasses1, pObj, i ) + { + if ( pObj->fPhase != pObj->fMarkB ) + printf( "The node %d is not constant under cex!\n", pObj->Id ); + } + Vec_PtrForEachEntry( Aig_Obj_t **, 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; + int nBTracksOld; + // 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) ); + nBTracksOld = p->pPars->nBTLimitNode; + 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; +// if ( Aig_SupportSize(p->pManAig,pObj) > 16 ) +// continue; + // perform fraiging + if ( p->pPars->nLevelMax && (int)pObj->Level > p->pPars->nLevelMax ) + p->pPars->nBTLimitNode = 5; + Fra_FraigNode( p, pObj ); + if ( p->pPars->nLevelMax && (int)pObj->Level > p->pPars->nLevelMax ) + p->pPars->nBTLimitNode = nBTracksOld; + // check implications + 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_ManDupOrdered(pManAig); +clk = clock(); + 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 +if ( p->pPars->fVerbose ) +Fra_ClassesPrint( p->pCla, 1 ); + Fra_FraigSweep( p ); + // call back the procedure to check implications + if ( pManAig->pImpFunc ) + pManAig->pImpFunc( p, pManAig->pImpData ); + // no need to filter one-hot clauses because they satisfy base case by construction + // 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 + { + Fra_ClassesCopyReprs( p->pCla, p->vTimeouts ); + 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, int nLevelMax ) +{ + 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; + pPars->nLevelMax = nLevelMax; + 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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fra/fraHot.c b/src/proof/fra/fraHot.c new file mode 100644 index 00000000..29c9c33d --- /dev/null +++ b/src/proof/fra/fraHot.c @@ -0,0 +1,476 @@ +/**CFile**************************************************************** + + FileName [fraHot.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [New FRAIG package.] + + Synopsis [Computing and using one-hotness conditions.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 30, 2007.] + + Revision [$Id: fraHot.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fra.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Fra_RegToLit( int n, int c ) { return c? -n-1 : n+1; } +static inline int Fra_LitReg( int n ) { return (n>0)? n-1 : -n-1; } +static inline int Fra_LitSign( int n ) { return (n<0); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns 1 if simulation info is composed of all zeros.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_OneHotNodeIsConst( 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 simulation infos are equal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_OneHotNodesAreEqual( Fra_Sml_t * pSeq, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) +{ + unsigned * pSims0, * pSims1; + int i; + pSims0 = Fra_ObjSim(pSeq, pObj0->Id); + pSims1 = Fra_ObjSim(pSeq, pObj1->Id); + for ( i = pSeq->nWordsPref; i < pSeq->nWordsTotal; i++ ) + if ( pSims0[i] != pSims1[i] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if implications holds.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_OneHotNodesAreClause( Fra_Sml_t * pSeq, Aig_Obj_t * pObj1, Aig_Obj_t * pObj2, int fCompl1, int fCompl2 ) +{ + unsigned * pSim1, * pSim2; + int k; + pSim1 = Fra_ObjSim(pSeq, pObj1->Id); + pSim2 = Fra_ObjSim(pSeq, pObj2->Id); + if ( fCompl1 && fCompl2 ) + { + for ( k = pSeq->nWordsPref; k < pSeq->nWordsTotal; k++ ) + if ( pSim1[k] & pSim2[k] ) + return 0; + } + else if ( fCompl1 ) + { + for ( k = pSeq->nWordsPref; k < pSeq->nWordsTotal; k++ ) + if ( pSim1[k] & ~pSim2[k] ) + return 0; + } + else if ( fCompl2 ) + { + for ( k = pSeq->nWordsPref; k < pSeq->nWordsTotal; k++ ) + if ( ~pSim1[k] & pSim2[k] ) + return 0; + } + else + assert( 0 ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes one-hot implications.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Fra_OneHotCompute( Fra_Man_t * p, Fra_Sml_t * pSim ) +{ + int fSkipConstEqu = 1; + Vec_Int_t * vOneHots; + Aig_Obj_t * pObj1, * pObj2; + int i, k; + int nTruePis = Aig_ManPiNum(pSim->pAig) - Aig_ManRegNum(pSim->pAig); + assert( pSim->pAig == p->pManAig ); + vOneHots = Vec_IntAlloc( 100 ); + Aig_ManForEachLoSeq( pSim->pAig, pObj1, i ) + { + if ( fSkipConstEqu && Fra_OneHotNodeIsConst(pSim, pObj1) ) + continue; + assert( i-nTruePis >= 0 ); +// Aig_ManForEachLoSeq( pSim->pAig, pObj2, k ) +// Vec_PtrForEachEntryStart( Aig_Obj_t *, pSim->pAig->vPis, pObj2, k, Aig_ManPiNum(p)-Aig_ManRegNum(p) ) + Vec_PtrForEachEntryStart( Aig_Obj_t *, pSim->pAig->vPis, pObj2, k, i+1 ) + { + if ( fSkipConstEqu && Fra_OneHotNodeIsConst(pSim, pObj2) ) + continue; + if ( fSkipConstEqu && Fra_OneHotNodesAreEqual( pSim, pObj1, pObj2 ) ) + continue; + assert( k-nTruePis >= 0 ); + if ( Fra_OneHotNodesAreClause( pSim, pObj1, pObj2, 1, 1 ) ) + { + Vec_IntPush( vOneHots, Fra_RegToLit(i-nTruePis, 1) ); + Vec_IntPush( vOneHots, Fra_RegToLit(k-nTruePis, 1) ); + continue; + } + if ( Fra_OneHotNodesAreClause( pSim, pObj1, pObj2, 0, 1 ) ) + { + Vec_IntPush( vOneHots, Fra_RegToLit(i-nTruePis, 0) ); + Vec_IntPush( vOneHots, Fra_RegToLit(k-nTruePis, 1) ); + continue; + } + if ( Fra_OneHotNodesAreClause( pSim, pObj1, pObj2, 1, 0 ) ) + { + Vec_IntPush( vOneHots, Fra_RegToLit(i-nTruePis, 1) ); + Vec_IntPush( vOneHots, Fra_RegToLit(k-nTruePis, 0) ); + continue; + } + } + } + return vOneHots; +} + +/**Function************************************************************* + + Synopsis [Assumes one-hot implications in the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +**********************************************************************/ +void Fra_OneHotAssume( Fra_Man_t * p, Vec_Int_t * vOneHots ) +{ + Aig_Obj_t * pObj1, * pObj2; + int i, Out1, Out2, pLits[2]; + int nPiNum = Aig_ManPiNum(p->pManFraig) - Aig_ManRegNum(p->pManFraig); + assert( p->pPars->nFramesK == 1 ); // add to only one frame + for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 ) + { + Out1 = Vec_IntEntry( vOneHots, i ); + Out2 = Vec_IntEntry( vOneHots, i+1 ); + if ( Out1 == 0 && Out2 == 0 ) + continue; + pObj1 = Aig_ManPi( p->pManFraig, nPiNum + Fra_LitReg(Out1) ); + pObj2 = Aig_ManPi( p->pManFraig, nPiNum + Fra_LitReg(Out2) ); + pLits[0] = toLitCond( Fra_ObjSatNum(pObj1), Fra_LitSign(Out1) ); + pLits[1] = toLitCond( Fra_ObjSatNum(pObj2), Fra_LitSign(Out2) ); + // add constraint to solver + if ( !sat_solver_addclause( p->pSat, pLits, pLits + 2 ) ) + { + printf( "Fra_OneHotAssume(): Adding clause makes SAT solver unsat.\n" ); + sat_solver_delete( p->pSat ); + p->pSat = NULL; + return; + } + } +} + +/**Function************************************************************* + + Synopsis [Checks one-hot implications.] + + Description [] + + SideEffects [] + + SeeAlso [] + +**********************************************************************/ +void Fra_OneHotCheck( Fra_Man_t * p, Vec_Int_t * vOneHots ) +{ + Aig_Obj_t * pObj1, * pObj2; + int RetValue, i, Out1, Out2; + int nTruePos = Aig_ManPoNum(p->pManFraig) - Aig_ManRegNum(p->pManFraig); + for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 ) + { + Out1 = Vec_IntEntry( vOneHots, i ); + Out2 = Vec_IntEntry( vOneHots, i+1 ); + if ( Out1 == 0 && Out2 == 0 ) + continue; + pObj1 = Aig_ManPo( p->pManFraig, nTruePos + Fra_LitReg(Out1) ); + pObj2 = Aig_ManPo( p->pManFraig, nTruePos + Fra_LitReg(Out2) ); + RetValue = Fra_NodesAreClause( p, pObj1, pObj2, Fra_LitSign(Out1), Fra_LitSign(Out2) ); + if ( RetValue != 1 ) + { + p->pCla->fRefinement = 1; + if ( RetValue == 0 ) + Fra_SmlResimulate( p ); + if ( Vec_IntEntry(vOneHots, i) != 0 ) + printf( "Fra_OneHotCheck(): Clause is not refined!\n" ); + assert( Vec_IntEntry(vOneHots, i) == 0 ); + } + } +} + +/**Function************************************************************* + + Synopsis [Removes those implications that no longer hold.] + + Description [Returns 1 if refinement has happened.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_OneHotRefineUsingCex( Fra_Man_t * p, Vec_Int_t * vOneHots ) +{ + Aig_Obj_t * pObj1, * pObj2; + int i, Out1, Out2, RetValue = 0; + int nPiNum = Aig_ManPiNum(p->pManAig) - Aig_ManRegNum(p->pManAig); + assert( p->pSml->pAig == p->pManAig ); + for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 ) + { + Out1 = Vec_IntEntry( vOneHots, i ); + Out2 = Vec_IntEntry( vOneHots, i+1 ); + if ( Out1 == 0 && Out2 == 0 ) + continue; + // get the corresponding nodes + pObj1 = Aig_ManPi( p->pManAig, nPiNum + Fra_LitReg(Out1) ); + pObj2 = Aig_ManPi( p->pManAig, nPiNum + Fra_LitReg(Out2) ); + // check if implication holds using this simulation info + if ( !Fra_OneHotNodesAreClause( p->pSml, pObj1, pObj2, Fra_LitSign(Out1), Fra_LitSign(Out2) ) ) + { + Vec_IntWriteEntry( vOneHots, i, 0 ); + Vec_IntWriteEntry( vOneHots, i+1, 0 ); + RetValue = 1; + } + } + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Removes those implications that no longer hold.] + + Description [Returns 1 if refinement has happened.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_OneHotCount( Fra_Man_t * p, Vec_Int_t * vOneHots ) +{ + int i, Out1, Out2, Counter = 0; + for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 ) + { + Out1 = Vec_IntEntry( vOneHots, i ); + Out2 = Vec_IntEntry( vOneHots, i+1 ); + if ( Out1 == 0 && Out2 == 0 ) + continue; + Counter++; + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Estimates the coverage of state space by clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_OneHotEstimateCoverage( Fra_Man_t * p, Vec_Int_t * vOneHots ) +{ + int nSimWords = (1<<14); + int nRegs = Aig_ManRegNum(p->pManAig); + Vec_Ptr_t * vSimInfo; + unsigned * pSim1, * pSim2, * pSimTot; + int i, w, Out1, Out2, nCovered, Counter = 0; + int clk = clock(); + + // generate random sim-info at register outputs + vSimInfo = Vec_PtrAllocSimInfo( nRegs + 1, nSimWords ); +// srand( 0xAABBAABB ); + Aig_ManRandom(1); + for ( i = 0; i < nRegs; i++ ) + { + pSim1 = (unsigned *)Vec_PtrEntry( vSimInfo, i ); + for ( w = 0; w < nSimWords; w++ ) + pSim1[w] = Fra_ObjRandomSim(); + } + pSimTot = (unsigned *)Vec_PtrEntry( vSimInfo, nRegs ); + + // collect simulation info + memset( pSimTot, 0, sizeof(unsigned) * nSimWords ); + for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 ) + { + Out1 = Vec_IntEntry( vOneHots, i ); + Out2 = Vec_IntEntry( vOneHots, i+1 ); + if ( Out1 == 0 && Out2 == 0 ) + continue; +//printf( "(%c%d,%c%d) ", +//Fra_LitSign(Out1)? '-': '+', Fra_LitReg(Out1), +//Fra_LitSign(Out2)? '-': '+', Fra_LitReg(Out2) ); + Counter++; + pSim1 = (unsigned *)Vec_PtrEntry( vSimInfo, Fra_LitReg(Out1) ); + pSim2 = (unsigned *)Vec_PtrEntry( vSimInfo, Fra_LitReg(Out2) ); + if ( Fra_LitSign(Out1) && Fra_LitSign(Out2) ) + for ( w = 0; w < nSimWords; w++ ) + pSimTot[w] |= pSim1[w] & pSim2[w]; + else if ( Fra_LitSign(Out1) ) + for ( w = 0; w < nSimWords; w++ ) + pSimTot[w] |= pSim1[w] & ~pSim2[w]; + else if ( Fra_LitSign(Out2) ) + for ( w = 0; w < nSimWords; w++ ) + pSimTot[w] |= ~pSim1[w] & pSim2[w]; + else + assert( 0 ); + } +//printf( "\n" ); + // count the total number of patterns contained in the don't-care + nCovered = 0; + for ( w = 0; w < nSimWords; w++ ) + nCovered += Aig_WordCountOnes( pSimTot[w] ); + Vec_PtrFree( vSimInfo ); + // print the result + printf( "Care states ratio = %f. ", 1.0 * (nSimWords * 32 - nCovered) / (nSimWords * 32) ); + printf( "(%d out of %d patterns) ", nSimWords * 32 - nCovered, nSimWords * 32 ); + ABC_PRT( "Time", clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [Creates one-hotness EXDC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Fra_OneHotCreateExdc( Fra_Man_t * p, Vec_Int_t * vOneHots ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj1, * pObj2, * pObj; + int i, Out1, Out2, nTruePis; + pNew = Aig_ManStart( Vec_IntSize(vOneHots)/2 ); +// for ( i = 0; i < Aig_ManRegNum(p->pManAig); i++ ) +// Aig_ObjCreatePi(pNew); + Aig_ManForEachPi( p->pManAig, pObj, i ) + Aig_ObjCreatePi(pNew); + nTruePis = Aig_ManPiNum(p->pManAig) - Aig_ManRegNum(p->pManAig); + for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 ) + { + Out1 = Vec_IntEntry( vOneHots, i ); + Out2 = Vec_IntEntry( vOneHots, i+1 ); + if ( Out1 == 0 && Out2 == 0 ) + continue; + pObj1 = Aig_ManPi( pNew, nTruePis + Fra_LitReg(Out1) ); + pObj2 = Aig_ManPi( pNew, nTruePis + Fra_LitReg(Out2) ); + pObj1 = Aig_NotCond( pObj1, Fra_LitSign(Out1) ); + pObj2 = Aig_NotCond( pObj2, Fra_LitSign(Out2) ); + pObj = Aig_Or( pNew, pObj1, pObj2 ); + Aig_ObjCreatePo( pNew, pObj ); + } + Aig_ManCleanup(pNew); +// printf( "Created AIG with %d nodes and %d outputs.\n", Aig_ManNodeNum(pNew), Aig_ManPoNum(pNew) ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Assumes one-hot implications in the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +**********************************************************************/ +void Fra_OneHotAddKnownConstraint( Fra_Man_t * p, Vec_Ptr_t * vOnehots ) +{ + Vec_Int_t * vGroup; + Aig_Obj_t * pObj1, * pObj2; + int k, i, j, Out1, Out2, pLits[2]; + // + // these constrants should be added to different timeframes! + // (also note that PIs follow first - then registers) + // + Vec_PtrForEachEntry( Vec_Int_t *, vOnehots, vGroup, k ) + { + Vec_IntForEachEntry( vGroup, Out1, i ) + Vec_IntForEachEntryStart( vGroup, Out2, j, i+1 ) + { + pObj1 = Aig_ManPi( p->pManFraig, Out1 ); + pObj2 = Aig_ManPi( p->pManFraig, Out2 ); + pLits[0] = toLitCond( Fra_ObjSatNum(pObj1), 1 ); + pLits[1] = toLitCond( Fra_ObjSatNum(pObj2), 1 ); + // add constraint to solver + if ( !sat_solver_addclause( p->pSat, pLits, pLits + 2 ) ) + { + printf( "Fra_OneHotAddKnownConstraint(): Adding clause makes SAT solver unsat.\n" ); + sat_solver_delete( p->pSat ); + p->pSat = NULL; + return; + } + } + } +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fra/fraImp.c b/src/proof/fra/fraImp.c new file mode 100644 index 00000000..9877ceaa --- /dev/null +++ b/src/proof/fra/fraImp.c @@ -0,0 +1,731 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 = ABC_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 = ABC_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 = ABC_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 = (int *)Vec_PtrEntry( vNodes, pnBits[i] ); + pMemory[ pnNodes[pnBits[i]]++ ] = i; + } + // add 0s in the end + nTotal = 0; + Vec_PtrForEachEntry( int *, vNodes, pMemory, i ) + { + pMemory[ pnNodes[i]++ ] = 0; + nTotal += pnNodes[i]; + } + assert( nTotal == nNodes + nBits + 1 ); + ABC_FREE( pnNodes ); + ABC_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 = ABC_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; + } + ABC_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 = Abc_MaxInt( pImp1[0], pImp1[1] ); + int Max2 = Abc_MaxInt( 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 = ABC_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, 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 = (int *)Vec_PtrEntry( vNodes, i ); *pNodesI; pNodesI++ ) + for ( pNodesK = (int *)Vec_PtrEntry( vNodes, k ); *pNodesK; pNodesK++ ) + nImpsTotal++; + + // compute implications and their costs + pImpCosts = ABC_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 = (int *)Vec_PtrEntry( vNodes, i ); *pNodesI; pNodesI++ ) + for ( pNodesK = (int *)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 = Abc_MinInt( CostMin, pImpCosts[ Vec_IntSize(vImps) ] ); + CostMax = Abc_MaxInt( 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 + ABC_FREE( pImpCosts ); + { + void * pTemp = Vec_PtrEntry(vNodes, 0); + ABC_FREE( pTemp ); + } + 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 ); +ABC_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 constraint 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 = Abc_MaxInt( 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, 1 ); + // go through the implications and check how many of them do not hold + pfFails = ABC_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]; + ABC_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((Aig_Obj_t *)pLeft->pData, !pLeft->fPhase), + Aig_NotCond((Aig_Obj_t *)pRight->pData, pRight->fPhase) ); + Aig_ObjCreatePo( pNew, pMiter ); + } + pNew->nAsserts = Aig_ManPoNum(pNew) - nPosOld; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fra/fraInd.c b/src/proof/fra/fraInd.c new file mode 100644 index 00000000..1224bab3 --- /dev/null +++ b/src/proof/fra/fraInd.c @@ -0,0 +1,709 @@ +/**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 "src/sat/cnf/cnf.h" +#include "src/opt/dar/dar.h" +#include "src/aig/saig/saig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs AIG rewriting on the constraint 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", NULL, NULL ); +//Aig_ManDumpBlif( pTemp, "2.blif", NULL, NULL ); +// 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, pObjNew, pObjReprNew ); + pMiter = Aig_NotCond( pMiter, !Aig_ObjPhaseReal(pMiter) ); + assert( Aig_ObjPhaseReal(pMiter) == 1 ); + 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 = Abc_UtilStrsav( p->pManAig->pName ); + pManFraig->pSpec = Abc_UtilStrsav( p->pManAig->pSpec ); + 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 = ABC_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; + } + } + ABC_FREE( pLatches ); +} + + +/**Function************************************************************* + + Synopsis [Performs partitioned sequential SAT sweepingG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Fra_FraigInductionPart( Aig_Man_t * pAig, Fra_Ssw_t * pPars ) +{ + int fPrintParts = 0; + char Buffer[100]; + Aig_Man_t * pTemp, * pNew; + Vec_Ptr_t * vResult; + Vec_Int_t * vPart; + int * pMapBack; + int i, nCountPis, nCountRegs; + int nClasses, nPartSize, fVerbose; + int clk = clock(); + + // save parameters + nPartSize = pPars->nPartSize; pPars->nPartSize = 0; + fVerbose = pPars->fVerbose; pPars->fVerbose = 0; + // generate partitions + if ( pAig->vClockDoms ) + { + // divide large clock domains into separate partitions + vResult = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( Vec_Int_t *, (Vec_Ptr_t *)pAig->vClockDoms, vPart, i ) + { + if ( nPartSize && Vec_IntSize(vPart) > nPartSize ) + Aig_ManPartDivide( vResult, vPart, nPartSize, pPars->nOverSize ); + else + Vec_PtrPush( vResult, Vec_IntDup(vPart) ); + } + } + else + vResult = Aig_ManRegPartitionSimple( pAig, nPartSize, pPars->nOverSize ); +// vResult = Aig_ManPartitionSmartRegisters( pAig, nPartSize, 0 ); +// vResult = Aig_ManRegPartitionSmart( pAig, nPartSize ); + if ( fPrintParts ) + { + // print partitions + printf( "Simple partitioning. %d partitions are saved:\n", Vec_PtrSize(vResult) ); + Vec_PtrForEachEntry( Vec_Int_t *, vResult, vPart, i ) + { + sprintf( Buffer, "part%03d.aig", i ); + pTemp = Aig_ManRegCreatePart( pAig, vPart, &nCountPis, &nCountRegs, NULL ); + Ioa_WriteAiger( pTemp, Buffer, 0, 0 ); + printf( "part%03d.aig : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d.\n", + i, Vec_IntSize(vPart), Aig_ManPiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Aig_ManNodeNum(pTemp) ); + Aig_ManStop( pTemp ); + } + } + + // perform SSW with partitions + Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) ); + Vec_PtrForEachEntry( Vec_Int_t *, vResult, vPart, i ) + { + pTemp = Aig_ManRegCreatePart( pAig, vPart, &nCountPis, &nCountRegs, &pMapBack ); + // create the projection of 1-hot registers + if ( pAig->vOnehots ) + pTemp->vOnehots = Aig_ManRegProjectOnehots( pAig, pTemp, pAig->vOnehots, fVerbose ); + // run SSW + pNew = Fra_FraigInduction( pTemp, pPars ); + nClasses = Aig_TransferMappedClasses( pAig, pTemp, pMapBack ); + if ( fVerbose ) + printf( "%3d : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d. It = %3d. Cl = %5d.\n", + i, Vec_IntSize(vPart), Aig_ManPiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Aig_ManNodeNum(pTemp), pPars->nIters, nClasses ); + Aig_ManStop( pNew ); + Aig_ManStop( pTemp ); + ABC_FREE( pMapBack ); + } + // remap the AIG + pNew = Aig_ManDupRepr( pAig, 0 ); + Aig_ManSeqCleanup( pNew ); +// Aig_ManPrintStats( pAig ); +// Aig_ManPrintStats( pNew ); + Vec_VecFree( (Vec_Vec_t *)vResult ); + pPars->nPartSize = nPartSize; + pPars->fVerbose = fVerbose; + if ( fVerbose ) + { + ABC_PRT( "Total time", clock() - clk ); + } + return pNew; +} + +/**Function************************************************************* + + Synopsis [Performs sequential SAT sweeping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Fra_FraigInduction( Aig_Man_t * pManAig, Fra_Ssw_t * pParams ) +{ + 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 = NULL; + int nNodesBeg, nRegsBeg; + int nIter = -1; // Suppress "might be used uninitialized" + int i, clk = clock(), clk2; + int TimeToStop = (pParams->TimeLimit == 0.0)? 0 : clock() + (int)(pParams->TimeLimit * CLOCKS_PER_SEC); + + if ( Aig_ManNodeNum(pManAig) == 0 ) + { + pParams->nIters = 0; + // Ntl_ManFinalize() needs the following to satisfy an assertion + Aig_ManReprStart(pManAig,Aig_ManObjNumMax(pManAig)); + return Aig_ManDupOrdered(pManAig); + } + assert( Aig_ManRegNum(pManAig) > 0 ); + assert( pParams->nFramesK > 0 ); +//Aig_ManShow( pManAig, 0, NULL ); + + if ( pParams->fWriteImps && pParams->nPartSize > 0 ) + { + pParams->nPartSize = 0; + printf( "Partitioning was disabled to allow implication writing.\n" ); + } + // perform partitioning + if ( (pParams->nPartSize > 0 && pParams->nPartSize < Aig_ManRegNum(pManAig)) + || (pManAig->vClockDoms && Vec_VecSize(pManAig->vClockDoms) > 0) ) + return Fra_FraigInductionPart( pManAig, pParams ); + + 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 = pParams->nFramesP; + pPars->nFramesK = pParams->nFramesK; + pPars->nMaxImps = pParams->nMaxImps; + pPars->nMaxLevs = pParams->nMaxLevs; + pPars->fVerbose = pParams->fVerbose; + pPars->fRewrite = pParams->fRewrite; + pPars->fLatchCorr = pParams->fLatchCorr; + pPars->fUseImps = pParams->fUseImps; + pPars->fWriteImps = pParams->fWriteImps; + pPars->fUse1Hot = pParams->fUse1Hot; + + assert( !(pPars->nFramesP > 0 && pPars->fUse1Hot) ); + assert( !(pPars->nFramesK > 1 && pPars->fUse1Hot) ); + + // start the fraig manager for this run + p = Fra_ManStart( pManAig, pPars ); + p->pPars->nBTLimitNode = 0; + // 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 ( pPars->fVerbose ) +printf( "Simulating %d AIG nodes for %d cycles ... ", Aig_ManNodeNum(pManAig), pPars->nFramesP + 32 ); + p->pSml = Fra_SmlSimulateSeq( pManAig, pPars->nFramesP, 32, 1, 1 ); //pPars->nFramesK + 1, 1 ); +if ( pPars->fVerbose ) +{ +ABC_PRT( "Time", clock() - clk ); +} + Fra_ClassesPrepare( p->pCla, p->pPars->fLatchCorr, p->pPars->nMaxLevs ); +// Fra_ClassesPostprocess( p->pCla ); + // compute one-hotness conditions + if ( p->pPars->fUse1Hot ) + p->vOneHots = Fra_OneHotCompute( p, p->pSml ); + // 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 ); + + if ( pParams->TimeLimit != 0.0 && clock() > TimeToStop ) + { + if ( !pParams->fSilent ) + printf( "Fra_FraigInduction(): Runtime limit exceeded.\n" ); + goto finish; + } + + // 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", NULL, NULL ); +// 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; + int nHotsOld = p->vOneHots? Fra_OneHotCount(p, p->vOneHots) : 0; + int clk3 = clock(); + + if ( pParams->TimeLimit != 0.0 && clock() > TimeToStop ) + { + if ( !pParams->fSilent ) + printf( "Fra_FraigInduction(): Runtime limit exceeded.\n" ); + goto finish; + } + + // 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", NULL, NULL ); + + // 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_DataTranformPolarity( pCnf, 0 ); +//Cnf_DataWriteIntoFile( pCnf, "temp.cnf", 1 ); + + p->pSat = (sat_solver *)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, (Vec_Ptr_t *)1 ); + } + Cnf_DataFree( pCnf ); + + // add one-hotness clauses + if ( p->pPars->fUse1Hot ) + Fra_OneHotAssume( p, p->vOneHots ); +// if ( p->pManAig->vOnehots ) +// Fra_OneHotAddKnownConstraint( p, p->pManAig->vOnehots ); + + // report the intermediate results + if ( pPars->fVerbose ) + { + printf( "%3d : C = %6d. Cl = %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) ); + if ( p->pPars->fUse1Hot ) + printf( "1h = %6d. ", Fra_OneHotCount(p, p->vOneHots) ); + printf( "NR = %6d. ", Aig_ManNodeNum(p->pManFraig) ); +// printf( "\n" ); + } + + // perform sweeping + p->nSatCallsRecent = 0; + p->nSatCallsSkipped = 0; +clk2 = clock(); + if ( p->pPars->fUse1Hot ) + Fra_OneHotCheck( p, p->vOneHots ); + Fra_FraigSweep( p ); + if ( pPars->fVerbose ) + { + ABC_PRT( "T", clock() - clk3 ); + } + +// Sat_SolverPrintStats( stdout, p->pSat ); + // remove FRAIG and SAT solver + Aig_ManStop( p->pManFraig ); p->pManFraig = NULL; +// printf( "Vars = %d. Clauses = %d. Learnts = %d.\n", p->pSat->size, p->pSat->clauses.size, p->pSat->learnts.size ); + 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) && + nHotsOld == (p->vOneHots? Fra_OneHotCount(p, p->vOneHots) : 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) ); + ABC_PRT( "Time", clock() - clk ); + } +*/ + + // move the classes into representatives and reduce AIG +clk2 = clock(); + if ( p->pPars->fWriteImps && p->vOneHots && Fra_OneHotCount(p, p->vOneHots) ) + { + extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact ); + Aig_Man_t * pNew; + char * pFileName = Ioa_FileNameGenericAppend( p->pManAig->pName, "_care.aig" ); + printf( "Care one-hotness clauses will be written into file \"%s\".\n", pFileName ); + pManAigNew = Aig_ManDupOrdered( pManAig ); + pNew = Fra_OneHotCreateExdc( p, p->vOneHots ); + Ioa_WriteAiger( pNew, pFileName, 0, 1 ); + Aig_ManStop( pNew ); + } + else + { + // 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 ); + // remove pointers to the dead nodes +// Aig_ManForEachObj( pManAig, pObj, i ) +// if ( pObj->pData && Aig_ObjIsNone(pObj->pData) ) +// pObj->pData = NULL; +// 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 +finish: + 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" ); + pParams->nIters = nIter; + return pManAigNew; +} + +/**Function************************************************************* + + Synopsis [Outputs a set of pairs of equivalent nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_FraigInductionTest( char * pFileName, Fra_Ssw_t * pParams ) +{ + FILE * pFile; + char * pFilePairs; + Aig_Man_t * pMan, * pNew; + Aig_Obj_t * pObj, * pRepr; + int * pNum2Id; + int i, Counter = 0; + pMan = Saig_ManReadBlif( pFileName ); + if ( pMan == NULL ) + return 0; + // perform seq SAT sweeping + pNew = Fra_FraigInduction( pMan, pParams ); + if ( pNew == NULL ) + { + Aig_ManStop( pMan ); + return 0; + } + if ( pParams->fVerbose ) + { + printf( "Original AIG: " ); + Aig_ManPrintStats( pMan ); + printf( "Reduced AIG: " ); + Aig_ManPrintStats( pNew ); + } + Aig_ManStop( pNew ); + pNum2Id = (int *)pMan->pData; + // write the output file + pFilePairs = Aig_FileNameGenericAppend( pFileName, ".pairs" ); + pFile = fopen( pFilePairs, "w" ); + Aig_ManForEachObj( pMan, pObj, i ) + if ( (pRepr = pMan->pReprs[pObj->Id]) ) + { + fprintf( pFile, "%d %d %c\n", pNum2Id[pObj->Id], pNum2Id[pRepr->Id], (Aig_ObjPhase(pObj) ^ Aig_ObjPhase(pRepr))? '-' : '+' ); + Counter++; + } + fclose( pFile ); + if ( pParams->fVerbose ) + { + printf( "Result: %d pairs of seq equiv nodes are written into file \"%s\".\n", Counter, pFilePairs ); + } + Aig_ManStop( pMan ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fra/fraIndVer.c b/src/proof/fra/fraIndVer.c new file mode 100644 index 00000000..64437607 --- /dev/null +++ b/src/proof/fra/fraIndVer.c @@ -0,0 +1,166 @@ +/**CFile**************************************************************** + + FileName [fraIndVer.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [New FRAIG package.] + + Synopsis [Verification of the inductive invariant.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 30, 2007.] + + Revision [$Id: fraIndVer.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fra.h" +#include "src/sat/cnf/cnf.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Verifies the inductive invariant.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_InvariantVerify( Aig_Man_t * pAig, int nFrames, Vec_Int_t * vClauses, Vec_Int_t * vLits ) +{ + Cnf_Dat_t * pCnf; + sat_solver * pSat; + int * pStart; + int RetValue, Beg, End, i, k; + int CounterBase = 0, CounterInd = 0; + int clk = clock(); + + if ( nFrames != 1 ) + { + printf( "Invariant verification: Can only verify for K = 1\n" ); + return 1; + } + + // derive CNF + pCnf = Cnf_DeriveSimple( pAig, Aig_ManPoNum(pAig) ); +/* + // add the property + { + Aig_Obj_t * pObj; + int Lits[1]; + + pObj = Aig_ManPo( pAig, 0 ); + Lits[0] = toLitCond( pCnf->pVarNums[pObj->Id], 1 ); + + Vec_IntPush( vLits, Lits[0] ); + Vec_IntPush( vClauses, Vec_IntSize(vLits) ); + printf( "Added the target property to the set of clauses to be inductively checked.\n" ); + } +*/ + // derive initialized frames for the base case + pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, nFrames, 1 ); + // check clauses in the base case + Beg = 0; + pStart = Vec_IntArray( vLits ); + Vec_IntForEachEntry( vClauses, End, i ) + { + // complement the literals + for ( k = Beg; k < End; k++ ) + pStart[k] = lit_neg(pStart[k]); + RetValue = sat_solver_solve( pSat, pStart + Beg, pStart + End, 0, 0, 0, 0 ); + for ( k = Beg; k < End; k++ ) + pStart[k] = lit_neg(pStart[k]); + Beg = End; + if ( RetValue == l_False ) + continue; +// printf( "Clause %d failed the base case.\n", i ); + CounterBase++; + } + sat_solver_delete( pSat ); + + // derive initialized frames for the base case + pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, nFrames + 1, 0 ); + assert( pSat->size == 2 * pCnf->nVars ); + // add clauses to the first frame + Beg = 0; + pStart = Vec_IntArray( vLits ); + Vec_IntForEachEntry( vClauses, End, i ) + { + RetValue = sat_solver_addclause( pSat, pStart + Beg, pStart + End ); + Beg = End; + if ( RetValue == 0 ) + { + Cnf_DataFree( pCnf ); + sat_solver_delete( pSat ); + printf( "Invariant verification: SAT solver is unsat after adding a clause.\n" ); + return 0; + } + } + // simplify the solver + if ( pSat->qtail != pSat->qhead ) + { + RetValue = sat_solver_simplify(pSat); + assert( RetValue != 0 ); + assert( pSat->qtail == pSat->qhead ); + } + + // check clauses in the base case + Beg = 0; + pStart = Vec_IntArray( vLits ); + Vec_IntForEachEntry( vClauses, End, i ) + { + // complement the literals + for ( k = Beg; k < End; k++ ) + { + pStart[k] += 2 * pCnf->nVars; + pStart[k] = lit_neg(pStart[k]); + } + RetValue = sat_solver_solve( pSat, pStart + Beg, pStart + End, 0, 0, 0, 0 ); + for ( k = Beg; k < End; k++ ) + { + pStart[k] = lit_neg(pStart[k]); + pStart[k] -= 2 * pCnf->nVars; + } + Beg = End; + if ( RetValue == l_False ) + continue; +// printf( "Clause %d failed the inductive case.\n", i ); + CounterInd++; + } + sat_solver_delete( pSat ); + Cnf_DataFree( pCnf ); + if ( CounterBase ) + printf( "Invariant verification: %d clauses (out of %d) FAILED the base case.\n", CounterBase, Vec_IntSize(vClauses) ); + if ( CounterInd ) + printf( "Invariant verification: %d clauses (out of %d) FAILED the inductive case.\n", CounterInd, Vec_IntSize(vClauses) ); + if ( CounterBase || CounterInd ) + return 0; + printf( "Invariant verification: %d clauses verified correctly. ", Vec_IntSize(vClauses) ); + ABC_PRT( "Time", clock() - clk ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fra/fraLcr.c b/src/proof/fra/fraLcr.c new file mode 100644 index 00000000..b18a8fcd --- /dev/null +++ b/src/proof/fra/fraLcr.c @@ -0,0 +1,709 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 = ABC_ALLOC( Fra_Lcr_t, 1 ); + memset( p, 0, sizeof(Fra_Lcr_t) ); + p->pAig = pAig; + p->pInToOutPart = ABC_ALLOC( int, Aig_ManPiNum(pAig) ); + memset( p->pInToOutPart, 0, sizeof(int) * Aig_ManPiNum(pAig) ); + p->pInToOutNum = ABC_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 ); + ABC_PRT( "AIG simulation ", p->timeSim ); + ABC_PRT( "AIG partitioning", p->timePart ); + ABC_PRT( "AIG rebuiding ", p->timeTrav ); + ABC_PRT( "FRAIGing ", p->timeFraig ); + ABC_PRT( "AIG updating ", p->timeUpdate ); + ABC_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 ); + ABC_FREE( p->pInToOutPart ); + ABC_FREE( p->pInToOutNum ); + ABC_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 = ABC_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 = (Fra_Man_t *)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 = (Aig_Man_t *)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 = (Fra_Man_t *)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 = (Aig_Man_t *)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 [Duplicates the AIG manager recursively.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Fra_LcrManDup_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pObjNew; + if ( pObj->pData ) + return (Aig_Obj_t *)pObj->pData; + Fra_LcrManDup_rec( pNew, p, Aig_ObjFanin0(pObj) ); + if ( Aig_ObjIsBuf(pObj) ) + return (Aig_Obj_t *)(pObj->pData = Aig_ObjChild0Copy(pObj)); + Fra_LcrManDup_rec( pNew, p, Aig_ObjFanin1(pObj) ); + pObjNew = Aig_Oper( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj), Aig_ObjType(pObj) ); + Aig_Regular(pObjNew)->pHaig = pObj->pHaig; + return (Aig_Obj_t *)(pObj->pData = pObjNew); +} + +/**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( Aig_Obj_t **, 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 = Fra_LcrManDup_rec( pNew, pLcr->pAig, Aig_ObjFanin0(pObjPo) ); + pMiter = Aig_Exor( pNew, pMiter, pObjNew ); + } + Aig_ObjCreatePo( pNew, pMiter ); + } + // go over the constant candidates + Vec_PtrForEachEntry( Aig_Obj_t *, pLcr->pCla->vClasses1, pObj, i ) + { + assert( Aig_ObjIsPi(pObj) ); + pObjPo = Aig_ManPo( pLcr->pAig, Offset+(long)pObj->pNext ); + pMiter = Fra_LcrManDup_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( Vec_Int_t *, vParts, vOne, i ) + { + vOneNew = Vec_IntAlloc( Vec_IntSize(vOne) ); + Vec_IntForEachEntry( vOne, Out, k ) + { + if ( Out < Vec_PtrSize(pCla->vClasses) ) + { + ppClass = (Aig_Obj_t **)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 = (Aig_Obj_t *)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 (Aig_Obj_t *)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( (Aig_Obj_t *)pObj->pData, pRepr->fPhase ^ pObj->fPhase ); + } + return (Aig_Obj_t *)pObj->pData; + } + Fra_LcrCreatePart_rec( pCla, pNew, p, Aig_ObjFanin0(pObj) ); + Fra_LcrCreatePart_rec( pCla, pNew, p, Aig_ObjFanin1(pObj) ); + return (Aig_Obj_t *)(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( Aig_Obj_t *, p->pCla->vClasses1, pObj, i ) + { + pObj = Aig_ManPo( p->pCla->pAig, Offset+(long)pObj->pNext ); + pObj->fMarkA = 1; + } + Vec_PtrForEachEntry( Aig_Obj_t **, 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( Aig_Obj_t *, p->pCla->vClasses1, pObj, i ) + { + pObj = Aig_ManPo( p->pCla->pAig, Offset+(long)pObj->pNext ); + pObj->fMarkA = 0; + } + Vec_PtrForEachEntry( Aig_Obj_t **, 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, float TimeLimit ) +{ + int nPartSize = 200; + int fReprSelect = 0; + Fra_Lcr_t * p; + Fra_Sml_t * pSml; + Fra_Man_t * pTemp; + Aig_Man_t * pAigPart, * pAigTemp, * pAigNew = NULL; + Vec_Int_t * vPart; + int i, nIter, timeSim, clk = clock(), clk2, clk3; + int TimeToStop = (TimeLimit == 0.0)? 0 : clock() + (int)(TimeLimit * CLOCKS_PER_SEC); + if ( Aig_ManNodeNum(pAig) == 0 ) + { + if ( pnIter ) *pnIter = 0; + // Ntl_ManFinalize() requires the following to satisfy an assertion. + Aig_ManReprStart(pAig,Aig_ManObjNumMax(pAig)); + return Aig_ManDupOrdered(pAig); + } + 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, 1 ); +if ( fVerbose ) +{ +ABC_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 ) +{ +ABC_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( Vec_Int_t *, p->vParts, vPart, i ) + { + int clk3 = clock(); + if ( TimeLimit != 0.0 && clock() > TimeToStop ) + { + Vec_PtrForEachEntry( Aig_Man_t *, p->vFraigs, pAigPart, i ) + Aig_ManStop( pAigPart ); + Aig_ManCleanMarkA( pAig ); + Aig_ManCleanMarkB( pAig ); + printf( "Fra_FraigLatchCorrespondence(): Runtime limit exceeded.\n" ); + goto finish; + } +clk2 = clock(); + pAigPart = Fra_LcrCreatePart( p, vPart ); +p->timeTrav += clock() - clk2; +clk2 = clock(); + pAigTemp = Fra_FraigEquivence( pAigPart, nConfMax, 0 ); +p->timeFraig += clock() - clk2; + Vec_PtrPush( p->vFraigs, pAigTemp ); +/* + { + char Name[1000]; + sprintf( Name, "part%04d.blif", i ); + Aig_ManDumpBlif( pAigPart, Name, NULL, NULL ); + } +printf( "Finished part %4d (out of %4d). ", i, Vec_PtrSize(p->vParts) ); +ABC_PRT( "Time", clock() - clk3 ); +*/ + + 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) ); + ABC_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( Aig_Man_t *, 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; + } + } + 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); +finish: + ABC_FREE( pTemp ); + Lcr_ManFree( p ); + if ( pnIter ) *pnIter = nIter; + return pAigNew; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fra/fraMan.c b/src/proof/fra/fraMan.c new file mode 100644 index 00000000..90e8b762 --- /dev/null +++ b/src/proof/fra/fraMan.c @@ -0,0 +1,314 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 = ABC_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 = Abc_BitWordNum( (Aig_ManPiNum(pManAig) - Aig_ManRegNum(pManAig)) * p->nFramesAll + Aig_ManRegNum(pManAig) ); + p->pPatWords = ABC_ALLOC( unsigned, p->nPatWords ); + p->vPiVars = Vec_PtrAlloc( 100 ); + // equivalence classes + p->pCla = Fra_ClassesStart( pManAig ); + // allocate other members + p->pMemFraig = ABC_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 ); + Aig_ManRandom(1); + // 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 = ABC_REALLOC( Vec_Ptr_t *, p->pMemFanins, nMemAllocNew ); + p->pMemSatNums = ABC_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 = Abc_UtilStrsav( p->pManAig->pName ); + pManFraig->pSpec = Abc_UtilStrsav( p->pManAig->pSpec ); + 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 = ABC_ALLOC( Vec_Ptr_t *, p->nMemAlloc ); + memset( p->pMemFanins, 0, sizeof(Vec_Ptr_t *) * p->nMemAlloc ); + p->pMemSatNums = ABC_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 ) + ABC_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 ); + if ( p->vOneHots ) Vec_IntFree( p->vOneHots ); + ABC_FREE( p->pMemFraig ); + ABC_FREE( p->pMemFanins ); + ABC_FREE( p->pMemSatNums ); + ABC_FREE( p->pPatWords ); + ABC_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 ); + if ( p->pPars->fUse1Hot ) Fra_OneHotEstimateCoverage( p, p->vOneHots ); + ABC_PRT( "AIG simulation ", p->pSml->timeSim ); + ABC_PRT( "AIG traversal ", p->timeTrav ); + if ( p->timeRwr ) + { + ABC_PRT( "AIG rewriting ", p->timeRwr ); + } + ABC_PRT( "SAT solving ", p->timeSat ); + ABC_PRT( " Unsat ", p->timeSatUnsat ); + ABC_PRT( " Sat ", p->timeSatSat ); + ABC_PRT( " Fail ", p->timeSatFail ); + ABC_PRT( "Class refining ", p->timeRef ); + ABC_PRT( "TOTAL RUNTIME ", p->timeTotal ); + if ( p->time1 ) { ABC_PRT( "time1 ", p->time1 ); } + if ( p->nSpeculs ) + printf( "Speculations = %d.\n", p->nSpeculs ); + fflush( stdout ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fra/fraPart.c b/src/proof/fra/fraPart.c new file mode 100644 index 00000000..e9739f97 --- /dev/null +++ b/src/proof/fra/fraPart.c @@ -0,0 +1,268 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 ); +ABC_PRT( "Supports", clock() - clk ); + // remove last entry + Aig_ManForEachPo( p, pObj, i ) + { + vSup = Vec_VecEntryInt( 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_VecEntryInt( vSupps, i ); + Vec_IntForEachEntry( vSup, Entry, k ) + Vec_VecPush( vSuppsIn, Entry, (void *)(ABC_PTRUINT_T)i ); + } +ABC_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_VecEntryInt( 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_VecEntryInt( 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 ); +ABC_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 ); +ABC_PRT( "Supports", clock() - clk ); + // remove last entry + Aig_ManForEachPo( p, pObj, i ) + { + vSup = Vec_VecEntryInt( 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_VecEntryInt( vSupps, i ); + Vec_IntForEachEntry( vSup, Entry, k ) + Vec_VecPush( vSuppsIn, Entry, (void *)(ABC_PTRUINT_T)i ); + } +ABC_PRT( "Inverse ", clock() - clk ); + + // create affective supports +clk = clock(); + pSupp = ABC_ALLOC( char, Aig_ManPiNum(p) ); + Aig_ManForEachPo( p, pObj, i ) + { + if ( i % 50 != 0 ) + continue; + vSup = Vec_VecEntryInt( 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_VecEntryInt( vSuppsIn, Entry ); + // go though each assert of this input + Vec_IntForEachEntry( vSup2, Entry2, m ) + { + vSup3 = Vec_VecEntryInt( 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" ); +ABC_PRT( "Extension ", clock() - clk ); + + ABC_FREE( pSupp ); + Vec_VecFree( vSupps ); + Vec_VecFree( vSuppsIn ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fra/fraSat.c b/src/proof/fra/fraSat.c new file mode 100644 index 00000000..fef642f5 --- /dev/null +++ b/src/proof/fra/fraSat.c @@ -0,0 +1,566 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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, + (ABC_INT64_T)nBTLimit, (ABC_INT64_T)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, + (ABC_INT64_T)nBTLimit, (ABC_INT64_T)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; + ABC_PRT( "Sat", clock() - clk2 ); + clk2 = clock(); + RetVal = Fra_NodesAreEquivBdd( pOld, pNew ); +// printf( "%d ", RetVal ); + assert( RetVal ); + ABC_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, + (ABC_INT64_T)nBTLimit, (ABC_INT64_T)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 the result of test for pObj => pNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_NodesAreClause( 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, + (ABC_INT64_T)nBTLimit, (ABC_INT64_T)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, + (ABC_INT64_T)p->pPars->nBTLimitMiter, (ABC_INT64_T)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 + if ( p->pSat->factors == NULL ) + p->pSat->factors = ABC_CALLOC( double, p->pSat->size ); + 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( Aig_Obj_t *, 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 = Abc_MaxInt( (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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fra/fraSec.c b/src/proof/fra/fraSec.c new file mode 100644 index 00000000..8067b8c2 --- /dev/null +++ b/src/proof/fra/fraSec.c @@ -0,0 +1,696 @@ +/**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 "src/aig/ioa/ioa.h" +#include "src/proof/int/int.h" +#include "src/proof/ssw/ssw.h" +#include "src/aig/saig/saig.h" +#include "src/proof/bbr/bbr.h" +#include "src/proof/pdr/pdr.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_SecSetDefaultParams( Fra_Sec_t * p ) +{ + memset( p, 0, sizeof(Fra_Sec_t) ); + p->fTryComb = 1; // try CEC call as a preprocessing step + p->fTryBmc = 1; // try BMC call as a preprocessing step + p->nFramesMax = 4; // the max number of frames used for induction + p->nBTLimit = 1000; // conflict limit at a node during induction + p->nBTLimitGlobal = 5000000; // global conflict limit during induction + p->nBTLimitInter = 10000; // conflict limit during interpolation + p->nBddVarsMax = 150; // the limit on the number of registers in BDD reachability + p->nBddMax = 50000; // the limit on the number of BDD nodes + p->nBddIterMax = 1000000; // the limit on the number of BDD iterations + p->fPhaseAbstract = 0; // enables phase abstraction + p->fRetimeFirst = 1; // enables most-forward retiming at the beginning + p->fRetimeRegs = 1; // enables min-register retiming at the beginning + p->fFraiging = 1; // enables fraiging at the beginning + p->fInduction = 1; // enables the use of induction (signal correspondence) + p->fInterpolation = 1; // enables interpolation + p->fInterSeparate = 0; // enables interpolation for each outputs separately + p->fReachability = 1; // enables BDD based reachability + p->fReorderImage = 1; // enables variable reordering during image computation + p->fStopOnFirstFail = 1; // enables stopping after first output of a miter has failed to prove + p->fUseNewProver = 0; // enables new prover + p->fUsePdr = 1; // enables PDR + p->nPdrTimeout = 60; // enabled PDR timeout + p->fSilent = 0; // disables all output + p->fVerbose = 0; // enables verbose reporting of statistics + p->fVeryVerbose = 0; // enables very verbose reporting + p->TimeLimit = 0; // enables the timeout + // internal parameters + p->fReportSolution = 0; // enables specialized format for reporting solution +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_FraigSec( Aig_Man_t * p, Fra_Sec_t * pParSec, Aig_Man_t ** ppResult ) +{ + Ssw_Pars_t Pars2, * pPars2 = &Pars2; + Fra_Ssw_t Pars, * pPars = &Pars; + Fra_Sml_t * pSml; + Aig_Man_t * pNew, * pTemp; + int nFrames, RetValue, nIter, clk, clkTotal = clock(); + int TimeOut = 0; + int fLatchCorr = 0; + float TimeLeft = 0.0; + pParSec->nSMnumber = -1; + + // try the miter before solving + pNew = Aig_ManDupSimple( p ); + RetValue = Fra_FraigMiterStatus( pNew ); + if ( RetValue >= 0 ) + goto finish; + + // prepare parameters + memset( pPars, 0, sizeof(Fra_Ssw_t) ); + pPars->fLatchCorr = fLatchCorr; + pPars->fVerbose = pParSec->fVeryVerbose; + if ( pParSec->fVerbose ) + { + printf( "Original miter: Latches = %5d. Nodes = %6d.\n", + Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); + } +//Aig_ManDumpBlif( pNew, "after.blif", NULL, NULL ); + + // perform sequential cleanup +clk = clock(); + if ( pNew->nRegs ) + pNew = Aig_ManReduceLaches( pNew, 0 ); + if ( pNew->nRegs ) + pNew = Aig_ManConstReduce( pNew, 0, -1, -1, 0, 0 ); + if ( pParSec->fVerbose ) + { + printf( "Sequential cleanup: Latches = %5d. Nodes = %6d. ", + Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); +ABC_PRT( "Time", clock() - clk ); + } + RetValue = Fra_FraigMiterStatus( pNew ); + if ( RetValue >= 0 ) + goto finish; + + // perform phase abstraction +clk = clock(); + if ( pParSec->fPhaseAbstract ) + { + extern Aig_Man_t * Saig_ManPhaseAbstractAuto( Aig_Man_t * p, int fVerbose ); + pNew->nTruePis = Aig_ManPiNum(pNew) - Aig_ManRegNum(pNew); + pNew->nTruePos = Aig_ManPoNum(pNew) - Aig_ManRegNum(pNew); + pNew = Saig_ManPhaseAbstractAuto( pTemp = pNew, 0 ); + Aig_ManStop( pTemp ); + if ( pParSec->fVerbose ) + { + printf( "Phase abstraction: Latches = %5d. Nodes = %6d. ", + Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); +ABC_PRT( "Time", clock() - clk ); + } + } + + // perform forward retiming + if ( pParSec->fRetimeFirst && pNew->nRegs ) + { +clk = clock(); +// pNew = Rtm_ManRetime( pTemp = pNew, 1, 1000, 0 ); + pNew = Saig_ManRetimeForward( pTemp = pNew, 100, 0 ); + Aig_ManStop( pTemp ); + if ( pParSec->fVerbose ) + { + printf( "Forward retiming: Latches = %5d. Nodes = %6d. ", + Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); +ABC_PRT( "Time", clock() - clk ); + } + } + + // run latch correspondence +clk = clock(); + if ( pNew->nRegs ) + { + pNew = Aig_ManDupOrdered( pTemp = pNew ); +// pNew = Aig_ManDupDfs( pTemp = pNew ); + Aig_ManStop( pTemp ); +/* + if ( RetValue == -1 && pParSec->TimeLimit ) + { + TimeLeft = (float)pParSec->TimeLimit - ((float)(clock()-clkTotal)/(float)(CLOCKS_PER_SEC)); + TimeLeft = Abc_MaxInt( TimeLeft, 0.0 ); + if ( TimeLeft == 0.0 ) + { + if ( !pParSec->fSilent ) + printf( "Runtime limit exceeded.\n" ); + RetValue = -1; + TimeOut = 1; + goto finish; + } + } +*/ + +// pNew = Fra_FraigLatchCorrespondence( pTemp = pNew, 0, 1000, 1, pParSec->fVeryVerbose, &nIter, TimeLeft ); +//Aig_ManDumpBlif( pNew, "ex.blif", NULL, NULL ); + Ssw_ManSetDefaultParamsLcorr( pPars2 ); + pNew = Ssw_LatchCorrespondence( pTemp = pNew, pPars2 ); + nIter = pPars2->nIters; + + // prepare parameters for scorr + Ssw_ManSetDefaultParams( pPars2 ); + + if ( pTemp->pSeqModel ) + { + if ( !Saig_ManVerifyCex( pTemp, pTemp->pSeqModel ) ) + printf( "Fra_FraigSec(): Counter-example verification has FAILED.\n" ); + if ( Saig_ManPiNum(p) != Saig_ManPiNum(pTemp) ) + printf( "The counter-example is invalid because of phase abstraction.\n" ); + else + { + ABC_FREE( p->pSeqModel ); + p->pSeqModel = Abc_CexDup( pTemp->pSeqModel, Aig_ManRegNum(p) ); + ABC_FREE( pTemp->pSeqModel ); + } + } + if ( pNew == NULL ) + { + if ( p->pSeqModel ) + { + RetValue = 0; + if ( !pParSec->fSilent ) + { + printf( "Networks are NOT EQUIVALENT after simulation. " ); +ABC_PRT( "Time", clock() - clkTotal ); + } + if ( pParSec->fReportSolution && !pParSec->fRecursive ) + { + printf( "SOLUTION: FAIL " ); +ABC_PRT( "Time", clock() - clkTotal ); + } + Aig_ManStop( pTemp ); + return RetValue; + } + pNew = pTemp; + RetValue = -1; + TimeOut = 1; + goto finish; + } + Aig_ManStop( pTemp ); + + if ( pParSec->fVerbose ) + { + printf( "Latch-corr (I=%3d): Latches = %5d. Nodes = %6d. ", + nIter, Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); +ABC_PRT( "Time", clock() - clk ); + } + } +/* + if ( RetValue == -1 && pParSec->TimeLimit ) + { + TimeLeft = (float)pParSec->TimeLimit - ((float)(clock()-clkTotal)/(float)(CLOCKS_PER_SEC)); + TimeLeft = Abc_MaxInt( TimeLeft, 0.0 ); + if ( TimeLeft == 0.0 ) + { + if ( !pParSec->fSilent ) + printf( "Runtime limit exceeded.\n" ); + RetValue = -1; + TimeOut = 1; + goto finish; + } + } +*/ + // perform fraiging + if ( pParSec->fFraiging ) + { +clk = clock(); + pNew = Fra_FraigEquivence( pTemp = pNew, 100, 0 ); + Aig_ManStop( pTemp ); + if ( pParSec->fVerbose ) + { + printf( "Fraiging: Latches = %5d. Nodes = %6d. ", + Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); +ABC_PRT( "Time", clock() - clk ); + } + } + + if ( pNew->nRegs == 0 ) + RetValue = Fra_FraigCec( &pNew, 100000, 0 ); + + RetValue = Fra_FraigMiterStatus( pNew ); + if ( RetValue >= 0 ) + goto finish; +/* + if ( RetValue == -1 && pParSec->TimeLimit ) + { + TimeLeft = (float)pParSec->TimeLimit - ((float)(clock()-clkTotal)/(float)(CLOCKS_PER_SEC)); + TimeLeft = Abc_MaxInt( TimeLeft, 0.0 ); + if ( TimeLeft == 0.0 ) + { + if ( !pParSec->fSilent ) + printf( "Runtime limit exceeded.\n" ); + RetValue = -1; + TimeOut = 1; + goto finish; + } + } +*/ + // perform min-area retiming + if ( pParSec->fRetimeRegs && pNew->nRegs ) + { +// extern Aig_Man_t * Saig_ManRetimeMinArea( Aig_Man_t * p, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose ); +clk = clock(); + pNew->nTruePis = Aig_ManPiNum(pNew) - Aig_ManRegNum(pNew); + pNew->nTruePos = Aig_ManPoNum(pNew) - Aig_ManRegNum(pNew); +// pNew = Rtm_ManRetime( pTemp = pNew, 1, 1000, 0 ); + pNew = Saig_ManRetimeMinArea( pTemp = pNew, 1000, 0, 0, 1, 0 ); + Aig_ManStop( pTemp ); + pNew = Aig_ManDupOrdered( pTemp = pNew ); + Aig_ManStop( pTemp ); + if ( pParSec->fVerbose ) + { + printf( "Min-reg retiming: Latches = %5d. Nodes = %6d. ", + Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); +ABC_PRT( "Time", clock() - clk ); + } + } + + // perform seq sweeping while increasing the number of frames + RetValue = Fra_FraigMiterStatus( pNew ); + if ( RetValue == -1 && pParSec->fInduction ) + for ( nFrames = 1; nFrames <= pParSec->nFramesMax; nFrames *= 2 ) + { +/* + if ( RetValue == -1 && pParSec->TimeLimit ) + { + TimeLeft = (float)pParSec->TimeLimit - ((float)(clock()-clkTotal)/(float)(CLOCKS_PER_SEC)); + TimeLeft = Abc_MaxInt( TimeLeft, 0.0 ); + if ( TimeLeft == 0.0 ) + { + if ( !pParSec->fSilent ) + printf( "Runtime limit exceeded.\n" ); + RetValue = -1; + TimeOut = 1; + goto finish; + } + } +*/ + +clk = clock(); + pPars->nFramesK = nFrames; + pPars->TimeLimit = TimeLeft; + pPars->fSilent = pParSec->fSilent; +// pNew = Fra_FraigInduction( pTemp = pNew, pPars ); + + pPars2->nFramesK = nFrames; + pPars2->nBTLimit = pParSec->nBTLimit; + pPars2->nBTLimitGlobal = pParSec->nBTLimitGlobal; +// pPars2->nBTLimit = 1000 * nFrames; + + if ( RetValue == -1 && pPars2->nConflicts > pPars2->nBTLimitGlobal ) + { + if ( !pParSec->fSilent ) + printf( "Global conflict limit (%d) exceeded.\n", pPars2->nBTLimitGlobal ); + RetValue = -1; + TimeOut = 1; + goto finish; + } + + Aig_ManSetRegNum( pNew, pNew->nRegs ); +// pNew = Ssw_SignalCorrespondence( pTemp = pNew, pPars2 ); + if ( Aig_ManRegNum(pNew) > 0 ) + pNew = Ssw_SignalCorrespondence( pTemp = pNew, pPars2 ); + else + pNew = Aig_ManDupSimpleDfs( pTemp = pNew ); + + if ( pNew == NULL ) + { + pNew = pTemp; + RetValue = -1; + TimeOut = 1; + goto finish; + } + +// printf( "Total conflicts = %d.\n", pPars2->nConflicts ); + + Aig_ManStop( pTemp ); + RetValue = Fra_FraigMiterStatus( pNew ); + if ( pParSec->fVerbose ) + { + printf( "K-step (K=%2d,I=%3d): Latches = %5d. Nodes = %6d. ", + nFrames, pPars2->nIters, Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); +ABC_PRT( "Time", clock() - clk ); + } + if ( RetValue != -1 ) + break; + + // perform retiming +// if ( pParSec->fRetimeFirst && pNew->nRegs ) + if ( pNew->nRegs ) + { +// extern Aig_Man_t * Saig_ManRetimeMinArea( Aig_Man_t * p, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose ); +clk = clock(); + pNew->nTruePis = Aig_ManPiNum(pNew) - Aig_ManRegNum(pNew); + pNew->nTruePos = Aig_ManPoNum(pNew) - Aig_ManRegNum(pNew); +// pNew = Rtm_ManRetime( pTemp = pNew, 1, 1000, 0 ); + pNew = Saig_ManRetimeMinArea( pTemp = pNew, 1000, 0, 0, 1, 0 ); + Aig_ManStop( pTemp ); + pNew = Aig_ManDupOrdered( pTemp = pNew ); + Aig_ManStop( pTemp ); + if ( pParSec->fVerbose ) + { + printf( "Min-reg retiming: Latches = %5d. Nodes = %6d. ", + Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); +ABC_PRT( "Time", clock() - clk ); + } + } + + if ( pNew->nRegs ) + pNew = Aig_ManConstReduce( pNew, 0, -1, -1, 0, 0 ); + + // perform rewriting +clk = clock(); + pNew = Aig_ManDupOrdered( pTemp = pNew ); + Aig_ManStop( pTemp ); +// pNew = Dar_ManRewriteDefault( pTemp = pNew ); + pNew = Dar_ManCompress2( pTemp = pNew, 1, 0, 1, 0, 0 ); + Aig_ManStop( pTemp ); + if ( pParSec->fVerbose ) + { + printf( "Rewriting: Latches = %5d. Nodes = %6d. ", + Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); +ABC_PRT( "Time", clock() - clk ); + } + + // perform sequential simulation + if ( pNew->nRegs ) + { +clk = clock(); + pSml = Fra_SmlSimulateSeq( pNew, 0, 128 * nFrames, 1 + 16/(1+Aig_ManNodeNum(pNew)/1000), 1 ); + if ( pParSec->fVerbose ) + { + printf( "Seq simulation : Latches = %5d. Nodes = %6d. ", + Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); +ABC_PRT( "Time", clock() - clk ); + } + if ( pSml->fNonConstOut ) + { + pNew->pSeqModel = Fra_SmlGetCounterExample( pSml ); + // transfer to the original manager + if ( Saig_ManPiNum(p) != Saig_ManPiNum(pNew) ) + printf( "The counter-example is invalid because of phase abstraction.\n" ); + else + { + ABC_FREE( p->pSeqModel ); + p->pSeqModel = Abc_CexDup( pNew->pSeqModel, Aig_ManRegNum(p) ); + ABC_FREE( pNew->pSeqModel ); + } + + Fra_SmlStop( pSml ); + Aig_ManStop( pNew ); + RetValue = 0; + if ( !pParSec->fSilent ) + { + printf( "Networks are NOT EQUIVALENT after simulation. " ); +ABC_PRT( "Time", clock() - clkTotal ); + } + if ( pParSec->fReportSolution && !pParSec->fRecursive ) + { + printf( "SOLUTION: FAIL " ); +ABC_PRT( "Time", clock() - clkTotal ); + } + return RetValue; + } + Fra_SmlStop( pSml ); + } + } + + // get the miter status + RetValue = Fra_FraigMiterStatus( pNew ); + + // try interplation +clk = clock(); + Aig_ManSetRegNum( pNew, Aig_ManRegNum(pNew) ); + if ( pParSec->fInterpolation && RetValue == -1 && Aig_ManRegNum(pNew) > 0 ) + { + Inter_ManParams_t Pars, * pPars = &Pars; + int Depth; + ABC_FREE( pNew->pSeqModel ); + Inter_ManSetDefaultParams( pPars ); +// pPars->nBTLimit = 100; + pPars->nBTLimit = pParSec->nBTLimitInter; + pPars->fVerbose = pParSec->fVeryVerbose; + if ( Saig_ManPoNum(pNew) == 1 ) + { + RetValue = Inter_ManPerformInterpolation( pNew, pPars, &Depth ); + } + else if ( pParSec->fInterSeparate ) + { + Abc_Cex_t * pCex = NULL; + Aig_Man_t * pTemp, * pAux; + Aig_Obj_t * pObjPo; + int i, Counter = 0; + Saig_ManForEachPo( pNew, pObjPo, i ) + { + if ( Aig_ObjFanin0(pObjPo) == Aig_ManConst1(pNew) ) + continue; + if ( pPars->fVerbose ) + printf( "Solving output %2d (out of %2d):\n", i, Saig_ManPoNum(pNew) ); + pTemp = Aig_ManDupOneOutput( pNew, i, 1 ); + pTemp = Aig_ManScl( pAux = pTemp, 1, 1, 0, -1, -1, 0, 0 ); + Aig_ManStop( pAux ); + if ( Saig_ManRegNum(pTemp) > 0 ) + { + RetValue = Inter_ManPerformInterpolation( pTemp, pPars, &Depth ); + if ( pTemp->pSeqModel ) + { + pCex = p->pSeqModel = Abc_CexDup( pTemp->pSeqModel, Aig_ManRegNum(p) ); + pCex->iPo = i; + Aig_ManStop( pTemp ); + break; + } + // if solved, remove the output + if ( RetValue == 1 ) + { + Aig_ObjPatchFanin0( pNew, pObjPo, Aig_ManConst0(pNew) ); + // printf( "Output %3d : Solved ", i ); + } + else + { + Counter++; + // printf( "Output %3d : Undec ", i ); + } + } + else + Counter++; +// Aig_ManPrintStats( pTemp ); + Aig_ManStop( pTemp ); + printf( "Solving output %3d (out of %3d) using interpolation.\r", i, Saig_ManPoNum(pNew) ); + } + Aig_ManCleanup( pNew ); + if ( pCex == NULL ) + { + printf( "Interpolation left %d (out of %d) outputs unsolved \n", Counter, Saig_ManPoNum(pNew) ); + if ( Counter ) + RetValue = -1; + } + pNew = Aig_ManDupUnsolvedOutputs( pTemp = pNew, 1 ); + Aig_ManStop( pTemp ); + pNew = Aig_ManScl( pTemp = pNew, 1, 1, 0, -1, -1, 0, 0 ); + Aig_ManStop( pTemp ); + } + else + { + Aig_Man_t * pNewOrpos = Saig_ManDupOrpos( pNew ); + RetValue = Inter_ManPerformInterpolation( pNewOrpos, pPars, &Depth ); + if ( pNewOrpos->pSeqModel ) + { + Abc_Cex_t * pCex; + pCex = pNew->pSeqModel = pNewOrpos->pSeqModel; pNewOrpos->pSeqModel = NULL; + pCex->iPo = Saig_ManFindFailedPoCex( pNew, pNew->pSeqModel ); + } + Aig_ManStop( pNewOrpos ); + } + + if ( pParSec->fVerbose ) + { + if ( RetValue == 1 ) + printf( "Property proved using interpolation. " ); + else if ( RetValue == 0 ) + printf( "Property DISPROVED in frame %d using interpolation. ", Depth ); + else if ( RetValue == -1 ) + printf( "Property UNDECIDED after interpolation. " ); + else + assert( 0 ); +ABC_PRT( "Time", clock() - clk ); + } + } + + // try reachability analysis + if ( pParSec->fReachability && RetValue == -1 && Aig_ManRegNum(pNew) > 0 && Aig_ManRegNum(pNew) < pParSec->nBddVarsMax ) + { + Saig_ParBbr_t Pars, * pPars = &Pars; + Bbr_ManSetDefaultParams( pPars ); + pPars->TimeLimit = 0; + pPars->nBddMax = pParSec->nBddMax; + pPars->nIterMax = pParSec->nBddIterMax; + pPars->fPartition = 1; + pPars->fReorder = 1; + pPars->fReorderImage = 1; + pPars->fVerbose = 0; + pPars->fSilent = pParSec->fSilent; + pNew->nTruePis = Aig_ManPiNum(pNew) - Aig_ManRegNum(pNew); + pNew->nTruePos = Aig_ManPoNum(pNew) - Aig_ManRegNum(pNew); + RetValue = Aig_ManVerifyUsingBdds( pNew, pPars ); + } + + // try PDR + if ( pParSec->fUsePdr && RetValue == -1 && Aig_ManRegNum(pNew) > 0 ) + { + Abc_Cex_t * pCex = NULL; + Aig_Man_t * pNewOrpos = Saig_ManDupOrpos( pNew ); + Pdr_Par_t Pars, * pPars = &Pars; + Pdr_ManSetDefaultParams( pPars ); + pPars->nTimeOut = pParSec->nPdrTimeout; + pPars->fVerbose = pParSec->fVerbose; + if ( pParSec->fVerbose ) + printf( "Running property directed reachability...\n" ); + RetValue = Pdr_ManSolve( pNewOrpos, pPars, &pCex ); + if ( pCex ) + pCex->iPo = Saig_ManFindFailedPoCex( pNew, pCex ); + Aig_ManStop( pNewOrpos ); + pNew->pSeqModel = pCex; + } + +finish: + // report the miter + if ( RetValue == 1 ) + { + if ( !pParSec->fSilent ) + { + printf( "Networks are equivalent. " ); +ABC_PRT( "Time", clock() - clkTotal ); + } + if ( pParSec->fReportSolution && !pParSec->fRecursive ) + { + printf( "SOLUTION: PASS " ); +ABC_PRT( "Time", clock() - clkTotal ); + } + } + else if ( RetValue == 0 ) + { + if ( pNew->pSeqModel == NULL ) + { + int i; + // if the CEX is not derives, it is because tricial CEX should be assumed + pNew->pSeqModel = Abc_CexAlloc( Aig_ManRegNum(pNew), pNew->nTruePis, 1 ); + // if the CEX does not work, we need to change PIs to 1 because + // the only way it can happen is when a PO is equal to a PI... + if ( Saig_ManFindFailedPoCex( pNew, pNew->pSeqModel ) == -1 ) + for ( i = 0; i < pNew->nTruePis; i++ ) + Abc_InfoSetBit( pNew->pSeqModel->pData, i ); + } + if ( !pParSec->fSilent ) + { + printf( "Networks are NOT EQUIVALENT. " ); +ABC_PRT( "Time", clock() - clkTotal ); + } + if ( pParSec->fReportSolution && !pParSec->fRecursive ) + { + printf( "SOLUTION: FAIL " ); +ABC_PRT( "Time", clock() - clkTotal ); + } + } + else + { + /////////////////////////////////// + // save intermediate result + extern void Abc_FrameSetSave1( void * pAig ); + Abc_FrameSetSave1( Aig_ManDupSimple(pNew) ); + /////////////////////////////////// + if ( !pParSec->fSilent ) + { + printf( "Networks are UNDECIDED. " ); +ABC_PRT( "Time", clock() - clkTotal ); + } + if ( pParSec->fReportSolution && !pParSec->fRecursive ) + { + printf( "SOLUTION: UNDECIDED " ); +ABC_PRT( "Time", clock() - clkTotal ); + } + if ( !TimeOut && !pParSec->fSilent ) + { + static int Counter = 1; + char pFileName[1000]; + pParSec->nSMnumber = Counter; + sprintf( pFileName, "sm%02d.aig", Counter++ ); + Ioa_WriteAiger( pNew, pFileName, 0, 0 ); + printf( "The unsolved reduced miter is written into file \"%s\".\n", pFileName ); + } + } + if ( pNew->pSeqModel ) + { + if ( Saig_ManPiNum(p) != Saig_ManPiNum(pNew) ) + printf( "The counter-example is invalid because of phase abstraction.\n" ); + else + { + ABC_FREE( p->pSeqModel ); + p->pSeqModel = Abc_CexDup( pNew->pSeqModel, Aig_ManRegNum(p) ); + ABC_FREE( pNew->pSeqModel ); + } + } + if ( ppResult != NULL ) + *ppResult = Aig_ManDupSimpleDfs( pNew ); + if ( pNew ) + Aig_ManStop( pNew ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fra/fraSim.c b/src/proof/fra/fraSim.c new file mode 100644 index 00000000..eb42c665 --- /dev/null +++ b/src/proof/fra/fraSim.c @@ -0,0 +1,1023 @@ +/**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" +#include "src/aig/saig/saig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 = (Fra_Man_t *)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 = (Fra_Man_t *)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 = (Fra_Man_t *)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 [Counts the number of one's in the patten of the output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_SmlNodeCountOnes( Fra_Sml_t * p, Aig_Obj_t * pObj ) +{ + unsigned * pSims; + int i, Counter = 0; + pSims = Fra_ObjSim(p, pObj->Id); + for ( i = 0; i < p->nWordsTotal; i++ ) + Counter += Aig_WordCountOnes( pSims[i] ); + return Counter; +} + + + +/**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 ) + Abc_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 ) + if ( sat_solver_var_value(p->pSat, Fra_ObjSatNum(pObj)) ) + Abc_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, Abc_InfoHasBit( p->pPatWords, i ) ); + for ( i = Aig_ManPiNum(p->pManFraig) - Aig_ManRegNum(p->pManFraig); i < Aig_ManPiNum(p->pManFraig); i++ ) + Vec_IntPush( p->vCex, Abc_InfoHasBit( p->pPatWords, i ) ); + } + +/* + printf( "Pattern: " ); + Aig_ManForEachPi( p->pManFraig, pObj, i ) + printf( "%d", Abc_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 = ABC_ALLOC( int, Aig_ManPiNum(p->pManFraig)+1 ); + Aig_ManForEachPi( p->pManAig, pObjPi, i ) + { + pModel[i] = Abc_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, Abc_InfoHasBit(pPat, i), 0 ); + // flip one bit + Limit = Abc_MinInt( Aig_ManPiNum(p->pAig), p->nWordsTotal * 32 - 1 ); + for ( i = 0; i < Limit; i++ ) + Abc_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, Abc_InfoHasBit(pPat, nTruePis * f + i), f ); + // copy the latch info + k = 0; + Aig_ManForEachLoSeq( p->pAig, pObj, i ) + Fra_SmlAssignConst( p, pObj, Abc_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 = Abc_MinInt( nTruePis, p->nWordsFrame * 32 - 1 ); + for ( i = 0; i < Limit; i++ ) + Abc_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 [] + +***********************************************************************/ +int Fra_SmlNodesCompareInFrame( Fra_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1, int iFrame0, int iFrame1 ) +{ + unsigned * pSims0, * pSims1; + int i; + assert( !Aig_IsComplement(pObj0) ); + assert( !Aig_IsComplement(pObj1) ); + assert( iFrame0 == 0 || p->nWordsFrame < p->nWordsTotal ); + assert( iFrame1 == 0 || p->nWordsFrame < p->nWordsTotal ); + // get hold of the simulation information + pSims0 = Fra_ObjSim(p, pObj0->Id) + p->nWordsFrame * iFrame0; + pSims1 = Fra_ObjSim(p, pObj1->Id) + p->nWordsFrame * iFrame1; + // compare + for ( i = 0; i < p->nWordsFrame; i++ ) + if ( pSims0[i] != pSims1[i] ) + return 0; + return 1; +} + +/**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 ); + if ( p->vOneHots ) + nChanges += Fra_OneHotRefineUsingCex( p, p->vOneHots ); +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 *)ABC_ALLOC( char, 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 ) +{ + ABC_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, int fCheckMiter ) +{ + Fra_Sml_t * p; + p = Fra_SmlStart( pAig, nPref, nFrames, nWords ); + Fra_SmlInitialize( p, 1 ); + Fra_SmlSimulateOne( p ); + if ( fCheckMiter ) + p->fNonConstOut = Fra_SmlCheckNonConstOutputs( p ); + return p; +} + +/**Function************************************************************* + + Synopsis [Creates sequential counter-example from the simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Fra_SmlGetCounterExample( Fra_Sml_t * p ) +{ + Abc_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 = Abc_CexAlloc( 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 ( Abc_InfoHasBit( pSims, iBit ) ) + Abc_InfoSetBit( pCex->pData, k ); + } + for ( i = 0; i <= iFrame; i++ ) + { + Aig_ManForEachPiSeq( p->pAig, pObj, k ) + { + pSims = Fra_ObjSim( p, pObj->Id ); + if ( Abc_InfoHasBit( pSims, 32 * p->nWordsFrame * i + iBit ) ) + Abc_InfoSetBit( pCex->pData, pCex->nRegs + pCex->nPis * i + k ); + } + } + // verify the counter example + if ( !Saig_ManVerifyCex( p->pAig, pCex ) ) + { + printf( "Fra_SmlGetCounterExample(): Counter-example is invalid.\n" ); + Abc_CexFree( pCex ); + pCex = NULL; + } + return pCex; +} + +/**Function************************************************************* + + Synopsis [Generates seq counter-example from the combinational one.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Fra_SmlCopyCounterExample( Aig_Man_t * pAig, Aig_Man_t * pFrames, int * pModel ) +{ + Abc_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 = Abc_CexAlloc( 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] ) + Abc_InfoSetBit( pCex->pData, pCex->nRegs + i ); + if ( pCex->nRegs + i == pCex->nBits - 1 ) + break; + } + + // verify the counter example + if ( !Saig_ManVerifyCex( pAig, pCex ) ) + { + printf( "Fra_SmlGetCounterExample(): Counter-example is invalid.\n" ); + Abc_CexFree( pCex ); + pCex = NULL; + } + return pCex; + +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fra/fra_.c b/src/proof/fra/fra_.c new file mode 100644 index 00000000..8e5785ec --- /dev/null +++ b/src/proof/fra/fra_.c @@ -0,0 +1,53 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fra/module.make b/src/proof/fra/module.make new file mode 100644 index 00000000..a54a98de --- /dev/null +++ b/src/proof/fra/module.make @@ -0,0 +1,17 @@ +SRC += src/proof/fra/fraBmc.c \ + src/proof/fra/fraCec.c \ + src/proof/fra/fraClass.c \ + src/proof/fra/fraClau.c \ + src/proof/fra/fraClaus.c \ + src/proof/fra/fraCnf.c \ + src/proof/fra/fraCore.c \ + src/proof/fra/fraHot.c \ + src/proof/fra/fraImp.c \ + src/proof/fra/fraInd.c \ + src/proof/fra/fraIndVer.c \ + src/proof/fra/fraLcr.c \ + src/proof/fra/fraMan.c \ + src/proof/fra/fraPart.c \ + src/proof/fra/fraSat.c \ + src/proof/fra/fraSec.c \ + src/proof/fra/fraSim.c diff --git a/src/proof/fraig/fraig.h b/src/proof/fraig/fraig.h new file mode 100644 index 00000000..6d672716 --- /dev/null +++ b/src/proof/fraig/fraig.h @@ -0,0 +1,260 @@ +/**CFile**************************************************************** + + FileName [fraig.h] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [External declarations of the FRAIG package.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - October 1, 2004] + + Revision [$Id: fraig.h,v 1.18 2005/07/08 01:01:30 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__sat__fraig__fraig_h +#define ABC__sat__fraig__fraig_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Fraig_ManStruct_t_ Fraig_Man_t; +typedef struct Fraig_NodeStruct_t_ Fraig_Node_t; +typedef struct Fraig_NodeVecStruct_t_ Fraig_NodeVec_t; +typedef struct Fraig_HashTableStruct_t_ Fraig_HashTable_t; +typedef struct Fraig_ParamsStruct_t_ Fraig_Params_t; +typedef struct Fraig_PatternsStruct_t_ Fraig_Patterns_t; +typedef struct Prove_ParamsStruct_t_ Prove_Params_t; + +struct Fraig_ParamsStruct_t_ +{ + int nPatsRand; // the number of words of random simulation info + int nPatsDyna; // the number of words of dynamic simulation info + int nBTLimit; // the max number of backtracks to perform + int nSeconds; // the timeout for the final proof + int fFuncRed; // performs only one level hashing + int fFeedBack; // enables solver feedback + int fDist1Pats; // enables distance-1 patterns + int fDoSparse; // performs equiv tests for sparse functions + int fChoicing; // enables recording structural choices + int fTryProve; // tries to solve the final miter + int fVerbose; // the verbosiness flag + int fVerboseP; // the verbosiness flag (for proof reporting) + int fInternal; // is set to 1 for internal fraig calls + int nConfLimit; // the limit on the number of conflicts + ABC_INT64_T 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 + ABC_INT64_T nTotalBacktrackLimit; // global limit on the number of backtracks + ABC_INT64_T nTotalInspectLimit; // global limit on the number of clause inspects + // global resources applied + ABC_INT64_T nTotalBacktracksMade; // the total number of backtracks made + ABC_INT64_T nTotalInspectsMade; // the total number of inspects made +}; + +//////////////////////////////////////////////////////////////////////// +/// GLOBAL VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +// macros working with complemented attributes of the nodes +#define Fraig_IsComplement(p) (((int)((ABC_PTRUINT_T) (p) & 01))) +#define Fraig_Regular(p) ((Fraig_Node_t *)((ABC_PTRUINT_T)(p) & ~01)) +#define Fraig_Not(p) ((Fraig_Node_t *)((ABC_PTRUINT_T)(p) ^ 01)) +#define Fraig_NotCond(p,c) ((Fraig_Node_t *)((ABC_PTRUINT_T)(p) ^ (c))) + +// these are currently not used +#define Fraig_Ref(p) +#define Fraig_Deref(p) +#define Fraig_RecursiveDeref(p,c) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== fraigApi.c =============================================================*/ +extern Fraig_NodeVec_t * Fraig_ManReadVecInputs( Fraig_Man_t * p ); +extern Fraig_NodeVec_t * Fraig_ManReadVecOutputs( Fraig_Man_t * p ); +extern Fraig_NodeVec_t * Fraig_ManReadVecNodes( Fraig_Man_t * p ); +extern Fraig_Node_t ** Fraig_ManReadInputs ( Fraig_Man_t * p ); +extern Fraig_Node_t ** Fraig_ManReadOutputs( Fraig_Man_t * p ); +extern Fraig_Node_t ** Fraig_ManReadNodes( Fraig_Man_t * p ); +extern int Fraig_ManReadInputNum ( Fraig_Man_t * p ); +extern int Fraig_ManReadOutputNum( Fraig_Man_t * p ); +extern int Fraig_ManReadNodeNum( Fraig_Man_t * p ); +extern Fraig_Node_t * Fraig_ManReadConst1 ( Fraig_Man_t * p ); +extern Fraig_Node_t * Fraig_ManReadIthVar( Fraig_Man_t * p, int i ); +extern Fraig_Node_t * Fraig_ManReadIthNode( Fraig_Man_t * p, int i ); +extern char ** Fraig_ManReadInputNames( Fraig_Man_t * p ); +extern char ** Fraig_ManReadOutputNames( Fraig_Man_t * p ); +extern char * Fraig_ManReadVarsInt( Fraig_Man_t * p ); +extern char * Fraig_ManReadSat( Fraig_Man_t * p ); +extern int Fraig_ManReadFuncRed( Fraig_Man_t * p ); +extern int Fraig_ManReadFeedBack( Fraig_Man_t * p ); +extern int Fraig_ManReadDoSparse( Fraig_Man_t * p ); +extern int Fraig_ManReadChoicing( Fraig_Man_t * p ); +extern int Fraig_ManReadVerbose( Fraig_Man_t * p ); +extern int * Fraig_ManReadModel( Fraig_Man_t * p ); +extern int Fraig_ManReadPatternNumRandom( Fraig_Man_t * p ); +extern int Fraig_ManReadPatternNumDynamic( Fraig_Man_t * p ); +extern int Fraig_ManReadPatternNumDynamicFiltered( Fraig_Man_t * p ); +extern int Fraig_ManReadSatFails( Fraig_Man_t * p ); +extern int Fraig_ManReadConflicts( Fraig_Man_t * p ); +extern int Fraig_ManReadInspects( Fraig_Man_t * p ); + +extern void Fraig_ManSetFuncRed( Fraig_Man_t * p, int fFuncRed ); +extern void Fraig_ManSetFeedBack( Fraig_Man_t * p, int fFeedBack ); +extern void Fraig_ManSetDoSparse( Fraig_Man_t * p, int fDoSparse ); +extern void Fraig_ManSetChoicing( Fraig_Man_t * p, int fChoicing ); +extern void Fraig_ManSetTryProve( Fraig_Man_t * p, int fTryProve ); +extern void Fraig_ManSetVerbose( Fraig_Man_t * p, int fVerbose ); +extern void Fraig_ManSetTimeToGraph( Fraig_Man_t * p, int Time ); +extern void Fraig_ManSetTimeToNet( Fraig_Man_t * p, int Time ); +extern void Fraig_ManSetTimeTotal( Fraig_Man_t * p, int Time ); +extern void Fraig_ManSetOutputNames( Fraig_Man_t * p, char ** ppNames ); +extern void Fraig_ManSetInputNames( Fraig_Man_t * p, char ** ppNames ); +extern void Fraig_ManSetPo( Fraig_Man_t * p, Fraig_Node_t * pNode ); + +extern Fraig_Node_t * Fraig_NodeReadData0( Fraig_Node_t * p ); +extern Fraig_Node_t * Fraig_NodeReadData1( Fraig_Node_t * p ); +extern int Fraig_NodeReadNum( Fraig_Node_t * p ); +extern Fraig_Node_t * Fraig_NodeReadOne( Fraig_Node_t * p ); +extern Fraig_Node_t * Fraig_NodeReadTwo( Fraig_Node_t * p ); +extern Fraig_Node_t * Fraig_NodeReadNextE( Fraig_Node_t * p ); +extern Fraig_Node_t * Fraig_NodeReadRepr( Fraig_Node_t * p ); +extern int Fraig_NodeReadNumRefs( Fraig_Node_t * p ); +extern int Fraig_NodeReadNumFanouts( Fraig_Node_t * p ); +extern int Fraig_NodeReadSimInv( Fraig_Node_t * p ); +extern int Fraig_NodeReadNumOnes( Fraig_Node_t * p ); +extern unsigned * Fraig_NodeReadPatternsRandom( Fraig_Node_t * p ); +extern unsigned * Fraig_NodeReadPatternsDynamic( Fraig_Node_t * p ); + +extern void Fraig_NodeSetData0( Fraig_Node_t * p, Fraig_Node_t * pData ); +extern void Fraig_NodeSetData1( Fraig_Node_t * p, Fraig_Node_t * pData ); + +extern int Fraig_NodeIsConst( Fraig_Node_t * p ); +extern int Fraig_NodeIsVar( Fraig_Node_t * p ); +extern int Fraig_NodeIsAnd( Fraig_Node_t * p ); +extern int Fraig_NodeComparePhase( Fraig_Node_t * p1, Fraig_Node_t * p2 ); + +extern Fraig_Node_t * Fraig_NodeOr( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ); +extern Fraig_Node_t * Fraig_NodeAnd( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ); +extern Fraig_Node_t * Fraig_NodeOr( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ); +extern Fraig_Node_t * Fraig_NodeExor( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ); +extern Fraig_Node_t * Fraig_NodeMux( Fraig_Man_t * p, Fraig_Node_t * pNode, Fraig_Node_t * pNodeT, Fraig_Node_t * pNodeE ); +extern void Fraig_NodeSetChoice( Fraig_Man_t * pMan, Fraig_Node_t * pNodeOld, Fraig_Node_t * pNodeNew ); + +/*=== fraigMan.c =============================================================*/ +extern void Prove_ParamsSetDefault( Prove_Params_t * pParams ); +extern void Fraig_ParamsSetDefault( Fraig_Params_t * pParams ); +extern void Fraig_ParamsSetDefaultFull( Fraig_Params_t * pParams ); +extern Fraig_Man_t * Fraig_ManCreate( Fraig_Params_t * pParams ); +extern void Fraig_ManFree( Fraig_Man_t * pMan ); +extern void Fraig_ManPrintStats( Fraig_Man_t * p ); +extern Fraig_NodeVec_t * Fraig_ManGetSimInfo( Fraig_Man_t * p ); +extern int Fraig_ManCheckClauseUsingSimInfo( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2 ); +extern void Fraig_ManAddClause( Fraig_Man_t * p, Fraig_Node_t ** ppNodes, int nNodes ); + +/*=== fraigDfs.c =============================================================*/ +extern Fraig_NodeVec_t * Fraig_Dfs( Fraig_Man_t * pMan, int fEquiv ); +extern Fraig_NodeVec_t * Fraig_DfsOne( Fraig_Man_t * pMan, Fraig_Node_t * pNode, int fEquiv ); +extern Fraig_NodeVec_t * Fraig_DfsNodes( Fraig_Man_t * pMan, Fraig_Node_t ** ppNodes, int nNodes, int fEquiv ); +extern Fraig_NodeVec_t * Fraig_DfsReverse( Fraig_Man_t * pMan ); +extern int Fraig_CountNodes( Fraig_Man_t * pMan, int fEquiv ); +extern int Fraig_CheckTfi( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); +extern int Fraig_CountLevels( Fraig_Man_t * pMan ); + +/*=== fraigSat.c =============================================================*/ +extern int Fraig_NodesAreEqual( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit, int nTimeLimit ); +extern int Fraig_NodeIsEquivalent( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit, int nTimeLimit ); +extern void Fraig_ManProveMiter( Fraig_Man_t * p ); +extern int Fraig_ManCheckMiter( Fraig_Man_t * p ); +extern int Fraig_ManCheckClauseUsingSat( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit ); + +/*=== fraigVec.c ===============================================================*/ +extern Fraig_NodeVec_t * Fraig_NodeVecAlloc( int nCap ); +extern void Fraig_NodeVecFree( Fraig_NodeVec_t * p ); +extern Fraig_NodeVec_t * Fraig_NodeVecDup( Fraig_NodeVec_t * p ); +extern Fraig_Node_t ** Fraig_NodeVecReadArray( Fraig_NodeVec_t * p ); +extern int Fraig_NodeVecReadSize( Fraig_NodeVec_t * p ); +extern void Fraig_NodeVecGrow( Fraig_NodeVec_t * p, int nCapMin ); +extern void Fraig_NodeVecShrink( Fraig_NodeVec_t * p, int nSizeNew ); +extern void Fraig_NodeVecClear( Fraig_NodeVec_t * p ); +extern void Fraig_NodeVecPush( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ); +extern int Fraig_NodeVecPushUnique( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ); +extern void Fraig_NodeVecPushOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ); +extern int Fraig_NodeVecPushUniqueOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ); +extern void Fraig_NodeVecPushOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ); +extern int Fraig_NodeVecPushUniqueOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ); +extern Fraig_Node_t * Fraig_NodeVecPop( Fraig_NodeVec_t * p ); +extern void Fraig_NodeVecRemove( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ); +extern void Fraig_NodeVecWriteEntry( Fraig_NodeVec_t * p, int i, Fraig_Node_t * Entry ); +extern Fraig_Node_t * Fraig_NodeVecReadEntry( Fraig_NodeVec_t * p, int i ); +extern void Fraig_NodeVecSortByLevel( Fraig_NodeVec_t * p, int fIncreasing ); +extern void Fraig_NodeVecSortByNumber( Fraig_NodeVec_t * p ); + +/*=== fraigUtil.c ===============================================================*/ +extern void Fraig_ManMarkRealFanouts( Fraig_Man_t * p ); +extern int Fraig_ManCheckConsistency( Fraig_Man_t * p ); +extern int Fraig_GetMaxLevel( Fraig_Man_t * pMan ); +extern void Fraig_ManReportChoices( Fraig_Man_t * pMan ); +extern void Fraig_MappingSetChoiceLevels( Fraig_Man_t * pMan, int fMaximum ); +extern Fraig_NodeVec_t * Fraig_CollectSupergate( Fraig_Node_t * pNode, int fStopAtMux ); + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_END + + + +#endif diff --git a/src/proof/fraig/fraigApi.c b/src/proof/fraig/fraigApi.c new file mode 100644 index 00000000..6e0ab959 --- /dev/null +++ b/src/proof/fraig/fraigApi.c @@ -0,0 +1,302 @@ +/**CFile**************************************************************** + + FileName [fraigApi.c] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [Access APIs for the FRAIG manager and node.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - October 1, 2004] + + Revision [$Id: fraigApi.c,v 1.2 2005/07/08 01:01:30 alanmi Exp $] + +***********************************************************************/ + +#include "fraigInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Access functions to read the data members of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_NodeVec_t * Fraig_ManReadVecInputs( Fraig_Man_t * p ) { return p->vInputs; } +Fraig_NodeVec_t * Fraig_ManReadVecOutputs( Fraig_Man_t * p ) { return p->vOutputs; } +Fraig_NodeVec_t * Fraig_ManReadVecNodes( Fraig_Man_t * p ) { return p->vNodes; } +Fraig_Node_t ** Fraig_ManReadInputs ( Fraig_Man_t * p ) { return p->vInputs->pArray; } +Fraig_Node_t ** Fraig_ManReadOutputs( Fraig_Man_t * p ) { return p->vOutputs->pArray; } +Fraig_Node_t ** Fraig_ManReadNodes( Fraig_Man_t * p ) { return p->vNodes->pArray; } +int Fraig_ManReadInputNum ( Fraig_Man_t * p ) { return p->vInputs->nSize; } +int Fraig_ManReadOutputNum( Fraig_Man_t * p ) { return p->vOutputs->nSize; } +int Fraig_ManReadNodeNum( Fraig_Man_t * p ) { return p->vNodes->nSize; } +Fraig_Node_t * Fraig_ManReadConst1 ( Fraig_Man_t * p ) { return p->pConst1; } +Fraig_Node_t * Fraig_ManReadIthNode( Fraig_Man_t * p, int i ) { assert ( i < p->vNodes->nSize ); return p->vNodes->pArray[i]; } +char ** Fraig_ManReadInputNames( Fraig_Man_t * p ) { return p->ppInputNames; } +char ** Fraig_ManReadOutputNames( Fraig_Man_t * p ) { return p->ppOutputNames; } +char * Fraig_ManReadVarsInt( Fraig_Man_t * p ) { return (char *)p->vVarsInt; } +char * Fraig_ManReadSat( Fraig_Man_t * p ) { return (char *)p->pSat; } +int Fraig_ManReadFuncRed( Fraig_Man_t * p ) { return p->fFuncRed; } +int Fraig_ManReadFeedBack( Fraig_Man_t * p ) { return p->fFeedBack; } +int Fraig_ManReadDoSparse( Fraig_Man_t * p ) { return p->fDoSparse; } +int Fraig_ManReadChoicing( Fraig_Man_t * p ) { return p->fChoicing; } +int Fraig_ManReadVerbose( Fraig_Man_t * p ) { return p->fVerbose; } +int * Fraig_ManReadModel( Fraig_Man_t * p ) { return p->pModel; } +// returns the number of patterns used for random simulation (this number is fixed for the FRAIG run) +int Fraig_ManReadPatternNumRandom( Fraig_Man_t * p ) { return p->nWordsRand * 32; } +// returns the number of dynamic patterns accumulated at runtime (include SAT solver counter-examples and distance-1 patterns derived from them) +int Fraig_ManReadPatternNumDynamic( Fraig_Man_t * p ) { return p->iWordStart * 32; } +// returns the number of dynamic patterns proved useful to distinquish some FRAIG nodes (this number is more than 0 after the first garbage collection of patterns) +int Fraig_ManReadPatternNumDynamicFiltered( Fraig_Man_t * p ) { return p->iPatsPerm; } +// returns the number of times FRAIG package timed out +int Fraig_ManReadSatFails( Fraig_Man_t * p ) { return p->nSatFailsReal; } +// returns the number of conflicts in the SAT solver +int Fraig_ManReadConflicts( Fraig_Man_t * p ) { return p->pSat? Msat_SolverReadBackTracks(p->pSat) : 0; } +// returns the number of inspections in the SAT solver +int Fraig_ManReadInspects( Fraig_Man_t * p ) { return p->pSat? Msat_SolverReadInspects(p->pSat) : 0; } + +/**Function************************************************************* + + Synopsis [Access functions to set the data members of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_ManSetFuncRed( Fraig_Man_t * p, int fFuncRed ) { p->fFuncRed = fFuncRed; } +void Fraig_ManSetFeedBack( Fraig_Man_t * p, int fFeedBack ) { p->fFeedBack = fFeedBack; } +void Fraig_ManSetDoSparse( Fraig_Man_t * p, int fDoSparse ) { p->fDoSparse = fDoSparse; } +void Fraig_ManSetChoicing( Fraig_Man_t * p, int fChoicing ) { p->fChoicing = fChoicing; } +void Fraig_ManSetTryProve( Fraig_Man_t * p, int fTryProve ) { p->fTryProve = fTryProve; } +void Fraig_ManSetVerbose( Fraig_Man_t * p, int fVerbose ) { p->fVerbose = fVerbose; } +void Fraig_ManSetTimeToGraph( Fraig_Man_t * p, int Time ) { p->timeToAig = Time; } +void Fraig_ManSetTimeToNet( Fraig_Man_t * p, int Time ) { p->timeToNet = Time; } +void Fraig_ManSetTimeTotal( Fraig_Man_t * p, int Time ) { p->timeTotal = Time; } +void Fraig_ManSetOutputNames( Fraig_Man_t * p, char ** ppNames ) { p->ppOutputNames = ppNames; } +void Fraig_ManSetInputNames( Fraig_Man_t * p, char ** ppNames ) { p->ppInputNames = ppNames; } + +/**Function************************************************************* + + Synopsis [Access functions to read the data members of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_NodeReadData0( Fraig_Node_t * p ) { return p->pData0; } +Fraig_Node_t * Fraig_NodeReadData1( Fraig_Node_t * p ) { return p->pData1; } +int Fraig_NodeReadNum( Fraig_Node_t * p ) { return p->Num; } +Fraig_Node_t * Fraig_NodeReadOne( Fraig_Node_t * p ) { assert (!Fraig_IsComplement(p)); return p->p1; } +Fraig_Node_t * Fraig_NodeReadTwo( Fraig_Node_t * p ) { assert (!Fraig_IsComplement(p)); return p->p2; } +Fraig_Node_t * Fraig_NodeReadNextE( Fraig_Node_t * p ) { return p->pNextE; } +Fraig_Node_t * Fraig_NodeReadRepr( Fraig_Node_t * p ) { return p->pRepr; } +int Fraig_NodeReadNumRefs( Fraig_Node_t * p ) { return p->nRefs; } +int Fraig_NodeReadNumFanouts( Fraig_Node_t * p ) { return p->nFanouts; } +int Fraig_NodeReadSimInv( Fraig_Node_t * p ) { return p->fInv; } +int Fraig_NodeReadNumOnes( Fraig_Node_t * p ) { return p->nOnes; } +// returns the pointer to the random simulation patterns (their number is returned by Fraig_ManReadPatternNumRandom) +// memory pointed to by this and the following procedure is maintained by the FRAIG package and exists as long as the package runs +unsigned * Fraig_NodeReadPatternsRandom( Fraig_Node_t * p ) { return p->puSimR; } +// returns the pointer to the dynamic simulation patterns (their number is returned by Fraig_ManReadPatternNumDynamic or Fraig_ManReadPatternNumDynamicFiltered) +// if the number of patterns is not evenly divisible by 32, the patterns beyond the given number contain garbage +unsigned * Fraig_NodeReadPatternsDynamic( Fraig_Node_t * p ) { return p->puSimD; } + +/**Function************************************************************* + + Synopsis [Access functions to set the data members of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeSetData0( Fraig_Node_t * p, Fraig_Node_t * pData ) { p->pData0 = pData; } +void Fraig_NodeSetData1( Fraig_Node_t * p, Fraig_Node_t * pData ) { p->pData1 = pData; } + +/**Function************************************************************* + + Synopsis [Checks the type of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeIsConst( Fraig_Node_t * p ) { return (Fraig_Regular(p))->Num == 0; } +int Fraig_NodeIsVar( Fraig_Node_t * p ) { return (Fraig_Regular(p))->NumPi >= 0; } +int Fraig_NodeIsAnd( Fraig_Node_t * p ) { return (Fraig_Regular(p))->NumPi < 0 && (Fraig_Regular(p))->Num > 0; } +int Fraig_NodeComparePhase( Fraig_Node_t * p1, Fraig_Node_t * p2 ) { assert( !Fraig_IsComplement(p1) ); assert( !Fraig_IsComplement(p2) ); return p1->fInv ^ p2->fInv; } + +/**Function************************************************************* + + Synopsis [Returns a new primary input node.] + + Description [If the node with this number does not exist, + create a new PI node with this number.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_ManReadIthVar( Fraig_Man_t * p, int i ) +{ + int k; + if ( i < 0 ) + { + printf( "Requesting a PI with a negative number\n" ); + return NULL; + } + // create the PIs to fill in the interval + if ( i >= p->vInputs->nSize ) + for ( k = p->vInputs->nSize; k <= i; k++ ) + Fraig_NodeCreatePi( p ); + return p->vInputs->pArray[i]; +} + +/**Function************************************************************* + + Synopsis [Creates a new PO node.] + + Description [This procedure may take a complemented node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_ManSetPo( Fraig_Man_t * p, Fraig_Node_t * pNode ) +{ + // internal node may be a PO two times + Fraig_Regular(pNode)->fNodePo = 1; + Fraig_NodeVecPush( p->vOutputs, pNode ); +} + +/**Function************************************************************* + + Synopsis [Perfoms the AND operation with functional hashing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_NodeAnd( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ) +{ + return Fraig_NodeAndCanon( p, p1, p2 ); +} + +/**Function************************************************************* + + Synopsis [Perfoms the OR operation with functional hashing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_NodeOr( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ) +{ + return Fraig_Not( Fraig_NodeAndCanon( p, Fraig_Not(p1), Fraig_Not(p2) ) ); +} + +/**Function************************************************************* + + Synopsis [Perfoms the EXOR operation with functional hashing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_NodeExor( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ) +{ + return Fraig_NodeMux( p, p1, Fraig_Not(p2), p2 ); +} + +/**Function************************************************************* + + Synopsis [Perfoms the MUX operation with functional hashing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_NodeMux( Fraig_Man_t * p, Fraig_Node_t * pC, Fraig_Node_t * pT, Fraig_Node_t * pE ) +{ + Fraig_Node_t * pAnd1, * pAnd2, * pRes; + pAnd1 = Fraig_NodeAndCanon( p, pC, pT ); Fraig_Ref( pAnd1 ); + pAnd2 = Fraig_NodeAndCanon( p, Fraig_Not(pC), pE ); Fraig_Ref( pAnd2 ); + pRes = Fraig_NodeOr( p, pAnd1, pAnd2 ); + Fraig_RecursiveDeref( p, pAnd1 ); + Fraig_RecursiveDeref( p, pAnd2 ); + Fraig_Deref( pRes ); + return pRes; +} + + +/**Function************************************************************* + + Synopsis [Sets the node to be equivalent to the given one.] + + Description [This procedure is a work-around for the equivalence check. + Does not verify the equivalence. Use at the user's risk.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeSetChoice( Fraig_Man_t * pMan, Fraig_Node_t * pNodeOld, Fraig_Node_t * pNodeNew ) +{ +// assert( pMan->fChoicing ); + pNodeNew->pNextE = pNodeOld->pNextE; + pNodeOld->pNextE = pNodeNew; + pNodeNew->pRepr = pNodeOld; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fraig/fraigCanon.c b/src/proof/fraig/fraigCanon.c new file mode 100644 index 00000000..47539db2 --- /dev/null +++ b/src/proof/fraig/fraigCanon.c @@ -0,0 +1,223 @@ +/**CFile**************************************************************** + + FileName [fraigCanon.c] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [AND-node creation and elementary AND-operation.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - October 1, 2004] + + Revision [$Id: fraigCanon.c,v 1.4 2005/07/08 01:01:31 alanmi Exp $] + +***********************************************************************/ + +#include +#include "fraigInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [The internal AND operation for the two FRAIG nodes.] + + Description [This procedure is the core of the FRAIG package, because + it performs the two-step canonicization of FRAIG nodes. The first step + involves the lookup in the structural hash table (which hashes two ANDs + into a node that has them as fanins, if such a node exists). If the node + is not found in the structural hash table, an attempt is made to find a + functionally equivalent node in another hash table (which hashes the + simulation info into the nodes, which has this simulation info). Some + tricks used on the way are described in the comments to the code and + in the paper "FRAIGs: Functionally reduced AND-INV graphs".] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_NodeAndCanon( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2 ) +{ + Fraig_Node_t * pNodeNew, * pNodeOld, * pNodeRepr; + int fUseSatCheck; +// int RetValue; + + // check for trivial cases + if ( p1 == p2 ) + return p1; + if ( p1 == Fraig_Not(p2) ) + return Fraig_Not(pMan->pConst1); + if ( Fraig_NodeIsConst(p1) ) + { + if ( p1 == pMan->pConst1 ) + return p2; + return Fraig_Not(pMan->pConst1); + } + if ( Fraig_NodeIsConst(p2) ) + { + if ( p2 == pMan->pConst1 ) + return p1; + return Fraig_Not(pMan->pConst1); + } +/* + // check for less trivial cases + if ( Fraig_IsComplement(p1) ) + { + if ( RetValue = Fraig_NodeIsInSupergate( Fraig_Regular(p1), p2 ) ) + { + if ( RetValue == -1 ) + pMan->nImplies0++; + else + pMan->nImplies1++; + + if ( RetValue == -1 ) + return p2; + } + } + else + { + if ( RetValue = Fraig_NodeIsInSupergate( p1, p2 ) ) + { + if ( RetValue == 1 ) + pMan->nSimplifies1++; + else + pMan->nSimplifies0++; + + if ( RetValue == 1 ) + return p1; + return Fraig_Not(pMan->pConst1); + } + } + + if ( Fraig_IsComplement(p2) ) + { + if ( RetValue = Fraig_NodeIsInSupergate( Fraig_Regular(p2), p1 ) ) + { + if ( RetValue == -1 ) + pMan->nImplies0++; + else + pMan->nImplies1++; + + if ( RetValue == -1 ) + return p1; + } + } + else + { + if ( RetValue = Fraig_NodeIsInSupergate( p2, p1 ) ) + { + if ( RetValue == 1 ) + pMan->nSimplifies1++; + else + pMan->nSimplifies0++; + + if ( RetValue == 1 ) + return p2; + return Fraig_Not(pMan->pConst1); + } + } +*/ + // perform level-one structural hashing + if ( Fraig_HashTableLookupS( pMan, p1, p2, &pNodeNew ) ) // the node with these children is found + { + // if the existent node is part of the cone of unused logic + // (that is logic feeding the node which is equivalent to the given node) + // return the canonical representative of this node + // determine the phase of the given node, with respect to its canonical form + pNodeRepr = Fraig_Regular(pNodeNew)->pRepr; + if ( pMan->fFuncRed && pNodeRepr ) + return Fraig_NotCond( pNodeRepr, Fraig_IsComplement(pNodeNew) ^ Fraig_NodeComparePhase(Fraig_Regular(pNodeNew), pNodeRepr) ); + // otherwise, the node is itself a canonical representative, return it + return pNodeNew; + } + // the same node is not found, but the new one is created + + // if one level hashing is requested (without functionality hashing), return + if ( !pMan->fFuncRed ) + return pNodeNew; + + // check if the new node is unique using the simulation info + if ( pNodeNew->nOnes == 0 || pNodeNew->nOnes == (unsigned)pMan->nWordsRand * 32 ) + { + pMan->nSatZeros++; + if ( !pMan->fDoSparse ) // if we do not do sparse functions, skip + return pNodeNew; + // check the sparse function simulation hash table + pNodeOld = Fraig_HashTableLookupF0( pMan, pNodeNew ); + if ( pNodeOld == NULL ) // the node is unique (it is added to the table) + return pNodeNew; + } + else + { + // check the simulation hash table + pNodeOld = Fraig_HashTableLookupF( pMan, pNodeNew ); + if ( pNodeOld == NULL ) // the node is unique + return pNodeNew; + } + assert( pNodeOld->pRepr == 0 ); + // there is another node which looks the same according to simulation + + // use SAT to resolve the ambiguity + fUseSatCheck = (pMan->nInspLimit == 0 || Fraig_ManReadInspects(pMan) < pMan->nInspLimit); + if ( fUseSatCheck && Fraig_NodeIsEquivalent( pMan, pNodeOld, pNodeNew, pMan->nBTLimit, 1000000 ) ) + { + // set the node to be equivalent with this node + // to prevent loops, only set if the old node is not in the TFI of the new node + // the loop may happen in the following case: suppose + // NodeC = AND(NodeA, NodeB) and at the same time NodeA => NodeB + // in this case, NodeA and NodeC are functionally equivalent + // however, NodeA is a fanin of node NodeC (this leads to the loop) + // add the node to the list of equivalent nodes or dereference it + if ( pMan->fChoicing && !Fraig_CheckTfi( pMan, pNodeOld, pNodeNew ) ) + { + // if the old node is not in the TFI of the new node and choicing + // is enabled, add the new node to the list of equivalent ones + pNodeNew->pNextE = pNodeOld->pNextE; + pNodeOld->pNextE = pNodeNew; + } + // set the canonical representative of this node + pNodeNew->pRepr = pNodeOld; + // return the equivalent node + return Fraig_NotCond( pNodeOld, Fraig_NodeComparePhase(pNodeOld, pNodeNew) ); + } + + // now we add another member to this simulation class + if ( pNodeNew->nOnes == 0 || pNodeNew->nOnes == (unsigned)pMan->nWordsRand * 32 ) + { + Fraig_Node_t * pNodeTemp; + assert( pMan->fDoSparse ); + pNodeTemp = Fraig_HashTableLookupF0( pMan, pNodeNew ); +// assert( pNodeTemp == NULL ); +// Fraig_HashTableInsertF0( pMan, pNodeNew ); + } + else + { + pNodeNew->pNextD = pNodeOld->pNextD; + pNodeOld->pNextD = pNodeNew; + } + // return the new node + assert( pNodeNew->pRepr == 0 ); + return pNodeNew; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fraig/fraigChoice.c b/src/proof/fraig/fraigChoice.c new file mode 100644 index 00000000..21d4fe10 --- /dev/null +++ b/src/proof/fraig/fraigChoice.c @@ -0,0 +1,246 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fraig/fraigFanout.c b/src/proof/fraig/fraigFanout.c new file mode 100644 index 00000000..0e6c86f8 --- /dev/null +++ b/src/proof/fraig/fraigFanout.c @@ -0,0 +1,180 @@ +/**CFile**************************************************************** + + FileName [fraigFanout.c] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [Procedures to manipulate fanouts of the FRAIG nodes.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - October 1, 2004] + + Revision [$Id: fraigFanout.c,v 1.5 2005/07/08 01:01:31 alanmi Exp $] + +***********************************************************************/ + +#include "fraigInt.h" + +ABC_NAMESPACE_IMPL_START + + +#ifdef FRAIG_ENABLE_FANOUTS + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Add the fanout to the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeAddFaninFanout( Fraig_Node_t * pFanin, Fraig_Node_t * pFanout ) +{ + Fraig_Node_t * pPivot; + + // pFanins is a fanin of pFanout + assert( !Fraig_IsComplement(pFanin) ); + assert( !Fraig_IsComplement(pFanout) ); + assert( Fraig_Regular(pFanout->p1) == pFanin || Fraig_Regular(pFanout->p2) == pFanin ); + + pPivot = pFanin->pFanPivot; + if ( pPivot == NULL ) + { + pFanin->pFanPivot = pFanout; + return; + } + + if ( Fraig_Regular(pPivot->p1) == pFanin ) + { + if ( Fraig_Regular(pFanout->p1) == pFanin ) + { + pFanout->pFanFanin1 = pPivot->pFanFanin1; + pPivot->pFanFanin1 = pFanout; + } + else // if ( Fraig_Regular(pFanout->p2) == pFanin ) + { + pFanout->pFanFanin2 = pPivot->pFanFanin1; + pPivot->pFanFanin1 = pFanout; + } + } + else // if ( Fraig_Regular(pPivot->p2) == pFanin ) + { + assert( Fraig_Regular(pPivot->p2) == pFanin ); + if ( Fraig_Regular(pFanout->p1) == pFanin ) + { + pFanout->pFanFanin1 = pPivot->pFanFanin2; + pPivot->pFanFanin2 = pFanout; + } + else // if ( Fraig_Regular(pFanout->p2) == pFanin ) + { + pFanout->pFanFanin2 = pPivot->pFanFanin2; + pPivot->pFanFanin2 = pFanout; + } + } +} + +/**Function************************************************************* + + Synopsis [Add the fanout to the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeRemoveFaninFanout( Fraig_Node_t * pFanin, Fraig_Node_t * pFanoutToRemove ) +{ + Fraig_Node_t * pFanout, * pFanout2, ** ppFanList; + // start the linked list of fanouts + ppFanList = &pFanin->pFanPivot; + // go through the fanouts + Fraig_NodeForEachFanoutSafe( pFanin, pFanout, pFanout2 ) + { + // skip the fanout-to-remove + if ( pFanout == pFanoutToRemove ) + continue; + // add useful fanouts to the list + *ppFanList = pFanout; + ppFanList = Fraig_NodeReadNextFanoutPlace( pFanin, pFanout ); + } + *ppFanList = NULL; +} + +/**Function************************************************************* + + Synopsis [Transfers fanout to a different node.] + + Description [Assumes that the other node currently has no fanouts.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeTransferFanout( Fraig_Node_t * pNodeFrom, Fraig_Node_t * pNodeTo ) +{ + Fraig_Node_t * pFanout; + assert( pNodeTo->pFanPivot == NULL ); + assert( pNodeTo->pFanFanin1 == NULL ); + assert( pNodeTo->pFanFanin2 == NULL ); + // go through the fanouts and update their fanins + Fraig_NodeForEachFanout( pNodeFrom, pFanout ) + { + if ( Fraig_Regular(pFanout->p1) == pNodeFrom ) + pFanout->p1 = Fraig_NotCond( pNodeTo, Fraig_IsComplement(pFanout->p1) ); + else if ( Fraig_Regular(pFanout->p2) == pNodeFrom ) + pFanout->p2 = Fraig_NotCond( pNodeTo, Fraig_IsComplement(pFanout->p2) ); + } + // move the pointers + pNodeTo->pFanPivot = pNodeFrom->pFanPivot; + pNodeTo->pFanFanin1 = pNodeFrom->pFanFanin1; + pNodeTo->pFanFanin2 = pNodeFrom->pFanFanin2; + pNodeFrom->pFanPivot = NULL; + pNodeFrom->pFanFanin1 = NULL; + pNodeFrom->pFanFanin2 = NULL; +} + +/**Function************************************************************* + + Synopsis [Returns the number of fanouts of a node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeGetFanoutNum( Fraig_Node_t * pNode ) +{ + Fraig_Node_t * pFanout; + int Counter = 0; + Fraig_NodeForEachFanout( pNode, pFanout ) + Counter++; + return Counter; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +#endif + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fraig/fraigFeed.c b/src/proof/fraig/fraigFeed.c new file mode 100644 index 00000000..47f946e1 --- /dev/null +++ b/src/proof/fraig/fraigFeed.c @@ -0,0 +1,913 @@ +/**CFile**************************************************************** + + FileName [fraigFeed.c] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [Procedures to support the solver feedback.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - October 1, 2004] + + Revision [$Id: fraigFeed.c,v 1.8 2005/07/08 01:01:31 alanmi Exp $] + +***********************************************************************/ + +#include "fraigInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Fraig_FeedBackPrepare( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars ); +static int Fraig_FeedBackInsert( Fraig_Man_t * p, int nVarsPi ); +static void Fraig_FeedBackVerify( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); + +static void Fraig_FeedBackCovering( Fraig_Man_t * p, Msat_IntVec_t * vPats ); +static Fraig_NodeVec_t * Fraig_FeedBackCoveringStart( Fraig_Man_t * pMan ); +static int Fraig_GetSmallestColumn( int * pHits, int nHits ); +static int Fraig_GetHittingPattern( unsigned * pSims, int nWords ); +static void Fraig_CancelCoveredColumns( Fraig_NodeVec_t * vColumns, int * pHits, int iPat ); +static void Fraig_FeedBackCheckTable( Fraig_Man_t * p ); +static void Fraig_FeedBackCheckTableF0( Fraig_Man_t * p ); +static void Fraig_ReallocateSimulationInfo( Fraig_Man_t * p ); + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Initializes the feedback information.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_FeedBackInit( Fraig_Man_t * p ) +{ + p->vCones = Fraig_NodeVecAlloc( 500 ); + p->vPatsReal = Msat_IntVecAlloc( 1000 ); + p->pSimsReal = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); + memset( p->pSimsReal, 0, sizeof(unsigned) * p->nWordsDyna ); + p->pSimsTemp = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); + p->pSimsDiff = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); +} + +/**Function************************************************************* + + Synopsis [Processes the feedback from teh solver.] + + Description [Array pModel gives the value of each variable in the SAT + solver. Array vVars is the array of integer numbers of variables + involves in this conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_FeedBack( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) +{ + int nVarsPi, nWords; + int i, clk = clock(); + + // get the number of PI vars in the feedback (also sets the PI values) + nVarsPi = Fraig_FeedBackPrepare( p, pModel, vVars ); + + // set the PI values + nWords = Fraig_FeedBackInsert( p, nVarsPi ); + assert( p->iWordStart + nWords <= p->nWordsDyna ); + + // resimulates the words from p->iWordStart to iWordStop + for ( i = 1; i < p->vNodes->nSize; i++ ) + if ( Fraig_NodeIsAnd(p->vNodes->pArray[i]) ) + Fraig_NodeSimulate( p->vNodes->pArray[i], p->iWordStart, p->iWordStart + nWords, 0 ); + + if ( p->fDoSparse ) + Fraig_TableRehashF0( p, 0 ); + + if ( !p->fChoicing ) + Fraig_FeedBackVerify( p, pOld, pNew ); + + // if there is no room left, compress the patterns + if ( p->iWordStart + nWords == p->nWordsDyna ) + p->iWordStart = Fraig_FeedBackCompress( p ); + else // otherwise, update the starting word + p->iWordStart += nWords; + +p->timeFeed += clock() - clk; +} + +/**Function************************************************************* + + Synopsis [Get the number and values of the PI variables.] + + Description [Returns the number of PI variables involved in this feedback. + Fills in the internal presence and value data for the primary inputs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_FeedBackPrepare( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars ) +{ + Fraig_Node_t * pNode; + int i, nVars, nVarsPis, * pVars; + + // clean the presence flag for all PIs + for ( i = 0; i < p->vInputs->nSize; i++ ) + { + pNode = p->vInputs->pArray[i]; + pNode->fFeedUse = 0; + } + + // get the variables involved in the feedback + nVars = Msat_IntVecReadSize(vVars); + pVars = Msat_IntVecReadArray(vVars); + + // set the values for the present variables + nVarsPis = 0; + for ( i = 0; i < nVars; i++ ) + { + pNode = p->vNodes->pArray[ pVars[i] ]; + if ( !Fraig_NodeIsVar(pNode) ) + continue; + // set its value + pNode->fFeedUse = 1; + pNode->fFeedVal = !MSAT_LITSIGN(pModel[pVars[i]]); + nVarsPis++; + } + return nVarsPis; +} + +/**Function************************************************************* + + Synopsis [Inserts the new simulation patterns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_FeedBackInsert( Fraig_Man_t * p, int nVarsPi ) +{ + Fraig_Node_t * pNode; + int nWords, iPatFlip, nPatFlipLimit, i, w; + int fUseNoPats = 0; + int fUse2Pats = 0; + + // get the number of words + if ( fUse2Pats ) + nWords = FRAIG_NUM_WORDS( 2 * nVarsPi + 1 ); + else if ( fUseNoPats ) + nWords = 1; + else + nWords = FRAIG_NUM_WORDS( nVarsPi + 1 ); + // update the number of words if they do not fit into the simulation info + if ( nWords > p->nWordsDyna - p->iWordStart ) + nWords = p->nWordsDyna - p->iWordStart; + // determine the bound on the flipping bit + nPatFlipLimit = nWords * 32 - 2; + + // mark the real pattern + Msat_IntVecPush( p->vPatsReal, p->iWordStart * 32 ); + // record the real pattern + Fraig_BitStringSetBit( p->pSimsReal, p->iWordStart * 32 ); + + // set the values at the PIs + iPatFlip = 1; + for ( i = 0; i < p->vInputs->nSize; i++ ) + { + pNode = p->vInputs->pArray[i]; + for ( w = p->iWordStart; w < p->iWordStart + nWords; w++ ) + if ( !pNode->fFeedUse ) + pNode->puSimD[w] = FRAIG_RANDOM_UNSIGNED; + else if ( pNode->fFeedVal ) + pNode->puSimD[w] = FRAIG_FULL; + else // if ( !pNode->fFeedVal ) + pNode->puSimD[w] = 0; + + if ( fUse2Pats ) + { + // flip two patterns + if ( pNode->fFeedUse && 2 * iPatFlip < nPatFlipLimit ) + { + Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, 2 * iPatFlip - 1 ); + Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, 2 * iPatFlip ); + Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, 2 * iPatFlip + 1 ); + iPatFlip++; + } + } + else if ( fUseNoPats ) + { + } + else + { + // flip the diagonal + if ( pNode->fFeedUse && iPatFlip < nPatFlipLimit ) + { + Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, iPatFlip ); + iPatFlip++; + // Extra_PrintBinary( stdout, &pNode->puSimD, 45 ); printf( "\n" ); + } + } + // clean the use mask + pNode->fFeedUse = 0; + + // add the info to the D hash value of the PIs + for ( w = p->iWordStart; w < p->iWordStart + nWords; w++ ) + pNode->uHashD ^= pNode->puSimD[w] * s_FraigPrimes[w]; + + } + return nWords; +} + + +/**Function************************************************************* + + Synopsis [Checks that the SAT solver pattern indeed distinquishes the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_FeedBackVerify( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) +{ + int fValue1, fValue2, iPat; + iPat = Msat_IntVecReadEntry( p->vPatsReal, Msat_IntVecReadSize(p->vPatsReal)-1 ); + fValue1 = (Fraig_BitStringHasBit( pOld->puSimD, iPat )); + fValue2 = (Fraig_BitStringHasBit( pNew->puSimD, iPat )); +/* +Fraig_PrintNode( p, pOld ); +printf( "\n" ); +Fraig_PrintNode( p, pNew ); +printf( "\n" ); +*/ +// assert( fValue1 != fValue2 ); +} + +/**Function************************************************************* + + Synopsis [Compress the simulation patterns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_FeedBackCompress( Fraig_Man_t * p ) +{ + unsigned * pSims; + unsigned uHash; + int i, w, t, nPats, * pPats; + int fPerformChecks = (p->nBTLimit == -1); + + // solve the covering problem + if ( fPerformChecks ) + { + Fraig_FeedBackCheckTable( p ); + if ( p->fDoSparse ) + Fraig_FeedBackCheckTableF0( p ); + } + + // solve the covering problem + Fraig_FeedBackCovering( p, p->vPatsReal ); + + + // get the number of additional patterns + nPats = Msat_IntVecReadSize( p->vPatsReal ); + pPats = Msat_IntVecReadArray( p->vPatsReal ); + // get the new starting word + p->iWordStart = FRAIG_NUM_WORDS( p->iPatsPerm + nPats ); + + // set the simulation info for the PIs + for ( i = 0; i < p->vInputs->nSize; i++ ) + { + // get hold of the simulation info for this PI + pSims = p->vInputs->pArray[i]->puSimD; + // clean the storage for the new patterns + for ( w = p->iWordPerm; w < p->iWordStart; w++ ) + p->pSimsTemp[w] = 0; + // set the patterns + for ( t = 0; t < nPats; t++ ) + if ( Fraig_BitStringHasBit( pSims, pPats[t] ) ) + { + // check if this pattern falls into temporary storage + if ( p->iPatsPerm + t < p->iWordPerm * 32 ) + Fraig_BitStringSetBit( pSims, p->iPatsPerm + t ); + else + Fraig_BitStringSetBit( p->pSimsTemp, p->iPatsPerm + t ); + } + // copy the pattern + for ( w = p->iWordPerm; w < p->iWordStart; w++ ) + pSims[w] = p->pSimsTemp[w]; + // recompute the hashing info + uHash = 0; + for ( w = 0; w < p->iWordStart; w++ ) + uHash ^= pSims[w] * s_FraigPrimes[w]; + p->vInputs->pArray[i]->uHashD = uHash; + } + + // update info about the permanently stored patterns + p->iWordPerm = p->iWordStart; + p->iPatsPerm += nPats; + assert( p->iWordPerm == FRAIG_NUM_WORDS( p->iPatsPerm ) ); + + // resimulate and recompute the hash values + for ( i = 1; i < p->vNodes->nSize; i++ ) + if ( Fraig_NodeIsAnd(p->vNodes->pArray[i]) ) + { + p->vNodes->pArray[i]->uHashD = 0; + Fraig_NodeSimulate( p->vNodes->pArray[i], 0, p->iWordPerm, 0 ); + } + + // double-check that the nodes are still distinguished + if ( fPerformChecks ) + Fraig_FeedBackCheckTable( p ); + + // rehash the values in the F0 table + if ( p->fDoSparse ) + { + Fraig_TableRehashF0( p, 0 ); + if ( fPerformChecks ) + Fraig_FeedBackCheckTableF0( p ); + } + + // check if we need to resize the simulation info + // if less than FRAIG_WORDS_STORE words are left, reallocate simulation info + if ( p->iWordPerm + FRAIG_WORDS_STORE > p->nWordsDyna ) + Fraig_ReallocateSimulationInfo( p ); + + // set the real patterns + Msat_IntVecClear( p->vPatsReal ); + memset( p->pSimsReal, 0, sizeof(unsigned)*p->nWordsDyna ); + for ( w = 0; w < p->iWordPerm; w++ ) + p->pSimsReal[w] = FRAIG_FULL; + if ( p->iPatsPerm % 32 > 0 ) + p->pSimsReal[p->iWordPerm-1] = FRAIG_MASK( p->iPatsPerm % 32 ); +// printf( "The number of permanent words = %d.\n", p->iWordPerm ); + return p->iWordStart; +} + + + + +/**Function************************************************************* + + Synopsis [Checks the correctness of the functional simulation table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_FeedBackCovering( Fraig_Man_t * p, Msat_IntVec_t * vPats ) +{ + Fraig_NodeVec_t * vColumns; + unsigned * pSims; + int * pHits, iPat, iCol, i; + int nOnesTotal, nSolStarting; + int fVeryVerbose = 0; + + // collect the pairs to be distinguished + vColumns = Fraig_FeedBackCoveringStart( p ); + // collect the number of 1s in each simulation vector + nOnesTotal = 0; + pHits = ABC_ALLOC( int, vColumns->nSize ); + for ( i = 0; i < vColumns->nSize; i++ ) + { + pSims = (unsigned *)vColumns->pArray[i]; + pHits[i] = Fraig_BitStringCountOnes( pSims, p->iWordStart ); + nOnesTotal += pHits[i]; +// assert( pHits[i] > 0 ); + } + + // go through the patterns + nSolStarting = Msat_IntVecReadSize(vPats); + while ( (iCol = Fraig_GetSmallestColumn( pHits, vColumns->nSize )) != -1 ) + { + // find the pattern, which hits this column + iPat = Fraig_GetHittingPattern( (unsigned *)vColumns->pArray[iCol], p->iWordStart ); + // cancel the columns covered by this pattern + Fraig_CancelCoveredColumns( vColumns, pHits, iPat ); + // save the pattern + Msat_IntVecPush( vPats, iPat ); + } + + // free the set of columns + for ( i = 0; i < vColumns->nSize; i++ ) + Fraig_MemFixedEntryRecycle( p->mmSims, (char *)vColumns->pArray[i] ); + + // print stats related to the covering problem + if ( p->fVerbose && fVeryVerbose ) + { + printf( "%3d\\%3d\\%3d ", p->nWordsRand, p->nWordsDyna, p->iWordPerm ); + printf( "Col (pairs) = %5d. ", vColumns->nSize ); + printf( "Row (pats) = %5d. ", p->iWordStart * 32 ); + printf( "Dns = %6.2f %%. ", vColumns->nSize==0? 0.0 : 100.0 * nOnesTotal / vColumns->nSize / p->iWordStart / 32 ); + printf( "Sol = %3d (%3d). ", Msat_IntVecReadSize(vPats), nSolStarting ); + printf( "\n" ); + } + Fraig_NodeVecFree( vColumns ); + ABC_FREE( pHits ); +} + + +/**Function************************************************************* + + Synopsis [Checks the correctness of the functional simulation table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_NodeVec_t * Fraig_FeedBackCoveringStart( Fraig_Man_t * p ) +{ + Fraig_NodeVec_t * vColumns; + Fraig_HashTable_t * pT = p->pTableF; + Fraig_Node_t * pEntF, * pEntD; + unsigned * pSims; + unsigned * pUnsigned1, * pUnsigned2; + int i, k, m, w;//, nOnes; + + // start the set of columns + vColumns = Fraig_NodeVecAlloc( 100 ); + + // go through the pairs of nodes to be distinguished + for ( i = 0; i < pT->nBins; i++ ) + Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) + { + p->vCones->nSize = 0; + Fraig_TableBinForEachEntryD( pEntF, pEntD ) + Fraig_NodeVecPush( p->vCones, pEntD ); + if ( p->vCones->nSize == 1 ) + continue; + //////////////////////////////// bug fix by alanmi, September 14, 2006 + if ( p->vCones->nSize > 20 ) + continue; + //////////////////////////////// + + for ( k = 0; k < p->vCones->nSize; k++ ) + for ( m = k+1; m < p->vCones->nSize; m++ ) + { + if ( !Fraig_CompareSimInfoUnderMask( p->vCones->pArray[k], p->vCones->pArray[m], p->iWordStart, 0, p->pSimsReal ) ) + continue; + + // primary simulation patterns (counter-examples) cannot distinguish this pair + // get memory to store the feasible simulation patterns + pSims = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); + // find the pattern that distinguish this column, exept the primary ones + pUnsigned1 = p->vCones->pArray[k]->puSimD; + pUnsigned2 = p->vCones->pArray[m]->puSimD; + for ( w = 0; w < p->iWordStart; w++ ) + pSims[w] = (pUnsigned1[w] ^ pUnsigned2[w]) & ~p->pSimsReal[w]; + // store the pattern + Fraig_NodeVecPush( vColumns, (Fraig_Node_t *)pSims ); +// nOnes = Fraig_BitStringCountOnes(pSims, p->iWordStart); +// assert( nOnes > 0 ); + } + } + + // if the flag is not set, do not consider sparse nodes in p->pTableF0 + if ( !p->fDoSparse ) + return vColumns; + + // recalculate their hash values based on p->pSimsReal + pT = p->pTableF0; + for ( i = 0; i < pT->nBins; i++ ) + Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) + { + pSims = pEntF->puSimD; + pEntF->uHashD = 0; + for ( w = 0; w < p->iWordStart; w++ ) + pEntF->uHashD ^= (pSims[w] & p->pSimsReal[w]) * s_FraigPrimes[w]; + } + + // rehash the table using these values + Fraig_TableRehashF0( p, 1 ); + + // collect the classes of equivalent node pairs + for ( i = 0; i < pT->nBins; i++ ) + Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) + { + p->vCones->nSize = 0; + Fraig_TableBinForEachEntryD( pEntF, pEntD ) + Fraig_NodeVecPush( p->vCones, pEntD ); + if ( p->vCones->nSize == 1 ) + continue; + + // primary simulation patterns (counter-examples) cannot distinguish all these pairs + for ( k = 0; k < p->vCones->nSize; k++ ) + for ( m = k+1; m < p->vCones->nSize; m++ ) + { + // get memory to store the feasible simulation patterns + pSims = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); + // find the patterns that are not distinquished + pUnsigned1 = p->vCones->pArray[k]->puSimD; + pUnsigned2 = p->vCones->pArray[m]->puSimD; + for ( w = 0; w < p->iWordStart; w++ ) + pSims[w] = (pUnsigned1[w] ^ pUnsigned2[w]) & ~p->pSimsReal[w]; + // store the pattern + Fraig_NodeVecPush( vColumns, (Fraig_Node_t *)pSims ); +// nOnes = Fraig_BitStringCountOnes(pSims, p->iWordStart); +// assert( nOnes > 0 ); + } + } + return vColumns; +} + +/**Function************************************************************* + + Synopsis [Selects the column, which has the smallest number of hits.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_GetSmallestColumn( int * pHits, int nHits ) +{ + int i, iColMin = -1, nHitsMin = 1000000; + for ( i = 0; i < nHits; i++ ) + { + // skip covered columns + if ( pHits[i] == 0 ) + continue; + // take the column if it can only be covered by one pattern + if ( pHits[i] == 1 ) + return i; + // find the column, which requires the smallest number of patterns + if ( nHitsMin > pHits[i] ) + { + nHitsMin = pHits[i]; + iColMin = i; + } + } + return iColMin; +} + +/**Function************************************************************* + + Synopsis [Select the pattern, which hits this column.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_GetHittingPattern( unsigned * pSims, int nWords ) +{ + int i, b; + for ( i = 0; i < nWords; i++ ) + { + if ( pSims[i] == 0 ) + continue; + for ( b = 0; b < 32; b++ ) + if ( pSims[i] & (1 << b) ) + return i * 32 + b; + } + return -1; +} + +/**Function************************************************************* + + Synopsis [Cancel covered patterns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_CancelCoveredColumns( Fraig_NodeVec_t * vColumns, int * pHits, int iPat ) +{ + unsigned * pSims; + int i; + for ( i = 0; i < vColumns->nSize; i++ ) + { + pSims = (unsigned *)vColumns->pArray[i]; + if ( Fraig_BitStringHasBit( pSims, iPat ) ) + pHits[i] = 0; + } +} + + +/**Function************************************************************* + + Synopsis [Checks the correctness of the functional simulation table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_FeedBackCheckTable( Fraig_Man_t * p ) +{ + Fraig_HashTable_t * pT = p->pTableF; + Fraig_Node_t * pEntF, * pEntD; + int i, k, m, nPairs; + + nPairs = 0; + for ( i = 0; i < pT->nBins; i++ ) + Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) + { + p->vCones->nSize = 0; + Fraig_TableBinForEachEntryD( pEntF, pEntD ) + Fraig_NodeVecPush( p->vCones, pEntD ); + if ( p->vCones->nSize == 1 ) + continue; + for ( k = 0; k < p->vCones->nSize; k++ ) + for ( m = k+1; m < p->vCones->nSize; m++ ) + { + if ( Fraig_CompareSimInfo( p->vCones->pArray[k], p->vCones->pArray[m], p->iWordStart, 0 ) ) + printf( "Nodes %d and %d have the same D simulation info.\n", + p->vCones->pArray[k]->Num, p->vCones->pArray[m]->Num ); + nPairs++; + } + } +// printf( "\nThe total of %d node pairs have been verified.\n", nPairs ); +} + +/**Function************************************************************* + + Synopsis [Checks the correctness of the functional simulation table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_FeedBackCheckTableF0( Fraig_Man_t * p ) +{ + Fraig_HashTable_t * pT = p->pTableF0; + Fraig_Node_t * pEntF; + int i, k, m, nPairs; + + nPairs = 0; + for ( i = 0; i < pT->nBins; i++ ) + { + p->vCones->nSize = 0; + Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) + Fraig_NodeVecPush( p->vCones, pEntF ); + if ( p->vCones->nSize == 1 ) + continue; + for ( k = 0; k < p->vCones->nSize; k++ ) + for ( m = k+1; m < p->vCones->nSize; m++ ) + { + if ( Fraig_CompareSimInfo( p->vCones->pArray[k], p->vCones->pArray[m], p->iWordStart, 0 ) ) + printf( "Nodes %d and %d have the same D simulation info.\n", + p->vCones->pArray[k]->Num, p->vCones->pArray[m]->Num ); + nPairs++; + } + } +// printf( "\nThe total of %d node pairs have been verified.\n", nPairs ); +} + +/**Function************************************************************* + + Synopsis [Doubles the size of simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_ReallocateSimulationInfo( Fraig_Man_t * p ) +{ + Fraig_MemFixed_t * mmSimsNew; // new memory manager for simulation info + Fraig_Node_t * pNode; + unsigned * pSimsNew; + unsigned uSignOld; + int i; + + // allocate a new memory manager + p->nWordsDyna *= 2; + mmSimsNew = Fraig_MemFixedStart( sizeof(unsigned) * (p->nWordsRand + p->nWordsDyna) ); + + // set the new data for the constant node + pNode = p->pConst1; + pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); + pNode->puSimD = pNode->puSimR + p->nWordsRand; + memset( pNode->puSimR, 0, sizeof(unsigned) * p->nWordsRand ); + memset( pNode->puSimD, 0, sizeof(unsigned) * p->nWordsDyna ); + + // copy the simulation info of the PIs + for ( i = 0; i < p->vInputs->nSize; i++ ) + { + pNode = p->vInputs->pArray[i]; + // copy the simulation info + pSimsNew = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); + memmove( pSimsNew, pNode->puSimR, sizeof(unsigned) * (p->nWordsRand + p->iWordStart) ); + // attach the new info + pNode->puSimR = pSimsNew; + pNode->puSimD = pNode->puSimR + p->nWordsRand; + // signatures remain without changes + } + + // replace the manager to free up some memory + Fraig_MemFixedStop( p->mmSims, 0 ); + p->mmSims = mmSimsNew; + + // resimulate the internal nodes (this should lead to the same signatures) + for ( i = 1; i < p->vNodes->nSize; i++ ) + { + pNode = p->vNodes->pArray[i]; + if ( !Fraig_NodeIsAnd(pNode) ) + continue; + // allocate memory for the simulation info + pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); + pNode->puSimD = pNode->puSimR + p->nWordsRand; + // derive random simulation info + uSignOld = pNode->uHashR; + pNode->uHashR = 0; + Fraig_NodeSimulate( pNode, 0, p->nWordsRand, 1 ); + assert( uSignOld == pNode->uHashR ); + // derive dynamic simulation info + uSignOld = pNode->uHashD; + pNode->uHashD = 0; + Fraig_NodeSimulate( pNode, 0, p->iWordStart, 0 ); + assert( uSignOld == pNode->uHashD ); + } + + // realloc temporary storage + p->pSimsReal = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); + memset( p->pSimsReal, 0, sizeof(unsigned) * p->nWordsDyna ); + p->pSimsTemp = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); + p->pSimsDiff = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); +} + + +/**Function************************************************************* + + Synopsis [Generated trivial counter example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Fraig_ManAllocCounterExample( Fraig_Man_t * p ) +{ + int * pModel; + pModel = ABC_ALLOC( int, p->vInputs->nSize ); + memset( pModel, 0, sizeof(int) * p->vInputs->nSize ); + return pModel; +} + + +/**Function************************************************************* + + Synopsis [Saves the counter example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_ManSimulateBitNode_rec( Fraig_Man_t * p, Fraig_Node_t * pNode ) +{ + int Value0, Value1; + if ( Fraig_NodeIsTravIdCurrent( p, pNode ) ) + return pNode->fMark3; + Fraig_NodeSetTravIdCurrent( p, pNode ); + Value0 = Fraig_ManSimulateBitNode_rec( p, Fraig_Regular(pNode->p1) ); + Value1 = Fraig_ManSimulateBitNode_rec( p, Fraig_Regular(pNode->p2) ); + Value0 ^= Fraig_IsComplement(pNode->p1); + Value1 ^= Fraig_IsComplement(pNode->p2); + pNode->fMark3 = Value0 & Value1; + return pNode->fMark3; +} + +/**Function************************************************************* + + Synopsis [Simulates one bit.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_ManSimulateBitNode( Fraig_Man_t * p, Fraig_Node_t * pNode, int * pModel ) +{ + int fCompl, RetValue, i; + // set the PI values + Fraig_ManIncrementTravId( p ); + for ( i = 0; i < p->vInputs->nSize; i++ ) + { + Fraig_NodeSetTravIdCurrent( p, p->vInputs->pArray[i] ); + p->vInputs->pArray[i]->fMark3 = pModel[i]; + } + // perform the traversal + fCompl = Fraig_IsComplement(pNode); + RetValue = Fraig_ManSimulateBitNode_rec( p, Fraig_Regular(pNode) ); + return fCompl ^ RetValue; +} + + +/**Function************************************************************* + + Synopsis [Saves the counter example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Fraig_ManSaveCounterExample( Fraig_Man_t * p, Fraig_Node_t * pNode ) +{ + int * pModel; + int iPattern; + int i, fCompl; + + // the node can be complemented + fCompl = Fraig_IsComplement(pNode); + // because we compare with constant 0, p->pConst1 should also be complemented + fCompl = !fCompl; + + // derive the model + pModel = Fraig_ManAllocCounterExample( p ); + iPattern = Fraig_FindFirstDiff( p->pConst1, Fraig_Regular(pNode), fCompl, p->nWordsRand, 1 ); + if ( iPattern >= 0 ) + { + for ( i = 0; i < p->vInputs->nSize; i++ ) + if ( Fraig_BitStringHasBit( p->vInputs->pArray[i]->puSimR, iPattern ) ) + pModel[i] = 1; +/* +printf( "SAT solver's pattern:\n" ); +for ( i = 0; i < p->vInputs->nSize; i++ ) + printf( "%d", pModel[i] ); +printf( "\n" ); +*/ + assert( Fraig_ManSimulateBitNode( p, pNode, pModel ) ); + return pModel; + } + iPattern = Fraig_FindFirstDiff( p->pConst1, Fraig_Regular(pNode), fCompl, p->iWordStart, 0 ); + if ( iPattern >= 0 ) + { + for ( i = 0; i < p->vInputs->nSize; i++ ) + if ( Fraig_BitStringHasBit( p->vInputs->pArray[i]->puSimD, iPattern ) ) + pModel[i] = 1; +/* +printf( "SAT solver's pattern:\n" ); +for ( i = 0; i < p->vInputs->nSize; i++ ) + printf( "%d", pModel[i] ); +printf( "\n" ); +*/ + assert( Fraig_ManSimulateBitNode( p, pNode, pModel ) ); + return pModel; + } + ABC_FREE( pModel ); + return NULL; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fraig/fraigInt.h b/src/proof/fraig/fraigInt.h new file mode 100644 index 00000000..f6a5d74f --- /dev/null +++ b/src/proof/fraig/fraigInt.h @@ -0,0 +1,433 @@ +/**CFile**************************************************************** + + FileName [fraigInt.h] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [Internal declarations of the FRAIG package.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - October 1, 2004] + + Revision [$Id: fraigInt.h,v 1.15 2005/07/08 01:01:31 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__sat__fraig__fraigInt_h +#define ABC__sat__fraig__fraigInt_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + +#include "src/misc/util/abc_global.h" +#include "fraig.h" +#include "src/sat/msat/msat.h" + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +/* + The AIG node policy: + - Each node has its main number (pNode->Num) + This is the number of this node in the array of all nodes and its SAT variable number + - The PI nodes are stored along with other nodes + Additionally, PI nodes have a PI number, by which they are stored in the PI node array + - The constant node is has number 0 and is also stored in the array +*/ + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +// enable this macro to support the fanouts +#define FRAIG_ENABLE_FANOUTS +#define FRAIG_PATTERNS_RANDOM 2048 // should not be less than 128 and more than 32768 (2^15) +#define FRAIG_PATTERNS_DYNAMIC 2048 // should not be less than 256 and more than 32768 (2^15) +#define FRAIG_MAX_PRIMES 1024 // the maximum number of primes used for hashing + +// this parameter determines when simulation info is extended +// it will be extended when the free storage in the dynamic simulation +// info is less or equal to this number of words (FRAIG_WORDS_STORE) +// this is done because if the free storage for dynamic simulation info +// is not sufficient, computation becomes inefficient +#define FRAIG_WORDS_STORE 5 + +// the bit masks +#define FRAIG_MASK(n) ((~((unsigned)0)) >> (32-(n))) +#define FRAIG_FULL (~((unsigned)0)) +#define FRAIG_NUM_WORDS(n) (((n)>>5) + (((n)&31) > 0)) + +// generating random unsigned (#define RAND_MAX 0x7fff) +#define FRAIG_RANDOM_UNSIGNED ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand())) + +// macros to get hold of the bits in a bit string +#define Fraig_BitStringSetBit(p,i) ((p)[(i)>>5] |= (1<<((i) & 31))) +#define Fraig_BitStringXorBit(p,i) ((p)[(i)>>5] ^= (1<<((i) & 31))) +#define Fraig_BitStringHasBit(p,i) (((p)[(i)>>5] & (1<<((i) & 31))) > 0) + +// macros to get hold of the bits in the support info +//#define Fraig_NodeSetVarStr(p,i) (Fraig_Regular(p)->pSuppStr[((i)%FRAIG_SUPP_SIGN)>>5] |= (1<<(((i)%FRAIG_SUPP_SIGN) & 31))) +//#define Fraig_NodeHasVarStr(p,i) ((Fraig_Regular(p)->pSuppStr[((i)%FRAIG_SUPP_SIGN)>>5] & (1<<(((i)%FRAIG_SUPP_SIGN) & 31))) > 0) +#define Fraig_NodeSetVarStr(p,i) Fraig_BitStringSetBit(Fraig_Regular(p)->pSuppStr,i) +#define Fraig_NodeHasVarStr(p,i) Fraig_BitStringHasBit(Fraig_Regular(p)->pSuppStr,i) + +// copied from "extra.h" for stand-aloneness +#define Fraig_PrintTime(a,t) printf( "%s = ", (a) ); printf( "%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC) ) + +#define Fraig_HashKey2(a,b,TSIZE) (((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b) * 12582917) % TSIZE) +//#define Fraig_HashKey2(a,b,TSIZE) (( ((unsigned)(a)->Num * 19) ^ ((unsigned)(b)->Num * 1999) ) % TSIZE) +//#define Fraig_HashKey2(a,b,TSIZE) ( ((unsigned)((a)->Num + (b)->Num) * ((a)->Num + (b)->Num + 1) / 2) % TSIZE) +// the other two hash functions give bad distribution of hash chain lengths (not clear why) + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Fraig_MemFixed_t_ Fraig_MemFixed_t; + +// the mapping manager +struct Fraig_ManStruct_t_ +{ + // the AIG nodes + Fraig_NodeVec_t * vInputs; // the array of primary inputs + Fraig_NodeVec_t * vNodes; // the array of all nodes, including primary inputs + Fraig_NodeVec_t * vOutputs; // the array of primary outputs (some internal nodes) + Fraig_Node_t * pConst1; // the pointer to the constant node (vNodes->pArray[0]) + + // info about the original circuit + char ** ppInputNames; // the primary input names + char ** ppOutputNames; // the primary output names + + // various hash-tables + Fraig_HashTable_t * pTableS; // hashing by structure + Fraig_HashTable_t * pTableF; // hashing by simulation info + Fraig_HashTable_t * pTableF0; // hashing by simulation info (sparse functions) + + // parameters + int nWordsRand; // the number of words of random simulation info + int nWordsDyna; // the number of words of dynamic simulation info + int nBTLimit; // the max number of backtracks to perform + int nSeconds; // the runtime limit for the miter proof + int fFuncRed; // performs only one level hashing + int fFeedBack; // enables solver feedback + int fDist1Pats; // enables solver feedback + int fDoSparse; // performs equiv tests for sparse functions + int fChoicing; // enables recording structural choices + int fTryProve; // tries to solve the final miter + int fVerbose; // the verbosiness flag + int fVerboseP; // the verbosiness flag + ABC_INT64_T nInspLimit; // the inspection limit + + int nTravIds; // the traversal counter + int nTravIds2; // the traversal counter + + // info related to the solver feedback + int iWordStart; // the first word to use for simulation + int iWordPerm; // the number of words stored permanently + int iPatsPerm; // the number of patterns stored permanently + Fraig_NodeVec_t * vCones; // the temporary array of internal variables + Msat_IntVec_t * vPatsReal; // the array of real pattern numbers + unsigned * pSimsReal; // used for simulation patterns + unsigned * pSimsDiff; // used for simulation patterns + unsigned * pSimsTemp; // used for simulation patterns + + // the support information + int nSuppWords; + unsigned ** pSuppS; + unsigned ** pSuppF; + + // the memory managers + Fraig_MemFixed_t * mmNodes; // the memory manager for nodes + Fraig_MemFixed_t * mmSims; // the memory manager for simulation info + + // solving the SAT problem + Msat_Solver_t * pSat; // the SAT solver + Msat_IntVec_t * vProj; // the temporary array of projection vars + int nSatNums; // the counter of SAT variables + int * pModel; // the assignment, which satisfies the miter + // these arrays belong to the solver + Msat_IntVec_t * vVarsInt; // the temporary array of variables + Msat_ClauseVec_t * vAdjacents; // the temporary storage for connectivity + Msat_IntVec_t * vVarsUsed; // the array marking vars appearing in the cone + + // various statistic variables + int nSatCalls; // the number of times equivalence checking was called + int nSatProof; // the number of times a proof was found + int nSatCounter; // the number of times a counter example was found + int nSatFails; // the number of times the SAT solver failed to complete due to resource limit or prediction + int nSatFailsReal; // the number of times the SAT solver failed to complete due to resource limit + + int nSatCallsImp; // the number of times equivalence checking was called + int nSatProofImp; // the number of times a proof was found + int nSatCounterImp;// the number of times a counter example was found + int nSatFailsImp; // the number of times the SAT solver failed to complete + + int nSatZeros; // the number of times the simulation vector is zero + int nSatSupps; // the number of times the support info was useful + int nRefErrors; // the number of ref counting errors + int nImplies; // the number of implication cases + int nSatImpls; // the number of implication SAT calls + int nVarsClauses; // the number of variables with clauses + int nSimplifies0; + int nSimplifies1; + int nImplies0; + int nImplies1; + + // runtime statistics + int timeToAig; // time to transfer to the mapping structure + int timeSims; // time to compute k-feasible cuts + int timeTrav; // time to traverse the network + int timeFeed; // time for solver feedback (recording and resimulating) + int timeImply; // time to analyze implications + int timeSat; // time to compute the truth table for each cut + int timeToNet; // time to transfer back to the network + int timeTotal; // the total mapping time + int time1; // time to perform one task + int time2; // time to perform another task + int time3; // time to perform another task + int time4; // time to perform another task +}; + +// the mapping node +struct Fraig_NodeStruct_t_ +{ + // various numbers associated with the node + int Num; // the unique number (SAT var number) of this node + int NumPi; // if the node is a PI, this is its variable number + int Level; // the level of the node + int nRefs; // the number of references of the node + int TravId; // the traversal ID (use to avoid cleaning marks) + int TravId2; // the traversal ID (use to avoid cleaning marks) + + // general information about the node + unsigned fInv : 1; // the mark to show that simulation info is complemented + unsigned fNodePo : 1; // the mark used for primary outputs + unsigned fClauses : 1; // the clauses for this node are loaded + unsigned fMark0 : 1; // the mark used for traversals + unsigned fMark1 : 1; // the mark used for traversals + unsigned fMark2 : 1; // the mark used for traversals + unsigned fMark3 : 1; // the mark used for traversals + unsigned fFeedUse : 1; // the presence of the variable in the feedback + unsigned fFeedVal : 1; // the value of the variable in the feedback + unsigned fFailTfo : 1; // the node is in the TFO of the failed SAT run + unsigned nFanouts : 2; // the indicator of fanouts (none, one, or many) + unsigned nOnes : 20; // the number of 1's in the random sim info + + // the children of the node + Fraig_Node_t * p1; // the first child + Fraig_Node_t * p2; // the second child + Fraig_NodeVec_t * vFanins; // the fanins of the supergate rooted at this node +// Fraig_NodeVec_t * vFanouts; // the fanouts of the supergate rooted at this node + + // various linked lists + Fraig_Node_t * pNextS; // the next node in the structural hash table + Fraig_Node_t * pNextF; // the next node in the functional (simulation) hash table + Fraig_Node_t * pNextD; // the next node in the list of nodes based on dynamic simulation + Fraig_Node_t * pNextE; // the next structural choice (functionally-equivalent node) + Fraig_Node_t * pRepr; // the canonical functional representative of the node + + // simulation data + unsigned uHashR; // the hash value for random information + unsigned uHashD; // the hash value for dynamic information + unsigned * puSimR; // the simulation information (random) + unsigned * puSimD; // the simulation information (dynamic) + + // misc information + Fraig_Node_t * pData0; // temporary storage for the corresponding network node + Fraig_Node_t * pData1; // temporary storage for the corresponding network node + +#ifdef FRAIG_ENABLE_FANOUTS + // representation of node's fanouts + Fraig_Node_t * pFanPivot; // the first fanout of this node + Fraig_Node_t * pFanFanin1; // the next fanout of p1 + Fraig_Node_t * pFanFanin2; // the next fanout of p2 +#endif +}; + +// the vector of nodes +struct Fraig_NodeVecStruct_t_ +{ + int nCap; // the number of allocated entries + int nSize; // the number of entries in the array + Fraig_Node_t ** pArray; // the array of nodes +}; + +// the hash table +struct Fraig_HashTableStruct_t_ +{ + Fraig_Node_t ** pBins; // the table bins + int nBins; // the size of the table + int nEntries; // the total number of entries in the table +}; + +// getting hold of the next fanout of the node +#define Fraig_NodeReadNextFanout( pNode, pFanout ) \ + ( ( pFanout == NULL )? NULL : \ + ((Fraig_Regular((pFanout)->p1) == (pNode))? \ + (pFanout)->pFanFanin1 : (pFanout)->pFanFanin2) ) +// getting hold of the place where the next fanout will be attached +#define Fraig_NodeReadNextFanoutPlace( pNode, pFanout ) \ + ( (Fraig_Regular((pFanout)->p1) == (pNode))? \ + &(pFanout)->pFanFanin1 : &(pFanout)->pFanFanin2 ) +// iterator through the fanouts of the node +#define Fraig_NodeForEachFanout( pNode, pFanout ) \ + for ( pFanout = (pNode)->pFanPivot; pFanout; \ + pFanout = Fraig_NodeReadNextFanout(pNode, pFanout) ) +// safe iterator through the fanouts of the node +#define Fraig_NodeForEachFanoutSafe( pNode, pFanout, pFanout2 ) \ + for ( pFanout = (pNode)->pFanPivot, \ + pFanout2 = Fraig_NodeReadNextFanout(pNode, pFanout); \ + pFanout; \ + pFanout = pFanout2, \ + pFanout2 = Fraig_NodeReadNextFanout(pNode, pFanout) ) + +// iterators through the entries in the linked lists of nodes +// the list of nodes in the structural hash table +#define Fraig_TableBinForEachEntryS( pBin, pEnt ) \ + for ( pEnt = pBin; \ + pEnt; \ + pEnt = pEnt->pNextS ) +#define Fraig_TableBinForEachEntrySafeS( pBin, pEnt, pEnt2 ) \ + for ( pEnt = pBin, \ + pEnt2 = pEnt? pEnt->pNextS: NULL; \ + pEnt; \ + pEnt = pEnt2, \ + pEnt2 = pEnt? pEnt->pNextS: NULL ) +// the list of nodes in the functional (simulation) hash table +#define Fraig_TableBinForEachEntryF( pBin, pEnt ) \ + for ( pEnt = pBin; \ + pEnt; \ + pEnt = pEnt->pNextF ) +#define Fraig_TableBinForEachEntrySafeF( pBin, pEnt, pEnt2 ) \ + for ( pEnt = pBin, \ + pEnt2 = pEnt? pEnt->pNextF: NULL; \ + pEnt; \ + pEnt = pEnt2, \ + pEnt2 = pEnt? pEnt->pNextF: NULL ) +// the list of nodes with the same simulation and different functionality +#define Fraig_TableBinForEachEntryD( pBin, pEnt ) \ + for ( pEnt = pBin; \ + pEnt; \ + pEnt = pEnt->pNextD ) +#define Fraig_TableBinForEachEntrySafeD( pBin, pEnt, pEnt2 ) \ + for ( pEnt = pBin, \ + pEnt2 = pEnt? pEnt->pNextD: NULL; \ + pEnt; \ + pEnt = pEnt2, \ + pEnt2 = pEnt? pEnt->pNextD: NULL ) +// the list of nodes with the same functionality +#define Fraig_TableBinForEachEntryE( pBin, pEnt ) \ + for ( pEnt = pBin; \ + pEnt; \ + pEnt = pEnt->pNextE ) +#define Fraig_TableBinForEachEntrySafeE( pBin, pEnt, pEnt2 ) \ + for ( pEnt = pBin, \ + pEnt2 = pEnt? pEnt->pNextE: NULL; \ + pEnt; \ + pEnt = pEnt2, \ + pEnt2 = pEnt? pEnt->pNextE: NULL ) + +//////////////////////////////////////////////////////////////////////// +/// GLOBAL VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== fraigCanon.c =============================================================*/ +extern Fraig_Node_t * Fraig_NodeAndCanon( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2 ); +/*=== fraigFanout.c =============================================================*/ +extern void Fraig_NodeAddFaninFanout( Fraig_Node_t * pFanin, Fraig_Node_t * pFanout ); +extern void Fraig_NodeRemoveFaninFanout( Fraig_Node_t * pFanin, Fraig_Node_t * pFanoutToRemove ); +extern int Fraig_NodeGetFanoutNum( Fraig_Node_t * pNode ); +/*=== fraigFeed.c =============================================================*/ +extern void Fraig_FeedBackInit( Fraig_Man_t * p ); +extern void Fraig_FeedBack( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); +extern void Fraig_FeedBackTest( Fraig_Man_t * p ); +extern int Fraig_FeedBackCompress( Fraig_Man_t * p ); +extern int * Fraig_ManAllocCounterExample( Fraig_Man_t * p ); +extern int * Fraig_ManSaveCounterExample( Fraig_Man_t * p, Fraig_Node_t * pNode ); +/*=== fraigMan.c =============================================================*/ +extern void Fraig_ManCreateSolver( Fraig_Man_t * p ); +/*=== fraigMem.c =============================================================*/ +extern Fraig_MemFixed_t * Fraig_MemFixedStart( int nEntrySize ); +extern void Fraig_MemFixedStop( Fraig_MemFixed_t * p, int fVerbose ); +extern char * Fraig_MemFixedEntryFetch( Fraig_MemFixed_t * p ); +extern void Fraig_MemFixedEntryRecycle( Fraig_MemFixed_t * p, char * pEntry ); +extern void Fraig_MemFixedRestart( Fraig_MemFixed_t * p ); +extern int Fraig_MemFixedReadMemUsage( Fraig_MemFixed_t * p ); +/*=== fraigNode.c =============================================================*/ +extern Fraig_Node_t * Fraig_NodeCreateConst( Fraig_Man_t * p ); +extern Fraig_Node_t * Fraig_NodeCreatePi( Fraig_Man_t * p ); +extern Fraig_Node_t * Fraig_NodeCreate( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ); +extern void Fraig_NodeSimulate( Fraig_Node_t * pNode, int iWordStart, int iWordStop, int fUseRand ); +/*=== fraigPrime.c =============================================================*/ +extern int s_FraigPrimes[FRAIG_MAX_PRIMES]; +/*=== fraigSat.c ===============================================================*/ +extern int Fraig_NodeIsImplication( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit ); +/*=== fraigTable.c =============================================================*/ +extern Fraig_HashTable_t * Fraig_HashTableCreate( int nSize ); +extern void Fraig_HashTableFree( Fraig_HashTable_t * p ); +extern int Fraig_HashTableLookupS( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2, Fraig_Node_t ** ppNodeRes ); +extern Fraig_Node_t * Fraig_HashTableLookupF( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); +extern Fraig_Node_t * Fraig_HashTableLookupF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); +extern void Fraig_HashTableInsertF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); +extern int Fraig_CompareSimInfo( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand ); +extern int Fraig_CompareSimInfoUnderMask( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask ); +extern int Fraig_FindFirstDiff( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int fCompl, int iWordLast, int fUseRand ); +extern void Fraig_CollectXors( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask ); +extern void Fraig_TablePrintStatsS( Fraig_Man_t * pMan ); +extern void Fraig_TablePrintStatsF( Fraig_Man_t * pMan ); +extern void Fraig_TablePrintStatsF0( Fraig_Man_t * pMan ); +extern int Fraig_TableRehashF0( Fraig_Man_t * pMan, int fLinkEquiv ); +/*=== fraigUtil.c ===============================================================*/ +extern int Fraig_NodeCountPis( Msat_IntVec_t * vVars, int nVarsPi ); +extern int Fraig_NodeCountSuppVars( Fraig_Man_t * p, Fraig_Node_t * pNode, int fSuppStr ); +extern int Fraig_NodesCompareSupps( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); +extern int Fraig_NodeAndSimpleCase_rec( Fraig_Node_t * pOld, Fraig_Node_t * pNew ); +extern int Fraig_NodeIsExorType( Fraig_Node_t * pNode ); +extern void Fraig_ManSelectBestChoice( Fraig_Man_t * p ); +extern int Fraig_BitStringCountOnes( unsigned * pString, int nWords ); +extern void Fraig_PrintBinary( FILE * pFile, unsigned * pSign, int nBits ); +extern int Fraig_NodeIsExorType( Fraig_Node_t * pNode ); +extern int Fraig_NodeIsExor( Fraig_Node_t * pNode ); +extern int Fraig_NodeIsMuxType( Fraig_Node_t * pNode ); +extern Fraig_Node_t * Fraig_NodeRecognizeMux( Fraig_Node_t * pNode, Fraig_Node_t ** ppNodeT, Fraig_Node_t ** ppNodeE ); +extern int Fraig_ManCountExors( Fraig_Man_t * pMan ); +extern int Fraig_ManCountMuxes( Fraig_Man_t * pMan ); +extern int Fraig_NodeSimsContained( Fraig_Man_t * pMan, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2 ); +extern int Fraig_NodeIsInSupergate( Fraig_Node_t * pOld, Fraig_Node_t * pNew ); +extern Fraig_NodeVec_t * Fraig_CollectSupergate( Fraig_Node_t * pNode, int fStopAtMux ); +extern int Fraig_CountPis( Fraig_Man_t * p, Msat_IntVec_t * vVarNums ); +extern void Fraig_ManIncrementTravId( Fraig_Man_t * pMan ); +extern void Fraig_NodeSetTravIdCurrent( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); +extern int Fraig_NodeIsTravIdCurrent( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); +extern int Fraig_NodeIsTravIdPrevious( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); +/*=== fraigVec.c ===============================================================*/ +extern void Fraig_NodeVecSortByRefCount( Fraig_NodeVec_t * p ); + + + +ABC_NAMESPACE_HEADER_END + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/src/proof/fraig/fraigMan.c b/src/proof/fraig/fraigMan.c new file mode 100644 index 00000000..ba08d793 --- /dev/null +++ b/src/proof/fraig/fraigMan.c @@ -0,0 +1,545 @@ +/**CFile**************************************************************** + + FileName [fraigMan.c] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [Implementation of the FRAIG manager.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - October 1, 2004] + + Revision [$Id: fraigMan.c,v 1.11 2005/07/08 01:01:31 alanmi Exp $] + +***********************************************************************/ + +#include "fraigInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +int timeSelect; +int timeAssign; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Sets the default parameters of the package.] + + Description [This set of parameters is tuned for equivalence checking.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Prove_ParamsSetDefault( Prove_Params_t * pParams ) +{ + // clean the parameter structure + memset( pParams, 0, sizeof(Prove_Params_t) ); + // general parameters + pParams->fUseFraiging = 1; // enables fraiging + pParams->fUseRewriting = 1; // enables rewriting + pParams->fUseBdds = 0; // enables BDD construction when other methods fail + pParams->fVerbose = 0; // prints verbose stats + // iterations + pParams->nItersMax = 6; // the number of iterations + // mitering + pParams->nMiteringLimitStart = 5000; // 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: %.2f\n", pParams->nFraigingLimitMulti ); + printf( "Multiplicative coeficient for fraiging: %.2f\n", pParams->nRewritingLimitMulti ); + printf( "BDD size limit for bailing out: %d\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: %lld\n", pParams->nTotalBacktrackLimit ); + printf( "Total inspection limit: %lld\n", pParams->nTotalInspectLimit ); + printf( "Parameter dump complete.\n" ); +} + +/**Function************************************************************* + + Synopsis [Sets the default parameters of the package.] + + Description [This set of parameters is tuned for equivalence checking.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_ParamsSetDefault( Fraig_Params_t * pParams ) +{ + memset( pParams, 0, sizeof(Fraig_Params_t) ); + pParams->nPatsRand = FRAIG_PATTERNS_RANDOM; // the number of words of random simulation info + pParams->nPatsDyna = FRAIG_PATTERNS_DYNAMIC; // the number of words of dynamic simulation info + pParams->nBTLimit = 99; // the max number of backtracks to perform + pParams->nSeconds = 20; // the max number of seconds to solve the miter + pParams->fFuncRed = 1; // performs only one level hashing + pParams->fFeedBack = 1; // enables solver feedback + pParams->fDist1Pats = 1; // enables distance-1 patterns + pParams->fDoSparse = 0; // performs equiv tests for sparse functions + pParams->fChoicing = 0; // enables recording structural choices + pParams->fTryProve = 1; // tries to solve the final miter + pParams->fVerbose = 0; // the verbosiness flag + pParams->fVerboseP = 0; // the verbose flag for reporting the proof + pParams->fInternal = 0; // the flag indicates the internal run + pParams->nConfLimit = 0; // the limit on the number of conflicts + pParams->nInspLimit = 0; // the limit on the number of inspections +} + +/**Function************************************************************* + + Synopsis [Sets the default parameters of the package.] + + Description [This set of parameters is tuned for complete FRAIGing.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_ParamsSetDefaultFull( Fraig_Params_t * pParams ) +{ + memset( pParams, 0, sizeof(Fraig_Params_t) ); + pParams->nPatsRand = FRAIG_PATTERNS_RANDOM; // the number of words of random simulation info + pParams->nPatsDyna = FRAIG_PATTERNS_DYNAMIC; // the number of words of dynamic simulation info + pParams->nBTLimit = -1; // the max number of backtracks to perform + pParams->nSeconds = 20; // the max number of seconds to solve the miter + pParams->fFuncRed = 1; // performs only one level hashing + pParams->fFeedBack = 1; // enables solver feedback + pParams->fDist1Pats = 1; // enables distance-1 patterns + pParams->fDoSparse = 1; // performs equiv tests for sparse functions + pParams->fChoicing = 0; // enables recording structural choices + pParams->fTryProve = 0; // tries to solve the final miter + pParams->fVerbose = 0; // the verbosiness flag + pParams->fVerboseP = 0; // the verbose flag for reporting the proof + pParams->fInternal = 0; // the flag indicates the internal run + pParams->nConfLimit = 0; // the limit on the number of conflicts + pParams->nInspLimit = 0; // the limit on the number of inspections +} + +/**Function************************************************************* + + Synopsis [Creates the new FRAIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Man_t * Fraig_ManCreate( Fraig_Params_t * pParams ) +{ + Fraig_Params_t Params; + Fraig_Man_t * p; + + // set the random seed for simulation +// srand( 0xFEEDDEAF ); + srand( 0xDEADCAFE ); + + // set parameters for equivalence checking + if ( pParams == NULL ) + Fraig_ParamsSetDefault( pParams = &Params ); + // adjust the amount of simulation info + if ( pParams->nPatsRand < 128 ) + pParams->nPatsRand = 128; + if ( pParams->nPatsRand > 32768 ) + pParams->nPatsRand = 32768; + if ( pParams->nPatsDyna < 128 ) + pParams->nPatsDyna = 128; + if ( pParams->nPatsDyna > 32768 ) + pParams->nPatsDyna = 32768; + // if reduction is not performed, allocate minimum simulation info + if ( !pParams->fFuncRed ) + pParams->nPatsRand = pParams->nPatsDyna = 128; + + // start the manager + p = ABC_ALLOC( Fraig_Man_t, 1 ); + memset( p, 0, sizeof(Fraig_Man_t) ); + + // set the default parameters + p->nWordsRand = FRAIG_NUM_WORDS( pParams->nPatsRand ); // the number of words of random simulation info + p->nWordsDyna = FRAIG_NUM_WORDS( pParams->nPatsDyna ); // the number of patterns for dynamic simulation info + p->nBTLimit = pParams->nBTLimit; // -1 means infinite backtrack limit + p->nSeconds = pParams->nSeconds; // the timeout for the final miter + p->fFuncRed = pParams->fFuncRed; // enables functional reduction (otherwise, only one-level hashing is performed) + p->fFeedBack = pParams->fFeedBack; // enables solver feedback (the use of counter-examples in simulation) + p->fDist1Pats = pParams->fDist1Pats; // enables solver feedback (the use of counter-examples in simulation) + p->fDoSparse = pParams->fDoSparse; // performs equivalence checking for sparse functions (whose sim-info is 0) + p->fChoicing = pParams->fChoicing; // disable accumulation of structural choices (keeps only the first choice) + p->fTryProve = pParams->fTryProve; // disable accumulation of structural choices (keeps only the first choice) + p->fVerbose = pParams->fVerbose; // disable verbose output + p->fVerboseP = pParams->fVerboseP; // disable verbose output + p->nInspLimit = pParams->nInspLimit; // the limit on the number of inspections + + // start memory managers + p->mmNodes = Fraig_MemFixedStart( sizeof(Fraig_Node_t) ); + p->mmSims = Fraig_MemFixedStart( sizeof(unsigned) * (p->nWordsRand + p->nWordsDyna) ); + // allocate node arrays + p->vInputs = Fraig_NodeVecAlloc( 1000 ); // the array of primary inputs + p->vOutputs = Fraig_NodeVecAlloc( 1000 ); // the array of primary outputs + p->vNodes = Fraig_NodeVecAlloc( 1000 ); // the array of internal nodes + // start the tables + p->pTableS = Fraig_HashTableCreate( 1000 ); // hashing by structure + p->pTableF = Fraig_HashTableCreate( 1000 ); // hashing by function + p->pTableF0 = Fraig_HashTableCreate( 1000 ); // hashing by function (for sparse functions) + // create the constant node + p->pConst1 = Fraig_NodeCreateConst( p ); + // initialize SAT solver feedback data structures + Fraig_FeedBackInit( p ); + // initialize other variables + p->vProj = Msat_IntVecAlloc( 10 ); + p->nTravIds = 1; + p->nTravIds2 = 1; + return p; +} + +/**Function************************************************************* + + Synopsis [Deallocates the mapping manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_ManFree( Fraig_Man_t * p ) +{ + int i; + if ( p->fVerbose ) + { + if ( p->fChoicing ) Fraig_ManReportChoices( p ); + Fraig_ManPrintStats( p ); +// Fraig_TablePrintStatsS( p ); +// Fraig_TablePrintStatsF( p ); +// Fraig_TablePrintStatsF0( p ); + } + + for ( i = 0; i < p->vNodes->nSize; i++ ) + if ( p->vNodes->pArray[i]->vFanins ) + { + Fraig_NodeVecFree( p->vNodes->pArray[i]->vFanins ); + p->vNodes->pArray[i]->vFanins = NULL; + } + + if ( p->vInputs ) Fraig_NodeVecFree( p->vInputs ); + if ( p->vNodes ) Fraig_NodeVecFree( p->vNodes ); + if ( p->vOutputs ) Fraig_NodeVecFree( p->vOutputs ); + + if ( p->pTableS ) Fraig_HashTableFree( p->pTableS ); + if ( p->pTableF ) Fraig_HashTableFree( p->pTableF ); + if ( p->pTableF0 ) Fraig_HashTableFree( p->pTableF0 ); + + if ( p->pSat ) Msat_SolverFree( p->pSat ); + if ( p->vProj ) Msat_IntVecFree( p->vProj ); + if ( p->vCones ) Fraig_NodeVecFree( p->vCones ); + if ( p->vPatsReal ) Msat_IntVecFree( p->vPatsReal ); + if ( p->pModel ) ABC_FREE( p->pModel ); + + Fraig_MemFixedStop( p->mmNodes, 0 ); + Fraig_MemFixedStop( p->mmSims, 0 ); + + if ( p->pSuppS ) + { + ABC_FREE( p->pSuppS[0] ); + ABC_FREE( p->pSuppS ); + } + if ( p->pSuppF ) + { + ABC_FREE( p->pSuppF[0] ); + ABC_FREE( p->pSuppF ); + } + + ABC_FREE( p->ppOutputNames ); + ABC_FREE( p->ppInputNames ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Prepares the SAT solver to run on the two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_ManCreateSolver( Fraig_Man_t * p ) +{ + extern int timeSelect; + extern int timeAssign; + assert( p->pSat == NULL ); + // allocate data for SAT solving + p->pSat = Msat_SolverAlloc( 500, 1, 1, 1, 1, 0 ); + p->vVarsInt = Msat_SolverReadConeVars( p->pSat ); + p->vAdjacents = Msat_SolverReadAdjacents( p->pSat ); + p->vVarsUsed = Msat_SolverReadVarsUsed( p->pSat ); + timeSelect = 0; + timeAssign = 0; +} + + +/**Function************************************************************* + + Synopsis [Deallocates the mapping manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_ManPrintStats( Fraig_Man_t * p ) +{ + double nMemory; + nMemory = ((double)(p->vInputs->nSize + p->vNodes->nSize) * + (sizeof(Fraig_Node_t) + sizeof(unsigned)*(p->nWordsRand + p->nWordsDyna) /*+ p->nSuppWords*sizeof(unsigned)*/))/(1<<20); + printf( "Words: Random = %d. Dynamic = %d. Used = %d. Memory = %0.2f Mb.\n", + p->nWordsRand, p->nWordsDyna, p->iWordPerm, nMemory ); + printf( "Proof = %d. Counter-example = %d. Fail = %d. FailReal = %d. Zero = %d.\n", + p->nSatProof, p->nSatCounter, p->nSatFails, p->nSatFailsReal, p->nSatZeros ); + printf( "Nodes: Final = %d. Total = %d. Mux = %d. (Exor = %d.) ClaVars = %d.\n", + Fraig_CountNodes(p,0), p->vNodes->nSize, Fraig_ManCountMuxes(p), Fraig_ManCountExors(p), p->nVarsClauses ); + if ( p->pSat ) Msat_SolverPrintStats( p->pSat ); + Fraig_PrintTime( "AIG simulation ", p->timeSims ); + Fraig_PrintTime( "AIG traversal ", p->timeTrav ); + Fraig_PrintTime( "Solver feedback ", p->timeFeed ); + Fraig_PrintTime( "SAT solving ", p->timeSat ); + Fraig_PrintTime( "Network update ", p->timeToNet ); + Fraig_PrintTime( "TOTAL RUNTIME ", p->timeTotal ); + if ( p->time1 > 0 ) { Fraig_PrintTime( "time1", p->time1 ); } + if ( p->time2 > 0 ) { Fraig_PrintTime( "time2", p->time2 ); } + if ( p->time3 > 0 ) { Fraig_PrintTime( "time3", p->time3 ); } + if ( p->time4 > 0 ) { Fraig_PrintTime( "time4", p->time4 ); } +// ABC_PRT( "Selection ", timeSelect ); +// ABC_PRT( "Assignment", timeAssign ); + fflush( stdout ); +} + +/**Function************************************************************* + + Synopsis [Allocates simulation information for all nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_NodeVec_t * Fraig_UtilInfoAlloc( int nSize, int nWords, int fClean ) +{ + Fraig_NodeVec_t * vInfo; + unsigned * pUnsigned; + int i; + assert( nSize > 0 && nWords > 0 ); + vInfo = Fraig_NodeVecAlloc( nSize ); + pUnsigned = ABC_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 /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fraig/fraigMem.c b/src/proof/fraig/fraigMem.c new file mode 100644 index 00000000..ef52765e --- /dev/null +++ b/src/proof/fraig/fraigMem.c @@ -0,0 +1,251 @@ +/**CFile**************************************************************** + + FileName [fraigMem.c] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [Fixed-size-entry memory manager for the FRAIG package.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - October 1, 2004] + + Revision [$Id: fraigMem.c,v 1.4 2005/07/08 01:01:31 alanmi Exp $] + +***********************************************************************/ + +#include "fraigInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +struct Fraig_MemFixed_t_ +{ + // information about individual entries + int nEntrySize; // the size of one entry + int nEntriesAlloc; // the total number of entries allocated + int nEntriesUsed; // the number of entries in use + int nEntriesMax; // the max number of entries in use + char * pEntriesFree; // the linked list of free entries + + // this is where the memory is stored + int nChunkSize; // the size of one chunk + int nChunksAlloc; // the maximum number of memory chunks + int nChunks; // the current number of memory chunks + char ** pChunks; // the allocated memory + + // statistics + int nMemoryUsed; // memory used in the allocated entries + int nMemoryAlloc; // memory allocated +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the internal memory manager.] + + Description [Can only work with entry size at least 4 byte long.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_MemFixed_t * Fraig_MemFixedStart( int nEntrySize ) +{ + Fraig_MemFixed_t * p; + + p = ABC_ALLOC( Fraig_MemFixed_t, 1 ); + memset( p, 0, sizeof(Fraig_MemFixed_t) ); + + p->nEntrySize = nEntrySize; + p->nEntriesAlloc = 0; + p->nEntriesUsed = 0; + p->pEntriesFree = NULL; + + if ( nEntrySize * (1 << 10) < (1<<16) ) + p->nChunkSize = (1 << 10); + else + p->nChunkSize = (1<<16) / nEntrySize; + if ( p->nChunkSize < 8 ) + p->nChunkSize = 8; + + p->nChunksAlloc = 64; + p->nChunks = 0; + p->pChunks = ABC_ALLOC( char *, p->nChunksAlloc ); + + p->nMemoryUsed = 0; + p->nMemoryAlloc = 0; + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the internal memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_MemFixedStop( Fraig_MemFixed_t * p, int fVerbose ) +{ + int i; + if ( p == NULL ) + return; + if ( fVerbose ) + { + printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n", + p->nEntrySize, p->nChunkSize, p->nChunks ); + printf( " Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n", + p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc ); + } + for ( i = 0; i < p->nChunks; i++ ) + ABC_FREE( p->pChunks[i] ); + ABC_FREE( p->pChunks ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Extracts one entry from the memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Fraig_MemFixedEntryFetch( Fraig_MemFixed_t * p ) +{ + char * pTemp; + int i; + + // check if there are still free entries + if ( p->nEntriesUsed == p->nEntriesAlloc ) + { // need to allocate more entries + assert( p->pEntriesFree == NULL ); + if ( p->nChunks == p->nChunksAlloc ) + { + p->nChunksAlloc *= 2; + p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); + } + p->pEntriesFree = ABC_ALLOC( char, p->nEntrySize * p->nChunkSize ); + p->nMemoryAlloc += p->nEntrySize * p->nChunkSize; + // transform these entries into a linked list + pTemp = p->pEntriesFree; + for ( i = 1; i < p->nChunkSize; i++ ) + { + *((char **)pTemp) = pTemp + p->nEntrySize; + pTemp += p->nEntrySize; + } + // set the last link + *((char **)pTemp) = NULL; + // add the chunk to the chunk storage + p->pChunks[ p->nChunks++ ] = p->pEntriesFree; + // add to the number of entries allocated + p->nEntriesAlloc += p->nChunkSize; + } + // incrememt the counter of used entries + p->nEntriesUsed++; + if ( p->nEntriesMax < p->nEntriesUsed ) + p->nEntriesMax = p->nEntriesUsed; + // return the first entry in the free entry list + pTemp = p->pEntriesFree; + p->pEntriesFree = *((char **)pTemp); + return pTemp; +} + +/**Function************************************************************* + + Synopsis [Returns one entry into the memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_MemFixedEntryRecycle( Fraig_MemFixed_t * p, char * pEntry ) +{ + // decrement the counter of used entries + p->nEntriesUsed--; + // add the entry to the linked list of free entries + *((char **)pEntry) = p->pEntriesFree; + p->pEntriesFree = pEntry; +} + +/**Function************************************************************* + + Synopsis [Frees all associated memory and resets the manager.] + + Description [Relocates all the memory except the first chunk.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_MemFixedRestart( Fraig_MemFixed_t * p ) +{ + int i; + char * pTemp; + + // deallocate all chunks except the first one + for ( i = 1; i < p->nChunks; i++ ) + ABC_FREE( p->pChunks[i] ); + p->nChunks = 1; + // transform these entries into a linked list + pTemp = p->pChunks[0]; + for ( i = 1; i < p->nChunkSize; i++ ) + { + *((char **)pTemp) = pTemp + p->nEntrySize; + pTemp += p->nEntrySize; + } + // set the last link + *((char **)pTemp) = NULL; + // set the free entry list + p->pEntriesFree = p->pChunks[0]; + // set the correct statistics + p->nMemoryAlloc = p->nEntrySize * p->nChunkSize; + p->nMemoryUsed = 0; + p->nEntriesAlloc = p->nChunkSize; + p->nEntriesUsed = 0; +} + +/**Function************************************************************* + + Synopsis [Reports the memory usage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_MemFixedReadMemUsage( Fraig_MemFixed_t * p ) +{ + return p->nMemoryAlloc; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fraig/fraigNode.c b/src/proof/fraig/fraigNode.c new file mode 100644 index 00000000..609d5f65 --- /dev/null +++ b/src/proof/fraig/fraigNode.c @@ -0,0 +1,318 @@ +/**CFile**************************************************************** + + FileName [fraigNode.c] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [Implementation of the FRAIG node.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - October 1, 2004] + + Revision [$Id: fraigNode.c,v 1.3 2005/07/08 01:01:32 alanmi Exp $] + +***********************************************************************/ + +#include "fraigInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// returns the complemented attribute of the node +#define Fraig_NodeIsSimComplement(p) (Fraig_IsComplement(p)? !(Fraig_Regular(p)->fInv) : (p)->fInv) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates the constant 1 node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_NodeCreateConst( Fraig_Man_t * p ) +{ + Fraig_Node_t * pNode; + + // create the node + pNode = (Fraig_Node_t *)Fraig_MemFixedEntryFetch( p->mmNodes ); + memset( pNode, 0, sizeof(Fraig_Node_t) ); + + // assign the number and add to the array of nodes + pNode->Num = p->vNodes->nSize; + Fraig_NodeVecPush( p->vNodes, pNode ); + pNode->NumPi = -1; // this is not a PI, so its number is -1 + pNode->Level = 0; // just like a PI, it has 0 level + pNode->nRefs = 1; // it is a persistent node, which comes referenced + pNode->fInv = 1; // the simulation info is complemented + + // create the simulation info + pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); + pNode->puSimD = pNode->puSimR + p->nWordsRand; + memset( pNode->puSimR, 0, sizeof(unsigned) * p->nWordsRand ); + memset( pNode->puSimD, 0, sizeof(unsigned) * p->nWordsDyna ); + + // count the number of ones in the simulation vector + pNode->nOnes = p->nWordsRand * sizeof(unsigned) * 8; + + // insert it into the hash table + Fraig_HashTableLookupF0( p, pNode ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates a primary input node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_NodeCreatePi( Fraig_Man_t * p ) +{ + Fraig_Node_t * pNode, * pNodeRes; + int i, clk; + + // create the node + pNode = (Fraig_Node_t *)Fraig_MemFixedEntryFetch( p->mmNodes ); + memset( pNode, 0, sizeof(Fraig_Node_t) ); + pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); + pNode->puSimD = pNode->puSimR + p->nWordsRand; + memset( pNode->puSimD, 0, sizeof(unsigned) * p->nWordsDyna ); + + // assign the number and add to the array of nodes + pNode->Num = p->vNodes->nSize; + Fraig_NodeVecPush( p->vNodes, pNode ); + + // assign the PI number and add to the array of primary inputs + pNode->NumPi = p->vInputs->nSize; + Fraig_NodeVecPush( p->vInputs, pNode ); + + pNode->Level = 0; // PI has 0 level + pNode->nRefs = 1; // it is a persistent node, which comes referenced + pNode->fInv = 0; // the simulation info of the PI is not complemented + + // derive the simulation info for the new node +clk = clock(); + // set the random simulation info for the primary input + pNode->uHashR = 0; + for ( i = 0; i < p->nWordsRand; i++ ) + { + // generate the simulation info + pNode->puSimR[i] = FRAIG_RANDOM_UNSIGNED; + // for reasons that take very long to explain, it makes sense to have (0000000...) + // pattern in the set (this helps if we need to return the counter-examples) + if ( i == 0 ) + pNode->puSimR[i] <<= 1; + // compute the hash key + pNode->uHashR ^= pNode->puSimR[i] * s_FraigPrimes[i]; + } + // count the number of ones in the simulation vector + pNode->nOnes = Fraig_BitStringCountOnes( pNode->puSimR, p->nWordsRand ); + + // set the systematic simulation info for the primary input + pNode->uHashD = 0; + for ( i = 0; i < p->iWordStart; i++ ) + { + // generate the simulation info + pNode->puSimD[i] = FRAIG_RANDOM_UNSIGNED; + // compute the hash key + pNode->uHashD ^= pNode->puSimD[i] * s_FraigPrimes[i]; + } +p->timeSims += clock() - clk; + + // insert it into the hash table + pNodeRes = Fraig_HashTableLookupF( p, pNode ); + assert( pNodeRes == NULL ); + // add to the runtime of simulation + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates a new node.] + + Description [This procedure should be called to create the constant + node and the PI nodes first.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_NodeCreate( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ) +{ + Fraig_Node_t * pNode; + int clk; + + // create the node + pNode = (Fraig_Node_t *)Fraig_MemFixedEntryFetch( p->mmNodes ); + memset( pNode, 0, sizeof(Fraig_Node_t) ); + + // assign the children + pNode->p1 = p1; Fraig_Ref(p1); Fraig_Regular(p1)->nRefs++; + pNode->p2 = p2; Fraig_Ref(p2); Fraig_Regular(p2)->nRefs++; + + // assign the number and add to the array of nodes + pNode->Num = p->vNodes->nSize; + Fraig_NodeVecPush( p->vNodes, pNode ); + + // assign the PI number + pNode->NumPi = -1; + + // compute the level of this node + pNode->Level = 1 + Abc_MaxInt(Fraig_Regular(p1)->Level, Fraig_Regular(p2)->Level); + pNode->fInv = Fraig_NodeIsSimComplement(p1) & Fraig_NodeIsSimComplement(p2); + pNode->fFailTfo = Fraig_Regular(p1)->fFailTfo | Fraig_Regular(p2)->fFailTfo; + + // derive the simulation info +clk = clock(); + // allocate memory for the simulation info + pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); + pNode->puSimD = pNode->puSimR + p->nWordsRand; + // derive random simulation info + pNode->uHashR = 0; + Fraig_NodeSimulate( pNode, 0, p->nWordsRand, 1 ); + // derive dynamic simulation info + pNode->uHashD = 0; + Fraig_NodeSimulate( pNode, 0, p->iWordStart, 0 ); + // count the number of ones in the random simulation info + pNode->nOnes = Fraig_BitStringCountOnes( pNode->puSimR, p->nWordsRand ); + if ( pNode->fInv ) + pNode->nOnes = p->nWordsRand * 32 - pNode->nOnes; + // add to the runtime of simulation +p->timeSims += clock() - clk; + +#ifdef FRAIG_ENABLE_FANOUTS + // create the fanout info + Fraig_NodeAddFaninFanout( Fraig_Regular(p1), pNode ); + Fraig_NodeAddFaninFanout( Fraig_Regular(p2), pNode ); +#endif + return pNode; +} + + +/**Function************************************************************* + + Synopsis [Simulates the node.] + + Description [Simulates the random or dynamic simulation info through + the node. Uses phases of the children to determine their real simulation + info. Uses phase of the node to determine the way its simulation info + is stored. The resulting info is guaranteed to be 0 for the first pattern.] + + SideEffects [This procedure modified the hash value of the simulation info.] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeSimulate( Fraig_Node_t * pNode, int iWordStart, int iWordStop, int fUseRand ) +{ + unsigned * pSims, * pSims1, * pSims2; + unsigned uHash; + int fCompl, fCompl1, fCompl2, i; + + assert( !Fraig_IsComplement(pNode) ); + + // get hold of the simulation information + pSims = fUseRand? pNode->puSimR : pNode->puSimD; + pSims1 = fUseRand? Fraig_Regular(pNode->p1)->puSimR : Fraig_Regular(pNode->p1)->puSimD; + pSims2 = fUseRand? Fraig_Regular(pNode->p2)->puSimR : Fraig_Regular(pNode->p2)->puSimD; + + // get complemented attributes of the children using their random info + fCompl = pNode->fInv; + fCompl1 = Fraig_NodeIsSimComplement(pNode->p1); + fCompl2 = Fraig_NodeIsSimComplement(pNode->p2); + + // simulate + uHash = 0; + if ( fCompl1 && fCompl2 ) + { + if ( fCompl ) + for ( i = iWordStart; i < iWordStop; i++ ) + { + pSims[i] = (pSims1[i] | pSims2[i]); + uHash ^= pSims[i] * s_FraigPrimes[i]; + } + else + for ( i = iWordStart; i < iWordStop; i++ ) + { + pSims[i] = ~(pSims1[i] | pSims2[i]); + uHash ^= pSims[i] * s_FraigPrimes[i]; + } + } + else if ( fCompl1 && !fCompl2 ) + { + if ( fCompl ) + for ( i = iWordStart; i < iWordStop; i++ ) + { + pSims[i] = (pSims1[i] | ~pSims2[i]); + uHash ^= pSims[i] * s_FraigPrimes[i]; + } + else + for ( i = iWordStart; i < iWordStop; i++ ) + { + pSims[i] = (~pSims1[i] & pSims2[i]); + uHash ^= pSims[i] * s_FraigPrimes[i]; + } + } + else if ( !fCompl1 && fCompl2 ) + { + if ( fCompl ) + for ( i = iWordStart; i < iWordStop; i++ ) + { + pSims[i] = (~pSims1[i] | pSims2[i]); + uHash ^= pSims[i] * s_FraigPrimes[i]; + } + else + for ( i = iWordStart; i < iWordStop; i++ ) + { + pSims[i] = (pSims1[i] & ~pSims2[i]); + uHash ^= pSims[i] * s_FraigPrimes[i]; + } + } + else // if ( !fCompl1 && !fCompl2 ) + { + if ( fCompl ) + for ( i = iWordStart; i < iWordStop; i++ ) + { + pSims[i] = ~(pSims1[i] & pSims2[i]); + uHash ^= pSims[i] * s_FraigPrimes[i]; + } + else + for ( i = iWordStart; i < iWordStop; i++ ) + { + pSims[i] = (pSims1[i] & pSims2[i]); + uHash ^= pSims[i] * s_FraigPrimes[i]; + } + } + + if ( fUseRand ) + pNode->uHashR ^= uHash; + else + pNode->uHashD ^= uHash; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fraig/fraigPrime.c b/src/proof/fraig/fraigPrime.c new file mode 100644 index 00000000..4878738d --- /dev/null +++ b/src/proof/fraig/fraigPrime.c @@ -0,0 +1,113 @@ +/**CFile**************************************************************** + + FileName [fraigPrime.c] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [The table of the first 1000 primes.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - October 1, 2004] + + Revision [$Id: fraigPrime.c,v 1.4 2005/07/08 01:01:32 alanmi Exp $] + +***********************************************************************/ + +#include "fraigInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// The 1,024 smallest prime numbers used to compute the hash value +// http://www.math.utah.edu/~alfeld/math/primelist.html +int s_FraigPrimes[FRAIG_MAX_PRIMES] = { 2, 3, 5, +7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, +101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, +193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, +293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, +409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, +521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, +641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, +757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, +881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, +1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, +1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, +1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, +1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, +1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, +1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, +1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, +1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, +1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, +1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, +2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, +2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, +2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, +2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, +2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, +2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, +2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, +2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, +2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, +3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, +3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, +3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, +3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, +3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, +3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, +3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, +3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, +3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, +4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, +4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, +4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, +4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, +4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, +4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, +4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, +4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, +5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, +5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, +5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, +5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, +5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, +5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, +5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, +5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, +6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, +6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, +6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, +6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, +6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, +6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, +6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, +6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, +6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, +7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, +7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, +7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, +7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, +7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, +7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, +7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, +8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123, +8147, 8161 }; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fraig/fraigSat.c b/src/proof/fraig/fraigSat.c new file mode 100644 index 00000000..6ccd1b86 --- /dev/null +++ b/src/proof/fraig/fraigSat.c @@ -0,0 +1,1459 @@ +/**CFile**************************************************************** + + FileName [fraigSat.c] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [Proving functional equivalence using SAT.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - October 1, 2004] + + Revision [$Id: fraigSat.c,v 1.10 2005/07/08 01:01:32 alanmi Exp $] + +***********************************************************************/ + +#include +#include "fraigInt.h" +#include "src/sat/msat/msatInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Fraig_OrderVariables( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); +static void Fraig_SetupAdjacent( Fraig_Man_t * pMan, Msat_IntVec_t * vConeVars ); +static void Fraig_SetupAdjacentMark( Fraig_Man_t * pMan, Msat_IntVec_t * vConeVars ); +static void Fraig_PrepareCones( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); +static void Fraig_PrepareCones_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); + +static void Fraig_SupergateAddClauses( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper ); +static void Fraig_SupergateAddClausesExor( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); +static void Fraig_SupergateAddClausesMux( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); +//static void Fraig_DetectFanoutFreeCone( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); +static void Fraig_DetectFanoutFreeConeMux( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); +static void Fraig_SetActivity( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); + +// The lesson learned seems to be that variable should be in reverse topological order +// from the output of the miter. The ordering of adjacency lists is very important. +// The best way seems to be fanins followed by fanouts. Slight changes to this order +// leads to big degradation in quality. + +static int nMuxes; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks equivalence of two nodes.] + + Description [Returns 1 iff the nodes are equivalent.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodesAreEqual( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit, int nTimeLimit ) +{ + if ( pNode1 == pNode2 ) + return 1; + if ( pNode1 == Fraig_Not(pNode2) ) + return 0; + return Fraig_NodeIsEquivalent( p, Fraig_Regular(pNode1), Fraig_Regular(pNode2), nBTLimit, nTimeLimit ); +} + +/**Function************************************************************* + + Synopsis [Tries to prove the final miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_ManProveMiter( Fraig_Man_t * p ) +{ + Fraig_Node_t * pNode; + int i, clk; + + if ( !p->fTryProve ) + return; + + clk = clock(); + // consider all outputs of the multi-output miter + for ( i = 0; i < p->vOutputs->nSize; i++ ) + { + pNode = Fraig_Regular(p->vOutputs->pArray[i]); + // skip already constant nodes + if ( pNode == p->pConst1 ) + continue; + // skip nodes that are different according to simulation + if ( !Fraig_CompareSimInfo( pNode, p->pConst1, p->nWordsRand, 1 ) ) + continue; + if ( Fraig_NodeIsEquivalent( p, p->pConst1, pNode, -1, p->nSeconds ) ) + { + if ( Fraig_IsComplement(p->vOutputs->pArray[i]) ^ Fraig_NodeComparePhase(p->pConst1, pNode) ) + p->vOutputs->pArray[i] = Fraig_Not(p->pConst1); + else + p->vOutputs->pArray[i] = p->pConst1; + } + } + if ( p->fVerboseP ) + { +// ABC_PRT( "Final miter proof time", clock() - clk ); + } +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the miter is unsat; 0 if sat; -1 if undecided.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_ManCheckMiter( Fraig_Man_t * p ) +{ + Fraig_Node_t * pNode; + int i; + ABC_FREE( p->pModel ); + for ( i = 0; i < p->vOutputs->nSize; i++ ) + { + // get the output node (it can be complemented!) + pNode = p->vOutputs->pArray[i]; + // if the miter is constant 0, the problem is UNSAT + if ( pNode == Fraig_Not(p->pConst1) ) + continue; + // consider the special case when the miter is constant 1 + if ( pNode == p->pConst1 ) + { + // in this case, any counter example will do to distinquish it from constant 0 + // here we pick the counter example composed of all zeros + p->pModel = Fraig_ManAllocCounterExample( p ); + return 0; + } + // save the counter example + p->pModel = Fraig_ManSaveCounterExample( p, pNode ); + // if the model is not found, return undecided + if ( p->pModel == NULL ) + return -1; + else + return 0; + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if pOld is in the TFI of pNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_MarkTfi_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) +{ + // skip the visited node + if ( pNode->TravId == pMan->nTravIds ) + return 0; + pNode->TravId = pMan->nTravIds; + // skip the PI node + if ( pNode->NumPi >= 0 ) + return 1; + // check the children + return Fraig_MarkTfi_rec( pMan, Fraig_Regular(pNode->p1) ) + + Fraig_MarkTfi_rec( pMan, Fraig_Regular(pNode->p2) ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pOld is in the TFI of pNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_MarkTfi2_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) +{ + // skip the visited node + if ( pNode->TravId == pMan->nTravIds ) + return 0; + // skip the boundary node + if ( pNode->TravId == pMan->nTravIds-1 ) + { + pNode->TravId = pMan->nTravIds; + return 1; + } + pNode->TravId = pMan->nTravIds; + // skip the PI node + if ( pNode->NumPi >= 0 ) + return 1; + // check the children + return Fraig_MarkTfi2_rec( pMan, Fraig_Regular(pNode->p1) ) + + Fraig_MarkTfi2_rec( pMan, Fraig_Regular(pNode->p2) ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pOld is in the TFI of pNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_MarkTfi3_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) +{ + // skip the visited node + if ( pNode->TravId == pMan->nTravIds ) + return 1; + // skip the boundary node + if ( pNode->TravId == pMan->nTravIds-1 ) + { + pNode->TravId = pMan->nTravIds; + return 1; + } + pNode->TravId = pMan->nTravIds; + // skip the PI node + if ( pNode->NumPi >= 0 ) + return 0; + // check the children + return Fraig_MarkTfi3_rec( pMan, Fraig_Regular(pNode->p1) ) * + Fraig_MarkTfi3_rec( pMan, Fraig_Regular(pNode->p2) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_VarsStudy( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) +{ + int NumPis, NumCut, fContain; + + // mark the TFI of pNew + p->nTravIds++; + NumPis = Fraig_MarkTfi_rec( p, pNew ); + printf( "(%d)(%d,%d):", NumPis, pOld->Level, pNew->Level ); + + // check if the old is in the TFI + if ( pOld->TravId == p->nTravIds ) + { + printf( "* " ); + return; + } + + // count the boundary of nodes in pOld + p->nTravIds++; + NumCut = Fraig_MarkTfi2_rec( p, pOld ); + printf( "%d", NumCut ); + + // check if the new is contained in the old's support + p->nTravIds++; + fContain = Fraig_MarkTfi3_rec( p, pNew ); + printf( "%c ", fContain? '+':'-' ); +} + + +/**Function************************************************************* + + Synopsis [Checks whether two nodes are functinally equivalent.] + + Description [The flag (fComp) tells whether the nodes to be checked + are in the opposite polarity. The second flag (fSkipZeros) tells whether + the checking should be performed if the simulation vectors are zeros. + Returns 1 if the nodes are equivalent; 0 othewise.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeIsEquivalent( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit, int nTimeLimit ) +{ + int RetValue, RetValue1, i, fComp, clk; + int fVerbose = 0; + int fSwitch = 0; + + // make sure the nodes are not complemented + assert( !Fraig_IsComplement(pNew) ); + assert( !Fraig_IsComplement(pOld) ); + assert( pNew != pOld ); + + // if at least one of the nodes is a failed node, perform adjustments: + // if the backtrack limit is small, simply skip this node + // if the backtrack limit is > 10, take the quare root of the limit + if ( nBTLimit > 0 && (pOld->fFailTfo || pNew->fFailTfo) ) + { + p->nSatFails++; +// return 0; +// if ( nBTLimit > 10 ) +// nBTLimit /= 10; + if ( nBTLimit <= 10 ) + return 0; + nBTLimit = (int)sqrt((double)nBTLimit); +// fSwitch = 1; + } + + p->nSatCalls++; + + // make sure the solver is allocated and has enough variables + if ( p->pSat == NULL ) + Fraig_ManCreateSolver( p ); + // make sure the SAT solver has enough variables + for ( i = Msat_SolverReadVarNum(p->pSat); i < p->vNodes->nSize; i++ ) + Msat_SolverAddVar( p->pSat, p->vNodes->pArray[i]->Level ); + + + +/* + { + Fraig_Node_t * ppNodes[2] = { pOld, pNew }; + extern void Fraig_MappingShowNodes( Fraig_Man_t * pMan, Fraig_Node_t ** ppRoots, int nRoots, char * pFileName ); + Fraig_MappingShowNodes( p, ppNodes, 2, "temp_aig" ); + } +*/ + + nMuxes = 0; + + + // get the logic cone +clk = clock(); +// Fraig_VarsStudy( p, pOld, pNew ); + Fraig_OrderVariables( p, pOld, pNew ); +// Fraig_PrepareCones( p, pOld, pNew ); +p->timeTrav += clock() - clk; + +// printf( "The number of MUXes detected = %d (%5.2f %% of logic). ", nMuxes, 300.0*nMuxes/(p->vNodes->nSize - p->vInputs->nSize) ); +// ABC_PRT( "Time", clock() - clk ); + +if ( fVerbose ) + printf( "%d(%d) - ", Fraig_CountPis(p,p->vVarsInt), Msat_IntVecReadSize(p->vVarsInt) ); + + + // prepare variable activity + Fraig_SetActivity( p, pOld, pNew ); + + // get the complemented attribute + fComp = Fraig_NodeComparePhase( pOld, pNew ); +//Msat_SolverPrintClauses( p->pSat ); + + //////////////////////////////////////////// + // prepare the solver to run incrementally on these variables +//clk = clock(); + Msat_SolverPrepare( p->pSat, p->vVarsInt ); +//p->time3 += clock() - clk; + + + // solve under assumptions + // A = 1; B = 0 OR A = 1; B = 1 + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 0) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, !fComp) ); + +//Msat_SolverWriteDimacs( p->pSat, "temp_fraig.cnf" ); + + // run the solver +clk = clock(); + RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, nTimeLimit ); +p->timeSat += clock() - clk; + + if ( RetValue1 == MSAT_FALSE ) + { +//p->time1 += clock() - clk; + +if ( fVerbose ) +{ +// printf( "unsat %d ", Msat_SolverReadBackTracks(p->pSat) ); +//ABC_PRT( "time", clock() - clk ); +} + + // add the clause + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 1) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, fComp) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); + // continue solving the other implication + } + else if ( RetValue1 == MSAT_TRUE ) + { +//p->time2 += clock() - clk; + +if ( fVerbose ) +{ +// printf( "sat %d ", Msat_SolverReadBackTracks(p->pSat) ); +//ABC_PRT( "time", clock() - clk ); +} + + // record the counter example + Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pOld, pNew ); + +// if ( pOld->fFailTfo || pNew->fFailTfo ) +// printf( "*" ); +// printf( "s(%d)", pNew->Level ); + if ( fSwitch ) + printf( "s(%d)", pNew->Level ); + p->nSatCounter++; + return 0; + } + else // if ( RetValue1 == MSAT_UNKNOWN ) + { +p->time3 += clock() - clk; + +// if ( pOld->fFailTfo || pNew->fFailTfo ) +// printf( "*" ); +// printf( "T(%d)", pNew->Level ); + + // mark the node as the failed node + if ( pOld != p->pConst1 ) + pOld->fFailTfo = 1; + pNew->fFailTfo = 1; +// p->nSatFails++; + if ( fSwitch ) + printf( "T(%d)", pNew->Level ); + p->nSatFailsReal++; + return 0; + } + + // if the old node was constant 0, we already know the answer + if ( pOld == p->pConst1 ) + return 1; + + //////////////////////////////////////////// + // prepare the solver to run incrementally +//clk = clock(); + Msat_SolverPrepare( p->pSat, p->vVarsInt ); +//p->time3 += clock() - clk; + // solve under assumptions + // A = 0; B = 1 OR A = 0; B = 0 + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 1) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, fComp) ); + // run the solver +clk = clock(); + RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, nTimeLimit ); +p->timeSat += clock() - clk; + + if ( RetValue1 == MSAT_FALSE ) + { +//p->time1 += clock() - clk; + +if ( fVerbose ) +{ +// printf( "unsat %d ", Msat_SolverReadBackTracks(p->pSat) ); +//ABC_PRT( "time", clock() - clk ); +} + + // add the clause + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 0) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, !fComp) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); + // continue solving the other implication + } + else if ( RetValue1 == MSAT_TRUE ) + { +//p->time2 += clock() - clk; + +if ( fVerbose ) +{ +// printf( "sat %d ", Msat_SolverReadBackTracks(p->pSat) ); +//ABC_PRT( "time", clock() - clk ); +} + + // record the counter example + Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pOld, pNew ); + p->nSatCounter++; + +// if ( pOld->fFailTfo || pNew->fFailTfo ) +// printf( "*" ); +// printf( "s(%d)", pNew->Level ); + if ( fSwitch ) + printf( "s(%d)", pNew->Level ); + return 0; + } + else // if ( RetValue1 == MSAT_UNKNOWN ) + { +p->time3 += clock() - clk; + +// if ( pOld->fFailTfo || pNew->fFailTfo ) +// printf( "*" ); +// printf( "T(%d)", pNew->Level ); + if ( fSwitch ) + printf( "T(%d)", pNew->Level ); + + // mark the node as the failed node + pOld->fFailTfo = 1; + pNew->fFailTfo = 1; +// p->nSatFails++; + p->nSatFailsReal++; + return 0; + } + + // return SAT proof + p->nSatProof++; + +// if ( pOld->fFailTfo || pNew->fFailTfo ) +// printf( "*" ); +// printf( "u(%d)", pNew->Level ); + + if ( fSwitch ) + printf( "u(%d)", pNew->Level ); + + return 1; +} + + +/**Function************************************************************* + + Synopsis [Checks whether pOld => pNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeIsImplication( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit ) +{ + int RetValue, RetValue1, i, fComp, clk; + int fVerbose = 0; + + // make sure the nodes are not complemented + assert( !Fraig_IsComplement(pNew) ); + assert( !Fraig_IsComplement(pOld) ); + assert( pNew != pOld ); + + p->nSatCallsImp++; + + // make sure the solver is allocated and has enough variables + if ( p->pSat == NULL ) + Fraig_ManCreateSolver( p ); + // make sure the SAT solver has enough variables + for ( i = Msat_SolverReadVarNum(p->pSat); i < p->vNodes->nSize; i++ ) + Msat_SolverAddVar( p->pSat, p->vNodes->pArray[i]->Level ); + + // get the logic cone +clk = clock(); + Fraig_OrderVariables( p, pOld, pNew ); +// Fraig_PrepareCones( p, pOld, pNew ); +p->timeTrav += clock() - clk; + +if ( fVerbose ) + printf( "%d(%d) - ", Fraig_CountPis(p,p->vVarsInt), Msat_IntVecReadSize(p->vVarsInt) ); + + + // get the complemented attribute + fComp = Fraig_NodeComparePhase( pOld, pNew ); +//Msat_SolverPrintClauses( p->pSat ); + + //////////////////////////////////////////// + // prepare the solver to run incrementally on these variables +//clk = clock(); + Msat_SolverPrepare( p->pSat, p->vVarsInt ); +//p->time3 += clock() - clk; + + // solve under assumptions + // A = 1; B = 0 OR A = 1; B = 1 + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 0) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, !fComp) ); + // run the solver +clk = clock(); + RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, 1000000 ); +p->timeSat += clock() - clk; + + if ( RetValue1 == MSAT_FALSE ) + { +//p->time1 += clock() - clk; + +if ( fVerbose ) +{ +// printf( "unsat %d ", Msat_SolverReadBackTracks(p->pSat) ); +//ABC_PRT( "time", clock() - clk ); +} + + // add the clause + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 1) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, fComp) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); +// p->nSatProofImp++; + return 1; + } + else if ( RetValue1 == MSAT_TRUE ) + { +//p->time2 += clock() - clk; + +if ( fVerbose ) +{ +// printf( "sat %d ", Msat_SolverReadBackTracks(p->pSat) ); +//ABC_PRT( "time", clock() - clk ); +} + // record the counter example + Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pOld, pNew ); + p->nSatCounterImp++; + return 0; + } + else // if ( RetValue1 == MSAT_UNKNOWN ) + { +p->time3 += clock() - clk; + p->nSatFailsImp++; + return 0; + } +} + +/**Function************************************************************* + + Synopsis [Prepares the SAT solver to run on the two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_ManCheckClauseUsingSat( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit ) +{ + Fraig_Node_t * pNode1R, * pNode2R; + int RetValue, RetValue1, i, clk; + int fVerbose = 0; + + pNode1R = Fraig_Regular(pNode1); + pNode2R = Fraig_Regular(pNode2); + assert( pNode1R != pNode2R ); + + // make sure the solver is allocated and has enough variables + if ( p->pSat == NULL ) + Fraig_ManCreateSolver( p ); + // make sure the SAT solver has enough variables + for ( i = Msat_SolverReadVarNum(p->pSat); i < p->vNodes->nSize; i++ ) + Msat_SolverAddVar( p->pSat, p->vNodes->pArray[i]->Level ); + + // get the logic cone +clk = clock(); + Fraig_OrderVariables( p, pNode1R, pNode2R ); +// Fraig_PrepareCones( p, pNode1R, pNode2R ); +p->timeTrav += clock() - clk; + + //////////////////////////////////////////// + // prepare the solver to run incrementally on these variables +//clk = clock(); + Msat_SolverPrepare( p->pSat, p->vVarsInt ); +//p->time3 += clock() - clk; + + // solve under assumptions + // A = 1; B = 0 OR A = 1; B = 1 + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1R->Num, !Fraig_IsComplement(pNode1)) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2R->Num, !Fraig_IsComplement(pNode2)) ); + // run the solver +clk = clock(); + RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, 1000000 ); +p->timeSat += clock() - clk; + + if ( RetValue1 == MSAT_FALSE ) + { +//p->time1 += clock() - clk; + +if ( fVerbose ) +{ +// printf( "unsat %d ", Msat_SolverReadBackTracks(p->pSat) ); +//ABC_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) ); +//ABC_PRT( "time", clock() - clk ); +} + // record the counter example +// Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pNode1R, pNode2R ); + p->nSatCounterImp++; + return 0; + } + else // if ( RetValue1 == MSAT_UNKNOWN ) + { +p->time3 += clock() - clk; + p->nSatFailsImp++; + return 0; + } +} + + +/**Function************************************************************* + + Synopsis [Prepares the SAT solver to run on the two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_PrepareCones( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) +{ +// Msat_IntVec_t * vAdjs; +// int * pVars, nVars, i, k; + int nVarsAlloc; + + assert( pOld != pNew ); + assert( !Fraig_IsComplement(pOld) ); + assert( !Fraig_IsComplement(pNew) ); + // clean the variables + nVarsAlloc = Msat_IntVecReadSize(pMan->vVarsUsed); + Msat_IntVecFill( pMan->vVarsUsed, nVarsAlloc, 0 ); + Msat_IntVecClear( pMan->vVarsInt ); + + pMan->nTravIds++; + Fraig_PrepareCones_rec( pMan, pNew ); + Fraig_PrepareCones_rec( pMan, pOld ); + + +/* + nVars = Msat_IntVecReadSize( pMan->vVarsInt ); + pVars = Msat_IntVecReadArray( pMan->vVarsInt ); + for ( i = 0; i < nVars; i++ ) + { + // process its connections + vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] ); + printf( "%d=%d { ", pVars[i], Msat_IntVecReadSize(vAdjs) ); + for ( k = 0; k < Msat_IntVecReadSize(vAdjs); k++ ) + printf( "%d ", Msat_IntVecReadEntry(vAdjs,k) ); + printf( "}\n" ); + + } + i = 0; +*/ +} + +/**Function************************************************************* + + Synopsis [Traverses the cone, collects the numbers and adds the clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_PrepareCones_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) +{ + Fraig_Node_t * pFanin; + Msat_IntVec_t * vAdjs; + int fUseMuxes = 1, i; + int fItIsTime; + + // skip if the node is aleady visited + assert( !Fraig_IsComplement(pNode) ); + if ( pNode->TravId == pMan->nTravIds ) + return; + pNode->TravId = pMan->nTravIds; + + // collect the node's number (closer to reverse topological order) + Msat_IntVecPush( pMan->vVarsInt, pNode->Num ); + Msat_IntVecWriteEntry( pMan->vVarsUsed, pNode->Num, 1 ); + if ( !Fraig_NodeIsAnd( pNode ) ) + return; + + // if the node does not have fanins, create them + fItIsTime = 0; + if ( pNode->vFanins == NULL ) + { + fItIsTime = 1; + // create the fanins of the supergate + assert( pNode->fClauses == 0 ); + if ( fUseMuxes && Fraig_NodeIsMuxType(pNode) ) + { + pNode->vFanins = Fraig_NodeVecAlloc( 4 ); + Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p1) ); + Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p2) ); + Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p1) ); + Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p2) ); + Fraig_SupergateAddClausesMux( pMan, pNode ); + } + else + { + pNode->vFanins = Fraig_CollectSupergate( pNode, fUseMuxes ); + Fraig_SupergateAddClauses( pMan, pNode, pNode->vFanins ); + } + assert( pNode->vFanins->nSize > 1 ); + pNode->fClauses = 1; + pMan->nVarsClauses++; + + // add fanins + vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pNode->Num ); + assert( Msat_IntVecReadSize( vAdjs ) == 0 ); + for ( i = 0; i < pNode->vFanins->nSize; i++ ) + { + pFanin = Fraig_Regular(pNode->vFanins->pArray[i]); + Msat_IntVecPush( vAdjs, pFanin->Num ); + } + } + + // recursively visit the fanins + for ( i = 0; i < pNode->vFanins->nSize; i++ ) + Fraig_PrepareCones_rec( pMan, Fraig_Regular(pNode->vFanins->pArray[i]) ); + + if ( fItIsTime ) + { + // recursively visit the fanins + for ( i = 0; i < pNode->vFanins->nSize; i++ ) + { + pFanin = Fraig_Regular(pNode->vFanins->pArray[i]); + vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pFanin->Num ); + Msat_IntVecPush( vAdjs, pNode->Num ); + } + } +} + +/**Function************************************************************* + + Synopsis [Collect variables using their proximity from the nodes.] + + Description [This procedure creates a variable order based on collecting + first the nodes that are the closest to the given two target nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_OrderVariables( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) +{ + Fraig_Node_t * pNode, * pFanin; + int i, k, Number, fUseMuxes = 1; + int nVarsAlloc; + + assert( pOld != pNew ); + assert( !Fraig_IsComplement(pOld) ); + assert( !Fraig_IsComplement(pNew) ); + + pMan->nTravIds++; + + // clean the variables + nVarsAlloc = Msat_IntVecReadSize(pMan->vVarsUsed); + Msat_IntVecFill( pMan->vVarsUsed, nVarsAlloc, 0 ); + Msat_IntVecClear( pMan->vVarsInt ); + + // add the first node + Msat_IntVecPush( pMan->vVarsInt, pOld->Num ); + Msat_IntVecWriteEntry( pMan->vVarsUsed, pOld->Num, 1 ); + pOld->TravId = pMan->nTravIds; + + // add the second node + Msat_IntVecPush( pMan->vVarsInt, pNew->Num ); + Msat_IntVecWriteEntry( pMan->vVarsUsed, pNew->Num, 1 ); + pNew->TravId = pMan->nTravIds; + + // create the variable order + for ( i = 0; i < Msat_IntVecReadSize(pMan->vVarsInt); i++ ) + { + // get the new node on the frontier + Number = Msat_IntVecReadEntry(pMan->vVarsInt, i); + pNode = pMan->vNodes->pArray[Number]; + if ( !Fraig_NodeIsAnd(pNode) ) + continue; + + // if the node does not have fanins, create them + if ( pNode->vFanins == NULL ) + { + // create the fanins of the supergate + assert( pNode->fClauses == 0 ); + // detecting a fanout-free cone (experiment only) +// Fraig_DetectFanoutFreeCone( pMan, pNode ); + + if ( fUseMuxes && Fraig_NodeIsMuxType(pNode) ) + { + pNode->vFanins = Fraig_NodeVecAlloc( 4 ); + Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p1) ); + Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p2) ); + Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p1) ); + Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p2) ); + Fraig_SupergateAddClausesMux( pMan, pNode ); +// Fraig_DetectFanoutFreeConeMux( pMan, pNode ); + + nMuxes++; + } + else + { + pNode->vFanins = Fraig_CollectSupergate( pNode, fUseMuxes ); + Fraig_SupergateAddClauses( pMan, pNode, pNode->vFanins ); + } + assert( pNode->vFanins->nSize > 1 ); + pNode->fClauses = 1; + pMan->nVarsClauses++; + + pNode->fMark2 = 1; // goes together with Fraig_SetupAdjacentMark() + } + + // explore the implication fanins of pNode + for ( k = 0; k < pNode->vFanins->nSize; k++ ) + { + pFanin = Fraig_Regular(pNode->vFanins->pArray[k]); + if ( pFanin->TravId == pMan->nTravIds ) // already collected + continue; + // collect and mark + Msat_IntVecPush( pMan->vVarsInt, pFanin->Num ); + Msat_IntVecWriteEntry( pMan->vVarsUsed, pFanin->Num, 1 ); + pFanin->TravId = pMan->nTravIds; + } + } + + // set up the adjacent variable information +// Fraig_SetupAdjacent( pMan, pMan->vVarsInt ); + Fraig_SetupAdjacentMark( pMan, pMan->vVarsInt ); +} + + + +/**Function************************************************************* + + Synopsis [Set up the adjacent variable information.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_SetupAdjacent( Fraig_Man_t * pMan, Msat_IntVec_t * vConeVars ) +{ + Fraig_Node_t * pNode, * pFanin; + Msat_IntVec_t * vAdjs; + int * pVars, nVars, i, k; + + // clean the adjacents for the variables + nVars = Msat_IntVecReadSize( vConeVars ); + pVars = Msat_IntVecReadArray( vConeVars ); + for ( i = 0; i < nVars; i++ ) + { + // process its connections + vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] ); + Msat_IntVecClear( vAdjs ); + + pNode = pMan->vNodes->pArray[pVars[i]]; + if ( !Fraig_NodeIsAnd(pNode) ) + continue; + + // add fanins + vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] ); + for ( k = 0; k < pNode->vFanins->nSize; k++ ) +// for ( k = pNode->vFanins->nSize - 1; k >= 0; k-- ) + { + pFanin = Fraig_Regular(pNode->vFanins->pArray[k]); + Msat_IntVecPush( vAdjs, pFanin->Num ); +// Msat_IntVecPushUniqueOrder( vAdjs, pFanin->Num ); + } + } + // add the fanouts + for ( i = 0; i < nVars; i++ ) + { + pNode = pMan->vNodes->pArray[pVars[i]]; + if ( !Fraig_NodeIsAnd(pNode) ) + continue; + + // add the edges + for ( k = 0; k < pNode->vFanins->nSize; k++ ) +// for ( k = pNode->vFanins->nSize - 1; k >= 0; k-- ) + { + pFanin = Fraig_Regular(pNode->vFanins->pArray[k]); + vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pFanin->Num ); + Msat_IntVecPush( vAdjs, pNode->Num ); +// Msat_IntVecPushUniqueOrder( vAdjs, pFanin->Num ); + } + } +} + + +/**Function************************************************************* + + Synopsis [Set up the adjacent variable information.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_SetupAdjacentMark( Fraig_Man_t * pMan, Msat_IntVec_t * vConeVars ) +{ + Fraig_Node_t * pNode, * pFanin; + Msat_IntVec_t * vAdjs; + int * pVars, nVars, i, k; + + // clean the adjacents for the variables + nVars = Msat_IntVecReadSize( vConeVars ); + pVars = Msat_IntVecReadArray( vConeVars ); + for ( i = 0; i < nVars; i++ ) + { + pNode = pMan->vNodes->pArray[pVars[i]]; + if ( pNode->fMark2 == 0 ) + continue; +// pNode->fMark2 = 0; + + // process its connections +// vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] ); +// Msat_IntVecClear( vAdjs ); + + if ( !Fraig_NodeIsAnd(pNode) ) + continue; + + // add fanins + vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] ); + for ( k = 0; k < pNode->vFanins->nSize; k++ ) +// for ( k = pNode->vFanins->nSize - 1; k >= 0; k-- ) + { + pFanin = Fraig_Regular(pNode->vFanins->pArray[k]); + Msat_IntVecPush( vAdjs, pFanin->Num ); +// Msat_IntVecPushUniqueOrder( vAdjs, pFanin->Num ); + } + } + // add the fanouts + for ( i = 0; i < nVars; i++ ) + { + pNode = pMan->vNodes->pArray[pVars[i]]; + if ( pNode->fMark2 == 0 ) + continue; + pNode->fMark2 = 0; + + if ( !Fraig_NodeIsAnd(pNode) ) + continue; + + // add the edges + for ( k = 0; k < pNode->vFanins->nSize; k++ ) +// for ( k = pNode->vFanins->nSize - 1; k >= 0; k-- ) + { + pFanin = Fraig_Regular(pNode->vFanins->pArray[k]); + vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pFanin->Num ); + Msat_IntVecPush( vAdjs, pNode->Num ); +// Msat_IntVecPushUniqueOrder( vAdjs, pFanin->Num ); + } + } +} + + + + +/**Function************************************************************* + + Synopsis [Adds clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_SupergateAddClauses( Fraig_Man_t * p, Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper ) +{ + int fComp1, RetValue, nVars, Var, Var1, i; + + assert( Fraig_NodeIsAnd( pNode ) ); + nVars = Msat_SolverReadVarNum(p->pSat); + + Var = pNode->Num; + assert( Var < nVars ); + for ( i = 0; i < vSuper->nSize; i++ ) + { + // get the predecessor nodes + // get the complemented attributes of the nodes + fComp1 = Fraig_IsComplement(vSuper->pArray[i]); + // determine the variable numbers + Var1 = Fraig_Regular(vSuper->pArray[i])->Num; + // check that the variables are in the SAT manager + assert( Var1 < nVars ); + + // suppose the AND-gate is A * B = C + // add !A => !C or A + !C + // fprintf( pFile, "%d %d 0%c", Var1, -Var, 10 ); + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(Var1, fComp1) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(Var, 1) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); + } + + // add A & B => C or !A + !B + C +// fprintf( pFile, "%d %d %d 0%c", -Var1, -Var2, Var, 10 ); + Msat_IntVecClear( p->vProj ); + for ( i = 0; i < vSuper->nSize; i++ ) + { + // get the predecessor nodes + // get the complemented attributes of the nodes + fComp1 = Fraig_IsComplement(vSuper->pArray[i]); + // determine the variable numbers + Var1 = Fraig_Regular(vSuper->pArray[i])->Num; + + // add this variable to the array + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(Var1, !fComp1) ); + } + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(Var, 0) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); +} + +/**Function************************************************************* + + Synopsis [Adds clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_SupergateAddClausesExor( Fraig_Man_t * p, Fraig_Node_t * pNode ) +{ + Fraig_Node_t * pNode1, * pNode2; + int fComp, RetValue; + + assert( !Fraig_IsComplement( pNode ) ); + assert( Fraig_NodeIsExorType( pNode ) ); + // get nodes + pNode1 = Fraig_Regular(Fraig_Regular(pNode->p1)->p1); + pNode2 = Fraig_Regular(Fraig_Regular(pNode->p1)->p2); + // get the complemented attribute of the EXOR/NEXOR gate + fComp = Fraig_NodeIsExor( pNode ); // 1 if EXOR, 0 if NEXOR + + // create four clauses + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, fComp) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1->Num, fComp) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2->Num, fComp) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, fComp) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1->Num, !fComp) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2->Num, !fComp) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, !fComp) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1->Num, fComp) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2->Num, !fComp) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, !fComp) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1->Num, !fComp) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2->Num, fComp) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); +} + +/**Function************************************************************* + + Synopsis [Adds clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_SupergateAddClausesMux( Fraig_Man_t * p, Fraig_Node_t * pNode ) +{ + Fraig_Node_t * pNodeI, * pNodeT, * pNodeE; + int RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE; + + assert( !Fraig_IsComplement( pNode ) ); + assert( Fraig_NodeIsMuxType( pNode ) ); + // get nodes (I = if, T = then, E = else) + pNodeI = Fraig_NodeRecognizeMux( pNode, &pNodeT, &pNodeE ); + // get the variable numbers + VarF = pNode->Num; + VarI = pNodeI->Num; + VarT = Fraig_Regular(pNodeT)->Num; + VarE = Fraig_Regular(pNodeE)->Num; + // get the complementation flags + fCompT = Fraig_IsComplement(pNodeT); + fCompE = Fraig_IsComplement(pNodeE); + + // f = ITE(i, t, e) + + // i' + t' + f + // i' + t + f' + // i + e' + f + // i + e + f' + + // create four clauses + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarI, 1) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT, 1^fCompT) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 0) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarI, 1) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT, 0^fCompT) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 1) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarI, 0) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE, 1^fCompE) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 0) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarI, 0) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE, 0^fCompE) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 1) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); + + // two additional clauses + // t' & e' -> f' + // t & e -> f + + // t + e + f' + // t' + e' + f + + if ( VarT == VarE ) + { +// assert( fCompT == !fCompE ); + return; + } + + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT, 0^fCompT) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE, 0^fCompE) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 1) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT, 1^fCompT) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE, 1^fCompE) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 0) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); + +} + + + + + +/**Function************************************************************* + + Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_DetectFanoutFreeCone_rec( Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper, Fraig_NodeVec_t * vInside, int fFirst ) +{ + // make the pointer regular + pNode = Fraig_Regular(pNode); + // if the new node is complemented or a PI, another gate begins + if ( (!fFirst && pNode->nRefs > 1) || Fraig_NodeIsVar(pNode) ) + { + Fraig_NodeVecPushUnique( vSuper, pNode ); + return; + } + // go through the branches + Fraig_DetectFanoutFreeCone_rec( pNode->p1, vSuper, vInside, 0 ); + Fraig_DetectFanoutFreeCone_rec( pNode->p2, vSuper, vInside, 0 ); + // add the node + Fraig_NodeVecPushUnique( vInside, pNode ); +} + +/**Function************************************************************* + + Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +/* +void Fraig_DetectFanoutFreeCone( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) +{ + Fraig_NodeVec_t * vFanins; + Fraig_NodeVec_t * vInside; + int nCubes; + extern int Fraig_CutSopCountCubes( Fraig_Man_t * pMan, Fraig_NodeVec_t * vFanins, Fraig_NodeVec_t * vInside ); + + vFanins = Fraig_NodeVecAlloc( 8 ); + vInside = Fraig_NodeVecAlloc( 8 ); + + Fraig_DetectFanoutFreeCone_rec( pNode, vFanins, vInside, 1 ); + assert( vInside->pArray[vInside->nSize-1] == pNode ); + + nCubes = Fraig_CutSopCountCubes( pMan, vFanins, vInside ); + +printf( "%d(%d)", vFanins->nSize, nCubes ); + Fraig_NodeVecFree( vFanins ); + Fraig_NodeVecFree( vInside ); +} +*/ + + + +/**Function************************************************************* + + Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_DetectFanoutFreeConeMux_rec( Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper, Fraig_NodeVec_t * vInside, int fFirst ) +{ + // make the pointer regular + pNode = Fraig_Regular(pNode); + // if the new node is complemented or a PI, another gate begins + if ( (!fFirst && pNode->nRefs > 1) || Fraig_NodeIsVar(pNode) || !Fraig_NodeIsMuxType(pNode) ) + { + Fraig_NodeVecPushUnique( vSuper, pNode ); + return; + } + // go through the branches + Fraig_DetectFanoutFreeConeMux_rec( Fraig_Regular(pNode->p1)->p1, vSuper, vInside, 0 ); + Fraig_DetectFanoutFreeConeMux_rec( Fraig_Regular(pNode->p1)->p2, vSuper, vInside, 0 ); + Fraig_DetectFanoutFreeConeMux_rec( Fraig_Regular(pNode->p2)->p1, vSuper, vInside, 0 ); + Fraig_DetectFanoutFreeConeMux_rec( Fraig_Regular(pNode->p2)->p2, vSuper, vInside, 0 ); + // add the node + Fraig_NodeVecPushUnique( vInside, pNode ); +} + +/**Function************************************************************* + + Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_DetectFanoutFreeConeMux( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) +{ + Fraig_NodeVec_t * vFanins; + Fraig_NodeVec_t * vInside; + int nCubes; + extern int Fraig_CutSopCountCubes( Fraig_Man_t * pMan, Fraig_NodeVec_t * vFanins, Fraig_NodeVec_t * vInside ); + + vFanins = Fraig_NodeVecAlloc( 8 ); + vInside = Fraig_NodeVecAlloc( 8 ); + + Fraig_DetectFanoutFreeConeMux_rec( pNode, vFanins, vInside, 1 ); + assert( vInside->pArray[vInside->nSize-1] == pNode ); + +// nCubes = Fraig_CutSopCountCubes( pMan, vFanins, vInside ); + nCubes = 0; + +printf( "%d(%d)", vFanins->nSize, nCubes ); + Fraig_NodeVecFree( vFanins ); + Fraig_NodeVecFree( vInside ); +} + + + +/**Function************************************************************* + + Synopsis [Collect variables using their proximity from the nodes.] + + Description [This procedure creates a variable order based on collecting + first the nodes that are the closest to the given two target nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_SetActivity( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) +{ + Fraig_Node_t * pNode; + int i, Number, MaxLevel; + float * pFactors = Msat_SolverReadFactors(pMan->pSat); + if ( pFactors == NULL ) + return; + MaxLevel = Abc_MaxInt( 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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fraig/fraigTable.c b/src/proof/fraig/fraigTable.c new file mode 100644 index 00000000..6611e4fa --- /dev/null +++ b/src/proof/fraig/fraigTable.c @@ -0,0 +1,662 @@ +/**CFile**************************************************************** + + FileName [fraigTable.c] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [Structural and functional hash tables.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - October 1, 2004] + + Revision [$Id: fraigTable.c,v 1.7 2005/07/08 01:01:34 alanmi Exp $] + +***********************************************************************/ + +#include "fraigInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Fraig_TableResizeS( Fraig_HashTable_t * p ); +static void Fraig_TableResizeF( Fraig_HashTable_t * p, int fUseSimR ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_HashTable_t * Fraig_HashTableCreate( int nSize ) +{ + Fraig_HashTable_t * p; + // allocate the table + p = ABC_ALLOC( Fraig_HashTable_t, 1 ); + memset( p, 0, sizeof(Fraig_HashTable_t) ); + // allocate and clean the bins + p->nBins = Abc_PrimeCudd(nSize); + p->pBins = ABC_ALLOC( Fraig_Node_t *, p->nBins ); + memset( p->pBins, 0, sizeof(Fraig_Node_t *) * p->nBins ); + return p; +} + +/**Function************************************************************* + + Synopsis [Deallocates the supergate hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_HashTableFree( Fraig_HashTable_t * p ) +{ + ABC_FREE( p->pBins ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Looks up an entry in the structural hash table.] + + Description [If the entry with the same children does not exists, + creates it, inserts it into the table, and returns 0. If the entry + with the same children exists, finds it, and return 1. In both cases, + the new/old entry is returned in ppNodeRes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_HashTableLookupS( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2, Fraig_Node_t ** ppNodeRes ) +{ + Fraig_HashTable_t * p = pMan->pTableS; + Fraig_Node_t * pEnt; + unsigned Key; + + // order the arguments + if ( Fraig_Regular(p1)->Num > Fraig_Regular(p2)->Num ) + pEnt = p1, p1 = p2, p2 = pEnt; + + Key = Fraig_HashKey2( p1, p2, p->nBins ); + Fraig_TableBinForEachEntryS( p->pBins[Key], pEnt ) + if ( pEnt->p1 == p1 && pEnt->p2 == p2 ) + { + *ppNodeRes = pEnt; + return 1; + } + // check if it is a good time for table resizing + if ( p->nEntries >= 2 * p->nBins ) + { + Fraig_TableResizeS( p ); + Key = Fraig_HashKey2( p1, p2, p->nBins ); + } + // create the new node + pEnt = Fraig_NodeCreate( pMan, p1, p2 ); + // add the node to the corresponding linked list in the table + pEnt->pNextS = p->pBins[Key]; + p->pBins[Key] = pEnt; + *ppNodeRes = pEnt; + p->nEntries++; + return 0; +} + + +/**Function************************************************************* + + Synopsis [Insert the entry in the functional hash table.] + + Description [If the entry with the same key exists, return it right away. + If the entry with the same key does not exists, inserts it and returns NULL. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_HashTableLookupF( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) +{ + Fraig_HashTable_t * p = pMan->pTableF; + Fraig_Node_t * pEnt, * pEntD; + unsigned Key; + + // go through the hash table entries + Key = pNode->uHashR % p->nBins; + Fraig_TableBinForEachEntryF( p->pBins[Key], pEnt ) + { + // if their simulation info differs, skip + if ( !Fraig_CompareSimInfo( pNode, pEnt, pMan->nWordsRand, 1 ) ) + continue; + // equivalent up to the complement + Fraig_TableBinForEachEntryD( pEnt, pEntD ) + { + // if their simulation info differs, skip + if ( !Fraig_CompareSimInfo( pNode, pEntD, pMan->iWordStart, 0 ) ) + continue; + // found a simulation-equivalent node + return pEntD; + } + // did not find a simulation equivalent node + // add the node to the corresponding linked list + pNode->pNextD = pEnt->pNextD; + pEnt->pNextD = pNode; + // return NULL, because there is no functional equivalence in this case + return NULL; + } + + // check if it is a good time for table resizing + if ( p->nEntries >= 2 * p->nBins ) + { + Fraig_TableResizeF( p, 1 ); + Key = pNode->uHashR % p->nBins; + } + + // add the node to the corresponding linked list in the table + pNode->pNextF = p->pBins[Key]; + p->pBins[Key] = pNode; + p->nEntries++; + // return NULL, because there is no functional equivalence in this case + return NULL; +} + +/**Function************************************************************* + + Synopsis [Insert the entry in the functional hash table.] + + Description [If the entry with the same key exists, return it right away. + If the entry with the same key does not exists, inserts it and returns NULL. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_HashTableLookupF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) +{ + Fraig_HashTable_t * p = pMan->pTableF0; + Fraig_Node_t * pEnt; + unsigned Key; + + // go through the hash table entries + Key = pNode->uHashD % p->nBins; + Fraig_TableBinForEachEntryF( p->pBins[Key], pEnt ) + { + // if their simulation info differs, skip + if ( !Fraig_CompareSimInfo( pNode, pEnt, pMan->iWordStart, 0 ) ) + continue; + // found a simulation-equivalent node + return pEnt; + } + + // check if it is a good time for table resizing + if ( p->nEntries >= 2 * p->nBins ) + { + Fraig_TableResizeF( p, 0 ); + Key = pNode->uHashD % p->nBins; + } + + // add the node to the corresponding linked list in the table + pNode->pNextF = p->pBins[Key]; + p->pBins[Key] = pNode; + p->nEntries++; + // return NULL, because there is no functional equivalence in this case + return NULL; +} + +/**Function************************************************************* + + Synopsis [Insert the entry in the functional hash table.] + + Description [Unconditionally add the node to the corresponding + linked list in the table.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_HashTableInsertF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) +{ + Fraig_HashTable_t * p = pMan->pTableF0; + unsigned Key = pNode->uHashD % p->nBins; + + pNode->pNextF = p->pBins[Key]; + p->pBins[Key] = pNode; + p->nEntries++; +} + + +/**Function************************************************************* + + Synopsis [Resizes the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_TableResizeS( Fraig_HashTable_t * p ) +{ + Fraig_Node_t ** pBinsNew; + Fraig_Node_t * pEnt, * pEnt2; + int nBinsNew, Counter, i, clk; + unsigned Key; + +clk = clock(); + // get the new table size + nBinsNew = Abc_PrimeCudd(2 * p->nBins); + // allocate a new array + pBinsNew = ABC_ALLOC( Fraig_Node_t *, nBinsNew ); + memset( pBinsNew, 0, sizeof(Fraig_Node_t *) * nBinsNew ); + // rehash the entries from the old table + Counter = 0; + for ( i = 0; i < p->nBins; i++ ) + Fraig_TableBinForEachEntrySafeS( p->pBins[i], pEnt, pEnt2 ) + { + Key = Fraig_HashKey2( pEnt->p1, pEnt->p2, nBinsNew ); + pEnt->pNextS = pBinsNew[Key]; + pBinsNew[Key] = pEnt; + Counter++; + } + assert( Counter == p->nEntries ); +// printf( "Increasing the structural table size from %6d to %6d. ", p->nBins, nBinsNew ); +// ABC_PRT( "Time", clock() - clk ); + // replace the table and the parameters + ABC_FREE( p->pBins ); + p->pBins = pBinsNew; + p->nBins = nBinsNew; +} + +/**Function************************************************************* + + Synopsis [Resizes the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_TableResizeF( Fraig_HashTable_t * p, int fUseSimR ) +{ + Fraig_Node_t ** pBinsNew; + Fraig_Node_t * pEnt, * pEnt2; + int nBinsNew, Counter, i, clk; + unsigned Key; + +clk = clock(); + // get the new table size + nBinsNew = Abc_PrimeCudd(2 * p->nBins); + // allocate a new array + pBinsNew = ABC_ALLOC( Fraig_Node_t *, nBinsNew ); + memset( pBinsNew, 0, sizeof(Fraig_Node_t *) * nBinsNew ); + // rehash the entries from the old table + Counter = 0; + for ( i = 0; i < p->nBins; i++ ) + Fraig_TableBinForEachEntrySafeF( p->pBins[i], pEnt, pEnt2 ) + { + if ( fUseSimR ) + Key = pEnt->uHashR % nBinsNew; + else + Key = pEnt->uHashD % nBinsNew; + pEnt->pNextF = pBinsNew[Key]; + pBinsNew[Key] = pEnt; + Counter++; + } + assert( Counter == p->nEntries ); +// printf( "Increasing the functional table size from %6d to %6d. ", p->nBins, nBinsNew ); +// ABC_PRT( "Time", clock() - clk ); + // replace the table and the parameters + ABC_FREE( p->pBins ); + p->pBins = pBinsNew; + p->nBins = nBinsNew; +} + + +/**Function************************************************************* + + Synopsis [Compares two pieces of simulation info.] + + Description [Returns 1 if they are equal.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_CompareSimInfo( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand ) +{ + int i; + assert( !Fraig_IsComplement(pNode1) ); + assert( !Fraig_IsComplement(pNode2) ); + if ( fUseRand ) + { + // if their signatures differ, skip + if ( pNode1->uHashR != pNode2->uHashR ) + return 0; + // check the simulation info + for ( i = 0; i < iWordLast; i++ ) + if ( pNode1->puSimR[i] != pNode2->puSimR[i] ) + return 0; + } + else + { + // if their signatures differ, skip + if ( pNode1->uHashD != pNode2->uHashD ) + return 0; + // check the simulation info + for ( i = 0; i < iWordLast; i++ ) + if ( pNode1->puSimD[i] != pNode2->puSimD[i] ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Find the number of the different pattern.] + + Description [Returns -1 if there is no such pattern] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_FindFirstDiff( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int fCompl, int iWordLast, int fUseRand ) +{ + int i, v; + assert( !Fraig_IsComplement(pNode1) ); + assert( !Fraig_IsComplement(pNode2) ); + // take into account possible internal complementation + fCompl ^= pNode1->fInv; + fCompl ^= pNode2->fInv; + // find the pattern + if ( fCompl ) + { + if ( fUseRand ) + { + for ( i = 0; i < iWordLast; i++ ) + if ( pNode1->puSimR[i] != ~pNode2->puSimR[i] ) + for ( v = 0; v < 32; v++ ) + if ( (pNode1->puSimR[i] ^ ~pNode2->puSimR[i]) & (1 << v) ) + return i * 32 + v; + } + else + { + for ( i = 0; i < iWordLast; i++ ) + if ( pNode1->puSimD[i] != ~pNode2->puSimD[i] ) + for ( v = 0; v < 32; v++ ) + if ( (pNode1->puSimD[i] ^ ~pNode2->puSimD[i]) & (1 << v) ) + return i * 32 + v; + } + } + else + { + if ( fUseRand ) + { + for ( i = 0; i < iWordLast; i++ ) + if ( pNode1->puSimR[i] != pNode2->puSimR[i] ) + for ( v = 0; v < 32; v++ ) + if ( (pNode1->puSimR[i] ^ pNode2->puSimR[i]) & (1 << v) ) + return i * 32 + v; + } + else + { + for ( i = 0; i < iWordLast; i++ ) + if ( pNode1->puSimD[i] != pNode2->puSimD[i] ) + for ( v = 0; v < 32; v++ ) + if ( (pNode1->puSimD[i] ^ pNode2->puSimD[i]) & (1 << v) ) + return i * 32 + v; + } + } + return -1; +} + +/**Function************************************************************* + + Synopsis [Compares two pieces of simulation info.] + + Description [Returns 1 if they are equal.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_CompareSimInfoUnderMask( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask ) +{ + unsigned * pSims1, * pSims2; + int i; + assert( !Fraig_IsComplement(pNode1) ); + assert( !Fraig_IsComplement(pNode2) ); + // get hold of simulation info + pSims1 = fUseRand? pNode1->puSimR : pNode1->puSimD; + pSims2 = fUseRand? pNode2->puSimR : pNode2->puSimD; + // check the simulation info + for ( i = 0; i < iWordLast; i++ ) + if ( (pSims1[i] & puMask[i]) != (pSims2[i] & puMask[i]) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Compares two pieces of simulation info.] + + Description [Returns 1 if they are equal.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_CollectXors( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask ) +{ + unsigned * pSims1, * pSims2; + int i; + assert( !Fraig_IsComplement(pNode1) ); + assert( !Fraig_IsComplement(pNode2) ); + // get hold of simulation info + pSims1 = fUseRand? pNode1->puSimR : pNode1->puSimD; + pSims2 = fUseRand? pNode2->puSimR : pNode2->puSimD; + // check the simulation info + for ( i = 0; i < iWordLast; i++ ) + puMask[i] = ( pSims1[i] ^ pSims2[i] ); +} + + +/**Function************************************************************* + + Synopsis [Prints stats of the structural table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_TablePrintStatsS( Fraig_Man_t * pMan ) +{ + Fraig_HashTable_t * pT = pMan->pTableS; + Fraig_Node_t * pNode; + int i, Counter; + + printf( "Structural table. Table size = %d. Number of entries = %d.\n", pT->nBins, pT->nEntries ); + for ( i = 0; i < pT->nBins; i++ ) + { + Counter = 0; + Fraig_TableBinForEachEntryS( pT->pBins[i], pNode ) + Counter++; + if ( Counter > 1 ) + { + printf( "%d ", Counter ); + if ( Counter > 50 ) + printf( "{%d} ", i ); + } + } + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints stats of the structural table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_TablePrintStatsF( Fraig_Man_t * pMan ) +{ + Fraig_HashTable_t * pT = pMan->pTableF; + Fraig_Node_t * pNode; + int i, Counter; + + printf( "Functional table. Table size = %d. Number of entries = %d.\n", pT->nBins, pT->nEntries ); + for ( i = 0; i < pT->nBins; i++ ) + { + Counter = 0; + Fraig_TableBinForEachEntryF( pT->pBins[i], pNode ) + Counter++; + if ( Counter > 1 ) + printf( "{%d} ", Counter ); + } + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints stats of the structural table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_TablePrintStatsF0( Fraig_Man_t * pMan ) +{ + Fraig_HashTable_t * pT = pMan->pTableF0; + Fraig_Node_t * pNode; + int i, Counter; + + printf( "Zero-node table. Table size = %d. Number of entries = %d.\n", pT->nBins, pT->nEntries ); + for ( i = 0; i < pT->nBins; i++ ) + { + Counter = 0; + Fraig_TableBinForEachEntryF( pT->pBins[i], pNode ) + Counter++; + if ( Counter == 0 ) + continue; +/* + printf( "\nBin = %4d : Number of entries = %4d\n", i, Counter ); + Fraig_TableBinForEachEntryF( pT->pBins[i], pNode ) + printf( "Node %5d. Hash = %10d.\n", pNode->Num, pNode->uHashD ); +*/ + } + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Rehashes the table after the simulation info has changed.] + + Description [Assumes that the hash values have been updated after performing + additional simulation. Rehashes the table using the new hash values. + Uses pNextF to link the entries in the bins. Uses pNextD to link the entries + with identical hash values. Returns 1 if the identical entries have been found. + Note that identical hash values may mean that the simulation data is different.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_TableRehashF0( Fraig_Man_t * pMan, int fLinkEquiv ) +{ + Fraig_HashTable_t * pT = pMan->pTableF0; + Fraig_Node_t ** pBinsNew; + Fraig_Node_t * pEntF, * pEntF2, * pEnt, * pEntD2, * pEntN; + int ReturnValue, Counter, i; + unsigned Key; + + // allocate a new array of bins + pBinsNew = ABC_ALLOC( Fraig_Node_t *, pT->nBins ); + memset( pBinsNew, 0, sizeof(Fraig_Node_t *) * pT->nBins ); + + // rehash the entries in the table + // go through all the nodes in the F-lists (and possible in D-lists, if used) + Counter = 0; + ReturnValue = 0; + for ( i = 0; i < pT->nBins; i++ ) + Fraig_TableBinForEachEntrySafeF( pT->pBins[i], pEntF, pEntF2 ) + Fraig_TableBinForEachEntrySafeD( pEntF, pEnt, pEntD2 ) + { + // decide where to put entry pEnt + Key = pEnt->uHashD % pT->nBins; + if ( fLinkEquiv ) + { + // go through the entries in the new bin + Fraig_TableBinForEachEntryF( pBinsNew[Key], pEntN ) + { + // if they have different values skip + if ( pEnt->uHashD != pEntN->uHashD ) + continue; + // they have the same hash value, add pEnt to the D-list pEnt3 + pEnt->pNextD = pEntN->pNextD; + pEntN->pNextD = pEnt; + ReturnValue = 1; + Counter++; + break; + } + if ( pEntN != NULL ) // already linked + continue; + // we did not find equal entry + } + // link the new entry + pEnt->pNextF = pBinsNew[Key]; + pBinsNew[Key] = pEnt; + pEnt->pNextD = NULL; + Counter++; + } + assert( Counter == pT->nEntries ); + // replace the table and the parameters + ABC_FREE( pT->pBins ); + pT->pBins = pBinsNew; + return ReturnValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fraig/fraigUtil.c b/src/proof/fraig/fraigUtil.c new file mode 100644 index 00000000..ae78a61f --- /dev/null +++ b/src/proof/fraig/fraigUtil.c @@ -0,0 +1,1039 @@ +/**CFile**************************************************************** + + FileName [fraigUtil.c] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [Various utilities.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - October 1, 2004] + + Revision [$Id: fraigUtil.c,v 1.15 2005/07/08 01:01:34 alanmi Exp $] + +***********************************************************************/ + +#include "fraigInt.h" +#include + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int bit_count[256] = { + 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, + 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 +}; + +static void Fraig_Dfs_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_NodeVec_t * vNodes, int fEquiv ); +static int Fraig_CheckTfi_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_Node_t * pOld ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_NodeVec_t * Fraig_Dfs( Fraig_Man_t * pMan, int fEquiv ) +{ + Fraig_NodeVec_t * vNodes; + int i; + pMan->nTravIds++; + vNodes = Fraig_NodeVecAlloc( 100 ); + for ( i = 0; i < pMan->vOutputs->nSize; i++ ) + Fraig_Dfs_rec( pMan, Fraig_Regular(pMan->vOutputs->pArray[i]), vNodes, fEquiv ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_NodeVec_t * Fraig_DfsOne( Fraig_Man_t * pMan, Fraig_Node_t * pNode, int fEquiv ) +{ + Fraig_NodeVec_t * vNodes; + pMan->nTravIds++; + vNodes = Fraig_NodeVecAlloc( 100 ); + Fraig_Dfs_rec( pMan, Fraig_Regular(pNode), vNodes, fEquiv ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_NodeVec_t * Fraig_DfsNodes( Fraig_Man_t * pMan, Fraig_Node_t ** ppNodes, int nNodes, int fEquiv ) +{ + Fraig_NodeVec_t * vNodes; + int i; + pMan->nTravIds++; + vNodes = Fraig_NodeVecAlloc( 100 ); + for ( i = 0; i < nNodes; i++ ) + Fraig_Dfs_rec( pMan, Fraig_Regular(ppNodes[i]), vNodes, fEquiv ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Recursively computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_Dfs_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_NodeVec_t * vNodes, int fEquiv ) +{ + assert( !Fraig_IsComplement(pNode) ); + // skip the visited node + if ( pNode->TravId == pMan->nTravIds ) + return; + pNode->TravId = pMan->nTravIds; + // visit the transitive fanin + if ( Fraig_NodeIsAnd(pNode) ) + { + Fraig_Dfs_rec( pMan, Fraig_Regular(pNode->p1), vNodes, fEquiv ); + Fraig_Dfs_rec( pMan, Fraig_Regular(pNode->p2), vNodes, fEquiv ); + } + if ( fEquiv && pNode->pNextE ) + Fraig_Dfs_rec( pMan, pNode->pNextE, vNodes, fEquiv ); + // save the node + Fraig_NodeVecPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_CountNodes( Fraig_Man_t * pMan, int fEquiv ) +{ + Fraig_NodeVec_t * vNodes; + int RetValue; + vNodes = Fraig_Dfs( pMan, fEquiv ); + RetValue = vNodes->nSize; + Fraig_NodeVecFree( vNodes ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pOld is in the TFI of pNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_CheckTfi( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) +{ + assert( !Fraig_IsComplement(pOld) ); + assert( !Fraig_IsComplement(pNew) ); + pMan->nTravIds++; + return Fraig_CheckTfi_rec( pMan, pNew, pOld ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pOld is in the TFI of pNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_CheckTfi_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_Node_t * pOld ) +{ + // check the trivial cases + if ( pNode == NULL ) + return 0; + if ( pNode->Num < pOld->Num && !pMan->fChoicing ) + return 0; + if ( pNode == pOld ) + return 1; + // skip the visited node + if ( pNode->TravId == pMan->nTravIds ) + return 0; + pNode->TravId = pMan->nTravIds; + // check the children + if ( Fraig_CheckTfi_rec( pMan, Fraig_Regular(pNode->p1), pOld ) ) + return 1; + if ( Fraig_CheckTfi_rec( pMan, Fraig_Regular(pNode->p2), pOld ) ) + return 1; + // check equivalent nodes + return Fraig_CheckTfi_rec( pMan, pNode->pNextE, pOld ); +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if pOld is in the TFI of pNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_CheckTfi2( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) +{ + Fraig_NodeVec_t * vNodes; + int RetValue; + vNodes = Fraig_DfsOne( pMan, pNew, 1 ); + RetValue = (pOld->TravId == pMan->nTravIds); + Fraig_NodeVecFree( vNodes ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Sets the number of fanouts (none, one, or many).] + + Description [This procedure collects the nodes reachable from + the POs of the AIG and sets the type of fanout counter (none, one, + or many) for each node. This procedure is useful to determine + fanout-free cones of AND-nodes, which is helpful for rebalancing + the AIG (see procedure Fraig_ManRebalance, or something like that).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_ManMarkRealFanouts( Fraig_Man_t * p ) +{ + Fraig_NodeVec_t * vNodes; + Fraig_Node_t * pNodeR; + int i; + // collect the nodes reachable + vNodes = Fraig_Dfs( p, 0 ); + // clean the fanouts field + for ( i = 0; i < vNodes->nSize; i++ ) + { + vNodes->pArray[i]->nFanouts = 0; + vNodes->pArray[i]->pData0 = NULL; + } + // mark reachable nodes by setting the two-bit counter pNode->nFans + for ( i = 0; i < vNodes->nSize; i++ ) + { + pNodeR = Fraig_Regular(vNodes->pArray[i]->p1); + if ( pNodeR && ++pNodeR->nFanouts == 3 ) + pNodeR->nFanouts = 2; + pNodeR = Fraig_Regular(vNodes->pArray[i]->p2); + if ( pNodeR && ++pNodeR->nFanouts == 3 ) + pNodeR->nFanouts = 2; + } + Fraig_NodeVecFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Creates the constant 1 node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_BitStringCountOnes( unsigned * pString, int nWords ) +{ + unsigned char * pSuppBytes = (unsigned char *)pString; + int i, nOnes, nBytes = sizeof(unsigned) * nWords; + // count the number of ones in the simulation vector + for ( i = nOnes = 0; i < nBytes; i++ ) + nOnes += bit_count[pSuppBytes[i]]; + return nOnes; +} + +/**Function************************************************************* + + Synopsis [Verify one useful property.] + + Description [This procedure verifies one useful property. After + the FRAIG construction with choice nodes is over, each primary node + should have fanins that are primary nodes. The primary nodes is the + one that does not have pNode->pRepr set to point to another node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_ManCheckConsistency( Fraig_Man_t * p ) +{ + Fraig_Node_t * pNode; + Fraig_NodeVec_t * pVec; + int i; + pVec = Fraig_Dfs( p, 0 ); + for ( i = 0; i < pVec->nSize; i++ ) + { + pNode = pVec->pArray[i]; + if ( Fraig_NodeIsVar(pNode) ) + { + if ( pNode->pRepr ) + printf( "Primary input %d is a secondary node.\n", pNode->Num ); + } + else if ( Fraig_NodeIsConst(pNode) ) + { + if ( pNode->pRepr ) + printf( "Constant 1 %d is a secondary node.\n", pNode->Num ); + } + else + { + if ( pNode->pRepr ) + printf( "Internal node %d is a secondary node.\n", pNode->Num ); + if ( Fraig_Regular(pNode->p1)->pRepr ) + printf( "Internal node %d has first fanin %d that is a secondary node.\n", + pNode->Num, Fraig_Regular(pNode->p1)->Num ); + if ( Fraig_Regular(pNode->p2)->pRepr ) + printf( "Internal node %d has second fanin %d that is a secondary node.\n", + pNode->Num, Fraig_Regular(pNode->p2)->Num ); + } + } + Fraig_NodeVecFree( pVec ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Prints the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_PrintNode( Fraig_Man_t * p, Fraig_Node_t * pNode ) +{ + Fraig_NodeVec_t * vNodes; + Fraig_Node_t * pTemp; + int fCompl1, fCompl2, i; + + vNodes = Fraig_DfsOne( p, pNode, 0 ); + for ( i = 0; i < vNodes->nSize; i++ ) + { + pTemp = vNodes->pArray[i]; + if ( Fraig_NodeIsVar(pTemp) ) + { + printf( "%3d : PI ", pTemp->Num ); + Fraig_PrintBinary( stdout, (unsigned *)&pTemp->puSimR, 20 ); + printf( " " ); + Fraig_PrintBinary( stdout, (unsigned *)&pTemp->puSimD, 20 ); + printf( " %d\n", pTemp->fInv ); + continue; + } + + fCompl1 = Fraig_IsComplement(pTemp->p1); + fCompl2 = Fraig_IsComplement(pTemp->p2); + printf( "%3d : %c%3d %c%3d ", pTemp->Num, + (fCompl1? '-':'+'), Fraig_Regular(pTemp->p1)->Num, + (fCompl2? '-':'+'), Fraig_Regular(pTemp->p2)->Num ); + Fraig_PrintBinary( stdout, (unsigned *)&pTemp->puSimR, 20 ); + printf( " " ); + Fraig_PrintBinary( stdout, (unsigned *)&pTemp->puSimD, 20 ); + printf( " %d\n", pTemp->fInv ); + } + Fraig_NodeVecFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Prints the bit string.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_PrintBinary( FILE * pFile, unsigned * pSign, int nBits ) +{ + int Remainder, nWords; + int w, i; + + Remainder = (nBits%(sizeof(unsigned)*8)); + nWords = (nBits/(sizeof(unsigned)*8)) + (Remainder>0); + + for ( w = nWords-1; w >= 0; w-- ) + for ( i = ((w == nWords-1 && Remainder)? Remainder-1: 31); i >= 0; i-- ) + fprintf( pFile, "%c", '0' + (int)((pSign[w] & (1< 0) ); + +// fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Sets up the mask.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_GetMaxLevel( Fraig_Man_t * pMan ) +{ + int nLevelMax, i; + nLevelMax = 0; + for ( i = 0; i < pMan->vOutputs->nSize; i++ ) + nLevelMax = nLevelMax > Fraig_Regular(pMan->vOutputs->pArray[i])->Level? + nLevelMax : Fraig_Regular(pMan->vOutputs->pArray[i])->Level; + return nLevelMax; +} + +/**Function************************************************************* + + Synopsis [Analyses choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_MappingUpdateLevel_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, int fMaximum ) +{ + Fraig_Node_t * pTemp; + int Level1, Level2, LevelE; + assert( !Fraig_IsComplement(pNode) ); + if ( !Fraig_NodeIsAnd(pNode) ) + return pNode->Level; + // skip the visited node + if ( pNode->TravId == pMan->nTravIds ) + return pNode->Level; + pNode->TravId = pMan->nTravIds; + // compute levels of the children nodes + Level1 = Fraig_MappingUpdateLevel_rec( pMan, Fraig_Regular(pNode->p1), fMaximum ); + Level2 = Fraig_MappingUpdateLevel_rec( pMan, Fraig_Regular(pNode->p2), fMaximum ); + pNode->Level = 1 + Abc_MaxInt( Level1, Level2 ); + if ( pNode->pNextE ) + { + LevelE = Fraig_MappingUpdateLevel_rec( pMan, pNode->pNextE, fMaximum ); + if ( fMaximum ) + { + if ( pNode->Level < LevelE ) + pNode->Level = LevelE; + } + else + { + if ( pNode->Level > LevelE ) + pNode->Level = LevelE; + } + // set the level of all equivalent nodes to be the same minimum + if ( pNode->pRepr == NULL ) // the primary node + for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE ) + pTemp->Level = pNode->Level; + } + return pNode->Level; +} + +/**Function************************************************************* + + Synopsis [Resets the levels of the nodes in the choice graph.] + + Description [Makes the level of the choice nodes to be equal to the + maximum of the level of the nodes in the equivalence class. This way + sorting by level leads to the reverse topological order, which is + needed for the required time computation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_MappingSetChoiceLevels( Fraig_Man_t * pMan, int fMaximum ) +{ + int i; + pMan->nTravIds++; + for ( i = 0; i < pMan->vOutputs->nSize; i++ ) + Fraig_MappingUpdateLevel_rec( pMan, Fraig_Regular(pMan->vOutputs->pArray[i]), fMaximum ); +} + +/**Function************************************************************* + + Synopsis [Reports statistics on choice nodes.] + + Description [The number of choice nodes is the number of primary nodes, + which has pNextE set to a pointer. The number of choices is the number + of entries in the equivalent-node lists of the primary nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_ManReportChoices( Fraig_Man_t * pMan ) +{ + Fraig_Node_t * pNode, * pTemp; + int nChoiceNodes, nChoices; + int i, LevelMax1, LevelMax2; + + // report the number of levels + LevelMax1 = Fraig_GetMaxLevel( pMan ); + Fraig_MappingSetChoiceLevels( pMan, 0 ); + LevelMax2 = Fraig_GetMaxLevel( pMan ); + + // report statistics about choices + nChoiceNodes = nChoices = 0; + for ( i = 0; i < pMan->vNodes->nSize; i++ ) + { + pNode = pMan->vNodes->pArray[i]; + if ( pNode->pRepr == NULL && pNode->pNextE != NULL ) + { // this is a choice node = the primary node that has equivalent nodes + nChoiceNodes++; + for ( pTemp = pNode; pTemp; pTemp = pTemp->pNextE ) + nChoices++; + } + } + printf( "Maximum level: Original = %d. Reduced due to choices = %d.\n", LevelMax1, LevelMax2 ); + printf( "Choice stats: Choice nodes = %d. Total choices = %d.\n", nChoiceNodes, nChoices ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is the root of EXOR/NEXOR gate.] + + Description [The node can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeIsExorType( Fraig_Node_t * pNode ) +{ + Fraig_Node_t * pNode1, * pNode2; + // make the node regular (it does not matter for EXOR/NEXOR) + pNode = Fraig_Regular(pNode); + // if the node or its children are not ANDs or not compl, this cannot be EXOR type + if ( !Fraig_NodeIsAnd(pNode) ) + return 0; + if ( !Fraig_NodeIsAnd(pNode->p1) || !Fraig_IsComplement(pNode->p1) ) + return 0; + if ( !Fraig_NodeIsAnd(pNode->p2) || !Fraig_IsComplement(pNode->p2) ) + return 0; + + // get children + pNode1 = Fraig_Regular(pNode->p1); + pNode2 = Fraig_Regular(pNode->p2); + assert( pNode1->Num < pNode2->Num ); + + // compare grandchildren + return pNode1->p1 == Fraig_Not(pNode2->p1) && pNode1->p2 == Fraig_Not(pNode2->p2); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] + + Description [The node can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeIsMuxType( Fraig_Node_t * pNode ) +{ + Fraig_Node_t * pNode1, * pNode2; + + // make the node regular (it does not matter for EXOR/NEXOR) + pNode = Fraig_Regular(pNode); + // if the node or its children are not ANDs or not compl, this cannot be EXOR type + if ( !Fraig_NodeIsAnd(pNode) ) + return 0; + if ( !Fraig_NodeIsAnd(pNode->p1) || !Fraig_IsComplement(pNode->p1) ) + return 0; + if ( !Fraig_NodeIsAnd(pNode->p2) || !Fraig_IsComplement(pNode->p2) ) + return 0; + + // get children + pNode1 = Fraig_Regular(pNode->p1); + pNode2 = Fraig_Regular(pNode->p2); + assert( pNode1->Num < pNode2->Num ); + + // compare grandchildren + // node is an EXOR/NEXOR + if ( pNode1->p1 == Fraig_Not(pNode2->p1) && pNode1->p2 == Fraig_Not(pNode2->p2) ) + return 1; + + // otherwise the node is MUX iff it has a pair of equal grandchildren + return pNode1->p1 == Fraig_Not(pNode2->p1) || + pNode1->p1 == Fraig_Not(pNode2->p2) || + pNode1->p2 == Fraig_Not(pNode2->p1) || + pNode1->p2 == Fraig_Not(pNode2->p2); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is EXOR, 0 if it is NEXOR.] + + Description [The node should be EXOR type and not complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeIsExor( Fraig_Node_t * pNode ) +{ + Fraig_Node_t * pNode1; + assert( !Fraig_IsComplement(pNode) ); + assert( Fraig_NodeIsExorType(pNode) ); + assert( Fraig_IsComplement(pNode->p1) ); + // get children + pNode1 = Fraig_Regular(pNode->p1); + return Fraig_IsComplement(pNode1->p1) == Fraig_IsComplement(pNode1->p2); +} + +/**Function************************************************************* + + Synopsis [Recognizes what nodes are control and data inputs of a MUX.] + + Description [If the node is a MUX, returns the control variable C. + Assigns nodes T and E to be the then and else variables of the MUX. + Node C is never complemented. Nodes T and E can be complemented. + This function also recognizes EXOR/NEXOR gates as MUXes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_NodeRecognizeMux( Fraig_Node_t * pNode, Fraig_Node_t ** ppNodeT, Fraig_Node_t ** ppNodeE ) +{ + Fraig_Node_t * pNode1, * pNode2; + assert( !Fraig_IsComplement(pNode) ); + assert( Fraig_NodeIsMuxType(pNode) ); + // get children + pNode1 = Fraig_Regular(pNode->p1); + pNode2 = Fraig_Regular(pNode->p2); + // find the control variable + if ( pNode1->p1 == Fraig_Not(pNode2->p1) ) + { + if ( Fraig_IsComplement(pNode1->p1) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Fraig_Not(pNode2->p2); + *ppNodeE = Fraig_Not(pNode1->p2); + return pNode2->p1; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Fraig_Not(pNode1->p2); + *ppNodeE = Fraig_Not(pNode2->p2); + return pNode1->p1; + } + } + else if ( pNode1->p1 == Fraig_Not(pNode2->p2) ) + { + if ( Fraig_IsComplement(pNode1->p1) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Fraig_Not(pNode2->p1); + *ppNodeE = Fraig_Not(pNode1->p2); + return pNode2->p2; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Fraig_Not(pNode1->p2); + *ppNodeE = Fraig_Not(pNode2->p1); + return pNode1->p1; + } + } + else if ( pNode1->p2 == Fraig_Not(pNode2->p1) ) + { + if ( Fraig_IsComplement(pNode1->p2) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Fraig_Not(pNode2->p2); + *ppNodeE = Fraig_Not(pNode1->p1); + return pNode2->p1; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Fraig_Not(pNode1->p1); + *ppNodeE = Fraig_Not(pNode2->p2); + return pNode1->p2; + } + } + else if ( pNode1->p2 == Fraig_Not(pNode2->p2) ) + { + if ( Fraig_IsComplement(pNode1->p2) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Fraig_Not(pNode2->p1); + *ppNodeE = Fraig_Not(pNode1->p1); + return pNode2->p2; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Fraig_Not(pNode1->p1); + *ppNodeE = Fraig_Not(pNode2->p1); + return pNode1->p2; + } + } + assert( 0 ); // this is not MUX + return NULL; +} + +/**Function************************************************************* + + Synopsis [Counts the number of EXOR type nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_ManCountExors( Fraig_Man_t * pMan ) +{ + int i, nExors; + nExors = 0; + for ( i = 0; i < pMan->vNodes->nSize; i++ ) + nExors += Fraig_NodeIsExorType( pMan->vNodes->pArray[i] ); + return nExors; + +} + +/**Function************************************************************* + + Synopsis [Counts the number of EXOR type nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_ManCountMuxes( Fraig_Man_t * pMan ) +{ + int i, nMuxes; + nMuxes = 0; + for ( i = 0; i < pMan->vNodes->nSize; i++ ) + nMuxes += Fraig_NodeIsMuxType( pMan->vNodes->pArray[i] ); + return nMuxes; + +} + +/**Function************************************************************* + + Synopsis [Returns 1 if siminfo of Node1 is contained in siminfo of Node2.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeSimsContained( Fraig_Man_t * pMan, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2 ) +{ + unsigned * pUnsigned1, * pUnsigned2; + int i; + + // compare random siminfo + pUnsigned1 = pNode1->puSimR; + pUnsigned2 = pNode2->puSimR; + for ( i = 0; i < pMan->nWordsRand; i++ ) + if ( pUnsigned1[i] & ~pUnsigned2[i] ) + return 0; + + // compare systematic siminfo + pUnsigned1 = pNode1->puSimD; + pUnsigned2 = pNode2->puSimD; + for ( i = 0; i < pMan->iWordStart; i++ ) + if ( pUnsigned1[i] & ~pUnsigned2[i] ) + return 0; + + return 1; +} + +/**Function************************************************************* + + Synopsis [Count the number of PI variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_CountPis( Fraig_Man_t * p, Msat_IntVec_t * vVarNums ) +{ + int * pVars, nVars, i, Counter; + + nVars = Msat_IntVecReadSize(vVarNums); + pVars = Msat_IntVecReadArray(vVarNums); + Counter = 0; + for ( i = 0; i < nVars; i++ ) + Counter += Fraig_NodeIsVar( p->vNodes->pArray[pVars[i]] ); + return Counter; +} + + + +/**Function************************************************************* + + Synopsis [Counts the number of EXOR type nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_ManPrintRefs( Fraig_Man_t * pMan ) +{ + Fraig_NodeVec_t * vPivots; + Fraig_Node_t * pNode, * pNode2; + int i, k, Counter, nProved; + int clk; + + vPivots = Fraig_NodeVecAlloc( 1000 ); + for ( i = 0; i < pMan->vNodes->nSize; i++ ) + { + pNode = pMan->vNodes->pArray[i]; + + if ( pNode->nOnes == 0 || pNode->nOnes == (unsigned)pMan->nWordsRand * 32 ) + continue; + + if ( pNode->nRefs > 5 ) + { + Fraig_NodeVecPush( vPivots, pNode ); +// printf( "Node %6d : nRefs = %2d Level = %3d.\n", pNode->Num, pNode->nRefs, pNode->Level ); + } + } + printf( "Total nodes = %d. Referenced nodes = %d.\n", pMan->vNodes->nSize, vPivots->nSize ); + +clk = clock(); + // count implications + Counter = nProved = 0; + for ( i = 0; i < vPivots->nSize; i++ ) + for ( k = i+1; k < vPivots->nSize; k++ ) + { + pNode = vPivots->pArray[i]; + pNode2 = vPivots->pArray[k]; + if ( Fraig_NodeSimsContained( pMan, pNode, pNode2 ) ) + { + if ( Fraig_NodeIsImplication( pMan, pNode, pNode2, -1 ) ) + nProved++; + Counter++; + } + else if ( Fraig_NodeSimsContained( pMan, pNode2, pNode ) ) + { + if ( Fraig_NodeIsImplication( pMan, pNode2, pNode, -1 ) ) + nProved++; + Counter++; + } + } + printf( "Number of candidate pairs = %d. Proved = %d.\n", Counter, nProved ); +//ABC_PRT( "Time", clock() - clk ); + return 0; +} + + +/**Function************************************************************* + + Synopsis [Checks if pNew exists among the implication fanins of pOld.] + + Description [If pNew is an implication fanin of pOld, returns 1. + If Fraig_Not(pNew) is an implication fanin of pOld, return -1. + Otherwise returns 0.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeIsInSupergate( Fraig_Node_t * pOld, Fraig_Node_t * pNew ) +{ + int RetValue1, RetValue2; + if ( Fraig_Regular(pOld) == Fraig_Regular(pNew) ) + return (pOld == pNew)? 1 : -1; + if ( Fraig_IsComplement(pOld) || Fraig_NodeIsVar(pOld) ) + return 0; + RetValue1 = Fraig_NodeIsInSupergate( pOld->p1, pNew ); + RetValue2 = Fraig_NodeIsInSupergate( pOld->p2, pNew ); + if ( RetValue1 == -1 || RetValue2 == -1 ) + return -1; + if ( RetValue1 == 1 || RetValue2 == 1 ) + return 1; + return 0; +} + + +/**Function************************************************************* + + Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_CollectSupergate_rec( Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper, int fFirst, int fStopAtMux ) +{ + // if the new node is complemented or a PI, another gate begins +// if ( Fraig_IsComplement(pNode) || Fraig_NodeIsVar(pNode) || Fraig_NodeIsMuxType(pNode) ) + if ( (!fFirst && Fraig_Regular(pNode)->nRefs > 1) || + Fraig_IsComplement(pNode) || Fraig_NodeIsVar(pNode) || + (fStopAtMux && Fraig_NodeIsMuxType(pNode)) ) + { + Fraig_NodeVecPushUnique( vSuper, pNode ); + return; + } + // go through the branches + Fraig_CollectSupergate_rec( pNode->p1, vSuper, 0, fStopAtMux ); + Fraig_CollectSupergate_rec( pNode->p2, vSuper, 0, fStopAtMux ); +} + +/**Function************************************************************* + + Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_NodeVec_t * Fraig_CollectSupergate( Fraig_Node_t * pNode, int fStopAtMux ) +{ + Fraig_NodeVec_t * vSuper; + vSuper = Fraig_NodeVecAlloc( 8 ); + Fraig_CollectSupergate_rec( pNode, vSuper, 1, fStopAtMux ); + return vSuper; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_ManIncrementTravId( Fraig_Man_t * pMan ) +{ + pMan->nTravIds2++; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeSetTravIdCurrent( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) +{ + pNode->TravId2 = pMan->nTravIds2; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeIsTravIdCurrent( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) +{ + return pNode->TravId2 == pMan->nTravIds2; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeIsTravIdPrevious( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) +{ + return pNode->TravId2 == pMan->nTravIds2 - 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fraig/fraigVec.c b/src/proof/fraig/fraigVec.c new file mode 100644 index 00000000..25d50bf3 --- /dev/null +++ b/src/proof/fraig/fraigVec.c @@ -0,0 +1,550 @@ +/**CFile**************************************************************** + + FileName [fraigVec.c] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [Vector of FRAIG nodes.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - October 1, 2004] + + Revision [$Id: fraigVec.c,v 1.7 2005/07/08 01:01:34 alanmi Exp $] + +***********************************************************************/ + +#include "fraigInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates a vector with the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_NodeVec_t * Fraig_NodeVecAlloc( int nCap ) +{ + Fraig_NodeVec_t * p; + p = ABC_ALLOC( Fraig_NodeVec_t, 1 ); + if ( nCap > 0 && nCap < 8 ) + nCap = 8; + p->nSize = 0; + p->nCap = nCap; + p->pArray = p->nCap? ABC_ALLOC( Fraig_Node_t *, p->nCap ) : NULL; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeVecFree( Fraig_NodeVec_t * p ) +{ + ABC_FREE( p->pArray ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Duplicates the integer array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_NodeVec_t * Fraig_NodeVecDup( Fraig_NodeVec_t * pVec ) +{ + Fraig_NodeVec_t * p; + p = ABC_ALLOC( Fraig_NodeVec_t, 1 ); + p->nSize = pVec->nSize; + p->nCap = pVec->nCap; + p->pArray = p->nCap? ABC_ALLOC( Fraig_Node_t *, p->nCap ) : NULL; + memcpy( p->pArray, pVec->pArray, sizeof(Fraig_Node_t *) * pVec->nSize ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t ** Fraig_NodeVecReadArray( Fraig_NodeVec_t * p ) +{ + return p->pArray; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeVecReadSize( Fraig_NodeVec_t * p ) +{ + return p->nSize; +} + +/**Function************************************************************* + + Synopsis [Resizes the vector to the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeVecGrow( Fraig_NodeVec_t * p, int nCapMin ) +{ + if ( p->nCap >= nCapMin ) + return; + p->pArray = ABC_REALLOC( Fraig_Node_t *, p->pArray, nCapMin ); + p->nCap = nCapMin; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeVecShrink( Fraig_NodeVec_t * p, int nSizeNew ) +{ + assert( p->nSize >= nSizeNew ); + p->nSize = nSizeNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeVecClear( Fraig_NodeVec_t * p ) +{ + p->nSize = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeVecPush( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ) +{ + if ( p->nSize == p->nCap ) + { + if ( p->nCap < 16 ) + Fraig_NodeVecGrow( p, 16 ); + else + Fraig_NodeVecGrow( p, 2 * p->nCap ); + } + p->pArray[p->nSize++] = Entry; +} + +/**Function************************************************************* + + Synopsis [Add the element while ensuring uniqueness.] + + Description [Returns 1 if the element was found, and 0 if it was new. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeVecPushUnique( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ) +{ + int i; + for ( i = 0; i < p->nSize; i++ ) + if ( p->pArray[i] == Entry ) + return 1; + Fraig_NodeVecPush( p, Entry ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Inserts a new node in the order by arrival times.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeVecPushOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ) +{ + Fraig_Node_t * pNode1, * pNode2; + int i; + Fraig_NodeVecPush( p, pNode ); + // find the p of the node + for ( i = p->nSize-1; i > 0; i-- ) + { + pNode1 = p->pArray[i ]; + pNode2 = p->pArray[i-1]; + if ( pNode1 >= pNode2 ) + break; + p->pArray[i ] = pNode2; + p->pArray[i-1] = pNode1; + } +} + +/**Function************************************************************* + + Synopsis [Add the element while ensuring uniqueness in the order.] + + Description [Returns 1 if the element was found, and 0 if it was new. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeVecPushUniqueOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ) +{ + int i; + for ( i = 0; i < p->nSize; i++ ) + if ( p->pArray[i] == pNode ) + return 1; + Fraig_NodeVecPushOrder( p, pNode ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Inserts a new node in the order by arrival times.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeVecPushOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ) +{ + Fraig_Node_t * pNode1, * pNode2; + int i; + Fraig_NodeVecPush( p, pNode ); + // find the p of the node + for ( i = p->nSize-1; i > 0; i-- ) + { + pNode1 = p->pArray[i ]; + pNode2 = p->pArray[i-1]; + if ( Fraig_Regular(pNode1)->Level <= Fraig_Regular(pNode2)->Level ) + break; + p->pArray[i ] = pNode2; + p->pArray[i-1] = pNode1; + } +} + +/**Function************************************************************* + + Synopsis [Add the element while ensuring uniqueness in the order.] + + Description [Returns 1 if the element was found, and 0 if it was new. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeVecPushUniqueOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ) +{ + int i; + for ( i = 0; i < p->nSize; i++ ) + if ( p->pArray[i] == pNode ) + return 1; + Fraig_NodeVecPushOrderByLevel( p, pNode ); + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_NodeVecPop( Fraig_NodeVec_t * p ) +{ + return p->pArray[--p->nSize]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeVecRemove( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ) +{ + int i; + for ( i = 0; i < p->nSize; i++ ) + if ( p->pArray[i] == Entry ) + break; + assert( i < p->nSize ); + for ( i++; i < p->nSize; i++ ) + p->pArray[i-1] = p->pArray[i]; + p->nSize--; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeVecWriteEntry( Fraig_NodeVec_t * p, int i, Fraig_Node_t * Entry ) +{ + assert( i >= 0 && i < p->nSize ); + p->pArray[i] = Entry; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_NodeVecReadEntry( Fraig_NodeVec_t * p, int i ) +{ + assert( i >= 0 && i < p->nSize ); + return p->pArray[i]; +} + +/**Function************************************************************* + + Synopsis [Comparison procedure for two clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeVecCompareLevelsIncreasing( Fraig_Node_t ** pp1, Fraig_Node_t ** pp2 ) +{ + int Level1 = Fraig_Regular(*pp1)->Level; + int Level2 = Fraig_Regular(*pp2)->Level; + if ( Level1 < Level2 ) + return -1; + if ( Level1 > Level2 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Comparison procedure for two clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeVecCompareLevelsDecreasing( Fraig_Node_t ** pp1, Fraig_Node_t ** pp2 ) +{ + int Level1 = Fraig_Regular(*pp1)->Level; + int Level2 = Fraig_Regular(*pp2)->Level; + if ( Level1 > Level2 ) + return -1; + if ( Level1 < Level2 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Comparison procedure for two clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeVecCompareNumbers( Fraig_Node_t ** pp1, Fraig_Node_t ** pp2 ) +{ + int Num1 = Fraig_Regular(*pp1)->Num; + int Num2 = Fraig_Regular(*pp2)->Num; + if ( Num1 < Num2 ) + return -1; + if ( Num1 > Num2 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Comparison procedure for two clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeVecCompareRefCounts( Fraig_Node_t ** pp1, Fraig_Node_t ** pp2 ) +{ + int nRefs1 = Fraig_Regular(*pp1)->nRefs; + int nRefs2 = Fraig_Regular(*pp2)->nRefs; + + if ( nRefs1 < nRefs2 ) + return -1; + if ( nRefs1 > nRefs2 ) + return 1; + + nRefs1 = Fraig_Regular(*pp1)->Level; + nRefs2 = Fraig_Regular(*pp2)->Level; + + if ( nRefs1 < nRefs2 ) + return -1; + if ( nRefs1 > nRefs2 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Sorting the entries by their integer value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeVecSortByLevel( Fraig_NodeVec_t * p, int fIncreasing ) +{ + if ( fIncreasing ) + qsort( (void *)p->pArray, p->nSize, sizeof(Fraig_Node_t *), + (int (*)(const void *, const void *)) Fraig_NodeVecCompareLevelsIncreasing ); + else + qsort( (void *)p->pArray, p->nSize, sizeof(Fraig_Node_t *), + (int (*)(const void *, const void *)) Fraig_NodeVecCompareLevelsDecreasing ); +} + +/**Function************************************************************* + + Synopsis [Sorting the entries by their integer value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeVecSortByNumber( Fraig_NodeVec_t * p ) +{ + qsort( (void *)p->pArray, p->nSize, sizeof(Fraig_Node_t *), + (int (*)(const void *, const void *)) Fraig_NodeVecCompareNumbers ); +} + +/**Function************************************************************* + + Synopsis [Sorting the entries by their integer value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeVecSortByRefCount( Fraig_NodeVec_t * p ) +{ + qsort( (void *)p->pArray, p->nSize, sizeof(Fraig_Node_t *), + (int (*)(const void *, const void *)) Fraig_NodeVecCompareRefCounts ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/fraig/module.make b/src/proof/fraig/module.make new file mode 100644 index 00000000..4ca7cdce --- /dev/null +++ b/src/proof/fraig/module.make @@ -0,0 +1,12 @@ +SRC += src/proof/fraig/fraigApi.c \ + src/proof/fraig/fraigCanon.c \ + src/proof/fraig/fraigFanout.c \ + src/proof/fraig/fraigFeed.c \ + src/proof/fraig/fraigMan.c \ + src/proof/fraig/fraigMem.c \ + src/proof/fraig/fraigNode.c \ + src/proof/fraig/fraigPrime.c \ + src/proof/fraig/fraigSat.c \ + src/proof/fraig/fraigTable.c \ + src/proof/fraig/fraigUtil.c \ + src/proof/fraig/fraigVec.c diff --git a/src/proof/int/int.h b/src/proof/int/int.h new file mode 100644 index 00000000..a93e3c93 --- /dev/null +++ b/src/proof/int/int.h @@ -0,0 +1,94 @@ +/**CFile**************************************************************** + + FileName [int.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Interpolation engine.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 24, 2008.] + + Revision [$Id: int.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__int__int_h +#define ABC__aig__int__int_h + + +/* + The interpolation algorithm implemented here was introduced in the paper: + K. L. McMillan. Interpolation and SAT-based model checking. CAV’03, pp. 1-13. +*/ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +// simulation manager +typedef struct Inter_ManParams_t_ Inter_ManParams_t; +struct Inter_ManParams_t_ +{ + int nBTLimit; // limit on the number of conflicts + int nFramesMax; // the max number timeframes to unroll + int nSecLimit; // time limit in seconds + int nFramesK; // the number of timeframes to use in induction + int fRewrite; // use additional rewriting to simplify timeframes + int fTransLoop; // add transition into the init state under new PI var + int fUsePudlak; // use Pudluk interpolation procedure + int fUseOther; // use other undisclosed option + int fUseMiniSat; // use MiniSat-1.14p instead of internal proof engine + int fCheckKstep; // check using K-step induction + int fUseBias; // bias decisions to global variables + int fUseBackward; // perform backward interpolation + int fUseSeparate; // solve each output separately + int fDropSatOuts; // replace by 1 the solved outputs + int fDropInvar; // dump inductive invariant into file + int fVerbose; // print verbose statistics + int iFrameMax; // the time frame reached +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== intCore.c ==========================================================*/ +extern void Inter_ManSetDefaultParams( Inter_ManParams_t * p ); +extern int Inter_ManPerformInterpolation( Aig_Man_t * pAig, Inter_ManParams_t * pPars, int * piFrame ); + + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/proof/int/intCheck.c b/src/proof/int/intCheck.c new file mode 100644 index 00000000..6b36fe30 --- /dev/null +++ b/src/proof/int/intCheck.c @@ -0,0 +1,305 @@ +/**CFile**************************************************************** + + FileName [intCheck.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Interpolation engine.] + + Synopsis [Procedures to perform incremental inductive check.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 24, 2008.] + + Revision [$Id: intCheck.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "intInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// checking manager +struct Inter_Check_t_ +{ + int nFramesK; // the number of timeframes (K=1 for simple induction) + int nVars; // the current number of variables in the solver + Aig_Man_t * pFrames; // unrolled timeframes + Cnf_Dat_t * pCnf; // CNF of unrolled timeframes + sat_solver * pSat; // SAT solver + Vec_Int_t * vOrLits; // OR vars in each time frame (total number is the number nFrames) + Vec_Int_t * vAndLits; // AND vars in the last timeframe (total number is the number of interpolants) + Vec_Int_t * vAssLits; // assumptions (the union of the two) +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Create timeframes of the manager for interpolation.] + + Description [The resulting manager is combinational. The primary inputs + corresponding to register outputs are ordered first.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Inter_ManUnrollFrames( Aig_Man_t * pAig, int nFrames ) +{ + Aig_Man_t * pFrames; + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + int i, f; + assert( Saig_ManRegNum(pAig) > 0 ); + pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFrames ); + // map the constant node + Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames ); + // create variables for register outputs + Saig_ManForEachLo( pAig, pObj, i ) + pObj->pData = Aig_ObjCreatePi( pFrames ); + // add timeframes + for ( f = 0; f < nFrames; f++ ) + { + // create PI nodes for this frame + Saig_ManForEachPi( pAig, pObj, i ) + pObj->pData = Aig_ObjCreatePi( pFrames ); + // add internal nodes of this frame + Aig_ManForEachNode( pAig, pObj, i ) + pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + // save register inputs + Saig_ManForEachLi( pAig, pObj, i ) + pObj->pData = Aig_ObjChild0Copy(pObj); + // transfer to register outputs + Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) + { + pObjLo->pData = pObjLi->pData; + Aig_ObjCreatePo( pFrames, (Aig_Obj_t *)pObjLo->pData ); + } + } + Aig_ManCleanup( pFrames ); + return pFrames; +} + +/**Function************************************************************* + + Synopsis [This procedure sets default values of interpolation parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Inter_Check_t * Inter_CheckStart( Aig_Man_t * pTrans, int nFramesK ) +{ + Inter_Check_t * p; + // create solver + p = ABC_CALLOC( Inter_Check_t, 1 ); + p->vOrLits = Vec_IntAlloc( 100 ); + p->vAndLits = Vec_IntAlloc( 100 ); + p->vAssLits = Vec_IntAlloc( 100 ); + // generate the timeframes + p->pFrames = Inter_ManUnrollFrames( pTrans, nFramesK ); + assert( Aig_ManPiNum(p->pFrames) == nFramesK * Saig_ManPiNum(pTrans) + Saig_ManRegNum(pTrans) ); + assert( Aig_ManPoNum(p->pFrames) == nFramesK * Saig_ManRegNum(pTrans) ); + // convert to CNF + p->pCnf = Cnf_Derive( p->pFrames, Aig_ManPoNum(p->pFrames) ); + p->pSat = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, 1, 0 ); + // assign parameters + p->nFramesK = nFramesK; + p->nVars = p->pCnf->nVars; + return p; +} + +/**Function************************************************************* + + Synopsis [This procedure sets default values of interpolation parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Inter_CheckStop( Inter_Check_t * p ) +{ + if ( p == NULL ) + return; + Vec_IntFree( p->vOrLits ); + Vec_IntFree( p->vAndLits ); + Vec_IntFree( p->vAssLits ); + Cnf_DataFree( p->pCnf ); + Aig_ManStop( p->pFrames ); + sat_solver_delete( p->pSat ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [Creates one OR-gate: A + B = C.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Inter_CheckAddOrGate( Inter_Check_t * p, int iVarA, int iVarB, int iVarC ) +{ + int RetValue, pLits[3]; + // add A => C or !A + C + pLits[0] = toLitCond(iVarA, 1); + pLits[1] = toLitCond(iVarC, 0); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); + assert( RetValue ); + // add B => C or !B + C + pLits[0] = toLitCond(iVarB, 1); + pLits[1] = toLitCond(iVarC, 0); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); + assert( RetValue ); + // add !A & !B => !C or A + B + !C + pLits[0] = toLitCond(iVarA, 0); + pLits[1] = toLitCond(iVarB, 0); + pLits[2] = toLitCond(iVarC, 1); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); +} + +/**Function************************************************************* + + Synopsis [Creates equality: A = B.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Inter_CheckAddEqual( Inter_Check_t * p, int iVarA, int iVarB ) +{ + int RetValue, pLits[3]; + // add A => B or !A + B + pLits[0] = toLitCond(iVarA, 1); + pLits[1] = toLitCond(iVarB, 0); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); + assert( RetValue ); + // add B => A or !B + A + pLits[0] = toLitCond(iVarB, 1); + pLits[1] = toLitCond(iVarA, 0); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); + assert( RetValue ); +} + +/**Function************************************************************* + + Synopsis [Perform the checking.] + + Description [Returns 1 if the check has passed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Inter_CheckPerform( Inter_Check_t * p, Cnf_Dat_t * pCnfInt, int nTimeNewOut ) +{ + Aig_Obj_t * pObj, * pObj2; + int i, f, VarA, VarB, RetValue, Entry, status; + int nRegs = Aig_ManPiNum(pCnfInt->pMan); + assert( Aig_ManPoNum(p->pCnf->pMan) == p->nFramesK * nRegs ); + assert( Aig_ManPoNum(pCnfInt->pMan) == 1 ); + + // set runtime limit + if ( nTimeNewOut ) + sat_solver_set_runtime_limit( p->pSat, nTimeNewOut ); + + // add clauses to the SAT solver + Cnf_DataLift( pCnfInt, p->nVars ); + for ( f = 0; f <= p->nFramesK; f++ ) + { + // add clauses to the solver + for ( i = 0; i < pCnfInt->nClauses; i++ ) + { + RetValue = sat_solver_addclause( p->pSat, pCnfInt->pClauses[i], pCnfInt->pClauses[i+1] ); + assert( RetValue ); + } + // add equality clauses for the flop variables + Aig_ManForEachPi( pCnfInt->pMan, pObj, i ) + { + pObj2 = f ? Aig_ManPo(p->pFrames, i + (f-1) * nRegs) : Aig_ManPi(p->pFrames, i); + Inter_CheckAddEqual( p, pCnfInt->pVarNums[pObj->Id], p->pCnf->pVarNums[pObj2->Id] ); + } + // add final clauses + if ( f < p->nFramesK ) + { + if ( f == Vec_IntSize(p->vOrLits) ) // find time here + { + // add literal to this frame + VarB = pCnfInt->pVarNums[ Aig_ManPo(pCnfInt->pMan, 0)->Id ]; + Vec_IntPush( p->vOrLits, VarB ); + } + else + { + // add OR gate for this frame + VarA = Vec_IntEntry( p->vOrLits, f ); + VarB = pCnfInt->pVarNums[ Aig_ManPo(pCnfInt->pMan, 0)->Id ]; + Inter_CheckAddOrGate( p, VarA, VarB, p->nVars + pCnfInt->nVars ); + Vec_IntWriteEntry( p->vOrLits, f, p->nVars + pCnfInt->nVars ); // using var ID! + } + } + else + { + // add AND gate for this frame + VarB = pCnfInt->pVarNums[ Aig_ManPo(pCnfInt->pMan, 0)->Id ]; + Vec_IntPush( p->vAndLits, VarB ); + } + // update variable IDs + Cnf_DataLift( pCnfInt, pCnfInt->nVars + 1 ); + p->nVars += pCnfInt->nVars + 1; + } + Cnf_DataLift( pCnfInt, -p->nVars ); + assert( Vec_IntSize(p->vOrLits) == p->nFramesK ); + + // collect the assumption literals + Vec_IntClear( p->vAssLits ); + Vec_IntForEachEntry( p->vOrLits, Entry, i ) + Vec_IntPush( p->vAssLits, toLitCond(Entry, 0) ); + Vec_IntForEachEntry( p->vAndLits, Entry, i ) + Vec_IntPush( p->vAssLits, toLitCond(Entry, 1) ); +/* + if ( pCnfInt->nLiterals == 3635 ) + { + int s = 0; + } +*/ + // call the SAT solver + status = sat_solver_solve( p->pSat, Vec_IntArray(p->vAssLits), + Vec_IntArray(p->vAssLits) + Vec_IntSize(p->vAssLits), + (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + + return status == l_False; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/int/intContain.c b/src/proof/int/intContain.c new file mode 100644 index 00000000..58b408d7 --- /dev/null +++ b/src/proof/int/intContain.c @@ -0,0 +1,341 @@ +/**CFile**************************************************************** + + FileName [intContain.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Interpolation engine.] + + Synopsis [Interpolant containment checking.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 24, 2008.] + + Revision [$Id: intContain.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "intInt.h" +#include "src/proof/fra/fra.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern int Inter_ManCheckUniqueness( Aig_Man_t * p, sat_solver * pSat, Cnf_Dat_t * pCnf, int nFrames ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks constainment of two interpolants.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Inter_ManCheckContainment( Aig_Man_t * pNew, Aig_Man_t * pOld ) +{ + Aig_Man_t * pMiter, * pAigTemp; + int RetValue; + pMiter = Aig_ManCreateMiter( pNew, pOld, 1 ); +// pMiter = Dar_ManRwsat( pAigTemp = pMiter, 1, 0 ); +// Aig_ManStop( pAigTemp ); + RetValue = Fra_FraigMiterStatus( pMiter ); + if ( RetValue == -1 ) + { + pAigTemp = Fra_FraigEquivence( pMiter, 1000000, 1 ); + RetValue = Fra_FraigMiterStatus( pAigTemp ); + Aig_ManStop( pAigTemp ); +// RetValue = Fra_FraigSat( pMiter, 1000000, 0, 0, 0, 0 ); + } + assert( RetValue != -1 ); + Aig_ManStop( pMiter ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Checks constainment of two interpolants.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Inter_ManCheckEquivalence( Aig_Man_t * pNew, Aig_Man_t * pOld ) +{ + Aig_Man_t * pMiter, * pAigTemp; + int RetValue; + pMiter = Aig_ManCreateMiter( pNew, pOld, 0 ); +// pMiter = Dar_ManRwsat( pAigTemp = pMiter, 1, 0 ); +// Aig_ManStop( pAigTemp ); + RetValue = Fra_FraigMiterStatus( pMiter ); + if ( RetValue == -1 ) + { + pAigTemp = Fra_FraigEquivence( pMiter, 1000000, 1 ); + RetValue = Fra_FraigMiterStatus( pAigTemp ); + Aig_ManStop( pAigTemp ); +// RetValue = Fra_FraigSat( pMiter, 1000000, 0, 0, 0, 0 ); + } + assert( RetValue != -1 ); + Aig_ManStop( pMiter ); + return RetValue; +} + + +/**Function************************************************************* + + Synopsis [Create timeframes of the manager for interpolation.] + + Description [The resulting manager is combinational. The primary inputs + corresponding to register outputs are ordered first.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Inter_ManFramesLatches( Aig_Man_t * pAig, int nFrames, Vec_Ptr_t ** pvMapReg ) +{ + Aig_Man_t * pFrames; + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + int i, f; + assert( Saig_ManRegNum(pAig) > 0 ); + pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFrames ); + // map the constant node + Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames ); + // create variables for register outputs + *pvMapReg = Vec_PtrAlloc( (nFrames+1) * Saig_ManRegNum(pAig) ); + Saig_ManForEachLo( pAig, pObj, i ) + { + pObj->pData = Aig_ObjCreatePi( pFrames ); + Vec_PtrPush( *pvMapReg, pObj->pData ); + } + // add timeframes + for ( f = 0; f < nFrames; f++ ) + { + // create PI nodes for this frame + Saig_ManForEachPi( pAig, pObj, i ) + pObj->pData = Aig_ObjCreatePi( pFrames ); + // add internal nodes of this frame + Aig_ManForEachNode( pAig, pObj, i ) + pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + // save register inputs + Saig_ManForEachLi( pAig, pObj, i ) + pObj->pData = Aig_ObjChild0Copy(pObj); + // transfer to register outputs + Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) + { + pObjLo->pData = pObjLi->pData; + Vec_PtrPush( *pvMapReg, pObjLo->pData ); + } + } + return pFrames; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG while mapping PIs into the given array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Inter_ManAppendCone( Aig_Man_t * pOld, Aig_Man_t * pNew, Aig_Obj_t ** ppNewPis, int fCompl ) +{ + Aig_Obj_t * pObj; + int i; + assert( Aig_ManPoNum(pOld) == 1 ); + // create the PIs + Aig_ManCleanData( pOld ); + Aig_ManConst1(pOld)->pData = Aig_ManConst1(pNew); + Aig_ManForEachPi( pOld, pObj, i ) + pObj->pData = ppNewPis[i]; + // duplicate internal nodes + Aig_ManForEachNode( pOld, pObj, i ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + // add one PO to new + pObj = Aig_ManPo( pOld, 0 ); + Aig_ObjCreatePo( pNew, Aig_NotCond( Aig_ObjChild0Copy(pObj), fCompl ) ); +} + + +/**Function************************************************************* + + Synopsis [Checks constainment of two interpolants inductively.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Inter_ManCheckInductiveContainment( Aig_Man_t * pTrans, Aig_Man_t * pInter, int nSteps, int fBackward ) +{ + Aig_Man_t * pFrames; + Aig_Obj_t ** ppNodes; + Vec_Ptr_t * vMapRegs; + Cnf_Dat_t * pCnf; + sat_solver * pSat; + int f, nRegs, status; + nRegs = Saig_ManRegNum(pTrans); + assert( nRegs > 0 ); + // generate the timeframes + pFrames = Inter_ManFramesLatches( pTrans, nSteps, &vMapRegs ); + assert( Vec_PtrSize(vMapRegs) == (nSteps + 1) * nRegs ); + // add main constraints to the timeframes + ppNodes = (Aig_Obj_t **)Vec_PtrArray(vMapRegs); + if ( !fBackward ) + { + // forward inductive check: p -> p -> ... -> !p + for ( f = 0; f < nSteps; f++ ) + Inter_ManAppendCone( pInter, pFrames, ppNodes + f * nRegs, 0 ); + Inter_ManAppendCone( pInter, pFrames, ppNodes + f * nRegs, 1 ); + } + else + { + // backward inductive check: p -> !p -> ... -> !p + Inter_ManAppendCone( pInter, pFrames, ppNodes + 0 * nRegs, 1 ); + for ( f = 1; f <= nSteps; f++ ) + Inter_ManAppendCone( pInter, pFrames, ppNodes + f * nRegs, 0 ); + } + Vec_PtrFree( vMapRegs ); + Aig_ManCleanup( pFrames ); + + // convert to CNF + pCnf = Cnf_Derive( pFrames, 0 ); + pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); +// Cnf_DataFree( pCnf ); +// Aig_ManStop( pFrames ); + + if ( pSat == NULL ) + { + Cnf_DataFree( pCnf ); + Aig_ManStop( pFrames ); + return 1; + } + + // solve the problem + status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + +// Inter_ManCheckUniqueness( pTrans, pSat, pCnf, nSteps ); + + Cnf_DataFree( pCnf ); + Aig_ManStop( pFrames ); + + sat_solver_delete( pSat ); + return status == l_False; +} +ABC_NAMESPACE_IMPL_END + +#include "src/proof/fra/fra.h" + +ABC_NAMESPACE_IMPL_START + + +/**Function************************************************************* + + Synopsis [Check if cex satisfies uniqueness constraints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Inter_ManCheckUniqueness( Aig_Man_t * p, sat_solver * pSat, Cnf_Dat_t * pCnf, int nFrames ) +{ + extern int Fra_SmlNodesCompareInFrame( Fra_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1, int iFrame0, int iFrame1 ); + extern void Fra_SmlAssignConst( Fra_Sml_t * p, Aig_Obj_t * pObj, int fConst1, int iFrame ); + extern void Fra_SmlSimulateOne( Fra_Sml_t * p ); + + Fra_Sml_t * pSml; + Vec_Int_t * vPis; + Aig_Obj_t * pObj, * pObj0; + int i, k, v, iBit, * pCounterEx; + int Counter; + if ( nFrames == 1 ) + return 1; +// if ( pSat->model.size == 0 ) + + // possible consequences here!!! + assert( 0 ); + + if ( sat_solver_nvars(pSat) == 0 ) + return 1; +// assert( Saig_ManPoNum(p) == 1 ); + assert( Aig_ManRegNum(p) > 0 ); + assert( Aig_ManRegNum(p) < Aig_ManPiNum(p) ); + + // get the counter-example + vPis = Vec_IntAlloc( 100 ); + Aig_ManForEachPi( pCnf->pMan, pObj, k ) + Vec_IntPush( vPis, pCnf->pVarNums[Aig_ObjId(pObj)] ); + assert( Vec_IntSize(vPis) == Aig_ManRegNum(p) + nFrames * Saig_ManPiNum(p) ); + pCounterEx = Sat_SolverGetModel( pSat, vPis->pArray, vPis->nSize ); + Vec_IntFree( vPis ); + + // start a new sequential simulator + pSml = Fra_SmlStart( p, 0, nFrames, 1 ); + // assign simulation info for the registers + iBit = 0; + Aig_ManForEachLoSeq( p, pObj, i ) + Fra_SmlAssignConst( pSml, pObj, pCounterEx[iBit++], 0 ); + // assign simulation info for the primary inputs + for ( i = 0; i < nFrames; i++ ) + Aig_ManForEachPiSeq( p, pObj, k ) + Fra_SmlAssignConst( pSml, pObj, pCounterEx[iBit++], i ); + assert( iBit == Aig_ManPiNum(pCnf->pMan) ); + // run simulation + Fra_SmlSimulateOne( pSml ); + + // check if the given output has failed +// RetValue = !Fra_SmlNodeIsZero( pSml, Aig_ManPo(pAig, 0) ); +// assert( RetValue ); + + // check values at the internal nodes + Counter = 0; + for ( i = 0; i < nFrames; i++ ) + for ( k = i+1; k < nFrames; k++ ) + { + for ( v = 0; v < Aig_ManRegNum(p); v++ ) + { + pObj0 = Aig_ManLo(p, v); + if ( !Fra_SmlNodesCompareInFrame( pSml, pObj0, pObj0, i, k ) ) + break; + } + if ( v == Aig_ManRegNum(p) ) + Counter++; + } + printf( "Uniquness does not hold in %d frames.\n", Counter ); + + Fra_SmlStop( pSml ); + ABC_FREE( pCounterEx ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/int/intCore.c b/src/proof/int/intCore.c new file mode 100644 index 00000000..3bd111be --- /dev/null +++ b/src/proof/int/intCore.c @@ -0,0 +1,389 @@ +/**CFile**************************************************************** + + FileName [intCore.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Interpolation engine.] + + Synopsis [Core procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 24, 2008.] + + Revision [$Id: intCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "intInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [This procedure sets default values of interpolation parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Inter_ManSetDefaultParams( Inter_ManParams_t * p ) +{ + memset( p, 0, sizeof(Inter_ManParams_t) ); + p->nBTLimit = 10000; // limit on the number of conflicts + p->nFramesMax = 40; // the max number timeframes to unroll + p->nSecLimit = 0; // time limit in seconds + p->nFramesK = 1; // the number of timeframes to use in induction + p->fRewrite = 0; // use additional rewriting to simplify timeframes + p->fTransLoop = 0; // add transition into the init state under new PI var + p->fUsePudlak = 0; // use Pudluk interpolation procedure + p->fUseOther = 0; // use other undisclosed option + p->fUseMiniSat = 0; // use MiniSat-1.14p instead of internal proof engine + p->fCheckKstep = 1; // check using K-step induction + p->fUseBias = 0; // bias decisions to global variables + p->fUseBackward = 0; // perform backward interpolation + p->fUseSeparate = 0; // solve each output separately + p->fDropSatOuts = 0; // replace by 1 the solved outputs + p->fVerbose = 0; // print verbose statistics + p->iFrameMax =-1; +} + +/**Function************************************************************* + + Synopsis [Interplates while the number of conflicts is not exceeded.] + + Description [Returns 1 if proven. 0 if failed. -1 if undecided.] + + SideEffects [Does not check the property in 0-th frame.] + + SeeAlso [] + +***********************************************************************/ +int Inter_ManPerformInterpolation( Aig_Man_t * pAig, Inter_ManParams_t * pPars, int * piFrame ) +{ + extern int Inter_ManCheckInductiveContainment( Aig_Man_t * pTrans, Aig_Man_t * pInter, int nSteps, int fBackward ); + Inter_Man_t * p; + Inter_Check_t * pCheck = NULL; + Aig_Man_t * pAigTemp; + int s, i, RetValue, Status, clk, clk2, clkTotal = clock(), timeTemp; + int nTimeNewOut = pPars->nSecLimit ? time(NULL) + pPars->nSecLimit : 0; + + // sanity checks + assert( Saig_ManRegNum(pAig) > 0 ); + assert( Saig_ManPiNum(pAig) > 0 ); + assert( Saig_ManPoNum(pAig)-Saig_ManConstrNum(pAig) == 1 ); + if ( pPars->fVerbose && Saig_ManConstrNum(pAig) ) + printf( "Performing interpolation with %d constraints...\n", Saig_ManConstrNum(pAig) ); + + if ( Inter_ManCheckInitialState(pAig) ) + { + *piFrame = 0; + printf( "Property trivially fails in the initial state.\n" ); + return 0; + } +/* + if ( Inter_ManCheckAllStates(pAig) ) + { + printf( "Property trivially holds in all states.\n" ); + return 1; + } +*/ + // create interpolation manager + // can perform SAT sweeping and/or rewriting of this AIG... + p = Inter_ManCreate( pAig, pPars ); + if ( pPars->fTransLoop ) + p->pAigTrans = Inter_ManStartOneOutput( pAig, 0 ); + else + p->pAigTrans = Inter_ManStartDuplicated( pAig ); + // derive CNF for the transformed AIG +clk = clock(); + p->pCnfAig = Cnf_Derive( p->pAigTrans, Aig_ManRegNum(p->pAigTrans) ); +p->timeCnf += clock() - clk; + if ( pPars->fVerbose ) + { + printf( "AIG: PI/PO/Reg = %d/%d/%d. And = %d. Lev = %d. CNF: Var/Cla = %d/%d.\n", + Saig_ManPiNum(pAig), Saig_ManPoNum(pAig), Saig_ManRegNum(pAig), + Aig_ManAndNum(pAig), Aig_ManLevelNum(pAig), + p->pCnfAig->nVars, p->pCnfAig->nClauses ); + } + + // derive interpolant + *piFrame = -1; + p->nFrames = 1; + for ( s = 0; ; s++ ) + { + Cnf_Dat_t * pCnfInter2; + +clk2 = clock(); + // initial state + if ( pPars->fUseBackward ) + p->pInter = Inter_ManStartOneOutput( pAig, 1 ); + else + p->pInter = Inter_ManStartInitState( Aig_ManRegNum(pAig) ); + assert( Aig_ManPoNum(p->pInter) == 1 ); +clk = clock(); + p->pCnfInter = Cnf_Derive( p->pInter, 0 ); +p->timeCnf += clock() - clk; + // timeframes + p->pFrames = Inter_ManFramesInter( pAig, p->nFrames, pPars->fUseBackward ); +clk = clock(); + if ( pPars->fRewrite ) + { + p->pFrames = Dar_ManRwsat( pAigTemp = p->pFrames, 1, 0 ); + Aig_ManStop( pAigTemp ); +// p->pFrames = Fra_FraigEquivence( pAigTemp = p->pFrames, 100, 0 ); +// Aig_ManStop( pAigTemp ); + } +p->timeRwr += clock() - clk; + // can also do SAT sweeping on the timeframes... +clk = clock(); + if ( pPars->fUseBackward ) + p->pCnfFrames = Cnf_Derive( p->pFrames, Aig_ManPoNum(p->pFrames) ); + else +// p->pCnfFrames = Cnf_Derive( p->pFrames, 0 ); + p->pCnfFrames = Cnf_DeriveSimple( p->pFrames, 0 ); +p->timeCnf += clock() - clk; + // report statistics + if ( pPars->fVerbose ) + { + printf( "Step = %2d. Frames = 1 + %d. And = %5d. Lev = %5d. ", + s+1, p->nFrames, Aig_ManNodeNum(p->pFrames), Aig_ManLevelNum(p->pFrames) ); + ABC_PRT( "Time", clock() - clk2 ); + } + + + ////////////////////////////////////////// + // start containment checking + if ( !(pPars->fTransLoop || pPars->fUseBackward) ) + { + pCheck = Inter_CheckStart( p->pAigTrans, pPars->nFramesK ); + // try new containment check for the initial state +clk = clock(); + pCnfInter2 = Cnf_Derive( p->pInter, 1 ); +p->timeCnf += clock() - clk; + RetValue = Inter_CheckPerform( pCheck, pCnfInter2, nTimeNewOut ); +// assert( RetValue == 0 ); + Cnf_DataFree( pCnfInter2 ); + if ( p->vInters ) + Vec_PtrPush( p->vInters, Aig_ManDupSimple(p->pInter) ); + } + ////////////////////////////////////////// + + // iterate the interpolation procedure + for ( i = 0; ; i++ ) + { + if ( p->nFrames + i >= pPars->nFramesMax ) + { + if ( pPars->fVerbose ) + printf( "Reached limit (%d) on the number of timeframes.\n", pPars->nFramesMax ); + p->timeTotal = clock() - clkTotal; + Inter_ManStop( p, 0 ); + Inter_CheckStop( pCheck ); + return -1; + } + + // perform interpolation + clk = clock(); +#ifdef ABC_USE_LIBRARIES + if ( pPars->fUseMiniSat ) + { + assert( !pPars->fUseBackward ); + RetValue = Inter_ManPerformOneStepM114p( p, pPars->fUsePudlak, pPars->fUseOther ); + } + else +#endif + RetValue = Inter_ManPerformOneStep( p, pPars->fUseBias, pPars->fUseBackward, nTimeNewOut ); + + if ( pPars->fVerbose ) + { + printf( " I = %2d. Bmc =%3d. IntAnd =%6d. IntLev =%5d. Conf =%6d. ", + i+1, i + 1 + p->nFrames, Aig_ManNodeNum(p->pInter), Aig_ManLevelNum(p->pInter), p->nConfCur ); + ABC_PRT( "Time", clock() - clk ); + } + // remember the number of timeframes completed + pPars->iFrameMax = i + 1 + p->nFrames; + if ( RetValue == 0 ) // found a (spurious?) counter-example + { + if ( i == 0 ) // real counterexample + { + if ( pPars->fVerbose ) + printf( "Found a real counterexample in frame %d.\n", p->nFrames ); + p->timeTotal = clock() - clkTotal; + *piFrame = p->nFrames; +// pAig->pSeqModel = (Abc_Cex_t *)Inter_ManGetCounterExample( pAig, p->nFrames+1, pPars->fVerbose ); + { + int RetValue; + Saig_ParBmc_t ParsBmc, * pParsBmc = &ParsBmc; + Saig_ParBmcSetDefaultParams( pParsBmc ); + pParsBmc->nConfLimit = 100000000; + pParsBmc->nStart = p->nFrames; + pParsBmc->fVerbose = pPars->fVerbose; + RetValue = Saig_ManBmcScalable( pAig, pParsBmc ); + if ( RetValue == 1 ) + printf( "Error: The problem should be SAT but it is UNSAT.\n" ); + else if ( RetValue == -1 ) + printf( "Error: The problem timed out.\n" ); + } + Inter_ManStop( p, 0 ); + Inter_CheckStop( pCheck ); + return 0; + } + // likely spurious counter-example + p->nFrames += i; + Inter_ManClean( p ); + break; + } + else if ( RetValue == -1 ) + { + if ( pPars->nSecLimit && time(NULL) > nTimeNewOut ) // timed out + { + if ( pPars->fVerbose ) + printf( "Reached timeout (%d seconds).\n", pPars->nSecLimit ); + } + else + { + assert( p->nConfCur >= p->nConfLimit ); + if ( pPars->fVerbose ) + printf( "Reached limit (%d) on the number of conflicts.\n", p->nConfLimit ); + } + p->timeTotal = clock() - clkTotal; + Inter_ManStop( p, 0 ); + Inter_CheckStop( pCheck ); + return -1; + } + assert( RetValue == 1 ); // found new interpolant + // compress the interpolant +clk = clock(); + if ( p->pInterNew ) + { +// Ioa_WriteAiger( p->pInterNew, "interpol.aig", 0, 0 ); + p->pInterNew = Dar_ManRwsat( pAigTemp = p->pInterNew, 1, 0 ); +// p->pInterNew = Dar_ManRwsat( pAigTemp = p->pInterNew, 0, 0 ); + Aig_ManStop( pAigTemp ); + } +p->timeRwr += clock() - clk; + + // check if interpolant is trivial + if ( p->pInterNew == NULL || Aig_ObjChild0(Aig_ManPo(p->pInterNew,0)) == Aig_ManConst0(p->pInterNew) ) + { +// printf( "interpolant is constant 0\n" ); + if ( pPars->fVerbose ) + printf( "The problem is trivially true for all states.\n" ); + p->timeTotal = clock() - clkTotal; + Inter_ManStop( p, 1 ); + Inter_CheckStop( pCheck ); + return 1; + } + + // check containment of interpolants +clk = clock(); + if ( pPars->fCheckKstep ) // k-step unique-state induction + { + if ( Aig_ManPiNum(p->pInterNew) == Aig_ManPiNum(p->pInter) ) + { + if ( pPars->fTransLoop || pPars->fUseBackward ) + Status = Inter_ManCheckInductiveContainment( p->pAigTrans, p->pInterNew, pPars->nFramesK, pPars->fUseBackward ); + else + { // new containment check +clk2 = clock(); + pCnfInter2 = Cnf_Derive( p->pInterNew, 1 ); +p->timeCnf += clock() - clk2; +timeTemp = clock() - clk2; + + Status = Inter_CheckPerform( pCheck, pCnfInter2, nTimeNewOut ); + Cnf_DataFree( pCnfInter2 ); + if ( p->vInters ) + Vec_PtrPush( p->vInters, Aig_ManDupSimple(p->pInterNew) ); + } + } + else + Status = 0; + } + else // combinational containment + { + if ( Aig_ManPiNum(p->pInterNew) == Aig_ManPiNum(p->pInter) ) + Status = Inter_ManCheckContainment( p->pInterNew, p->pInter ); + else + Status = 0; + } +p->timeEqu += clock() - clk - timeTemp; + if ( Status ) // contained + { + if ( pPars->fVerbose ) + printf( "Proved containment of interpolants.\n" ); + p->timeTotal = clock() - clkTotal; + Inter_ManStop( p, 1 ); + Inter_CheckStop( pCheck ); + return 1; + } + if ( pPars->nSecLimit && time(NULL) > nTimeNewOut ) + { + printf( "Reached timeout (%d seconds).\n", pPars->nSecLimit ); + p->timeTotal = clock() - clkTotal; + Inter_ManStop( p, 1 ); + Inter_CheckStop( pCheck ); + return -1; + } + // save interpolant and convert it into CNF + if ( pPars->fTransLoop ) + { + Aig_ManStop( p->pInter ); + p->pInter = p->pInterNew; + } + else + { + if ( pPars->fUseBackward ) + { + p->pInter = Aig_ManCreateMiter( pAigTemp = p->pInter, p->pInterNew, 2 ); + Aig_ManStop( pAigTemp ); + Aig_ManStop( p->pInterNew ); + // compress the interpolant +clk = clock(); + p->pInter = Dar_ManRwsat( pAigTemp = p->pInter, 1, 0 ); + Aig_ManStop( pAigTemp ); +p->timeRwr += clock() - clk; + } + else // forward with the new containment checking (using only the frontier) + { + Aig_ManStop( p->pInter ); + p->pInter = p->pInterNew; + } + } + p->pInterNew = NULL; + Cnf_DataFree( p->pCnfInter ); +clk = clock(); + p->pCnfInter = Cnf_Derive( p->pInter, 0 ); +p->timeCnf += clock() - clk; + } + + // start containment checking + Inter_CheckStop( pCheck ); + } + assert( 0 ); + return RetValue; +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/int/intCtrex.c b/src/proof/int/intCtrex.c new file mode 100644 index 00000000..9ba8c9df --- /dev/null +++ b/src/proof/int/intCtrex.c @@ -0,0 +1,167 @@ +/**CFile**************************************************************** + + FileName [intCtrex.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Interpolation engine.] + + Synopsis [Counter-example generation after disproving the property.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 24, 2008.] + + Revision [$Id: intCtrex.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "intInt.h" +#include "src/proof/ssw/ssw.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Unroll the circuit the given number of timeframes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Inter_ManFramesBmc( Aig_Man_t * pAig, int nFrames ) +{ + Aig_Man_t * pFrames; + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + int i, f; + assert( Saig_ManRegNum(pAig) > 0 ); + assert( Saig_ManPoNum(pAig) == 1 ); + pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFrames ); + // map the constant node + Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames ); + // create variables for register outputs + Saig_ManForEachLo( pAig, pObj, i ) + pObj->pData = Aig_ManConst0( pFrames ); + // add timeframes + for ( f = 0; f < nFrames; f++ ) + { + // create PI nodes for this frame + Saig_ManForEachPi( pAig, pObj, i ) + pObj->pData = Aig_ObjCreatePi( pFrames ); + // add internal nodes of this frame + Aig_ManForEachNode( pAig, pObj, i ) + pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + if ( f == nFrames - 1 ) + break; + // transfer to register outputs + Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) + pObjLi->pData = Aig_ObjChild0Copy(pObjLi); + // transfer to register outputs + Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) + pObjLo->pData = pObjLi->pData; + } + // create POs for the output of the last frame + pObj = Aig_ManPo( pAig, 0 ); + Aig_ObjCreatePo( pFrames, Aig_ObjChild0Copy(pObj) ); + Aig_ManCleanup( pFrames ); + return pFrames; +} + +/**Function************************************************************* + + Synopsis [Run the SAT solver on the unrolled instance.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Inter_ManGetCounterExample( Aig_Man_t * pAig, int nFrames, int fVerbose ) +{ + int nConfLimit = 1000000; + Abc_Cex_t * pCtrex = NULL; + Aig_Man_t * pFrames; + sat_solver * pSat; + Cnf_Dat_t * pCnf; + int status, clk = clock(); + Vec_Int_t * vCiIds; + // create timeframes + assert( Saig_ManPoNum(pAig) == 1 ); + pFrames = Inter_ManFramesBmc( pAig, nFrames ); + // derive CNF + pCnf = Cnf_Derive( pFrames, 0 ); + Cnf_DataTranformPolarity( pCnf, 0 ); + vCiIds = Cnf_DataCollectPiSatNums( pCnf, pFrames ); + Aig_ManStop( pFrames ); + // convert into SAT solver + pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + Cnf_DataFree( pCnf ); + if ( pSat == NULL ) + { + printf( "Counter-example generation in command \"int\" has failed.\n" ); + printf( "Use command \"bmc2\" to produce a valid counter-example.\n" ); + Vec_IntFree( vCiIds ); + return NULL; + } + // simplify the problem + status = sat_solver_simplify(pSat); + if ( status == 0 ) + { + Vec_IntFree( vCiIds ); + sat_solver_delete( pSat ); + return NULL; + } + // solve the miter + status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + // if the problem is SAT, get the counterexample + if ( status == l_True ) + { + int i, * pModel = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize ); + pCtrex = Abc_CexAlloc( Saig_ManRegNum(pAig), Saig_ManPiNum(pAig), nFrames ); + pCtrex->iFrame = nFrames - 1; + pCtrex->iPo = 0; + for ( i = 0; i < Vec_IntSize(vCiIds); i++ ) + if ( pModel[i] ) + Abc_InfoSetBit( pCtrex->pData, Saig_ManRegNum(pAig) + i ); + ABC_FREE( pModel ); + } + // free the sat_solver + sat_solver_delete( pSat ); + Vec_IntFree( vCiIds ); + // verify counter-example + status = Saig_ManVerifyCex( pAig, pCtrex ); + if ( status == 0 ) + printf( "Inter_ManGetCounterExample(): Counter-example verification has FAILED.\n" ); + // report the results + if ( fVerbose ) + { + ABC_PRT( "Total ctrex generation time", clock() - clk ); + } + return pCtrex; + +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/int/intDup.c b/src/proof/int/intDup.c new file mode 100644 index 00000000..551473ef --- /dev/null +++ b/src/proof/int/intDup.c @@ -0,0 +1,184 @@ +/**CFile**************************************************************** + + FileName [intDup.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Interpolation engine.] + + Synopsis [Specialized AIG duplication procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 24, 2008.] + + Revision [$Id: intDup.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "intInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Create trivial AIG manager for the init state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Inter_ManStartInitState( int nRegs ) +{ + Aig_Man_t * p; + Aig_Obj_t * pRes; + Aig_Obj_t ** ppInputs; + int i; + assert( nRegs > 0 ); + ppInputs = ABC_ALLOC( Aig_Obj_t *, nRegs ); + p = Aig_ManStart( nRegs ); + for ( i = 0; i < nRegs; i++ ) + ppInputs[i] = Aig_Not( Aig_ObjCreatePi(p) ); + pRes = Aig_Multi( p, ppInputs, nRegs, AIG_OBJ_AND ); + Aig_ObjCreatePo( p, pRes ); + ABC_FREE( ppInputs ); + return p; +} + +/**Function************************************************************* + + Synopsis [Duplicate the AIG w/o POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Inter_ManStartDuplicated( Aig_Man_t * p ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj; + int i; + assert( Aig_ManRegNum(p) > 0 ); + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + // create the PIs + Aig_ManCleanData( p ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManForEachPi( p, pObj, i ) + pObj->pData = Aig_ObjCreatePi( pNew ); + // set registers + pNew->nTruePis = p->nTruePis; + pNew->nTruePos = Saig_ManConstrNum(p); + pNew->nRegs = p->nRegs; + // duplicate internal nodes + Aig_ManForEachNode( p, pObj, i ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + + // create constraint outputs + Saig_ManForEachPo( p, pObj, i ) + { + if ( i < Saig_ManPoNum(p)-Saig_ManConstrNum(p) ) + continue; + Aig_ObjCreatePo( pNew, Aig_Not( Aig_ObjChild0Copy(pObj) ) ); + } + + // create register inputs with MUXes + Saig_ManForEachLi( p, pObj, i ) + Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); + Aig_ManCleanup( pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicate the AIG w/o POs and transforms to transit into init state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Inter_ManStartOneOutput( Aig_Man_t * p, int fAddFirstPo ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + Aig_Obj_t * pCtrl = NULL; // Suppress "might be used uninitialized" + int i; + assert( Aig_ManRegNum(p) > 0 ); + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + // create the PIs + Aig_ManCleanData( p ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManForEachPi( p, pObj, i ) + { + if ( i == Saig_ManPiNum(p) ) + pCtrl = Aig_ObjCreatePi( pNew ); + pObj->pData = Aig_ObjCreatePi( pNew ); + } + // set registers + pNew->nRegs = fAddFirstPo? 0 : p->nRegs; + pNew->nTruePis = fAddFirstPo? Aig_ManPiNum(p) + 1 : p->nTruePis + 1; + pNew->nTruePos = fAddFirstPo + Saig_ManConstrNum(p); + // duplicate internal nodes + Aig_ManForEachNode( p, pObj, i ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + + // create constraint outputs + Saig_ManForEachPo( p, pObj, i ) + { + if ( i < Saig_ManPoNum(p)-Saig_ManConstrNum(p) ) + continue; + Aig_ObjCreatePo( pNew, Aig_Not( Aig_ObjChild0Copy(pObj) ) ); + } + + // add the PO + if ( fAddFirstPo ) + { + pObj = Aig_ManPo( p, 0 ); + Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); + } + else + { + // create register inputs with MUXes + Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) + { + pObj = Aig_Mux( pNew, pCtrl, (Aig_Obj_t *)pObjLo->pData, Aig_ObjChild0Copy(pObjLi) ); + // pObj = Aig_Mux( pNew, pCtrl, Aig_ManConst0(pNew), Aig_ObjChild0Copy(pObjLi) ); + Aig_ObjCreatePo( pNew, pObj ); + } + } + Aig_ManCleanup( pNew ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/int/intFrames.c b/src/proof/int/intFrames.c new file mode 100644 index 00000000..0fbab6cb --- /dev/null +++ b/src/proof/int/intFrames.c @@ -0,0 +1,115 @@ +/**CFile**************************************************************** + + FileName [intFrames.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Interpolation engine.] + + Synopsis [Sequential AIG unrolling for interpolation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 24, 2008.] + + Revision [$Id: intFrames.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "intInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Create timeframes of the manager for interpolation.] + + Description [The resulting manager is combinational. The primary inputs + corresponding to register outputs are ordered first. The only POs of the + manager is the property output of the last timeframe.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Inter_ManFramesInter( Aig_Man_t * pAig, int nFrames, int fAddRegOuts ) +{ + Aig_Man_t * pFrames; + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + int i, f; + assert( Saig_ManRegNum(pAig) > 0 ); + assert( Saig_ManPoNum(pAig)-Saig_ManConstrNum(pAig) == 1 ); + pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFrames ); + // map the constant node + Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames ); + // create variables for register outputs + if ( fAddRegOuts ) + { + Saig_ManForEachLo( pAig, pObj, i ) + pObj->pData = Aig_ManConst0( pFrames ); + } + else + { + Saig_ManForEachLo( pAig, pObj, i ) + pObj->pData = Aig_ObjCreatePi( pFrames ); + } + // add timeframes + for ( f = 0; f < nFrames; f++ ) + { + // create PI nodes for this frame + Saig_ManForEachPi( pAig, pObj, i ) + pObj->pData = Aig_ObjCreatePi( pFrames ); + // add internal nodes of this frame + Aig_ManForEachNode( pAig, pObj, i ) + pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + // add outputs for constraints + Saig_ManForEachPo( pAig, pObj, i ) + { + if ( i < Saig_ManPoNum(pAig)-Saig_ManConstrNum(pAig) ) + continue; + Aig_ObjCreatePo( pFrames, Aig_Not( Aig_ObjChild0Copy(pObj) ) ); + } + if ( f == nFrames - 1 ) + break; + // save register inputs + Saig_ManForEachLi( pAig, pObj, i ) + pObj->pData = Aig_ObjChild0Copy(pObj); + // transfer to register outputs + Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) + pObjLo->pData = pObjLi->pData; + } + // create POs for each register output + if ( fAddRegOuts ) + { + Saig_ManForEachLi( pAig, pObj, i ) + Aig_ObjCreatePo( pFrames, Aig_ObjChild0Copy(pObj) ); + } + // create the only PO of the manager + else + { + pObj = Aig_ManPo( pAig, 0 ); + Aig_ObjCreatePo( pFrames, Aig_ObjChild0Copy(pObj) ); + } + Aig_ManCleanup( pFrames ); + return pFrames; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/int/intInt.h b/src/proof/int/intInt.h new file mode 100644 index 00000000..6a033d85 --- /dev/null +++ b/src/proof/int/intInt.h @@ -0,0 +1,142 @@ +/**CFile**************************************************************** + + FileName [intInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Interpolation engine.] + + Synopsis [Internal declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 24, 2008.] + + Revision [$Id: intInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__int__intInt_h +#define ABC__aig__int__intInt_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "src/aig/saig/saig.h" +#include "src/sat/cnf/cnf.h" +#include "src/sat/bsat/satSolver.h" +#include "src/sat/bsat/satStore.h" +#include "int.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +// interpolation manager +typedef struct Inter_Man_t_ Inter_Man_t; +struct Inter_Man_t_ +{ + // AIG manager + Aig_Man_t * pAig; // the original AIG manager + Aig_Man_t * pAigTrans; // the transformed original AIG manager + Cnf_Dat_t * pCnfAig; // CNF for the original manager + // interpolant + Aig_Man_t * pInter; // the current interpolant + Cnf_Dat_t * pCnfInter; // CNF for the current interplant + // timeframes + Aig_Man_t * pFrames; // the timeframes + Cnf_Dat_t * pCnfFrames; // CNF for the timeframes + // other data + Vec_Int_t * vVarsAB; // the variables participating in + // temporary place for the new interpolant + Aig_Man_t * pInterNew; + Vec_Ptr_t * vInters; + // parameters + int nFrames; // the number of timeframes + int nConfCur; // the current number of conflicts + int nConfLimit; // the limit on the number of conflicts + int fVerbose; // the verbosiness flag + // runtime + int timeRwr; + int timeCnf; + int timeSat; + int timeInt; + int timeEqu; + int timeOther; + int timeTotal; +}; + +// containment checking manager +typedef struct Inter_Check_t_ Inter_Check_t; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== intCheck.c ============================================================*/ +extern Inter_Check_t * Inter_CheckStart( Aig_Man_t * pTrans, int nFramesK ); +extern void Inter_CheckStop( Inter_Check_t * p ); +extern int Inter_CheckPerform( Inter_Check_t * p, Cnf_Dat_t * pCnf, int nTimeNewOut ); + +/*=== intContain.c ============================================================*/ +extern int Inter_ManCheckContainment( Aig_Man_t * pNew, Aig_Man_t * pOld ); +extern int Inter_ManCheckEquivalence( Aig_Man_t * pNew, Aig_Man_t * pOld ); +extern int Inter_ManCheckInductiveContainment( Aig_Man_t * pTrans, Aig_Man_t * pInter, int nSteps, int fBackward ); + +/*=== intCtrex.c ============================================================*/ +extern void * Inter_ManGetCounterExample( Aig_Man_t * pAig, int nFrames, int fVerbose ); + +/*=== intDup.c ============================================================*/ +extern Aig_Man_t * Inter_ManStartInitState( int nRegs ); +extern Aig_Man_t * Inter_ManStartDuplicated( Aig_Man_t * p ); +extern Aig_Man_t * Inter_ManStartOneOutput( Aig_Man_t * p, int fAddFirstPo ); + +/*=== intFrames.c ============================================================*/ +extern Aig_Man_t * Inter_ManFramesInter( Aig_Man_t * pAig, int nFrames, int fAddRegOuts ); + +/*=== intMan.c ============================================================*/ +extern Inter_Man_t * Inter_ManCreate( Aig_Man_t * pAig, Inter_ManParams_t * pPars ); +extern void Inter_ManClean( Inter_Man_t * p ); +extern void Inter_ManStop( Inter_Man_t * p, int fProved ); + +/*=== intM114.c ============================================================*/ +extern int Inter_ManPerformOneStep( Inter_Man_t * p, int fUseBias, int fUseBackward, int nTimeNewOut ); + +/*=== intM114p.c ============================================================*/ +#ifdef ABC_USE_LIBRARIES +extern int Inter_ManPerformOneStepM114p( Inter_Man_t * p, int fUsePudlak, int fUseOther ); +#endif + +/*=== intUtil.c ============================================================*/ +extern int Inter_ManCheckInitialState( Aig_Man_t * p ); +extern int Inter_ManCheckAllStates( Aig_Man_t * p ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/proof/int/intInter.c b/src/proof/int/intInter.c new file mode 100644 index 00000000..ef32294b --- /dev/null +++ b/src/proof/int/intInter.c @@ -0,0 +1,145 @@ +/**CFile**************************************************************** + + FileName [intInter.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Interpolation engine.] + + Synopsis [Experimental procedures to derive and compare interpolants.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 24, 2008.] + + Revision [$Id: intInter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "intInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Inter_ManDupExpand( Aig_Man_t * pInter, Aig_Man_t * pOther ) +{ + Aig_Man_t * pInterC; + assert( Aig_ManPiNum(pInter) <= Aig_ManPiNum(pOther) ); + pInterC = Aig_ManDupSimple( pInter ); + Aig_IthVar( pInterC, Aig_ManPiNum(pOther)-1 ); + assert( Aig_ManPiNum(pInterC) == Aig_ManPiNum(pOther) ); + return pInterC; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Inter_ManVerifyInterpolant1( Inta_Man_t * pMan, Sto_Man_t * pCnf, Aig_Man_t * pInter ) +{ + extern Aig_Man_t * Inta_ManDeriveClauses( Inta_Man_t * pMan, Sto_Man_t * pCnf, int fClausesA ); + Aig_Man_t * pLower, * pUpper, * pInterC; + int RetValue1, RetValue2; + + pLower = Inta_ManDeriveClauses( pMan, pCnf, 1 ); + pUpper = Inta_ManDeriveClauses( pMan, pCnf, 0 ); + Aig_ManFlipFirstPo( pUpper ); + + pInterC = Inter_ManDupExpand( pInter, pLower ); + RetValue1 = Inter_ManCheckContainment( pLower, pInterC ); + Aig_ManStop( pInterC ); + + pInterC = Inter_ManDupExpand( pInter, pUpper ); + RetValue2 = Inter_ManCheckContainment( pInterC, pUpper ); + Aig_ManStop( pInterC ); + + if ( RetValue1 && RetValue2 ) + printf( "Im is correct.\n" ); + if ( !RetValue1 ) + printf( "Property A => Im fails.\n" ); + if ( !RetValue2 ) + printf( "Property Im => !B fails.\n" ); + + Aig_ManStop( pLower ); + Aig_ManStop( pUpper ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Inter_ManVerifyInterpolant2( Intb_Man_t * pMan, Sto_Man_t * pCnf, Aig_Man_t * pInter ) +{ + extern Aig_Man_t * Intb_ManDeriveClauses( Intb_Man_t * pMan, Sto_Man_t * pCnf, int fClausesA ); + Aig_Man_t * pLower, * pUpper, * pInterC; + int RetValue1, RetValue2; + + pLower = Intb_ManDeriveClauses( pMan, pCnf, 1 ); + pUpper = Intb_ManDeriveClauses( pMan, pCnf, 0 ); + Aig_ManFlipFirstPo( pUpper ); + + pInterC = Inter_ManDupExpand( pInter, pLower ); +//Aig_ManPrintStats( pLower ); +//Aig_ManPrintStats( pUpper ); +//Aig_ManPrintStats( pInterC ); +//Aig_ManDumpBlif( pInterC, "inter_c.blif", NULL, NULL ); + RetValue1 = Inter_ManCheckContainment( pLower, pInterC ); + Aig_ManStop( pInterC ); + + pInterC = Inter_ManDupExpand( pInter, pUpper ); + RetValue2 = Inter_ManCheckContainment( pInterC, pUpper ); + Aig_ManStop( pInterC ); + + if ( RetValue1 && RetValue2 ) + printf( "Ip is correct.\n" ); + if ( !RetValue1 ) + printf( "Property A => Ip fails.\n" ); + if ( !RetValue2 ) + printf( "Property Ip => !B fails.\n" ); + + Aig_ManStop( pLower ); + Aig_ManStop( pUpper ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/int/intM114.c b/src/proof/int/intM114.c new file mode 100644 index 00000000..139c9bbd --- /dev/null +++ b/src/proof/int/intM114.c @@ -0,0 +1,320 @@ +/**CFile**************************************************************** + + FileName [intM114.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Interpolation engine.] + + Synopsis [Intepolation using ABC's proof generator added to MiniSat-1.14c.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 24, 2008.] + + Revision [$Id: intM114.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "intInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the SAT solver for one interpolation run.] + + Description [pInter is the previous interpolant. pAig is one time frame. + pFrames is the unrolled time frames.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +sat_solver * Inter_ManDeriveSatSolver( + Aig_Man_t * pInter, Cnf_Dat_t * pCnfInter, + Aig_Man_t * pAig, Cnf_Dat_t * pCnfAig, + Aig_Man_t * pFrames, Cnf_Dat_t * pCnfFrames, + Vec_Int_t * vVarsAB, int fUseBackward ) +{ + sat_solver * pSat; + Aig_Obj_t * pObj, * pObj2; + int i, Lits[2]; + +//Aig_ManDumpBlif( pInter, "out_inter.blif", NULL, NULL ); +//Aig_ManDumpBlif( pAig, "out_aig.blif", NULL, NULL ); +//Aig_ManDumpBlif( pFrames, "out_frames.blif", NULL, NULL ); + + // sanity checks + assert( Aig_ManRegNum(pInter) == 0 ); + assert( Aig_ManRegNum(pAig) > 0 ); + assert( Aig_ManRegNum(pFrames) == 0 ); + assert( Aig_ManPoNum(pInter) == 1 ); + assert( Aig_ManPoNum(pFrames) == fUseBackward? Saig_ManRegNum(pAig) : 1 ); + assert( fUseBackward || Aig_ManPiNum(pInter) == Aig_ManRegNum(pAig) ); +// assert( (Aig_ManPiNum(pFrames) - Aig_ManRegNum(pAig)) % Saig_ManPiNum(pAig) == 0 ); + + // prepare CNFs + Cnf_DataLift( pCnfAig, pCnfFrames->nVars ); + Cnf_DataLift( pCnfInter, pCnfFrames->nVars + pCnfAig->nVars ); + + // start the solver + pSat = sat_solver_new(); + sat_solver_store_alloc( pSat ); + sat_solver_setnvars( pSat, pCnfInter->nVars + pCnfAig->nVars + pCnfFrames->nVars ); + + // add clauses of A + // interpolant + for ( i = 0; i < pCnfInter->nClauses; i++ ) + { + if ( !sat_solver_addclause( pSat, pCnfInter->pClauses[i], pCnfInter->pClauses[i+1] ) ) + { + sat_solver_delete( pSat ); + // return clauses to the original state + Cnf_DataLift( pCnfAig, -pCnfFrames->nVars ); + Cnf_DataLift( pCnfInter, -pCnfFrames->nVars -pCnfAig->nVars ); + return NULL; + } + } + // connector clauses + if ( fUseBackward ) + { + Saig_ManForEachLi( pAig, pObj2, i ) + { + if ( Saig_ManRegNum(pAig) == Aig_ManPiNum(pInter) ) + pObj = Aig_ManPi( pInter, i ); + else + { + assert( Aig_ManPiNum(pAig) == Aig_ManPiNum(pInter) ); + pObj = Aig_ManPi( pInter, Aig_ManPiNum(pAig)-Saig_ManRegNum(pAig) + i ); + } + + Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 0 ); + Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 ); + if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) + assert( 0 ); + Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 1 ); + Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 ); + if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) + assert( 0 ); + } + } + else + { + Aig_ManForEachPi( pInter, pObj, i ) + { + pObj2 = Saig_ManLo( pAig, i ); + + Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 0 ); + Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 ); + if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) + assert( 0 ); + Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 1 ); + Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 ); + if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) + assert( 0 ); + } + } + // one timeframe + for ( i = 0; i < pCnfAig->nClauses; i++ ) + { + if ( !sat_solver_addclause( pSat, pCnfAig->pClauses[i], pCnfAig->pClauses[i+1] ) ) + assert( 0 ); + } + // connector clauses + Vec_IntClear( vVarsAB ); + if ( fUseBackward ) + { + Aig_ManForEachPo( pFrames, pObj, i ) + { + assert( pCnfFrames->pVarNums[pObj->Id] >= 0 ); + Vec_IntPush( vVarsAB, pCnfFrames->pVarNums[pObj->Id] ); + + pObj2 = Saig_ManLo( pAig, i ); + Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 0 ); + Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 ); + if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) + assert( 0 ); + Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 1 ); + Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 ); + if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) + assert( 0 ); + } + } + else + { + Aig_ManForEachPi( pFrames, pObj, i ) + { + if ( i == Aig_ManRegNum(pAig) ) + break; + Vec_IntPush( vVarsAB, pCnfFrames->pVarNums[pObj->Id] ); + + pObj2 = Saig_ManLi( pAig, i ); + Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 0 ); + Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 ); + if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) + assert( 0 ); + Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 1 ); + Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 ); + if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) + assert( 0 ); + } + } + // add clauses of B + sat_solver_store_mark_clauses_a( pSat ); + for ( i = 0; i < pCnfFrames->nClauses; i++ ) + { + if ( !sat_solver_addclause( pSat, pCnfFrames->pClauses[i], pCnfFrames->pClauses[i+1] ) ) + { + pSat->fSolved = 1; + break; + } + } + sat_solver_store_mark_roots( pSat ); + // return clauses to the original state + Cnf_DataLift( pCnfAig, -pCnfFrames->nVars ); + Cnf_DataLift( pCnfInter, -pCnfFrames->nVars -pCnfAig->nVars ); + return pSat; +} + +/**Function************************************************************* + + Synopsis [Performs one SAT run with interpolation.] + + Description [Returns 1 if proven. 0 if failed. -1 if undecided.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Inter_ManPerformOneStep( Inter_Man_t * p, int fUseBias, int fUseBackward, int nTimeNewOut ) +{ + sat_solver * pSat; + void * pSatCnf = NULL; + Inta_Man_t * pManInterA; +// Intb_Man_t * pManInterB; + int * pGlobalVars; + int clk, status, RetValue; + int i, Var; +// assert( p->pInterNew == NULL ); + + // derive the SAT solver + pSat = Inter_ManDeriveSatSolver( p->pInter, p->pCnfInter, p->pAigTrans, p->pCnfAig, p->pFrames, p->pCnfFrames, p->vVarsAB, fUseBackward ); + if ( pSat == NULL ) + { + p->pInterNew = NULL; + return 1; + } + + // set runtime limit + if ( nTimeNewOut ) + sat_solver_set_runtime_limit( pSat, nTimeNewOut ); + + // collect global variables + pGlobalVars = ABC_CALLOC( int, sat_solver_nvars(pSat) ); + Vec_IntForEachEntry( p->vVarsAB, Var, i ) + pGlobalVars[Var] = 1; + pSat->pGlobalVars = fUseBias? pGlobalVars : NULL; + + // solve the problem +clk = clock(); + status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)p->nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + p->nConfCur = pSat->stats.conflicts; +p->timeSat += clock() - clk; + + pSat->pGlobalVars = NULL; + ABC_FREE( pGlobalVars ); + if ( status == l_False ) + { + pSatCnf = sat_solver_store_release( pSat ); + RetValue = 1; + } + else if ( status == l_True ) + { + RetValue = 0; + } + else + { + RetValue = -1; + } + sat_solver_delete( pSat ); + if ( pSatCnf == NULL ) + return RetValue; + + // create the resulting manager +clk = clock(); +/* + if ( !fUseIp ) + { + pManInterA = Inta_ManAlloc(); + p->pInterNew = Inta_ManInterpolate( pManInterA, pSatCnf, p->vVarsAB, 0 ); + Inta_ManFree( pManInterA ); + } + else + { + Aig_Man_t * pInterNew2; + int RetValue; + + pManInterA = Inta_ManAlloc(); + p->pInterNew = Inta_ManInterpolate( pManInterA, pSatCnf, p->vVarsAB, 0 ); +// Inter_ManVerifyInterpolant1( pManInterA, pSatCnf, p->pInterNew ); + Inta_ManFree( pManInterA ); + + pManInterB = Intb_ManAlloc(); + pInterNew2 = Intb_ManInterpolate( pManInterB, pSatCnf, p->vVarsAB, 0 ); + Inter_ManVerifyInterpolant2( pManInterB, pSatCnf, pInterNew2 ); + Intb_ManFree( pManInterB ); + + // check relationship + RetValue = Inter_ManCheckEquivalence( pInterNew2, p->pInterNew ); + if ( RetValue ) + printf( "Equivalence \"Ip == Im\" holds\n" ); + else + { +// printf( "Equivalence \"Ip == Im\" does not hold\n" ); + RetValue = Inter_ManCheckContainment( pInterNew2, p->pInterNew ); + if ( RetValue ) + printf( "Containment \"Ip -> Im\" holds\n" ); + else + printf( "Containment \"Ip -> Im\" does not hold\n" ); + + RetValue = Inter_ManCheckContainment( p->pInterNew, pInterNew2 ); + if ( RetValue ) + printf( "Containment \"Im -> Ip\" holds\n" ); + else + printf( "Containment \"Im -> Ip\" does not hold\n" ); + } + + Aig_ManStop( pInterNew2 ); + } +*/ + + pManInterA = Inta_ManAlloc(); + p->pInterNew = (Aig_Man_t *)Inta_ManInterpolate( pManInterA, (Sto_Man_t *)pSatCnf, p->vVarsAB, 0 ); + Inta_ManFree( pManInterA ); + +p->timeInt += clock() - clk; + Sto_ManFree( (Sto_Man_t *)pSatCnf ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/int/intM114p.c b/src/proof/int/intM114p.c new file mode 100644 index 00000000..7c011426 --- /dev/null +++ b/src/proof/int/intM114p.c @@ -0,0 +1,442 @@ +/**CFile**************************************************************** + + FileName [intM114p.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Interpolation engine.] + + Synopsis [Intepolation using interfaced to MiniSat-1.14p.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 24, 2008.] + + Revision [$Id: intM114p.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "intInt.h" +#include "src/sat/psat/m114p.h" + +#ifdef ABC_USE_LIBRARIES + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the SAT solver for one interpolation run.] + + Description [pInter is the previous interpolant. pAig is one time frame. + pFrames is the unrolled time frames.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +M114p_Solver_t Inter_ManDeriveSatSolverM114p( + Aig_Man_t * pInter, Cnf_Dat_t * pCnfInter, + Aig_Man_t * pAig, Cnf_Dat_t * pCnfAig, + Aig_Man_t * pFrames, Cnf_Dat_t * pCnfFrames, + Vec_Int_t ** pvMapRoots, Vec_Int_t ** pvMapVars ) +{ + M114p_Solver_t pSat; + Aig_Obj_t * pObj, * pObj2; + int i, Lits[2]; + + // sanity checks + assert( Aig_ManRegNum(pInter) == 0 ); + assert( Aig_ManRegNum(pAig) > 0 ); + assert( Aig_ManRegNum(pFrames) == 0 ); + assert( Aig_ManPoNum(pInter) == 1 ); + assert( Aig_ManPoNum(pFrames) == 1 ); + assert( Aig_ManPiNum(pInter) == Aig_ManRegNum(pAig) ); +// assert( (Aig_ManPiNum(pFrames) - Aig_ManRegNum(pAig)) % Saig_ManPiNum(pAig) == 0 ); + + // prepare CNFs + Cnf_DataLift( pCnfAig, pCnfFrames->nVars ); + Cnf_DataLift( pCnfInter, pCnfFrames->nVars + pCnfAig->nVars ); + + *pvMapRoots = Vec_IntAlloc( 10000 ); + *pvMapVars = Vec_IntAlloc( 0 ); + Vec_IntFill( *pvMapVars, pCnfInter->nVars + pCnfAig->nVars + pCnfFrames->nVars, -1 ); + for ( i = 0; i < pCnfFrames->nVars; i++ ) + Vec_IntWriteEntry( *pvMapVars, i, -2 ); + + // start the solver + pSat = M114p_SolverNew( 1 ); + M114p_SolverSetVarNum( pSat, pCnfInter->nVars + pCnfAig->nVars + pCnfFrames->nVars ); + + // add clauses of A + // interpolant + for ( i = 0; i < pCnfInter->nClauses; i++ ) + { + Vec_IntPush( *pvMapRoots, 0 ); + if ( !M114p_SolverAddClause( pSat, pCnfInter->pClauses[i], pCnfInter->pClauses[i+1] ) ) + assert( 0 ); + } + // connector clauses + Aig_ManForEachPi( pInter, pObj, i ) + { + pObj2 = Saig_ManLo( pAig, i ); + Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 0 ); + Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 ); + Vec_IntPush( *pvMapRoots, 0 ); + if ( !M114p_SolverAddClause( pSat, Lits, Lits+2 ) ) + assert( 0 ); + Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 1 ); + Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 ); + Vec_IntPush( *pvMapRoots, 0 ); + if ( !M114p_SolverAddClause( pSat, Lits, Lits+2 ) ) + assert( 0 ); + } + // one timeframe + for ( i = 0; i < pCnfAig->nClauses; i++ ) + { + Vec_IntPush( *pvMapRoots, 0 ); + if ( !M114p_SolverAddClause( pSat, pCnfAig->pClauses[i], pCnfAig->pClauses[i+1] ) ) + assert( 0 ); + } + // connector clauses + Aig_ManForEachPi( pFrames, pObj, i ) + { + if ( i == Aig_ManRegNum(pAig) ) + break; +// Vec_IntPush( vVarsAB, pCnfFrames->pVarNums[pObj->Id] ); + Vec_IntWriteEntry( *pvMapVars, pCnfFrames->pVarNums[pObj->Id], i ); + + pObj2 = Saig_ManLi( pAig, i ); + Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 0 ); + Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 ); + Vec_IntPush( *pvMapRoots, 0 ); + if ( !M114p_SolverAddClause( pSat, Lits, Lits+2 ) ) + assert( 0 ); + Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 1 ); + Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 ); + Vec_IntPush( *pvMapRoots, 0 ); + if ( !M114p_SolverAddClause( pSat, Lits, Lits+2 ) ) + assert( 0 ); + } + // add clauses of B + for ( i = 0; i < pCnfFrames->nClauses; i++ ) + { + Vec_IntPush( *pvMapRoots, 1 ); + if ( !M114p_SolverAddClause( pSat, pCnfFrames->pClauses[i], pCnfFrames->pClauses[i+1] ) ) + { +// assert( 0 ); + break; + } + } + // return clauses to the original state + Cnf_DataLift( pCnfAig, -pCnfFrames->nVars ); + Cnf_DataLift( pCnfInter, -pCnfFrames->nVars -pCnfAig->nVars ); + return pSat; +} + + +/**Function************************************************************* + + Synopsis [Performs one resolution step.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Inter_ManResolveM114p( Vec_Int_t * vResolvent, int * pLits, int nLits, int iVar ) +{ + int i, k, iLit = -1, fFound = 0; + // find the variable in the clause + for ( i = 0; i < vResolvent->nSize; i++ ) + if ( lit_var(vResolvent->pArray[i]) == iVar ) + { + iLit = vResolvent->pArray[i]; + vResolvent->pArray[i] = vResolvent->pArray[--vResolvent->nSize]; + break; + } + assert( iLit != -1 ); + // add other variables + for ( i = 0; i < nLits; i++ ) + { + if ( lit_var(pLits[i]) == iVar ) + { + assert( iLit == lit_neg(pLits[i]) ); + fFound = 1; + continue; + } + // check if this literal appears + for ( k = 0; k < vResolvent->nSize; k++ ) + if ( vResolvent->pArray[k] == pLits[i] ) + break; + if ( k < vResolvent->nSize ) + continue; + // add this literal + Vec_IntPush( vResolvent, pLits[i] ); + } + assert( fFound ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes interpolant using MiniSat-1.14p.] + + Description [Assumes that the solver returned UNSAT and proof + logging was enabled. Array vMapRoots maps number of each root clause + into 0 (clause of A) or 1 (clause of B). Array vMapVars maps each SAT + solver variable into -1 (var of A), -2 (var of B), and (var of C), + where is the var's 0-based number in the ordering of C variables.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Inter_ManInterpolateM114pPudlak( M114p_Solver_t s, Vec_Int_t * vMapRoots, Vec_Int_t * vMapVars ) +{ + Aig_Man_t * p; + Aig_Obj_t * pInter, * pInter2, * pVar; + Vec_Ptr_t * vInters; + Vec_Int_t * vLiterals, * vClauses, * vResolvent; + int * pLitsNext, nLitsNext, nOffset, iLit; + int * pLits, * pClauses, * pVars; + int nLits, nVars, i, k, v, iVar; + assert( M114p_SolverProofIsReady(s) ); + vInters = Vec_PtrAlloc( 1000 ); + + vLiterals = Vec_IntAlloc( 10000 ); + vClauses = Vec_IntAlloc( 1000 ); + vResolvent = Vec_IntAlloc( 100 ); + + // create elementary variables + p = Aig_ManStart( 10000 ); + Vec_IntForEachEntry( vMapVars, iVar, i ) + if ( iVar >= 0 ) + Aig_IthVar(p, iVar); + // process root clauses + M114p_SolverForEachRoot( s, &pLits, nLits, i ) + { + if ( Vec_IntEntry(vMapRoots, i) == 1 ) // clause of B + pInter = Aig_ManConst1(p); + else // clause of A + pInter = Aig_ManConst0(p); + Vec_PtrPush( vInters, pInter ); + + // save the root clause + Vec_IntPush( vClauses, Vec_IntSize(vLiterals) ); + Vec_IntPush( vLiterals, nLits ); + for ( v = 0; v < nLits; v++ ) + Vec_IntPush( vLiterals, pLits[v] ); + } + assert( Vec_PtrSize(vInters) == Vec_IntSize(vMapRoots) ); + + // process learned clauses + M114p_SolverForEachChain( s, &pClauses, &pVars, nVars, i ) + { + pInter = Vec_PtrEntry( vInters, pClauses[0] ); + + // initialize the resolvent + nOffset = Vec_IntEntry( vClauses, pClauses[0] ); + nLitsNext = Vec_IntEntry( vLiterals, nOffset ); + pLitsNext = Vec_IntArray(vLiterals) + nOffset + 1; + Vec_IntClear( vResolvent ); + for ( v = 0; v < nLitsNext; v++ ) + Vec_IntPush( vResolvent, pLitsNext[v] ); + + for ( k = 0; k < nVars; k++ ) + { + iVar = Vec_IntEntry( vMapVars, pVars[k] ); + pInter2 = Vec_PtrEntry( vInters, pClauses[k+1] ); + + // resolve it with the next clause + nOffset = Vec_IntEntry( vClauses, pClauses[k+1] ); + nLitsNext = Vec_IntEntry( vLiterals, nOffset ); + pLitsNext = Vec_IntArray(vLiterals) + nOffset + 1; + Inter_ManResolveM114p( vResolvent, pLitsNext, nLitsNext, pVars[k] ); + + if ( iVar == -1 ) // var of A + pInter = Aig_Or( p, pInter, pInter2 ); + else if ( iVar == -2 ) // var of B + pInter = Aig_And( p, pInter, pInter2 ); + else // var of C + { + // check polarity of the pivot variable in the clause + for ( v = 0; v < nLitsNext; v++ ) + if ( lit_var(pLitsNext[v]) == pVars[k] ) + break; + assert( v < nLitsNext ); + pVar = Aig_NotCond( Aig_IthVar(p, iVar), lit_sign(pLitsNext[v]) ); + pInter = Aig_Mux( p, pVar, pInter, pInter2 ); + } + } + Vec_PtrPush( vInters, pInter ); + + // store the resulting clause + Vec_IntPush( vClauses, Vec_IntSize(vLiterals) ); + Vec_IntPush( vLiterals, Vec_IntSize(vResolvent) ); + Vec_IntForEachEntry( vResolvent, iLit, v ) + Vec_IntPush( vLiterals, iLit ); + } + assert( Vec_PtrSize(vInters) == M114p_SolverProofClauseNum(s) ); + assert( Vec_IntSize(vResolvent) == 0 ); // the empty clause + Vec_PtrFree( vInters ); + Vec_IntFree( vLiterals ); + Vec_IntFree( vClauses ); + Vec_IntFree( vResolvent ); + Aig_ObjCreatePo( p, pInter ); + Aig_ManCleanup( p ); + return p; +} + + +/**Function************************************************************* + + Synopsis [Computes interpolant using MiniSat-1.14p.] + + Description [Assumes that the solver returned UNSAT and proof + logging was enabled. Array vMapRoots maps number of each root clause + into 0 (clause of A) or 1 (clause of B). Array vMapVars maps each SAT + solver variable into -1 (var of A), -2 (var of B), and (var of C), + where is the var's 0-based number in the ordering of C variables.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Inter_ManpInterpolateM114( M114p_Solver_t s, Vec_Int_t * vMapRoots, Vec_Int_t * vMapVars ) +{ + Aig_Man_t * p; + Aig_Obj_t * pInter, * pInter2, * pVar; + Vec_Ptr_t * vInters; + int * pLits, * pClauses, * pVars; + int nLits, nVars, i, k, iVar; + int nClauses; + + nClauses = M114p_SolverProofClauseNum(s); + + assert( M114p_SolverProofIsReady(s) ); + + vInters = Vec_PtrAlloc( 1000 ); + // process root clauses + p = Aig_ManStart( 10000 ); + M114p_SolverForEachRoot( s, &pLits, nLits, i ) + { + if ( Vec_IntEntry(vMapRoots, i) == 1 ) // clause of B + pInter = Aig_ManConst1(p); + else // clause of A + { + pInter = Aig_ManConst0(p); + for ( k = 0; k < nLits; k++ ) + { + iVar = Vec_IntEntry( vMapVars, lit_var(pLits[k]) ); + if ( iVar < 0 ) // var of A or B + continue; + // this is a variable of C + pVar = Aig_NotCond( Aig_IthVar(p, iVar), lit_sign(pLits[k]) ); + pInter = Aig_Or( p, pInter, pVar ); + } + } + Vec_PtrPush( vInters, pInter ); + } +// assert( Vec_PtrSize(vInters) == Vec_IntSize(vMapRoots) ); + + // process learned clauses + M114p_SolverForEachChain( s, &pClauses, &pVars, nVars, i ) + { + pInter = Vec_PtrEntry( vInters, pClauses[0] ); + for ( k = 0; k < nVars; k++ ) + { + iVar = Vec_IntEntry( vMapVars, pVars[k] ); + pInter2 = Vec_PtrEntry( vInters, pClauses[k+1] ); + if ( iVar == -1 ) // var of A + pInter = Aig_Or( p, pInter, pInter2 ); + else // var of B or C + pInter = Aig_And( p, pInter, pInter2 ); + } + Vec_PtrPush( vInters, pInter ); + } + + assert( Vec_PtrSize(vInters) == M114p_SolverProofClauseNum(s) ); + Vec_PtrFree( vInters ); + Aig_ObjCreatePo( p, pInter ); + Aig_ManCleanup( p ); + assert( Aig_ManCheck(p) ); + return p; +} + + +/**Function************************************************************* + + Synopsis [Performs one SAT run with interpolation.] + + Description [Returns 1 if proven. 0 if failed. -1 if undecided.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Inter_ManPerformOneStepM114p( Inter_Man_t * p, int fUsePudlak, int fUseOther ) +{ + M114p_Solver_t pSat; + Vec_Int_t * vMapRoots, * vMapVars; + int clk, status, RetValue; + assert( p->pInterNew == NULL ); + // derive the SAT solver + pSat = Inter_ManDeriveSatSolverM114p( p->pInter, p->pCnfInter, + p->pAigTrans, p->pCnfAig, p->pFrames, p->pCnfFrames, + &vMapRoots, &vMapVars ); + // solve the problem +clk = clock(); + status = M114p_SolverSolve( pSat, NULL, NULL, 0 ); + p->nConfCur = M114p_SolverGetConflictNum( pSat ); +p->timeSat += clock() - clk; + if ( status == 0 ) + { + RetValue = 1; +// Inter_ManpInterpolateM114Report( pSat, vMapRoots, vMapVars ); + +clk = clock(); + if ( fUsePudlak ) + p->pInterNew = Inter_ManInterpolateM114pPudlak( pSat, vMapRoots, vMapVars ); + else + p->pInterNew = Inter_ManpInterpolateM114( pSat, vMapRoots, vMapVars ); +p->timeInt += clock() - clk; + } + else if ( status == 1 ) + { + RetValue = 0; + } + else + { + RetValue = -1; + } + M114p_SolverDelete( pSat ); + Vec_IntFree( vMapRoots ); + Vec_IntFree( vMapVars ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_IMPL_END + +#endif + + diff --git a/src/proof/int/intMan.c b/src/proof/int/intMan.c new file mode 100644 index 00000000..6fd81d7a --- /dev/null +++ b/src/proof/int/intMan.c @@ -0,0 +1,163 @@ +/**CFile**************************************************************** + + FileName [intMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Interpolation engine.] + + Synopsis [Interpolation manager procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 24, 2008.] + + Revision [$Id: intMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "intInt.h" +#include "src/aig/ioa/ioa.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates the interpolation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Inter_Man_t * Inter_ManCreate( Aig_Man_t * pAig, Inter_ManParams_t * pPars ) +{ + Inter_Man_t * p; + // create interpolation manager + p = ABC_ALLOC( Inter_Man_t, 1 ); + memset( p, 0, sizeof(Inter_Man_t) ); + p->vVarsAB = Vec_IntAlloc( Aig_ManRegNum(pAig) ); + p->nConfLimit = pPars->nBTLimit; + p->fVerbose = pPars->fVerbose; + p->pAig = pAig; + if ( pPars->fDropInvar ) + p->vInters = Vec_PtrAlloc( 100 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Cleans the interpolation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Inter_ManClean( Inter_Man_t * p ) +{ + if ( p->vInters ) + { + Aig_Man_t * pMan; + int i; + Vec_PtrForEachEntry( Aig_Man_t *, p->vInters, pMan, i ) + Aig_ManStop( pMan ); + Vec_PtrClear( p->vInters ); + } + if ( p->pCnfInter ) + Cnf_DataFree( p->pCnfInter ); + if ( p->pCnfFrames ) + Cnf_DataFree( p->pCnfFrames ); + if ( p->pInter ) + Aig_ManStop( p->pInter ); + if ( p->pFrames ) + Aig_ManStop( p->pFrames ); +} + +/**Function************************************************************* + + Synopsis [Writes interpolant into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Inter_ManInterDump( Inter_Man_t * p, int fProved ) +{ + Aig_Man_t * pMan; + pMan = Aig_ManDupArray( p->vInters ); + Ioa_WriteAiger( pMan, "invar.aig", 0, 0 ); + Aig_ManStop( pMan ); + if ( fProved ) + printf( "Inductive invariant is dumped into file \"invar.aig\".\n" ); + else + printf( "Interpolants are dumped into file \"inter.aig\".\n" ); +} + +/**Function************************************************************* + + Synopsis [Frees the interpolation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Inter_ManStop( Inter_Man_t * p, int fProved ) +{ + if ( p->fVerbose ) + { + p->timeOther = p->timeTotal-p->timeRwr-p->timeCnf-p->timeSat-p->timeInt-p->timeEqu; + printf( "Runtime statistics:\n" ); + ABC_PRTP( "Rewriting ", p->timeRwr, p->timeTotal ); + ABC_PRTP( "CNF mapping", p->timeCnf, p->timeTotal ); + ABC_PRTP( "SAT solving", p->timeSat, p->timeTotal ); + ABC_PRTP( "Interpol ", p->timeInt, p->timeTotal ); + ABC_PRTP( "Containment", p->timeEqu, p->timeTotal ); + ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); + ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); + } + + if ( p->vInters ) + Inter_ManInterDump( p, fProved ); + + if ( p->pCnfAig ) + Cnf_DataFree( p->pCnfAig ); + if ( p->pAigTrans ) + Aig_ManStop( p->pAigTrans ); + if ( p->pInterNew ) + Aig_ManStop( p->pInterNew ); + Inter_ManClean( p ); + Vec_PtrFreeP( &p->vInters ); + Vec_IntFreeP( &p->vVarsAB ); + ABC_FREE( p ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/int/intUtil.c b/src/proof/int/intUtil.c new file mode 100644 index 00000000..8027bdef --- /dev/null +++ b/src/proof/int/intUtil.c @@ -0,0 +1,108 @@ +/**CFile**************************************************************** + + FileName [intUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Interpolation engine.] + + Synopsis [Various interpolation utilities.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 24, 2008.] + + Revision [$Id: intUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "intInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +/**Function************************************************************* + + Synopsis [Returns 1 if the property fails in the initial state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Inter_ManCheckInitialState( Aig_Man_t * p ) +{ + Cnf_Dat_t * pCnf; + Aig_Obj_t * pObj; + sat_solver * pSat; + int i, status; + int clk = clock(); + pCnf = Cnf_Derive( p, Saig_ManRegNum(p) ); + pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 1 ); + if ( pSat == NULL ) + { + Cnf_DataFree( pCnf ); + return 0; + } + status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + ABC_PRT( "Time", clock() - clk ); + if ( status == l_True ) + { + p->pSeqModel = Abc_CexAlloc( Aig_ManRegNum(p), Saig_ManPiNum(p), 1 ); + Saig_ManForEachPi( p, pObj, i ) + if ( sat_solver_var_value( pSat, pCnf->pVarNums[Aig_ObjId(pObj)] ) ) + Abc_InfoSetBit( p->pSeqModel->pData, Aig_ManRegNum(p) + i ); + } + Cnf_DataFree( pCnf ); + sat_solver_delete( pSat ); + return status == l_True; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the property holds in all states.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Inter_ManCheckAllStates( Aig_Man_t * p ) +{ + Cnf_Dat_t * pCnf; + sat_solver * pSat; + int status; + int clk = clock(); + pCnf = Cnf_Derive( p, Saig_ManRegNum(p) ); + pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + Cnf_DataFree( pCnf ); + if ( pSat == NULL ) + return 1; + status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + sat_solver_delete( pSat ); + ABC_PRT( "Time", clock() - clk ); + return status == l_False; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/int/module.make b/src/proof/int/module.make new file mode 100644 index 00000000..4a66b6ca --- /dev/null +++ b/src/proof/int/module.make @@ -0,0 +1,11 @@ +SRC += src/proof/int/intCheck.c \ + src/proof/int/intContain.c \ + src/proof/int/intCore.c \ + src/proof/int/intCtrex.c \ + src/proof/int/intDup.c \ + src/proof/int/intFrames.c \ + src/proof/int/intInter.c \ + src/proof/int/intM114.c \ + src/proof/int/intM114p.c \ + src/proof/int/intMan.c \ + src/proof/int/intUtil.c diff --git a/src/proof/live/liveness.c b/src/proof/live/liveness.c new file mode 100644 index 00000000..8368e121 --- /dev/null +++ b/src/proof/live/liveness.c @@ -0,0 +1,2575 @@ +/**CFile**************************************************************** + + FileName [liveness.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Liveness property checking.] + + Synopsis [Main implementation module.] + + Author [Sayak Ray] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 1, 2009.] + + Revision [$Id: liveness.c,v 1.00 2009/01/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include "src/base/main/main.h" +#include "src/aig/aig/aig.h" +#include "src/aig/saig/saig.h" +#include +#include "src/base/main/mainInt.h" + +ABC_NAMESPACE_IMPL_START + +#define PROPAGATE_NAMES +#define MULTIPLE_LTL_FORMULA +#define ALLOW_SAFETY_PROPERTIES + +#define FULL_BIERE_MODE 0 +#define IGNORE_LIVENESS_KEEP_SAFETY_MODE 1 +#define IGNORE_SAFETY_KEEP_LIVENESS_MODE 2 +#define IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE 3 +#define FULL_BIERE_ONE_LOOP_MODE 4 +//#define DUPLICATE_CKT_DEBUG + +extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); +extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); +//char *strdup(const char *string); + +//****************************************** +//external functions defined in ltl_parser.c +//****************************************** +typedef struct ltlNode_t ltlNode; +extern ltlNode *readLtlFormula( char *formula ); +extern void traverseAbstractSyntaxTree( ltlNode *node ); +extern ltlNode *parseFormulaCreateAST( char *inputFormula ); +extern int isWellFormed( ltlNode *topNode ); +extern int checkSignalNameExistence( Abc_Ntk_t *pNtk, ltlNode *topASTNode ); +extern void populateBoolWithAigNodePtr( Abc_Ntk_t *pNtk, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, ltlNode *topASTNode ); +extern int checkAllBoolHaveAIGPointer( ltlNode *topASTNode ); +extern void populateAigPointerUnitGF( Aig_Man_t *pAigNew, ltlNode *topASTNode, Vec_Ptr_t *vSignal, Vec_Vec_t *vAigGFMap ); +extern void setAIGNodePtrOfGloballyNode( ltlNode *astNode, Aig_Obj_t *pObjLo ); +extern Aig_Obj_t *buildLogicFromLTLNode( Aig_Man_t *pAig, ltlNode *pLtlNode ); +extern Aig_Obj_t *retriveAIGPointerFromLTLNode( ltlNode *astNode ); +extern void traverseAbstractSyntaxTree_postFix( ltlNode *node ); +//********************************** +//external function declaration ends +//********************************** + + +/******************************************************************* +LAYOUT OF PI VECTOR: + ++------------------------------------------------------------------------------------------------------------------------------------+ +| TRUE ORIGINAL PI (n) | SAVE(PI) (1) | ORIGINAL LO (k) | SAVED(LO) (1) | SHADOW_ORIGINAL LO (k) | LIVENESS LO (l) | FAIRNESS LO (f) | ++------------------------------------------------------------------------------------------------------------------------------------+ +<------------True PI----------------->|<----------------------------LO---------------------------------------------------------------> + +LAYOUT OF PO VECTOR: + ++-----------------------------------------------------------------------------------------------------------+ +| SOLE PO (1) | ORIGINAL LI (k) | SAVED LI (1) | SHADOW_ORIGINAL LI (k) | LIVENESS LI (l) | FAIRNESS LI (f) | ++-----------------------------------------------------------------------------------------------------------+ +<--True PO--->|<--------------------------------------LI----------------------------------------------------> + +********************************************************************/ + + +static int nodeName_starts_with( Abc_Obj_t *pNode, const char *prefix ) +{ + if( strstr( Abc_ObjName( pNode ), prefix ) == Abc_ObjName( pNode ) ) + return 1; + else + return 0; +} + +void printVecPtrOfString( Vec_Ptr_t *vec ) +{ + int i; + + for( i=0; i< Vec_PtrSize( vec ); i++ ) + { + printf("vec[%d] = %s\n", i, (char *)Vec_PtrEntry(vec, i) ); + } +} + +int getPoIndex( Aig_Man_t *pAig, Aig_Obj_t *pPivot ) +{ + int i; + Aig_Obj_t *pObj; + + Saig_ManForEachPo( pAig, pObj, i ) + { + if( pObj == pPivot ) + return i; + } + return -1; +} + +char * retrieveTruePiName( Abc_Ntk_t *pNtkOld, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, Aig_Obj_t *pObjPivot ) +{ + Aig_Obj_t *pObjOld, *pObj; + Abc_Obj_t *pNode; + int index; + + assert( Saig_ObjIsPi( pAigNew, pObjPivot ) ); + Aig_ManForEachPi( pAigNew, pObj, index ) + if( pObj == pObjPivot ) + break; + assert( index < Aig_ManPiNum( pAigNew ) - Aig_ManRegNum( pAigNew ) ); + if( index == Saig_ManPiNum( pAigNew ) - 1 ) + return "SAVE_BIERE"; + else + { + pObjOld = Aig_ManPi( pAigOld, index ); + pNode = Abc_NtkPi( pNtkOld, index ); + assert( pObjOld->pData == pObjPivot ); + return Abc_ObjName( pNode ); + } +} + +char * retrieveLOName( Abc_Ntk_t *pNtkOld, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, Aig_Obj_t *pObjPivot, Vec_Ptr_t *vLive, Vec_Ptr_t * vFair ) +{ + Aig_Obj_t *pObjOld, *pObj; + Abc_Obj_t *pNode; + int index, oldIndex, originalLatchNum = Saig_ManRegNum(pAigOld), strMatch, i; + char *dummyStr = (char *)malloc( sizeof(char) * 50 ); + + assert( Saig_ObjIsLo( pAigNew, pObjPivot ) ); + Saig_ManForEachLo( pAigNew, pObj, index ) + if( pObj == pObjPivot ) + break; + if( index < originalLatchNum ) + { + oldIndex = Saig_ManPiNum( pAigOld ) + index; + pObjOld = Aig_ManPi( pAigOld, oldIndex ); + pNode = Abc_NtkCi( pNtkOld, oldIndex ); + assert( pObjOld->pData == pObjPivot ); + return Abc_ObjName( pNode ); + } + else if( index == originalLatchNum ) + return "SAVED_LO"; + else if( index > originalLatchNum && index < 2 * originalLatchNum + 1 ) + { + oldIndex = Saig_ManPiNum( pAigOld ) + index - originalLatchNum - 1; + pObjOld = Aig_ManPi( pAigOld, oldIndex ); + pNode = Abc_NtkCi( pNtkOld, oldIndex ); + sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "SHADOW"); + return dummyStr; + } + else if( index >= 2 * originalLatchNum + 1 && index < 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) ) + { + oldIndex = index - 2 * originalLatchNum - 1; + strMatch = 0; + dummyStr[0] = '\0'; + Saig_ManForEachPo( pAigOld, pObj, i ) + { + pNode = Abc_NtkPo( pNtkOld, i ); + //if( strstr( Abc_ObjName( pNode ), "assert_fair" ) != NULL ) + if( nodeName_starts_with( pNode, "assert_fair" ) ) + { + if( strMatch == oldIndex ) + { + sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "LIVENESS"); + //return dummyStr; + break; + } + else + strMatch++; + } + } + assert( dummyStr[0] != '\0' ); + return dummyStr; + } + else if( index >= 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) && index < 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ) + { + oldIndex = index - 2 * originalLatchNum - 1 - Vec_PtrSize( vLive ); + strMatch = 0; + dummyStr[0] = '\0'; + Saig_ManForEachPo( pAigOld, pObj, i ) + { + pNode = Abc_NtkPo( pNtkOld, i ); + //if( strstr( Abc_ObjName( pNode ), "assume_fair" ) != NULL ) + if( nodeName_starts_with( pNode, "assume_fair" ) ) + { + if( strMatch == oldIndex ) + { + sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "FAIRNESS"); + //return dummyStr; + break; + } + else + strMatch++; + } + } + assert( dummyStr[0] != '\0' ); + return dummyStr; + } + else + return "UNKNOWN"; +} + +Vec_Ptr_t *vecPis, *vecPiNames; +Vec_Ptr_t *vecLos, *vecLoNames; + + +int Aig_ManPiCleanupBiere( Aig_Man_t * p ) +{ + int k = 0, nPisOld = Aig_ManPiNum(p); + + p->nObjs[AIG_OBJ_PI] = Vec_PtrSize( p->vPis ); + if ( Aig_ManRegNum(p) ) + p->nTruePis = Aig_ManPiNum(p) - Aig_ManRegNum(p); + + return nPisOld - Aig_ManPiNum(p); +} + + +int Aig_ManPoCleanupBiere( Aig_Man_t * p ) +{ + int k = 0, nPosOld = Aig_ManPoNum(p); + + p->nObjs[AIG_OBJ_PO] = Vec_PtrSize( p->vPos ); + if ( Aig_ManRegNum(p) ) + p->nTruePos = Aig_ManPoNum(p) - Aig_ManRegNum(p); + return nPosOld - Aig_ManPoNum(p); +} + +Aig_Man_t * LivenessToSafetyTransformation( int mode, Abc_Ntk_t * pNtk, Aig_Man_t * p, + Vec_Ptr_t *vLive, Vec_Ptr_t *vFair, Vec_Ptr_t *vAssertSafety, Vec_Ptr_t *vAssumeSafety ) +{ + Aig_Man_t * pNew; + int i, nRegCount; + Aig_Obj_t * pObjSavePi; + Aig_Obj_t *pObjSavedLo, *pObjSavedLi; + Aig_Obj_t *pObj, *pMatch; + Aig_Obj_t *pObjSaveOrSaved, *pObjSaveAndNotSaved, *pObjSavedLoAndEquality; + Aig_Obj_t *pObjShadowLo, *pObjShadowLi, *pObjShadowLiDriver; + Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc; + Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate; + Aig_Obj_t *pObjSafetyPropertyOutput; + Aig_Obj_t *pObjOriginalSafetyPropertyOutput; + Aig_Obj_t *pDriverImage, *pArgument, *collectiveAssertSafety, *collectiveAssumeSafety; + char *nodeName; + int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, piVecIndex = 0, liveLatch = 0, fairLatch = 0; + + vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); + vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); + + vecLos = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); + vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); + + //**************************************************************** + // Step1: create the new manager + // Note: The new manager is created with "2 * Aig_ManObjNumMax(p)" + // nodes, but this selection is arbitrary - need to be justified + //**************************************************************** + pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) ); + pNew->pName = (char *)malloc( strlen( pNtk->pName ) + strlen("_l2s") + 1 ); + sprintf(pNew->pName, "%s_%s", pNtk->pName, "l2s"); + pNew->pSpec = NULL; + + //**************************************************************** + // Step 2: map constant nodes + //**************************************************************** + pObj = Aig_ManConst1( p ); + pObj->pData = Aig_ManConst1( pNew ); + + //**************************************************************** + // Step 3: create true PIs + //**************************************************************** + Saig_ManForEachPi( p, pObj, i ) + { + piCopied++; + pObj->pData = Aig_ObjCreatePi(pNew); + Vec_PtrPush( vecPis, pObj->pData ); + nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) )); + Vec_PtrPush( vecPiNames, nodeName ); + } + + //**************************************************************** + // Step 4: create the special Pi corresponding to SAVE + //**************************************************************** + if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) + { + pObjSavePi = Aig_ObjCreatePi( pNew ); + nodeName = "SAVE_BIERE", + Vec_PtrPush( vecPiNames, nodeName ); + } + + //**************************************************************** + // Step 5: create register outputs + //**************************************************************** + Saig_ManForEachLo( p, pObj, i ) + { + loCopied++; + pObj->pData = Aig_ObjCreatePi(pNew); + Vec_PtrPush( vecLos, pObj->pData ); + nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) )); + Vec_PtrPush( vecLoNames, nodeName ); + } + + //**************************************************************** + // Step 6: create "saved" register output + //**************************************************************** + if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) + { + loCreated++; + pObjSavedLo = Aig_ObjCreatePi( pNew ); + Vec_PtrPush( vecLos, pObjSavedLo ); + nodeName = "SAVED_LO"; + Vec_PtrPush( vecLoNames, nodeName ); + } + + //**************************************************************** + // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi + //**************************************************************** + if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) + { + pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo ); + pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) ); + } + + //******************************************************************** + // Step 8: create internal nodes + //******************************************************************** + Aig_ManForEachNode( p, pObj, i ) + { + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + } + + + //******************************************************************** + // Step 8.x : create PO for each safety assertions + // NOTE : Here the output is purposely inverted as it will be thrown to + // dprove + //******************************************************************** + if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) + { + if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) == 0 ) + { + pObjAndAcc = Aig_ManConst1( pNew ); + Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) + { + pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); + pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); + } + pObjOriginalSafetyPropertyOutput = Aig_ObjCreatePo( pNew, Aig_Not(pObjAndAcc) ); + } + else if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) != 0 ) + { + pObjAndAcc = Aig_ManConst1( pNew ); + Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) + { + pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); + pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); + } + collectiveAssertSafety = pObjAndAcc; + + pObjAndAcc = Aig_ManConst1( pNew ); + Vec_PtrForEachEntry( Aig_Obj_t *, vAssumeSafety, pObj, i ) + { + pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); + pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); + } + collectiveAssumeSafety = pObjAndAcc; + pObjOriginalSafetyPropertyOutput = Aig_ObjCreatePo( pNew, Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ) ); + } + else + { + printf("WARNING!! No safety property is found, a new (negated) constant 1 output is created\n"); + pObjOriginalSafetyPropertyOutput = Aig_ObjCreatePo( pNew, Aig_Not( Aig_ManConst1(pNew) ) ); + } + } + + //******************************************************************** + // Step 9: create the safety property output gate for the liveness properties + // discuss with Sat/Alan for an alternative implementation + //******************************************************************** + if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) + { + pObjSafetyPropertyOutput = Aig_ObjCreatePo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData ); + } + + // create register inputs for the original registers + nRegCount = 0; + + Saig_ManForEachLo( p, pObj, i ) + { + pMatch = Saig_ObjLoToLi( p, pObj ); + Aig_ObjCreatePo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) ); + nRegCount++; + liCopied++; + } + + // create register input corresponding to the register "saved" + if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) + { + #ifndef DUPLICATE_CKT_DEBUG + pObjSavedLi = Aig_ObjCreatePo( pNew, pObjSaveOrSaved ); + nRegCount++; + liCreated++; + + //Changed on October 13, 2009 + //pObjAndAcc = NULL; + pObjAndAcc = Aig_ManConst1( pNew ); + + // create the family of shadow registers, then create the cascade of Xnor and And gates for the comparator + Saig_ManForEachLo( p, pObj, i ) + { + pObjShadowLo = Aig_ObjCreatePi( pNew ); + + #ifdef PROPAGATE_NAMES + Vec_PtrPush( vecLos, pObjShadowLo ); + nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ) ) + 10 ); + sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "SHADOW" ); + + Vec_PtrPush( vecLoNames, nodeName ); + #endif + + pObjShadowLiDriver = Aig_Mux( pNew, pObjSaveAndNotSaved, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); + pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver ); + nRegCount++; + loCreated++; liCreated++; + + pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); + pObjXnor = Aig_Not( pObjXor ); + + pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAcc ); + } + + // create the AND gate whose output will be the signal "looped" + pObjSavedLoAndEquality = Aig_And( pNew, pObjSavedLo, pObjAndAcc ); + + // create the master AND gate and corresponding AND and OR logic for the liveness properties + pObjAndAcc = Aig_ManConst1( pNew ); + if( vLive == NULL || Vec_PtrSize( vLive ) == 0 ) + { + printf("Circuit without any liveness property\n"); + } + else + { + Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i ) + { + liveLatch++; + pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); + pObjShadowLo = Aig_ObjCreatePi( pNew ); + + #ifdef PROPAGATE_NAMES + Vec_PtrPush( vecLos, pObjShadowLo ); + nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); + sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "LIVENESS" ); + Vec_PtrPush( vecLoNames, nodeName ); + #endif + + pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) ); + pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver ); + nRegCount++; + loCreated++; liCreated++; + + pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAcc ); + } + } + + pObjLive = pObjAndAcc; + + pObjAndAcc = Aig_ManConst1( pNew ); + if( vFair == NULL || Vec_PtrSize( vFair ) == 0 ) + printf("Circuit without any fairness property\n"); + else + { + Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i ) + { + fairLatch++; + pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); + pObjShadowLo = Aig_ObjCreatePi( pNew ); + + #ifdef PROPAGATE_NAMES + Vec_PtrPush( vecLos, pObjShadowLo ); + nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); + sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "FAIRNESS" ); + Vec_PtrPush( vecLoNames, nodeName ); + #endif + + pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) ); + pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver ); + nRegCount++; + loCreated++; liCreated++; + + pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAcc ); + } + } + + pObjFair = pObjAndAcc; + + //pObjSafetyGate = Aig_Exor( pNew, Aig_Not(Aig_ManConst1( pNew )), Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ) ); + //Following is the actual Biere translation + pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ); + + Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate ); + #endif + } + + Aig_ManSetRegNum( pNew, nRegCount ); + + Aig_ManPiCleanupBiere( pNew ); + Aig_ManPoCleanupBiere( pNew ); + + Aig_ManCleanup( pNew ); + + assert( Aig_ManCheck( pNew ) ); + + if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) + { + assert((Aig_Obj_t *)Vec_PtrEntry(pNew->vPos, Saig_ManPoNum(pNew)+Aig_ObjPioNum(pObjSavedLo)-Saig_ManPiNum(p)-1) == pObjSavedLi); + assert( Saig_ManPiNum( p ) + 1 == Saig_ManPiNum( pNew ) ); + assert( Saig_ManRegNum( pNew ) == Saig_ManRegNum( p ) * 2 + 1 + liveLatch + fairLatch ); + } + + return pNew; +} + + + + + +Aig_Man_t * LivenessToSafetyTransformationAbs( int mode, Abc_Ntk_t * pNtk, Aig_Man_t * p, Vec_Int_t *vFlops, + Vec_Ptr_t *vLive, Vec_Ptr_t *vFair, Vec_Ptr_t *vAssertSafety, Vec_Ptr_t *vAssumeSafety ) +{ + Aig_Man_t * pNew; + int i, nRegCount, iEntry; + Aig_Obj_t * pObjSavePi; + Aig_Obj_t *pObjSavedLo, *pObjSavedLi; + Aig_Obj_t *pObj, *pMatch; + Aig_Obj_t *pObjSaveOrSaved, *pObjSaveAndNotSaved, *pObjSavedLoAndEquality; + Aig_Obj_t *pObjShadowLo, *pObjShadowLi, *pObjShadowLiDriver; + Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc; + Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate; + Aig_Obj_t *pObjSafetyPropertyOutput; + Aig_Obj_t *pDriverImage, *pArgument, *collectiveAssertSafety, *collectiveAssumeSafety; + char *nodeName; + int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, piVecIndex = 0, liveLatch = 0, fairLatch = 0; + + vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); + vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); + + vecLos = Vec_PtrAlloc( Saig_ManRegNum( p ) + Vec_IntSize( vFlops ) + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); + vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p ) + Vec_IntSize( vFlops ) + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); + + //**************************************************************** + // Step1: create the new manager + // Note: The new manager is created with "2 * Aig_ManObjNumMax(p)" + // nodes, but this selection is arbitrary - need to be justified + //**************************************************************** + pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) ); + pNew->pName = (char *)malloc( strlen( pNtk->pName ) + strlen("_l2s") + 1 ); + sprintf(pNew->pName, "%s_%s", pNtk->pName, "l2s"); + pNew->pSpec = NULL; + + //**************************************************************** + // Step 2: map constant nodes + //**************************************************************** + pObj = Aig_ManConst1( p ); + pObj->pData = Aig_ManConst1( pNew ); + + //**************************************************************** + // Step 3: create true PIs + //**************************************************************** + Saig_ManForEachPi( p, pObj, i ) + { + piCopied++; + pObj->pData = Aig_ObjCreatePi(pNew); + Vec_PtrPush( vecPis, pObj->pData ); + nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) )); + Vec_PtrPush( vecPiNames, nodeName ); + } + + //**************************************************************** + // Step 4: create the special Pi corresponding to SAVE + //**************************************************************** + if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) + { + pObjSavePi = Aig_ObjCreatePi( pNew ); + nodeName = "SAVE_BIERE", + Vec_PtrPush( vecPiNames, nodeName ); + } + + //**************************************************************** + // Step 5: create register outputs + //**************************************************************** + Saig_ManForEachLo( p, pObj, i ) + { + loCopied++; + pObj->pData = Aig_ObjCreatePi(pNew); + Vec_PtrPush( vecLos, pObj->pData ); + nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) )); + Vec_PtrPush( vecLoNames, nodeName ); + } + + //**************************************************************** + // Step 6: create "saved" register output + //**************************************************************** + if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) + { + loCreated++; + pObjSavedLo = Aig_ObjCreatePi( pNew ); + Vec_PtrPush( vecLos, pObjSavedLo ); + nodeName = "SAVED_LO"; + Vec_PtrPush( vecLoNames, nodeName ); + } + + //**************************************************************** + // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi + //**************************************************************** + if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) + { + pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo ); + pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) ); + } + + //******************************************************************** + // Step 8: create internal nodes + //******************************************************************** + Aig_ManForEachNode( p, pObj, i ) + { + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + } + + + //******************************************************************** + // Step 8.x : create PO for each safety assertions + // NOTE : Here the output is purposely inverted as it will be thrown to + // dprove + //******************************************************************** + if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) + { + if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) == 0 ) + { + pObjAndAcc = Aig_ManConst1( pNew ); + Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) + { + pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); + pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); + } + Aig_ObjCreatePo( pNew, Aig_Not(pObjAndAcc) ); + } + else if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) != 0 ) + { + pObjAndAcc = Aig_ManConst1( pNew ); + Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) + { + pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); + pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); + } + collectiveAssertSafety = pObjAndAcc; + + pObjAndAcc = Aig_ManConst1( pNew ); + Vec_PtrForEachEntry( Aig_Obj_t *, vAssumeSafety, pObj, i ) + { + pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); + pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); + } + collectiveAssumeSafety = pObjAndAcc; + Aig_ObjCreatePo( pNew, Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ) ); + } + else + { + printf("WARNING!! No safety property is found, a new (negated) constant 1 output is created\n"); + Aig_ObjCreatePo( pNew, Aig_Not( Aig_ManConst1(pNew) ) ); + } + } + + //******************************************************************** + // Step 9: create the safety property output gate for the liveness properties + // discuss with Sat/Alan for an alternative implementation + //******************************************************************** + if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) + { + pObjSafetyPropertyOutput = Aig_ObjCreatePo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData ); + } + + // create register inputs for the original registers + nRegCount = 0; + + Saig_ManForEachLo( p, pObj, i ) + { + pMatch = Saig_ObjLoToLi( p, pObj ); + Aig_ObjCreatePo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) ); + nRegCount++; + liCopied++; + } + + // create register input corresponding to the register "saved" + if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) + { + #ifndef DUPLICATE_CKT_DEBUG + pObjSavedLi = Aig_ObjCreatePo( pNew, pObjSaveOrSaved ); + nRegCount++; + liCreated++; + + //Changed on October 13, 2009 + //pObjAndAcc = NULL; + pObjAndAcc = Aig_ManConst1( pNew ); + + // create the family of shadow registers, then create the cascade of Xnor and And gates for the comparator + //Saig_ManForEachLo( p, pObj, i ) + Saig_ManForEachLo( p, pObj, i ) + { + printf("Flop[%d] = %s\n", i, Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ) ); + } + Vec_IntForEachEntry( vFlops, iEntry, i ) + { + pObjShadowLo = Aig_ObjCreatePi( pNew ); + pObj = Aig_ManLo( p, iEntry ); + + #ifdef PROPAGATE_NAMES + Vec_PtrPush( vecLos, pObjShadowLo ); + nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + iEntry ) ) ) + 10 ); + sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + iEntry ) ), "SHADOW" ); + printf("Flop copied [%d] = %s\n", iEntry, nodeName ); + Vec_PtrPush( vecLoNames, nodeName ); + #endif + + pObjShadowLiDriver = Aig_Mux( pNew, pObjSaveAndNotSaved, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); + pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver ); + nRegCount++; + loCreated++; liCreated++; + + pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); + pObjXnor = Aig_Not( pObjXor ); + + pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAcc ); + } + + // create the AND gate whose output will be the signal "looped" + pObjSavedLoAndEquality = Aig_And( pNew, pObjSavedLo, pObjAndAcc ); + + // create the master AND gate and corresponding AND and OR logic for the liveness properties + pObjAndAcc = Aig_ManConst1( pNew ); + if( vLive == NULL || Vec_PtrSize( vLive ) == 0 ) + { + printf("Circuit without any liveness property\n"); + } + else + { + Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i ) + { + liveLatch++; + pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); + pObjShadowLo = Aig_ObjCreatePi( pNew ); + + #ifdef PROPAGATE_NAMES + Vec_PtrPush( vecLos, pObjShadowLo ); + nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); + sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "LIVENESS" ); + Vec_PtrPush( vecLoNames, nodeName ); + #endif + + pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) ); + pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver ); + nRegCount++; + loCreated++; liCreated++; + + pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAcc ); + } + } + + pObjLive = pObjAndAcc; + + pObjAndAcc = Aig_ManConst1( pNew ); + if( vFair == NULL || Vec_PtrSize( vFair ) == 0 ) + printf("Circuit without any fairness property\n"); + else + { + Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i ) + { + fairLatch++; + pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); + pObjShadowLo = Aig_ObjCreatePi( pNew ); + + #ifdef PROPAGATE_NAMES + Vec_PtrPush( vecLos, pObjShadowLo ); + nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); + sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "FAIRNESS" ); + Vec_PtrPush( vecLoNames, nodeName ); + #endif + + pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) ); + pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver ); + nRegCount++; + loCreated++; liCreated++; + + pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAcc ); + } + } + + pObjFair = pObjAndAcc; + + //pObjSafetyGate = Aig_Exor( pNew, Aig_Not(Aig_ManConst1( pNew )), Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ) ); + //Following is the actual Biere translation + pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ); + + Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate ); + #endif + } + + Aig_ManSetRegNum( pNew, nRegCount ); + + Aig_ManPiCleanupBiere( pNew ); + Aig_ManPoCleanupBiere( pNew ); + + Aig_ManCleanup( pNew ); + + assert( Aig_ManCheck( pNew ) ); + + if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) + { + assert((Aig_Obj_t *)Vec_PtrEntry(pNew->vPos, Saig_ManPoNum(pNew)+Aig_ObjPioNum(pObjSavedLo)-Saig_ManPiNum(p)-1) == pObjSavedLi); + assert( Saig_ManPiNum( p ) + 1 == Saig_ManPiNum( pNew ) ); + assert( Saig_ManRegNum( pNew ) == Saig_ManRegNum( p ) + Vec_IntSize( vFlops ) + 1 + liveLatch + fairLatch ); + } + + return pNew; +} + + + +Aig_Man_t * LivenessToSafetyTransformationOneStepLoop( int mode, Abc_Ntk_t * pNtk, Aig_Man_t * p, + Vec_Ptr_t *vLive, Vec_Ptr_t *vFair, Vec_Ptr_t *vAssertSafety, Vec_Ptr_t *vAssumeSafety ) +{ + Aig_Man_t * pNew; + int i, nRegCount; + Aig_Obj_t * pObjSavePi; + Aig_Obj_t *pObj, *pMatch; + Aig_Obj_t *pObjSavedLoAndEquality; + Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc, *pObjAndAccDummy; + Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate; + Aig_Obj_t *pObjSafetyPropertyOutput; + Aig_Obj_t *pDriverImage; + Aig_Obj_t *pObjCorrespondingLi; + Aig_Obj_t *pArgument; + Aig_Obj_t *collectiveAssertSafety, *collectiveAssumeSafety; + + char *nodeName; + int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, piVecIndex = 0; + + if( Aig_ManRegNum( p ) == 0 ) + { + printf("The input AIG contains no register, returning the original AIG as it is\n"); + return p; + } + + vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); + vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); + + vecLos = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); + vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); + + //**************************************************************** + // Step1: create the new manager + // Note: The new manager is created with "2 * Aig_ManObjNumMax(p)" + // nodes, but this selection is arbitrary - need to be justified + //**************************************************************** + pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( "live2safe" ); + pNew->pSpec = NULL; + + //**************************************************************** + // Step 2: map constant nodes + //**************************************************************** + pObj = Aig_ManConst1( p ); + pObj->pData = Aig_ManConst1( pNew ); + + //**************************************************************** + // Step 3: create true PIs + //**************************************************************** + Saig_ManForEachPi( p, pObj, i ) + { + piCopied++; + pObj->pData = Aig_ObjCreatePi(pNew); + Vec_PtrPush( vecPis, pObj->pData ); + nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) )); + Vec_PtrPush( vecPiNames, nodeName ); + } + + //**************************************************************** + // Step 4: create the special Pi corresponding to SAVE + //**************************************************************** + if( mode == FULL_BIERE_ONE_LOOP_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE ) + { + pObjSavePi = Aig_ObjCreatePi( pNew ); + nodeName = "SAVE_BIERE", + Vec_PtrPush( vecPiNames, nodeName ); + } + + //**************************************************************** + // Step 5: create register outputs + //**************************************************************** + Saig_ManForEachLo( p, pObj, i ) + { + loCopied++; + pObj->pData = Aig_ObjCreatePi(pNew); + Vec_PtrPush( vecLos, pObj->pData ); + nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) )); + Vec_PtrPush( vecLoNames, nodeName ); + } + + //**************************************************************** + // Step 6: create "saved" register output + //**************************************************************** + +#if 0 + loCreated++; + pObjSavedLo = Aig_ObjCreatePi( pNew ); + Vec_PtrPush( vecLos, pObjSavedLo ); + nodeName = "SAVED_LO"; + Vec_PtrPush( vecLoNames, nodeName ); +#endif + + //**************************************************************** + // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi + //**************************************************************** +#if 0 + pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo ); + pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) ); +#endif + + //******************************************************************** + // Step 8: create internal nodes + //******************************************************************** + Aig_ManForEachNode( p, pObj, i ) + { + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + } + +#if 0 + //******************************************************************** + // Step 8.x : create PO for each safety assertions + //******************************************************************** + Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) + { + pObj->pData = Aig_ObjCreatePo( pNew, Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ) ); + } +#endif + + if( mode == FULL_BIERE_ONE_LOOP_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) + { + if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) == 0 ) + { + pObjAndAcc = NULL; + Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) + { + //pObj->pData = Aig_ObjCreatePo( pNew, Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ) ); + pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); + if( pObjAndAcc == NULL ) + pObjAndAcc = pArgument; + else + { + pObjAndAccDummy = pObjAndAcc; + pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAccDummy ); + } + } + Aig_ObjCreatePo( pNew, Aig_Not(pObjAndAcc) ); + } + else if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) != 0 ) + { + pObjAndAcc = NULL; + Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) + { + //pObj->pData = Aig_ObjCreatePo( pNew, Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ) ); + pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); + if( pObjAndAcc == NULL ) + pObjAndAcc = pArgument; + else + { + pObjAndAccDummy = pObjAndAcc; + pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAccDummy ); + } + } + collectiveAssertSafety = pObjAndAcc; + pObjAndAcc = NULL; + Vec_PtrForEachEntry( Aig_Obj_t *, vAssumeSafety, pObj, i ) + { + //pObj->pData = Aig_ObjCreatePo( pNew, Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ) ); + pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); + if( pObjAndAcc == NULL ) + pObjAndAcc = pArgument; + else + { + pObjAndAccDummy = pObjAndAcc; + pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAccDummy ); + } + } + collectiveAssumeSafety = pObjAndAcc; + Aig_ObjCreatePo( pNew, Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ) ); + } + else + printf("No safety property is specified, hence no safety gate is created\n"); + } + + //******************************************************************** + // Step 9: create the safety property output gate + // create the safety property output gate, this will be the sole true PO + // of the whole circuit, discuss with Sat/Alan for an alternative implementation + //******************************************************************** + + if( mode == FULL_BIERE_ONE_LOOP_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE ) + { + pObjSafetyPropertyOutput = Aig_ObjCreatePo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData ); + } + + // create register inputs for the original registers + nRegCount = 0; + + Saig_ManForEachLo( p, pObj, i ) + { + pMatch = Saig_ObjLoToLi( p, pObj ); + //Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pMatch) ); + Aig_ObjCreatePo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) ); + nRegCount++; + liCopied++; + } + +#if 0 + // create register input corresponding to the register "saved" + pObjSavedLi = Aig_ObjCreatePo( pNew, pObjSaveOrSaved ); + nRegCount++; + liCreated++;7 +#endif + + pObjAndAcc = NULL; + + //**************************************************************************************************** + //For detection of loop of length 1 we do not need any shadow register, we only need equality detector + //between Lo_j and Li_j and then a cascade of AND gates + //**************************************************************************************************** + + if( mode == FULL_BIERE_ONE_LOOP_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE ) + { + Saig_ManForEachLo( p, pObj, i ) + { + pObjCorrespondingLi = Saig_ObjLoToLi( p, pObj ); + + pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0( pObjCorrespondingLi )->pData, Aig_ObjFaninC0( pObjCorrespondingLi ) ) ); + pObjXnor = Aig_Not( pObjXor ); + + if( pObjAndAcc == NULL ) + pObjAndAcc = pObjXnor; + else + { + pObjAndAccDummy = pObjAndAcc; + pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAccDummy ); + } + } + + // create the AND gate whose output will be the signal "looped" + pObjSavedLoAndEquality = Aig_And( pNew, pObjSavePi, pObjAndAcc ); + + // create the master AND gate and corresponding AND and OR logic for the liveness properties + pObjAndAcc = NULL; + if( vLive == NULL || Vec_PtrSize( vLive ) == 0 ) + printf("Circuit without any liveness property\n"); + else + { + Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i ) + { + pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); + if( pObjAndAcc == NULL ) + pObjAndAcc = pDriverImage; + else + { + pObjAndAccDummy = pObjAndAcc; + pObjAndAcc = Aig_And( pNew, pDriverImage, pObjAndAccDummy ); + } + } + } + + if( pObjAndAcc != NULL ) + pObjLive = pObjAndAcc; + else + pObjLive = Aig_ManConst1( pNew ); + + // create the master AND gate and corresponding AND and OR logic for the fairness properties + pObjAndAcc = NULL; + if( vFair == NULL || Vec_PtrSize( vFair ) == 0 ) + printf("Circuit without any fairness property\n"); + else + { + Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i ) + { + pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); + if( pObjAndAcc == NULL ) + pObjAndAcc = pDriverImage; + else + { + pObjAndAccDummy = pObjAndAcc; + pObjAndAcc = Aig_And( pNew, pDriverImage, pObjAndAccDummy ); + } + } + } + + if( pObjAndAcc != NULL ) + pObjFair = pObjAndAcc; + else + pObjFair = Aig_ManConst1( pNew ); + + pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ); + + Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate ); + } + + Aig_ManSetRegNum( pNew, nRegCount ); + + //printf("\nSaig_ManPiNum = %d, Reg Num = %d, before everything, before Pi cleanup\n", Vec_PtrSize( pNew->vPis ), pNew->nRegs ); + + Aig_ManPiCleanupBiere( pNew ); + Aig_ManPoCleanupBiere( pNew ); + + Aig_ManCleanup( pNew ); + + assert( Aig_ManCheck( pNew ) ); + + return pNew; +} + + + +Vec_Ptr_t * populateLivenessVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig ) +{ + Abc_Obj_t * pNode; + int i, liveCounter = 0; + Vec_Ptr_t * vLive; + + vLive = Vec_PtrAlloc( 100 ); + Abc_NtkForEachPo( pNtk, pNode, i ) + //if( strstr( Abc_ObjName( pNode ), "assert_fair") != NULL ) + if( nodeName_starts_with( pNode, "assert_fair" ) ) + { + Vec_PtrPush( vLive, Aig_ManPo( pAig, i ) ); + liveCounter++; + } + printf("Number of liveness property found = %d\n", liveCounter); + return vLive; +} + +Vec_Ptr_t * populateFairnessVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig ) +{ + Abc_Obj_t * pNode; + int i, fairCounter = 0; + Vec_Ptr_t * vFair; + + vFair = Vec_PtrAlloc( 100 ); + Abc_NtkForEachPo( pNtk, pNode, i ) + //if( strstr( Abc_ObjName( pNode ), "assume_fair") != NULL ) + if( nodeName_starts_with( pNode, "assume_fair" ) ) + { + Vec_PtrPush( vFair, Aig_ManPo( pAig, i ) ); + fairCounter++; + } + printf("Number of fairness property found = %d\n", fairCounter); + return vFair; +} + +Vec_Ptr_t * populateSafetyAssertionVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig ) +{ + Abc_Obj_t * pNode; + int i, assertSafetyCounter = 0; + Vec_Ptr_t * vAssertSafety; + + vAssertSafety = Vec_PtrAlloc( 100 ); + Abc_NtkForEachPo( pNtk, pNode, i ) + //if( strstr( Abc_ObjName( pNode ), "Assert") != NULL ) + if( nodeName_starts_with( pNode, "assert_safety" ) || nodeName_starts_with( pNode, "Assert" )) + { + Vec_PtrPush( vAssertSafety, Aig_ManPo( pAig, i ) ); + assertSafetyCounter++; + } + printf("Number of safety property found = %d\n", assertSafetyCounter); + return vAssertSafety; +} + +Vec_Ptr_t * populateSafetyAssumptionVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig ) +{ + Abc_Obj_t * pNode; + int i, assumeSafetyCounter = 0; + Vec_Ptr_t * vAssumeSafety; + + vAssumeSafety = Vec_PtrAlloc( 100 ); + Abc_NtkForEachPo( pNtk, pNode, i ) + //if( strstr( Abc_ObjName( pNode ), "Assert") != NULL ) + if( nodeName_starts_with( pNode, "assume_safety" ) || nodeName_starts_with( pNode, "Assume" )) + { + Vec_PtrPush( vAssumeSafety, Aig_ManPo( pAig, i ) ); + assumeSafetyCounter++; + } + printf("Number of assume_safety property found = %d\n", assumeSafetyCounter); + return vAssumeSafety; +} + +void updateNewNetworkNameManager( Abc_Ntk_t *pNtk, Aig_Man_t *pAig, Vec_Ptr_t *vPiNames, Vec_Ptr_t *vLoNames ) +{ + Aig_Obj_t *pObj; + Abc_Obj_t *pNode; + int i, ntkObjId; + + pNtk->pManName = Nm_ManCreate( Abc_NtkCiNum( pNtk ) ); + + if( vPiNames ) + { + Saig_ManForEachPi( pAig, pObj, i ) + { + ntkObjId = Abc_NtkCi( pNtk, i )->Id; + //printf("Pi %d, Saved Name = %s, id = %d\n", i, Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), Vec_PtrEntry(vPiNames, i), NULL ), ntkObjId); + Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), (char *)Vec_PtrEntry(vPiNames, i), NULL ); + } + } + if( vLoNames ) + { + Saig_ManForEachLo( pAig, pObj, i ) + { + ntkObjId = Abc_NtkCi( pNtk, Saig_ManPiNum( pAig ) + i )->Id; + //printf("Lo %d, Saved name = %s, id = %d\n", i, Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), Vec_PtrEntry(vLoNames, i), NULL ), ntkObjId); + Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), (char *)Vec_PtrEntry(vLoNames, i), NULL ); + } + } + + Abc_NtkForEachPo(pNtk, pNode, i) + { + Abc_ObjAssignName(pNode, "assert_safety_", Abc_ObjName(pNode) ); + } + + // assign latch input names + Abc_NtkForEachLatch(pNtk, pNode, i) + if ( Nm_ManFindNameById(pNtk->pManName, Abc_ObjFanin0(pNode)->Id) == NULL ) + Abc_ObjAssignName( Abc_ObjFanin0(pNode), Abc_ObjName(Abc_ObjFanin0(pNode)), NULL ); +} + + +int Abc_CommandAbcLivenessToSafety( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkTemp, *pNtkNew, *pNtkOld; + Aig_Man_t * pAig, *pAigNew; + int c; + Vec_Ptr_t * vLive, * vFair, *vAssertSafety, *vAssumeSafety; + int directive = -1; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + if( argc == 1 ) + { + assert( directive == -1 ); + directive = FULL_BIERE_MODE; + } + else + { + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "1slh" ) ) != EOF ) + { + switch( c ) + { + case '1': + if( directive == -1 ) + directive = FULL_BIERE_ONE_LOOP_MODE; + else + { + assert( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE || directive == IGNORE_SAFETY_KEEP_LIVENESS_MODE ); + if( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) + directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE; + else + directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE; + } + break; + case 's': + if( directive == -1 ) + directive = IGNORE_SAFETY_KEEP_LIVENESS_MODE; + else + { + if( directive != FULL_BIERE_ONE_LOOP_MODE ) + goto usage; + assert(directive == FULL_BIERE_ONE_LOOP_MODE); + directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE; + } + break; + case 'l': + if( directive == -1 ) + directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE; + else + { + if( directive != FULL_BIERE_ONE_LOOP_MODE ) + goto usage; + assert(directive == FULL_BIERE_ONE_LOOP_MODE); + directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE; + } + break; + case 'h': + goto usage; + default: + goto usage; + } + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if( !Abc_NtkIsStrash( pNtk ) ) + { + printf("The input network was not strashed, strashing....\n"); + pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); + pNtkOld = pNtkTemp; + pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); + vLive = populateLivenessVector( pNtk, pAig ); + vFair = populateFairnessVector( pNtk, pAig ); + vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); + vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); + } + else + { + pAig = Abc_NtkToDar( pNtk, 0, 1 ); + pNtkOld = pNtk; + vLive = populateLivenessVector( pNtk, pAig ); + vFair = populateFairnessVector( pNtk, pAig ); + vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); + vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); + } + + switch( directive ) + { + case FULL_BIERE_MODE: + //if( Vec_PtrSize(vLive) == 0 && Vec_PtrSize(vAssertSafety) == 0 ) + //{ + // printf("Input circuit has NO safety and NO liveness property, original network is not disturbed\n"); + // return 1; + //} + //else + //{ + pAigNew = LivenessToSafetyTransformation( FULL_BIERE_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); + if( Aig_ManRegNum(pAigNew) != 0 ) + printf("A new circuit is produced with\n\t2 POs - one for safety and one for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n"); + break; + //} + case FULL_BIERE_ONE_LOOP_MODE: + //if( Vec_PtrSize(vLive) == 0 && Vec_PtrSize(vAssertSafety) == 0 ) + //{ + // printf("Input circuit has NO safety and NO liveness property, original network is not disturbed\n"); + // return 1; + //} + //else + //{ + pAigNew = LivenessToSafetyTransformationOneStepLoop( FULL_BIERE_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); + if( Aig_ManRegNum(pAigNew) != 0 ) + printf("A new circuit is produced with\n\t2 POs - one for safety and one for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n"); + break; + //} + case IGNORE_LIVENESS_KEEP_SAFETY_MODE: + //if( Vec_PtrSize(vAssertSafety) == 0 ) + //{ + // printf("Input circuit has NO safety property, original network is not disturbed\n"); + // return 1; + //} + //else + //{ + pAigNew = LivenessToSafetyTransformation( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); + if( Aig_ManRegNum(pAigNew) != 0 ) + printf("A new circuit is produced with\n\t1 PO - only for safety property; liveness properties are ignored, if any.\n\tno additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n"); + break; + //} + case IGNORE_SAFETY_KEEP_LIVENESS_MODE: + //if( Vec_PtrSize(vLive) == 0 ) + //{ + // printf("Input circuit has NO liveness property, original network is not disturbed\n"); + // return 1; + //} + //else + //{ + pAigNew = LivenessToSafetyTransformation( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); + if( Aig_ManRegNum(pAigNew) != 0 ) + printf("A new circuit is produced with\n\t1 PO - only for liveness property; safety properties are ignored, if any.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n"); + break; + //} + case IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE: + //if( Vec_PtrSize(vLive) == 0 ) + //{ + // printf("Input circuit has NO liveness property, original network is not disturbed\n"); + // return 1; + //} + //else + //{ + pAigNew = LivenessToSafetyTransformationOneStepLoop( IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); + if( Aig_ManRegNum(pAigNew) != 0 ) + printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nShadow registers are not created\n"); + break; + //} + } + +#if 0 + if( argc == 1 ) + { + pAigNew = LivenessToSafetyTransformation( FULL_BIERE_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); + if( Aig_ManRegNum(pAigNew) != 0 ) + printf("New circuit is produced considering all safety, liveness and fairness outputs.\nBiere's logic is created\n"); + } + else + { + Extra_UtilGetoptReset(); + c = Extra_UtilGetopt( argc, argv, "1lsh" ); + if( c == '1' ) + { + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if( !Abc_NtkIsStrash( pNtk ) ) + { + printf("The input network was not strashed, strashing....\n"); + pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); + pNtkOld = pNtkTemp; + pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); + vLive = populateLivenessVector( pNtk, pAig ); + vFair = populateFairnessVector( pNtk, pAig ); + vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); + vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); + } + else + { + pAig = Abc_NtkToDar( pNtk, 0, 1 ); + pNtkOld = pNtk; + vLive = populateLivenessVector( pNtk, pAig ); + vFair = populateFairnessVector( pNtk, pAig ); + vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); + vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); + } + pAigNew = LivenessToSafetyTransformationOneStepLoop( pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); + } + else if( c == 'l' ) + { + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if( !Abc_NtkIsStrash( pNtk ) ) + { + printf("The input network was not strashed, strashing....\n"); + pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); + pNtkOld = pNtkTemp; + pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); + vLive = populateLivenessVector( pNtk, pAig ); + vFair = populateFairnessVector( pNtk, pAig ); + vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); + vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); + } + else + { + pAig = Abc_NtkToDar( pNtk, 0, 1 ); + pNtkOld = pNtk; + vLive = populateLivenessVector( pNtk, pAig ); + vFair = populateFairnessVector( pNtk, pAig ); + vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); + vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); + } + pAigNew = LivenessToSafetyTransformation( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); + if( Aig_ManRegNum(pAigNew) != 0 ) + printf("New circuit is produced ignoring liveness outputs!\nOnly safety outputs are kept.\nBiere's logic is not created\n"); + } + else if( c == 's' ) + { + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if( !Abc_NtkIsStrash( pNtk ) ) + { + printf("The input network was not strashed, strashing....\n"); + pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); + pNtkOld = pNtkTemp; + pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); + vLive = populateLivenessVector( pNtk, pAig ); + vFair = populateFairnessVector( pNtk, pAig ); + vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); + vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); + } + else + { + pAig = Abc_NtkToDar( pNtk, 0, 1 ); + pNtkOld = pNtk; + vLive = populateLivenessVector( pNtk, pAig ); + vFair = populateFairnessVector( pNtk, pAig ); + vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); + vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); + } + pAigNew = LivenessToSafetyTransformation( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); + if( Aig_ManRegNum(pAigNew) != 0 ) + printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nBiere's logic is created\n"); + } + else if( c == 'h' ) + goto usage; + else + goto usage; + } +#endif + +#if 0 + Aig_ManPrintStats( pAigNew ); + printf("\nDetail statistics*************************************\n"); + printf("Number of true primary inputs = %d\n", Saig_ManPiNum( pAigNew )); + printf("Number of true primary outputs = %d\n", Saig_ManPoNum( pAigNew )); + printf("Number of true latch outputs = %d\n", Saig_ManCiNum( pAigNew ) - Saig_ManPiNum( pAigNew )); + printf("Number of true latch inputs = %d\n", Saig_ManCoNum( pAigNew ) - Saig_ManPoNum( pAigNew )); + printf("Numer of registers = %d\n", Saig_ManRegNum( pAigNew ) ); + printf("\n*******************************************************\n"); +#endif + + pNtkNew = Abc_NtkFromAigPhase( pAigNew ); + pNtkNew->pName = Abc_UtilStrsav( pAigNew->pName ); + + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" ); + + updateNewNetworkNameManager( pNtkNew, pAigNew, vecPiNames, vecLoNames ); + Abc_FrameSetCurrentNetwork( pAbc, pNtkNew ); + +#if 0 +#ifndef DUPLICATE_CKT_DEBUG + Saig_ManForEachPi( pAigNew, pObj, i ) + assert( strcmp( (char *)Vec_PtrEntry(vecPiNames, i), retrieveTruePiName( pNtk, pAig, pAigNew, pObj ) ) == 0 ); + //printf("Name of %d-th Pi = %s, %s\n", i, retrieveTruePiName( pNtk, pAig, pAigNew, pObj ), (char *)Vec_PtrEntry(vecPiNames, i) ); + + Saig_ManForEachLo( pAigNew, pObj, i ) + assert( strcmp( (char *)Vec_PtrEntry(vecLoNames, i), retrieveLOName( pNtk, pAig, pAigNew, pObj, vLive, vFair ) ) == 0 ); +#endif +#endif + + return 0; + +usage: + fprintf( stdout, "usage: l2s [-1lsh]\n" ); + fprintf( stdout, "\t performs Armin Biere's live-to-safe transformation\n" ); + fprintf( stdout, "\t-1 : no shadow logic, presume all loops are self loops\n"); + fprintf( stdout, "\t-l : ignore liveness and fairness outputs\n"); + fprintf( stdout, "\t-s : ignore safety assertions and assumptions\n"); + fprintf( stdout, "\t-h : print command usage\n"); + return 1; +} + +Vec_Int_t * prepareFlopVector( Aig_Man_t * pAig, int vectorLength ) +{ + Vec_Int_t *vFlops; + int i; + + vFlops = Vec_IntAlloc( vectorLength ); + + for( i=0; ipName = Abc_UtilStrsav( pAigNew->pName ); + + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" ); + + updateNewNetworkNameManager( pNtkNew, pAigNew, vecPiNames,vecLoNames ); + Abc_FrameSetCurrentNetwork( pAbc, pNtkNew ); + +#if 0 +#ifndef DUPLICATE_CKT_DEBUG + Saig_ManForEachPi( pAigNew, pObj, i ) + assert( strcmp( (char *)Vec_PtrEntry(vecPiNames, i), retrieveTruePiName( pNtk, pAig, pAigNew, pObj ) ) == 0 ); + //printf("Name of %d-th Pi = %s, %s\n", i, retrieveTruePiName( pNtk, pAig, pAigNew, pObj ), (char *)Vec_PtrEntry(vecPiNames, i) ); + + Saig_ManForEachLo( pAigNew, pObj, i ) + assert( strcmp( (char *)Vec_PtrEntry(vecLoNames, i), retrieveLOName( pNtk, pAig, pAigNew, pObj, vLive, vFair ) ) == 0 ); +#endif +#endif + + return 0; + +usage: + fprintf( stdout, "usage: l2s [-1lsh]\n" ); + fprintf( stdout, "\t performs Armin Biere's live-to-safe transformation\n" ); + fprintf( stdout, "\t-1 : no shadow logic, presume all loops are self loops\n"); + fprintf( stdout, "\t-l : ignore liveness and fairness outputs\n"); + fprintf( stdout, "\t-s : ignore safety assertions and assumptions\n"); + fprintf( stdout, "\t-h : print command usage\n"); + return 1; +} + +Aig_Man_t * LivenessToSafetyTransformationWithLTL( int mode, Abc_Ntk_t * pNtk, Aig_Man_t * p, + Vec_Ptr_t *vLive, Vec_Ptr_t *vFair, Vec_Ptr_t *vAssertSafety, Vec_Ptr_t *vAssumeSafety, + int *numLtlProcessed, Vec_Ptr_t *ltlBuffer ) +{ + Aig_Man_t * pNew; + int i, ii, iii, nRegCount; + Aig_Obj_t * pObjSavePi; + Aig_Obj_t *pObjSavedLo, *pObjSavedLi; + Aig_Obj_t *pObj, *pMatch; + Aig_Obj_t *pObjSaveOrSaved, *pObjSaveAndNotSaved, *pObjSavedLoAndEquality; + Aig_Obj_t *pObjShadowLo, *pObjShadowLi, *pObjShadowLiDriver; + Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc; + Aig_Obj_t *pObjLive, *pObjSafetyGate; + Aig_Obj_t *pObjSafetyPropertyOutput; + Aig_Obj_t *pObjOriginalSafetyPropertyOutput; + Aig_Obj_t *pDriverImage, *pArgument, *collectiveAssertSafety, *collectiveAssumeSafety; + Aig_Obj_t *pNegatedSafetyConjunction = NULL; + Aig_Obj_t *pObjSafetyAndLiveToSafety; + char *nodeName, *pFormula; + int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, piVecIndex = 0, liveLatch = 0, fairLatch = 0; + Vec_Ptr_t *vSignal, *vTopASTNodeArray; + ltlNode *pEnrtyGLOBALLY; + ltlNode *topNodeOfAST, *tempTopASTNode; + Vec_Vec_t *vAigGFMap; + Vec_Ptr_t *vSignalMemory, *vGFFlopMemory, *vPoForLtlProps; + Vec_Ptr_t *vecInputLtlFormulae; + + vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); + vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); + + vecLos = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); + vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); + + //**************************************************************** + //step0: Parsing the LTL formula + //**************************************************************** + //Vec_PtrForEachEntry( char *, pNtk->vLtlProperties, pFormula, i ) + // printf("\ninput LTL formula [%d] = %s\n", i, pFormula ); + + +#ifdef MULTIPLE_LTL_FORMULA + + + //*************************************************************************** + //Reading input LTL formulae from Ntk data-structure and creating + //AST for them, Steps involved: + // parsing -> AST creation -> well-formedness check -> signal name check + //*************************************************************************** + + //resetting numLtlProcessed + *numLtlProcessed = 0; + + if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) + { + //if( ltlBuffer ) + vecInputLtlFormulae = ltlBuffer; + //vecInputLtlFormulae = pNtk->vLtlProperties; + if( vecInputLtlFormulae ) + { + vTopASTNodeArray = Vec_PtrAlloc( Vec_PtrSize( vecInputLtlFormulae ) ); + printf("\n"); + Vec_PtrForEachEntry( char *, vecInputLtlFormulae, pFormula, i ) + { + tempTopASTNode = parseFormulaCreateAST( pFormula ); + //traverseAbstractSyntaxTree_postFix( tempTopASTNode ); + if( tempTopASTNode ) + { + printf("Formula %d: AST is created, ", i+1); + if( isWellFormed( tempTopASTNode ) ) + printf("Well-formedness check PASSED, "); + else + { + printf("Well-formedness check FAILED!!\n"); + printf("AST will be ignored for formula %d, no extra logic will be added for this formula\n", i+1 ); + //do memory management to free the created AST + continue; + } + if( checkSignalNameExistence( pNtk, tempTopASTNode ) ) + printf("Signal check PASSED\n"); + else + { + printf("Signal check FAILED!!"); + printf("AST will be ignored for formula %d, no extra logic will be added for this formula\n", i+1 ); + //do memory management to free the created AST + continue; + } + Vec_PtrPush( vTopASTNodeArray, tempTopASTNode ); + (*numLtlProcessed)++; + } + else + printf("\nNo AST has been created for formula %d, no extra logic will be added\n", i+1 ); + } + } + printf("\n"); + if( Vec_PtrSize( vTopASTNodeArray ) == 0 ) + { + //printf("\nNo AST has been created for any formula; hence the circuit is left untouched\n"); + printf("\nCurrently aborting, need to take care when Vec_PtrSize( vTopASTNodeArray ) == 0\n"); + exit(0); + } + } + + //**************************************************************** + // Step1: create the new manager + // Note: The new manager is created with "2 * Aig_ManObjNumMax(p)" + // nodes, but this selection is arbitrary - need to be justified + //**************************************************************** + pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) ); + pNew->pName = (char *)malloc( strlen( pNtk->pName ) + strlen("_l3s") + 1 ); + sprintf(pNew->pName, "%s_%s", pNtk->pName, "l3s"); + pNew->pSpec = NULL; + + //**************************************************************** + // Step 2: map constant nodes + //**************************************************************** + pObj = Aig_ManConst1( p ); + pObj->pData = Aig_ManConst1( pNew ); + + //**************************************************************** + // Step 3: create true PIs + //**************************************************************** + Saig_ManForEachPi( p, pObj, i ) + { + piCopied++; + pObj->pData = Aig_ObjCreatePi(pNew); + Vec_PtrPush( vecPis, pObj->pData ); + nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) )); + Vec_PtrPush( vecPiNames, nodeName ); + } + + //**************************************************************** + // Step 4: create the special Pi corresponding to SAVE + //**************************************************************** + if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) + { + pObjSavePi = Aig_ObjCreatePi( pNew ); + nodeName = "SAVE_BIERE", + Vec_PtrPush( vecPiNames, nodeName ); + } + + //**************************************************************** + // Step 5: create register outputs + //**************************************************************** + Saig_ManForEachLo( p, pObj, i ) + { + loCopied++; + pObj->pData = Aig_ObjCreatePi(pNew); + Vec_PtrPush( vecLos, pObj->pData ); + nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) )); + Vec_PtrPush( vecLoNames, nodeName ); + } + + //**************************************************************** + // Step 6: create "saved" register output + //**************************************************************** + if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) + { + loCreated++; + pObjSavedLo = Aig_ObjCreatePi( pNew ); + Vec_PtrPush( vecLos, pObjSavedLo ); + nodeName = "SAVED_LO"; + Vec_PtrPush( vecLoNames, nodeName ); + } + + //**************************************************************** + // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi + //**************************************************************** + if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) + { + pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo ); + pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) ); + } + + //******************************************************************** + // Step 8: create internal nodes + //******************************************************************** + Aig_ManForEachNode( p, pObj, i ) + { + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + } + + + //******************************************************************** + // Step 8.x : create PO for each safety assertions + // NOTE : Here the output is purposely inverted as it will be thrown to + // dprove + //******************************************************************** + assert( pNegatedSafetyConjunction == NULL ); + if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE) + { + if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) == 0 ) + { + pObjAndAcc = Aig_ManConst1( pNew ); + Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) + { + pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); + pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); + } + pNegatedSafetyConjunction = Aig_Not(pObjAndAcc); + if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) + pObjOriginalSafetyPropertyOutput = Aig_ObjCreatePo( pNew, Aig_Not(pObjAndAcc) ); + } + else if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) != 0 ) + { + pObjAndAcc = Aig_ManConst1( pNew ); + Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) + { + pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); + pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); + } + collectiveAssertSafety = pObjAndAcc; + + pObjAndAcc = Aig_ManConst1( pNew ); + Vec_PtrForEachEntry( Aig_Obj_t *, vAssumeSafety, pObj, i ) + { + pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); + pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); + } + collectiveAssumeSafety = pObjAndAcc; + pNegatedSafetyConjunction = Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ); + if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) + pObjOriginalSafetyPropertyOutput = Aig_ObjCreatePo( pNew, Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ) ); + } + else + { + printf("WARNING!! No safety property is found, a new (negated) constant 1 output is created\n"); + pNegatedSafetyConjunction = Aig_Not( Aig_ManConst1(pNew) ); + if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) + pObjOriginalSafetyPropertyOutput = Aig_ObjCreatePo( pNew, Aig_Not( Aig_ManConst1(pNew) ) ); + } + } + assert( pNegatedSafetyConjunction != NULL ); + + //******************************************************************** + // Step 9: create the safety property output gate for the liveness properties + // discuss with Sat/Alan for an alternative implementation + //******************************************************************** + if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) + { + vPoForLtlProps = Vec_PtrAlloc( Vec_PtrSize( vTopASTNodeArray ) ); + if( Vec_PtrSize( vTopASTNodeArray ) ) + { + //no effective AST for any input LTL property + //must do something graceful + } + for( i=0; ipData ); + Vec_PtrPush( vPoForLtlProps, pObjSafetyPropertyOutput ); + } + } + + //************************************************************************************* + // Step 10: Placeholder PO's were created for Liveness property outputs in the + // last step. FYI, # of new liveness property outputs = # of LTL properties in the circuit + // It is time for creation of loop LI's and other stuff + // Now creating register inputs for the original flops + //************************************************************************************* + nRegCount = 0; + + Saig_ManForEachLo( p, pObj, i ) + { + pMatch = Saig_ObjLoToLi( p, pObj ); + Aig_ObjCreatePo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) ); + nRegCount++; + liCopied++; + } + + //************************************************************************************* + // Step 11: create register input corresponding to the register "saved" + //************************************************************************************* + if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) + { + #ifndef DUPLICATE_CKT_DEBUG + pObjSavedLi = Aig_ObjCreatePo( pNew, pObjSaveOrSaved ); + nRegCount++; + liCreated++; + + pObjAndAcc = Aig_ManConst1( pNew ); + + //************************************************************************************* + // Step 11: create the family of shadow registers, then create the cascade of Xnor + // and And gates for the comparator + //************************************************************************************* + Saig_ManForEachLo( p, pObj, i ) + { + //printf("\nKEMON RENDY = %s", Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i )) ); + //top|route0_target0_queue_with_credit0_queue0 + //top|route0_master0_queue2 + // if( strcmp( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "top|route0_queue1_num[0]" ) == 0 + // || strcmp( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "top|route0_queue1_num[1]" ) == 0 || strcmp( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "top|route0_queue1_num[2]" ) == 0 ) + { + pObjShadowLo = Aig_ObjCreatePi( pNew ); + + #ifdef PROPAGATE_NAMES + Vec_PtrPush( vecLos, pObjShadowLo ); + nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ) ) + 10 ); + sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "SHADOW" ); + + Vec_PtrPush( vecLoNames, nodeName ); + #endif + + pObjShadowLiDriver = Aig_Mux( pNew, pObjSaveAndNotSaved, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); + pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver ); + nRegCount++; + loCreated++; liCreated++; + + pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); + pObjXnor = Aig_Not( pObjXor ); + + pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAcc ); + } + } + + // create the AND gate whose output will be the signal "looped" + pObjSavedLoAndEquality = Aig_And( pNew, pObjSavedLo, pObjAndAcc ); + + // create the master AND gate and corresponding AND and OR logic for the liveness properties + + //************************************************************************************* + // Step 11: logic for LTL properties:- (looped & ~theta) where theta is the input ltl + // property + // Description of some data-structure: + //------------------------------------------------------------------------------------- + // Name | Type | Purpose + //------------------------------------------------------------------------------------- + // vSignalMemory | Vec_Ptr_t * | A vector across all ASTs of the LTL properties + // | | It remembers if OR+Latch for GF node has already been + // | | created for a particular signal. + // | | + // vGFFlopMemory | Vec_Ptr_t * | A vector across all ASTs of the LTL properties + // | | remembers if OR+Latch of a GF node has already been created + // | | + // vSignal | Vec_Ptr_t * | vector for each AST; contains pointers from GF nodes + // | | to AIG signals + // | | + // vAigGFMap | Vec_Vec_t * | vAigGFMap[ index ] = vector of GF nodes pointing to + // | | the same AIG node; "index" is the index of that + // | | AIG node in the vector vSignal + //************************************************************************************* + + vSignalMemory = Vec_PtrAlloc(10); + vGFFlopMemory = Vec_PtrAlloc(10); + + Vec_PtrForEachEntry( ltlNode *, vTopASTNodeArray, topNodeOfAST, iii ) + { + vSignal = Vec_PtrAlloc( 10 ); + vAigGFMap = Vec_VecAlloc( 10 ); + + //************************************************************************************* + //Step 11a: for the current AST, find out the leaf level Boolean signal pointers from + // the NEW aig. + //************************************************************************************* + populateBoolWithAigNodePtr( pNtk, p, pNew, topNodeOfAST ); + assert( checkAllBoolHaveAIGPointer( topNodeOfAST ) ); + + //************************************************************************************* + //Step 11b: for each GF node, compute the pointer in AIG that it should point to + // In particular, if the subtree below GF is some Boolean crown (including the case + // of simple negation, create new logic and populate the AIG pointer in GF node + // accordingly + //************************************************************************************* + populateAigPointerUnitGF( pNew, topNodeOfAST, vSignal, vAigGFMap ); + + //************************************************************************************* + //Step 11c: everything below GF are computed. Now, it is time to create logic for individual + // GF nodes (i.e. the OR gate and the latch and the Boolean crown of the AST + //************************************************************************************* + Vec_PtrForEachEntry( Aig_Obj_t *, vSignal, pObj, i ) + { + //********************************************************* + // Step 11c.1: if the OR+Latch of the particular signal is + // not already created, create it. It may have already been + // created from another property, so check it before creation + //********************************************************* + if( Vec_PtrFind( vSignalMemory, pObj ) == -1 ) + { + liveLatch++; + + pDriverImage = pObj; + pObjShadowLo = Aig_ObjCreatePi( pNew ); + pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) ); + pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver ); + + nRegCount++; + loCreated++; liCreated++; + + Vec_PtrPush( vSignalMemory, pObj ); + Vec_PtrPush( vGFFlopMemory, pObjShadowLo ); + + #if 1 + #ifdef PROPAGATE_NAMES + Vec_PtrPush( vecLos, pObjShadowLo ); + //nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); + //sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "LIVENESS" ); + nodeName = (char *)malloc( 20 ); + sprintf( nodeName, "n%d__%s", Aig_ObjId(pObjShadowLo), "GF_flop" ); + Vec_PtrPush( vecLoNames, nodeName ); + #endif + #endif + } + else + pObjShadowLo = (Aig_Obj_t *)Vec_PtrEntry( vGFFlopMemory, Vec_PtrFind( vSignalMemory, pObj ) ); + + Vec_VecForEachEntryLevel( ltlNode *, vAigGFMap, pEnrtyGLOBALLY, ii, i ) + setAIGNodePtrOfGloballyNode( pEnrtyGLOBALLY, pObjShadowLo); + + + //#ifdef PROPAGATE_NAMES + // Vec_PtrPush( vecLos, pObjShadowLo ); + // nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); + // sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "LIVENESS" ); + // Vec_PtrPush( vecLoNames, nodeName ); + //#endif + + } + + //********************************************************* + //Step 11c.2: creating the Boolean crown + //********************************************************* + buildLogicFromLTLNode( pNew, topNodeOfAST ); + + //********************************************************* + //Step 11c.3: creating logic for (looped & ~theta) and patching + // it with the proper PO + //Note: if ALLOW_SAFETY_PROPERTIES is defined then the final AND + //gate is a conjunction of safety & liveness, i.e. SAFETY & (looped => theta) + //since ABC convention demands a NOT gate at the end, the property logic + //becomes !( SAFETY & (looped => theta) ) = !SAFETY + (looped & !theta) + //********************************************************* + pObjLive = retriveAIGPointerFromLTLNode( topNodeOfAST ); + pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_Not(pObjLive) ); + #ifdef ALLOW_SAFETY_PROPERTIES + printf("liveness output is conjoined with safety assertions\n"); + pObjSafetyAndLiveToSafety = Aig_Or( pNew, pObjSafetyGate, pNegatedSafetyConjunction ); + pObjSafetyPropertyOutput = (Aig_Obj_t *)Vec_PtrEntry( vPoForLtlProps, iii ); + Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyAndLiveToSafety ); + #else + pObjSafetyPropertyOutput = Vec_PtrEntry( vPoForLtlProps, iii ); + Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate ); + #endif + //refreshing vSignal and vAigGFMap arrays + Vec_PtrFree( vSignal ); + Vec_VecFree( vAigGFMap ); + } + + #endif + } +#endif + + Aig_ManSetRegNum( pNew, nRegCount ); + + Aig_ManPiCleanupBiere( pNew ); + Aig_ManPoCleanupBiere( pNew ); + + Aig_ManCleanup( pNew ); + + assert( Aig_ManCheck( pNew ) ); + + if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) + { + assert((Aig_Obj_t *)Vec_PtrEntry(pNew->vPos, Saig_ManPoNum(pNew)+Aig_ObjPioNum(pObjSavedLo)-Saig_ManPiNum(p)-1) == pObjSavedLi); + assert( Saig_ManPiNum( p ) + 1 == Saig_ManPiNum( pNew ) ); + //assert( Saig_ManRegNum( pNew ) == Saig_ManRegNum( p ) * 2 + 1 + liveLatch + fairLatch ); + } + + + return pNew; +} + +int Abc_CommandAbcLivenessToSafetyWithLTL( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkTemp, *pNtkNew, *pNtkOld; + Aig_Man_t * pAig, *pAigNew; + int c; + Vec_Ptr_t * vLive, * vFair, *vAssertSafety, *vAssumeSafety; + int directive = -1; + char *ltfFormulaString = NULL; + int LTL_FLAG = 0, numOfLtlPropOutput; + Vec_Ptr_t *ltlBuffer; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + if( argc == 1 ) + { + assert( directive == -1 ); + directive = FULL_BIERE_MODE; + } + else + { + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "1slhf" ) ) != EOF ) + { + switch( c ) + { + case '1': + if( directive == -1 ) + directive = FULL_BIERE_ONE_LOOP_MODE; + else + { + assert( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE || directive == IGNORE_SAFETY_KEEP_LIVENESS_MODE ); + if( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) + directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE; + else + directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE; + } + break; + case 's': + if( directive == -1 ) + directive = IGNORE_SAFETY_KEEP_LIVENESS_MODE; + else + { + if( directive != FULL_BIERE_ONE_LOOP_MODE ) + goto usage; + assert(directive == FULL_BIERE_ONE_LOOP_MODE); + directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE; + } + break; + case 'l': + if( directive == -1 ) + directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE; + else + { + if( directive != FULL_BIERE_ONE_LOOP_MODE ) + goto usage; + assert(directive == FULL_BIERE_ONE_LOOP_MODE); + directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE; + } + break; + case 'f': + //assert( argc >= 3 ); + //vecLtlFormula = Vec_PtrAlloc( argc - 2 ); + //if( argc >= 3 ) + //{ + // for( t=3; t<=argc; t++ ) + // { + // printf("argv[%d] = %s\n", t-1, argv[t-1]); + // Vec_PtrPush( vecLtlFormula, argv[t-1] ); + // } + //} + //printf("argv[argc] = %s\n", argv[argc-1]); + //ltfFormulaString = argv[2]; + + //LTL_FLAG = 1; + printf("\nILLEGAL FLAG: aborting....\n"); + exit(0); + break; + case 'h': + goto usage; + default: + goto usage; + } + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if( !Abc_NtkIsStrash( pNtk ) ) + { + printf("The input network was not strashed, strashing....\n"); + pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); + pNtkOld = pNtkTemp; + pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); + vLive = populateLivenessVector( pNtk, pAig ); + vFair = populateFairnessVector( pNtk, pAig ); + vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); + vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); + } + else + { + pAig = Abc_NtkToDar( pNtk, 0, 1 ); + pNtkOld = pNtk; + vLive = populateLivenessVector( pNtk, pAig ); + vFair = populateFairnessVector( pNtk, pAig ); + vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); + vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); + } + + if( pAbc->vLTLProperties_global != NULL ) + ltlBuffer = pAbc->vLTLProperties_global; + else + ltlBuffer = NULL; + + switch( directive ) + { + case FULL_BIERE_MODE: + pAigNew = LivenessToSafetyTransformationWithLTL( FULL_BIERE_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety, &numOfLtlPropOutput, ltlBuffer ); + if( Aig_ManRegNum(pAigNew) != 0 ) + printf("A new circuit is produced with\n\t%d POs - one for safety and %d for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n", numOfLtlPropOutput+1, numOfLtlPropOutput); + break; + + case FULL_BIERE_ONE_LOOP_MODE: + pAigNew = LivenessToSafetyTransformationOneStepLoop( FULL_BIERE_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); + if( Aig_ManRegNum(pAigNew) != 0 ) + printf("A new circuit is produced with\n\t2 POs - one for safety and one for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n"); + break; + + case IGNORE_LIVENESS_KEEP_SAFETY_MODE: + pAigNew = LivenessToSafetyTransformationWithLTL( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety, &numOfLtlPropOutput, ltlBuffer ); + assert( numOfLtlPropOutput == 0 ); + if( Aig_ManRegNum(pAigNew) != 0 ) + printf("A new circuit is produced with\n\t1 PO - only for safety property; liveness properties are ignored, if any.\n\tno additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n"); + break; + + case IGNORE_SAFETY_KEEP_LIVENESS_MODE: + pAigNew = LivenessToSafetyTransformationWithLTL( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety, &numOfLtlPropOutput, ltlBuffer ); + if( Aig_ManRegNum(pAigNew) != 0 ) + printf("A new circuit is produced with\n\t%d PO - only for liveness property; safety properties are ignored, if any.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n", numOfLtlPropOutput); + break; + + case IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE: + pAigNew = LivenessToSafetyTransformationOneStepLoop( IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); + if( Aig_ManRegNum(pAigNew) != 0 ) + printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nShadow registers are not created\n"); + break; + } + +#if 0 + if( argc == 1 ) + { + pAigNew = LivenessToSafetyTransformation( FULL_BIERE_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); + if( Aig_ManRegNum(pAigNew) != 0 ) + printf("New circuit is produced considering all safety, liveness and fairness outputs.\nBiere's logic is created\n"); + } + else + { + Extra_UtilGetoptReset(); + c = Extra_UtilGetopt( argc, argv, "1lsh" ); + if( c == '1' ) + { + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if( !Abc_NtkIsStrash( pNtk ) ) + { + printf("The input network was not strashed, strashing....\n"); + pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); + pNtkOld = pNtkTemp; + pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); + vLive = populateLivenessVector( pNtk, pAig ); + vFair = populateFairnessVector( pNtk, pAig ); + vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); + vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); + } + else + { + pAig = Abc_NtkToDar( pNtk, 0, 1 ); + pNtkOld = pNtk; + vLive = populateLivenessVector( pNtk, pAig ); + vFair = populateFairnessVector( pNtk, pAig ); + vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); + vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); + } + pAigNew = LivenessToSafetyTransformationOneStepLoop( pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); + } + else if( c == 'l' ) + { + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if( !Abc_NtkIsStrash( pNtk ) ) + { + printf("The input network was not strashed, strashing....\n"); + pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); + pNtkOld = pNtkTemp; + pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); + vLive = populateLivenessVector( pNtk, pAig ); + vFair = populateFairnessVector( pNtk, pAig ); + vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); + vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); + } + else + { + pAig = Abc_NtkToDar( pNtk, 0, 1 ); + pNtkOld = pNtk; + vLive = populateLivenessVector( pNtk, pAig ); + vFair = populateFairnessVector( pNtk, pAig ); + vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); + vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); + } + pAigNew = LivenessToSafetyTransformation( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); + if( Aig_ManRegNum(pAigNew) != 0 ) + printf("New circuit is produced ignoring liveness outputs!\nOnly safety outputs are kept.\nBiere's logic is not created\n"); + } + else if( c == 's' ) + { + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if( !Abc_NtkIsStrash( pNtk ) ) + { + printf("The input network was not strashed, strashing....\n"); + pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); + pNtkOld = pNtkTemp; + pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); + vLive = populateLivenessVector( pNtk, pAig ); + vFair = populateFairnessVector( pNtk, pAig ); + vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); + vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); + } + else + { + pAig = Abc_NtkToDar( pNtk, 0, 1 ); + pNtkOld = pNtk; + vLive = populateLivenessVector( pNtk, pAig ); + vFair = populateFairnessVector( pNtk, pAig ); + vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); + vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); + } + pAigNew = LivenessToSafetyTransformation( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); + if( Aig_ManRegNum(pAigNew) != 0 ) + printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nBiere's logic is created\n"); + } + else if( c == 'h' ) + goto usage; + else + goto usage; + } +#endif + +#if 0 + Aig_ManPrintStats( pAigNew ); + printf("\nDetail statistics*************************************\n"); + printf("Number of true primary inputs = %d\n", Saig_ManPiNum( pAigNew )); + printf("Number of true primary outputs = %d\n", Saig_ManPoNum( pAigNew )); + printf("Number of true latch outputs = %d\n", Saig_ManCiNum( pAigNew ) - Saig_ManPiNum( pAigNew )); + printf("Number of true latch inputs = %d\n", Saig_ManCoNum( pAigNew ) - Saig_ManPoNum( pAigNew )); + printf("Numer of registers = %d\n", Saig_ManRegNum( pAigNew ) ); + printf("\n*******************************************************\n"); +#endif + + pNtkNew = Abc_NtkFromAigPhase( pAigNew ); + pNtkNew->pName = Abc_UtilStrsav( pAigNew->pName ); + + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" ); + + updateNewNetworkNameManager( pNtkNew, pAigNew, vecPiNames, vecLoNames ); + Abc_FrameSetCurrentNetwork( pAbc, pNtkNew ); + +#if 0 +#ifndef DUPLICATE_CKT_DEBUG + Saig_ManForEachPi( pAigNew, pObj, i ) + assert( strcmp( (char *)Vec_PtrEntry(vecPiNames, i), retrieveTruePiName( pNtk, pAig, pAigNew, pObj ) ) == 0 ); + //printf("Name of %d-th Pi = %s, %s\n", i, retrieveTruePiName( pNtk, pAig, pAigNew, pObj ), (char *)Vec_PtrEntry(vecPiNames, i) ); + + Saig_ManForEachLo( pAigNew, pObj, i ) + assert( strcmp( (char *)Vec_PtrEntry(vecLoNames, i), retrieveLOName( pNtk, pAig, pAigNew, pObj, vLive, vFair ) ) == 0 ); +#endif +#endif + + return 0; + +usage: + fprintf( stdout, "usage: l3s [-1lsh]\n" ); + fprintf( stdout, "\t performs Armin Biere's live-to-safe transformation\n" ); + fprintf( stdout, "\t-1 : no shadow logic, presume all loops are self loops\n"); + fprintf( stdout, "\t-l : ignore liveness and fairness outputs\n"); + fprintf( stdout, "\t-s : ignore safety assertions and assumptions\n"); + fprintf( stdout, "\t-h : print command usage\n"); + return 1; +} + + +ABC_NAMESPACE_IMPL_END diff --git a/src/proof/live/liveness_sim.c b/src/proof/live/liveness_sim.c new file mode 100644 index 00000000..50153e50 --- /dev/null +++ b/src/proof/live/liveness_sim.c @@ -0,0 +1,848 @@ +/**CFile**************************************************************** + + FileName [liveness_sim.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Liveness property checking.] + + Synopsis [Main implementation module.] + + Author [Sayak Ray] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 1, 2009.] + + Revision [$Id: liveness_sim.c,v 1.00 2009/01/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include "src/base/main/main.h" +#include "src/aig/aig/aig.h" +#include "src/aig/saig/saig.h" +#include + +ABC_NAMESPACE_IMPL_START + + +#define PROPAGATE_NAMES +//#define DUPLICATE_CKT_DEBUG + +extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); +extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); +//char *strdup(const char *string); + + +/******************************************************************* +LAYOUT OF PI VECTOR: + ++------------------------------------------------------------------------------------------------------------------------------------+ +| TRUE ORIGINAL PI (n) | SAVE(PI) (1) | ORIGINAL LO (k) | SAVED(LO) (1) | SHADOW_ORIGINAL LO (k) | LIVENESS LO (l) | FAIRNESS LO (f) | ++------------------------------------------------------------------------------------------------------------------------------------+ +<------------True PI----------------->|<----------------------------LO---------------------------------------------------------------> + +LAYOUT OF PO VECTOR: + ++-----------------------------------------------------------------------------------------------------------+ +| SOLE PO (1) | ORIGINAL LI (k) | SAVED LI (1) | SHADOW_ORIGINAL LI (k) | LIVENESS LI (l) | FAIRNESS LI (f) | ++-----------------------------------------------------------------------------------------------------------+ +<--True PO--->|<--------------------------------------LI----------------------------------------------------> + +********************************************************************/ + +static void printVecPtrOfString( Vec_Ptr_t *vec ) +{ + int i; + + for( i=0; i< Vec_PtrSize( vec ); i++ ) + { + printf("vec[%d] = %s\n", i, (char *)Vec_PtrEntry(vec, i) ); + } +} + +static int getPoIndex( Aig_Man_t *pAig, Aig_Obj_t *pPivot ) +{ + int i; + Aig_Obj_t *pObj; + + Saig_ManForEachPo( pAig, pObj, i ) + { + if( pObj == pPivot ) + return i; + } + return -1; +} + +static char * retrieveTruePiName( Abc_Ntk_t *pNtkOld, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, Aig_Obj_t *pObjPivot ) +{ + Aig_Obj_t *pObjOld, *pObj; + Abc_Obj_t *pNode; + int index; + + assert( Saig_ObjIsPi( pAigNew, pObjPivot ) ); + Aig_ManForEachPi( pAigNew, pObj, index ) + if( pObj == pObjPivot ) + break; + assert( index < Aig_ManPiNum( pAigNew ) - Aig_ManRegNum( pAigNew ) ); + if( index == Saig_ManPiNum( pAigNew ) - 1 ) + return "SAVE_BIERE"; + else + { + pObjOld = Aig_ManPi( pAigOld, index ); + pNode = Abc_NtkPi( pNtkOld, index ); + assert( pObjOld->pData == pObjPivot ); + return Abc_ObjName( pNode ); + } +} + +static char * retrieveLOName( Abc_Ntk_t *pNtkOld, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, Aig_Obj_t *pObjPivot, Vec_Ptr_t *vLive, Vec_Ptr_t * vFair ) +{ + Aig_Obj_t *pObjOld, *pObj; + Abc_Obj_t *pNode; + int index, oldIndex, originalLatchNum = Saig_ManRegNum(pAigOld), strMatch, i; + char *dummyStr = (char *)malloc( sizeof(char) * 50 ); + + assert( Saig_ObjIsLo( pAigNew, pObjPivot ) ); + Saig_ManForEachLo( pAigNew, pObj, index ) + if( pObj == pObjPivot ) + break; + if( index < originalLatchNum ) + { + oldIndex = Saig_ManPiNum( pAigOld ) + index; + pObjOld = Aig_ManPi( pAigOld, oldIndex ); + pNode = Abc_NtkCi( pNtkOld, oldIndex ); + assert( pObjOld->pData == pObjPivot ); + return Abc_ObjName( pNode ); + } + else if( index == originalLatchNum ) + return "SAVED_LO"; + else if( index > originalLatchNum && index < 2 * originalLatchNum + 1 ) + { + oldIndex = Saig_ManPiNum( pAigOld ) + index - originalLatchNum - 1; + pObjOld = Aig_ManPi( pAigOld, oldIndex ); + pNode = Abc_NtkCi( pNtkOld, oldIndex ); + sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "SHADOW"); + return dummyStr; + } + else if( index >= 2 * originalLatchNum + 1 && index < 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) ) + { + oldIndex = index - 2 * originalLatchNum - 1; + strMatch = 0; + Saig_ManForEachPo( pAigOld, pObj, i ) + { + pNode = Abc_NtkPo( pNtkOld, i ); + if( strstr( Abc_ObjName( pNode ), "assert_fair" ) != NULL ) + { + if( strMatch == oldIndex ) + { + sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "LIVENESS"); + return dummyStr; + } + else + strMatch++; + } + } + } + else if( index >= 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) && index < 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ) + { + oldIndex = index - 2 * originalLatchNum - 1 - Vec_PtrSize( vLive ); + strMatch = 0; + Saig_ManForEachPo( pAigOld, pObj, i ) + { + pNode = Abc_NtkPo( pNtkOld, i ); + if( strstr( Abc_ObjName( pNode ), "assume_fair" ) != NULL ) + { + if( strMatch == oldIndex ) + { + sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "FAIRNESS"); + return dummyStr; + } + else + strMatch++; + } + } + } + else + return "UNKNOWN"; +} + +extern Vec_Ptr_t *vecPis, *vecPiNames; +extern Vec_Ptr_t *vecLos, *vecLoNames; + + +static int Aig_ManPiCleanupBiere( Aig_Man_t * p ) +{ + int k = 0, nPisOld = Aig_ManPiNum(p); + + p->nObjs[AIG_OBJ_PI] = Vec_PtrSize( p->vPis ); + if ( Aig_ManRegNum(p) ) + p->nTruePis = Aig_ManPiNum(p) - Aig_ManRegNum(p); + + return nPisOld - Aig_ManPiNum(p); +} + + +static int Aig_ManPoCleanupBiere( Aig_Man_t * p ) +{ + int k = 0, nPosOld = Aig_ManPoNum(p); + + p->nObjs[AIG_OBJ_PO] = Vec_PtrSize( p->vPos ); + if ( Aig_ManRegNum(p) ) + p->nTruePos = Aig_ManPoNum(p) - Aig_ManRegNum(p); + return nPosOld - Aig_ManPoNum(p); +} + +static Aig_Man_t * LivenessToSafetyTransformationSim( Abc_Ntk_t * pNtk, Aig_Man_t * p, Vec_Ptr_t *vLive, Vec_Ptr_t *vFair ) +{ + Aig_Man_t * pNew; + int i, nRegCount; + Aig_Obj_t * pObjSavePi; + Aig_Obj_t *pObjSavedLo, *pObjSavedLi; + Aig_Obj_t *pObj, *pMatch; + Aig_Obj_t *pObjSaveOrSaved, *pObjSavedLoAndEquality; + Aig_Obj_t *pObjShadowLo, *pObjShadowLi, *pObjShadowLiDriver; + Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc, *pObjAndAccDummy; + Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate; + Aig_Obj_t *pObjSafetyPropertyOutput; + Aig_Obj_t *pDriverImage; + char *nodeName; + int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, piVecIndex = 0, liveLatch = 0, fairLatch = 0; + + vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); + vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); + + vecLos = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); + vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); + +#ifdef DUPLICATE_CKT_DEBUG + printf("\nCode is compiled in DEBUG mode, the input-output behavior will be the same as the original circuit\n"); + printf("Press any key to continue..."); + scanf("%c", &c); +#endif + + //**************************************************************** + // Step1: create the new manager + // Note: The new manager is created with "2 * Aig_ManObjNumMax(p)" + // nodes, but this selection is arbitrary - need to be justified + //**************************************************************** + pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( "live2safe" ); + pNew->pSpec = NULL; + + //**************************************************************** + // Step 2: map constant nodes + //**************************************************************** + pObj = Aig_ManConst1( p ); + pObj->pData = Aig_ManConst1( pNew ); + + //**************************************************************** + // Step 3: create true PIs + //**************************************************************** + Saig_ManForEachPi( p, pObj, i ) + { + piCopied++; + pObj->pData = Aig_ObjCreatePi(pNew); + Vec_PtrPush( vecPis, pObj->pData ); + nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) )); + Vec_PtrPush( vecPiNames, nodeName ); + } + + //**************************************************************** + // Step 4: create the special Pi corresponding to SAVE + //**************************************************************** +#ifndef DUPLICATE_CKT_DEBUG + pObjSavePi = Aig_ObjCreatePi( pNew ); + nodeName = Abc_UtilStrsav("SAVE_BIERE"), + Vec_PtrPush( vecPiNames, nodeName ); +#endif + + //**************************************************************** + // Step 5: create register outputs + //**************************************************************** + Saig_ManForEachLo( p, pObj, i ) + { + loCopied++; + pObj->pData = Aig_ObjCreatePi(pNew); + Vec_PtrPush( vecLos, pObj->pData ); + nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) )); + Vec_PtrPush( vecLoNames, nodeName ); + } + + //**************************************************************** + // Step 6: create "saved" register output + //**************************************************************** +#ifndef DUPLICATE_CKT_DEBUG + loCreated++; + pObjSavedLo = Aig_ObjCreatePi( pNew ); + Vec_PtrPush( vecLos, pObjSavedLo ); + nodeName = Abc_UtilStrsav("SAVED_LO"); + Vec_PtrPush( vecLoNames, nodeName ); +#endif + + //**************************************************************** + // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi + //**************************************************************** +#ifndef DUPLICATE_CKT_DEBUG + pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo ); + //pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) ); +#endif + + //******************************************************************** + // Step 8: create internal nodes + //******************************************************************** + Aig_ManForEachNode( p, pObj, i ) + { + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + } + + //******************************************************************** + // Step 9: create the safety property output gate + // create the safety property output gate, this will be the sole true PO + // of the whole circuit, discuss with Sat/Alan for an alternative implementation + //******************************************************************** +#ifndef DUPLICATE_CKT_DEBUG + pObjSafetyPropertyOutput = Aig_ObjCreatePo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData ); +#endif + + //******************************************************************** + // DEBUG: To recreate the same circuit, at least from the input and output + // behavior, we need to copy the original PO + //******************************************************************** +#ifdef DUPLICATE_CKT_DEBUG + Saig_ManForEachPo( p, pObj, i ) + { + Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); + } +#endif + + // create register inputs for the original registers + nRegCount = 0; + + Saig_ManForEachLo( p, pObj, i ) + { + pMatch = Saig_ObjLoToLi( p, pObj ); + //Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pMatch) ); + Aig_ObjCreatePo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) ); + nRegCount++; + liCopied++; + } + + // create register input corresponding to the register "saved" +#ifndef DUPLICATE_CKT_DEBUG + pObjSavedLi = Aig_ObjCreatePo( pNew, pObjSaveOrSaved ); + nRegCount++; + liCreated++; + + pObjAndAcc = NULL; + + // create the family of shadow registers, then create the cascade of Xnor and And gates for the comparator + Saig_ManForEachLo( p, pObj, i ) + { + pObjShadowLo = Aig_ObjCreatePi( pNew ); + +#ifdef PROPAGATE_NAMES + Vec_PtrPush( vecLos, pObjShadowLo ); + nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ) ) + 10 ); + sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "SHADOW" ); + Vec_PtrPush( vecLoNames, nodeName ); +#endif + + pObjShadowLiDriver = Aig_Mux( pNew, pObjSavePi, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); + pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver ); + nRegCount++; + loCreated++; liCreated++; + + pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); + pObjXnor = Aig_Not( pObjXor ); + if( pObjAndAcc == NULL ) + pObjAndAcc = pObjXnor; + else + { + pObjAndAccDummy = pObjAndAcc; + pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAccDummy ); + } + } + + // create the AND gate whose output will be the signal "looped" + pObjSavedLoAndEquality = Aig_And( pNew, pObjSavedLo, pObjAndAcc ); + + // create the master AND gate and corresponding AND and OR logic for the liveness properties + pObjAndAcc = NULL; + if( vLive == NULL || Vec_PtrSize( vLive ) == 0 ) + printf("\nCircuit without any liveness property\n"); + else + { + Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i ) + { + //assert( Aig_ObjIsNode( Aig_ObjChild0( pObj ) ) ); + //Aig_ObjPrint( pNew, pObj ); + liveLatch++; + pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); + pObjShadowLo = Aig_ObjCreatePi( pNew ); + +#ifdef PROPAGATE_NAMES + Vec_PtrPush( vecLos, pObjShadowLo ); + nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); + sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "LIVENESS" ); + Vec_PtrPush( vecLoNames, nodeName ); +#endif + + pObjShadowLiDriver = Aig_Or( pNew, Aig_Mux(pNew, pObjSavePi, Aig_Not(Aig_ManConst1(pNew)), pObjShadowLo), + Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) ); + pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver ); + nRegCount++; + loCreated++; liCreated++; + + if( pObjAndAcc == NULL ) + pObjAndAcc = pObjShadowLo; + else + { + pObjAndAccDummy = pObjAndAcc; + pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAccDummy ); + } + } + } + + if( pObjAndAcc != NULL ) + pObjLive = pObjAndAcc; + else + pObjLive = Aig_ManConst1( pNew ); + + // create the master AND gate and corresponding AND and OR logic for the fairness properties + pObjAndAcc = NULL; + if( vFair == NULL || Vec_PtrSize( vFair ) == 0 ) + printf("\nCircuit without any fairness property\n"); + else + { + Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i ) + { + fairLatch++; + //assert( Aig_ObjIsNode( Aig_ObjChild0( pObj ) ) ); + pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); + pObjShadowLo = Aig_ObjCreatePi( pNew ); + +#ifdef PROPAGATE_NAMES + Vec_PtrPush( vecLos, pObjShadowLo ); + nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); + sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "FAIRNESS" ); + Vec_PtrPush( vecLoNames, nodeName ); +#endif + + pObjShadowLiDriver = Aig_Or( pNew, Aig_Mux(pNew, pObjSavePi, Aig_Not(Aig_ManConst1(pNew)), pObjShadowLo), + Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) ); + pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver ); + nRegCount++; + loCreated++; liCreated++; + + if( pObjAndAcc == NULL ) + pObjAndAcc = pObjShadowLo; + else + { + pObjAndAccDummy = pObjAndAcc; + pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAccDummy ); + } + } + } + + if( pObjAndAcc != NULL ) + pObjFair = pObjAndAcc; + else + pObjFair = Aig_ManConst1( pNew ); + + //pObjSafetyGate = Aig_Exor( pNew, Aig_Not(Aig_ManConst1( pNew )), Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ) ); + pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ); + + Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate ); +#endif + + Aig_ManSetRegNum( pNew, nRegCount ); + + Aig_ManPiCleanupBiere( pNew ); + Aig_ManPoCleanupBiere( pNew ); + + Aig_ManCleanup( pNew ); + assert( Aig_ManCheck( pNew ) ); + +#ifndef DUPLICATE_CKT_DEBUG + assert((Aig_Obj_t *)Vec_PtrEntry(pNew->vPos, Saig_ManPoNum(pNew)+Aig_ObjPioNum(pObjSavedLo)-Saig_ManPiNum(p)-1) == pObjSavedLi); + assert( Saig_ManPoNum( pNew ) == 1 ); + assert( Saig_ManPiNum( p ) + 1 == Saig_ManPiNum( pNew ) ); + assert( Saig_ManRegNum( pNew ) == Saig_ManRegNum( p ) * 2 + 1 + liveLatch + fairLatch ); +#endif + + return pNew; +} + + +static Aig_Man_t * LivenessToSafetyTransformationOneStepLoopSim( Abc_Ntk_t * pNtk, Aig_Man_t * p, Vec_Ptr_t *vLive, Vec_Ptr_t *vFair ) +{ + Aig_Man_t * pNew; + int i, nRegCount; + Aig_Obj_t * pObjSavePi; + Aig_Obj_t *pObj, *pMatch; + Aig_Obj_t *pObjSavedLoAndEquality; + Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc, *pObjAndAccDummy; + Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate; + Aig_Obj_t *pObjSafetyPropertyOutput; + Aig_Obj_t *pDriverImage; + Aig_Obj_t *pObjCorrespondingLi; + + + char *nodeName; + int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, piVecIndex = 0; + + vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); + vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); + + vecLos = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); + vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); + + //**************************************************************** + // Step1: create the new manager + // Note: The new manager is created with "2 * Aig_ManObjNumMax(p)" + // nodes, but this selection is arbitrary - need to be justified + //**************************************************************** + pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( "live2safe" ); + pNew->pSpec = NULL; + + //**************************************************************** + // Step 2: map constant nodes + //**************************************************************** + pObj = Aig_ManConst1( p ); + pObj->pData = Aig_ManConst1( pNew ); + + //**************************************************************** + // Step 3: create true PIs + //**************************************************************** + Saig_ManForEachPi( p, pObj, i ) + { + piCopied++; + pObj->pData = Aig_ObjCreatePi(pNew); + Vec_PtrPush( vecPis, pObj->pData ); + nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) )); + Vec_PtrPush( vecPiNames, nodeName ); + } + + //**************************************************************** + // Step 4: create the special Pi corresponding to SAVE + //**************************************************************** + pObjSavePi = Aig_ObjCreatePi( pNew ); + nodeName = "SAVE_BIERE", + Vec_PtrPush( vecPiNames, nodeName ); + + //**************************************************************** + // Step 5: create register outputs + //**************************************************************** + Saig_ManForEachLo( p, pObj, i ) + { + loCopied++; + pObj->pData = Aig_ObjCreatePi(pNew); + Vec_PtrPush( vecLos, pObj->pData ); + nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) )); + Vec_PtrPush( vecLoNames, nodeName ); + } + + //**************************************************************** + // Step 6: create "saved" register output + //**************************************************************** + +#if 0 + loCreated++; + pObjSavedLo = Aig_ObjCreatePi( pNew ); + Vec_PtrPush( vecLos, pObjSavedLo ); + nodeName = "SAVED_LO"; + Vec_PtrPush( vecLoNames, nodeName ); +#endif + + //**************************************************************** + // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi + //**************************************************************** +#if 0 + pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo ); + pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) ); +#endif + + //******************************************************************** + // Step 8: create internal nodes + //******************************************************************** + Aig_ManForEachNode( p, pObj, i ) + { + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + } + + //******************************************************************** + // Step 9: create the safety property output gate + // create the safety property output gate, this will be the sole true PO + // of the whole circuit, discuss with Sat/Alan for an alternative implementation + //******************************************************************** + + pObjSafetyPropertyOutput = Aig_ObjCreatePo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData ); + + // create register inputs for the original registers + nRegCount = 0; + + Saig_ManForEachLo( p, pObj, i ) + { + pMatch = Saig_ObjLoToLi( p, pObj ); + //Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pMatch) ); + Aig_ObjCreatePo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) ); + nRegCount++; + liCopied++; + } + +#if 0 + // create register input corresponding to the register "saved" + pObjSavedLi = Aig_ObjCreatePo( pNew, pObjSaveOrSaved ); + nRegCount++; + liCreated++; +#endif + + pObjAndAcc = NULL; + + //**************************************************************************************************** + //For detection of loop of length 1 we do not need any shadow register, we only need equality detector + //between Lo_j and Li_j and then a cascade of AND gates + //**************************************************************************************************** + + Saig_ManForEachLo( p, pObj, i ) + { + pObjCorrespondingLi = Saig_ObjLoToLi( p, pObj ); + + pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0( pObjCorrespondingLi )->pData, Aig_ObjFaninC0( pObjCorrespondingLi ) ) ); + pObjXnor = Aig_Not( pObjXor ); + + if( pObjAndAcc == NULL ) + pObjAndAcc = pObjXnor; + else + { + pObjAndAccDummy = pObjAndAcc; + pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAccDummy ); + } + } + + // create the AND gate whose output will be the signal "looped" + pObjSavedLoAndEquality = Aig_And( pNew, pObjSavePi, pObjAndAcc ); + + // create the master AND gate and corresponding AND and OR logic for the liveness properties + pObjAndAcc = NULL; + if( vLive == NULL || Vec_PtrSize( vLive ) == 0 ) + printf("\nCircuit without any liveness property\n"); + else + { + Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i ) + { + pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); + if( pObjAndAcc == NULL ) + pObjAndAcc = pDriverImage; + else + { + pObjAndAccDummy = pObjAndAcc; + pObjAndAcc = Aig_And( pNew, pDriverImage, pObjAndAccDummy ); + } + } + } + + if( pObjAndAcc != NULL ) + pObjLive = pObjAndAcc; + else + pObjLive = Aig_ManConst1( pNew ); + + // create the master AND gate and corresponding AND and OR logic for the fairness properties + pObjAndAcc = NULL; + if( vFair == NULL || Vec_PtrSize( vFair ) == 0 ) + printf("\nCircuit without any fairness property\n"); + else + { + Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i ) + { + pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); + if( pObjAndAcc == NULL ) + pObjAndAcc = pDriverImage; + else + { + pObjAndAccDummy = pObjAndAcc; + pObjAndAcc = Aig_And( pNew, pDriverImage, pObjAndAccDummy ); + } + } + } + + if( pObjAndAcc != NULL ) + pObjFair = pObjAndAcc; + else + pObjFair = Aig_ManConst1( pNew ); + + pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ); + + Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate ); + + Aig_ManSetRegNum( pNew, nRegCount ); + + printf("\nSaig_ManPiNum = %d, Reg Num = %d, before everything, before Pi cleanup\n", Vec_PtrSize( pNew->vPis ), pNew->nRegs ); + + Aig_ManPiCleanupBiere( pNew ); + Aig_ManPoCleanupBiere( pNew ); + + Aig_ManCleanup( pNew ); + + assert( Aig_ManCheck( pNew ) ); + + return pNew; +} + + + +static Vec_Ptr_t * populateLivenessVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig ) +{ + Abc_Obj_t * pNode; + int i, liveCounter = 0; + Vec_Ptr_t * vLive; + + vLive = Vec_PtrAlloc( 100 ); + Abc_NtkForEachPo( pNtk, pNode, i ) + if( strstr( Abc_ObjName( pNode ), "assert_fair") != NULL ) + { + Vec_PtrPush( vLive, Aig_ManPo( pAig, i ) ); + liveCounter++; + } + printf("\nNumber of liveness property found = %d\n", liveCounter); + return vLive; +} + +static Vec_Ptr_t * populateFairnessVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig ) +{ + Abc_Obj_t * pNode; + int i, fairCounter = 0; + Vec_Ptr_t * vFair; + + vFair = Vec_PtrAlloc( 100 ); + Abc_NtkForEachPo( pNtk, pNode, i ) + if( strstr( Abc_ObjName( pNode ), "assume_fair") != NULL ) + { + Vec_PtrPush( vFair, Aig_ManPo( pAig, i ) ); + fairCounter++; + } + printf("\nNumber of fairness property found = %d\n", fairCounter); + return vFair; +} + +static void updateNewNetworkNameManager( Abc_Ntk_t *pNtk, Aig_Man_t *pAig, Vec_Ptr_t *vPiNames, Vec_Ptr_t *vLoNames ) +{ + Aig_Obj_t *pObj; + int i, ntkObjId; + + pNtk->pManName = Nm_ManCreate( Abc_NtkCiNum( pNtk ) ); + + Saig_ManForEachPi( pAig, pObj, i ) + { + ntkObjId = Abc_NtkCi( pNtk, i )->Id; + //printf("Pi %d, Saved Name = %s, id = %d\n", i, Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), Vec_PtrEntry(vPiNames, i), NULL ), ntkObjId); + Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), (char *)Vec_PtrEntry(vPiNames, i), NULL ); + } + Saig_ManForEachLo( pAig, pObj, i ) + { + ntkObjId = Abc_NtkCi( pNtk, Saig_ManPiNum( pAig ) + i )->Id; + //printf("Lo %d, Saved name = %s, id = %d\n", i, Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), Vec_PtrEntry(vLoNames, i), NULL ), ntkObjId); + Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), (char *)Vec_PtrEntry(vLoNames, i), NULL ); + } +} + + +int Abc_CommandAbcLivenessToSafetySim( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkTemp, *pNtkNew, *pNtkOld; + Aig_Man_t * pAig, *pAigNew; + int c; + Vec_Ptr_t * vLive, * vFair; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if( !Abc_NtkIsStrash( pNtk ) ) + { + printf("\nThe input network was not strashed, strashing....\n"); + pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); + pNtkOld = pNtkTemp; + pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); + vLive = populateLivenessVector( pNtk, pAig ); + vFair = populateFairnessVector( pNtk, pAig ); + } + else + { + pAig = Abc_NtkToDar( pNtk, 0, 1 ); + pNtkOld = pNtk; + vLive = populateLivenessVector( pNtk, pAig ); + vFair = populateFairnessVector( pNtk, pAig ); + } + +#if 0 + Aig_ManPrintStats( pAig ); + printf("\nDetail statistics*************************************\n"); + printf("Number of true primary inputs = %d\n", Saig_ManPiNum( pAig )); + printf("Number of true primary outputs = %d\n", Saig_ManPoNum( pAig )); + printf("Number of true latch outputs = %d\n", Saig_ManCiNum( pAig ) - Saig_ManPiNum( pAig )); + printf("Number of true latch inputs = %d\n", Saig_ManCoNum( pAig ) - Saig_ManPoNum( pAig )); + printf("Numer of registers = %d\n", Saig_ManRegNum( pAig ) ); + printf("\n*******************************************************\n"); +#endif + + c = Extra_UtilGetopt( argc, argv, "1" ); + if( c == '1' ) + pAigNew = LivenessToSafetyTransformationOneStepLoopSim( pNtk, pAig, vLive, vFair ); + else + pAigNew = LivenessToSafetyTransformationSim( pNtk, pAig, vLive, vFair ); + +#if 0 + Aig_ManPrintStats( pAigNew ); + printf("\nDetail statistics*************************************\n"); + printf("Number of true primary inputs = %d\n", Saig_ManPiNum( pAigNew )); + printf("Number of true primary outputs = %d\n", Saig_ManPoNum( pAigNew )); + printf("Number of true latch outputs = %d\n", Saig_ManCiNum( pAigNew ) - Saig_ManPiNum( pAigNew )); + printf("Number of true latch inputs = %d\n", Saig_ManCoNum( pAigNew ) - Saig_ManPoNum( pAigNew )); + printf("Numer of registers = %d\n", Saig_ManRegNum( pAigNew ) ); + printf("\n*******************************************************\n"); +#endif + + pNtkNew = Abc_NtkFromAigPhase( pAigNew ); + + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" ); + + updateNewNetworkNameManager( pNtkNew, pAigNew, vecPiNames,vecLoNames ); + Abc_FrameSetCurrentNetwork( pAbc, pNtkNew ); + + //Saig_ManForEachPi( pAigNew, pObj, i ) + // printf("Name of %d-th Pi = %s\n", i, retrieveTruePiName( pNtk, pAig, pAigNew, pObj ) ); + + //Saig_ManForEachLo( pAigNew, pObj, i ) + // printf("Name of %d-th Lo = %s\n", i, retrieveLOName( pNtk, pAig, pAigNew, pObj, vLive, vFair ) ); + + //printVecPtrOfString( vecPiNames ); + //printVecPtrOfString( vecLoNames ); + +#if 0 +#ifndef DUPLICATE_CKT_DEBUG + Saig_ManForEachPi( pAigNew, pObj, i ) + assert( strcmp( (char *)Vec_PtrEntry(vecPiNames, i), retrieveTruePiName( pNtk, pAig, pAigNew, pObj ) ) == 0 ); + //printf("Name of %d-th Pi = %s, %s\n", i, retrieveTruePiName( pNtk, pAig, pAigNew, pObj ), (char *)Vec_PtrEntry(vecPiNames, i) ); + + Saig_ManForEachLo( pAigNew, pObj, i ) + assert( strcmp( (char *)Vec_PtrEntry(vecLoNames, i), retrieveLOName( pNtk, pAig, pAigNew, pObj, vLive, vFair ) ) == 0 ); +#endif +#endif + + return 0; + +} +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/live/ltl_parser.c b/src/proof/live/ltl_parser.c new file mode 100644 index 00000000..5572611f --- /dev/null +++ b/src/proof/live/ltl_parser.c @@ -0,0 +1,839 @@ +/**CFile**************************************************************** + + FileName [ltl_parser.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Liveness property checking.] + + Synopsis [LTL checker.] + + Author [Sayak Ray] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 1, 2009.] + + Revision [$Id: ltl_parser.c,v 1.00 2009/01/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include +#include +#include +#include "src/aig/aig/aig.h" +#include "src/base/abc/abc.h" +#include "src/base/main/mainInt.h" + +ABC_NAMESPACE_IMPL_START + + +enum ltlToken { AND, OR, NOT, IMPLY, GLOBALLY, EVENTUALLY, NEXT, UNTIL, BOOL }; +enum ltlGrammerToken { OPERAND, LTL, BINOP, UOP }; +typedef enum ltlToken tokenType; +typedef enum ltlGrammerToken ltlGrammerTokenType; + +struct ltlNode_t +{ + tokenType type; + char *name; + Aig_Obj_t *pObj; + struct ltlNode_t *left; + struct ltlNode_t *right; +}; + +typedef struct ltlNode_t ltlNode; + +ltlNode *generateTypedNode( tokenType new_type ) +//void generateTypedNode( ltlNode *new_node, tokenType new_type ) +{ + ltlNode *new_node; + + new_node = (ltlNode *)malloc( sizeof(ltlNode) ); + if( new_node ) + { + new_node->type = new_type; + new_node->pObj = NULL; + new_node->name = NULL; + new_node->left = NULL; + new_node->right = NULL; + } + + return new_node; +} + +Aig_Obj_t *buildLogicFromLTLNode_combinationalOnly( Aig_Man_t *pAig, ltlNode *pLtlNode ); + +static inline int isNotVarNameSymbol( char c ) +{ + return ( c == ' ' || c == '\t' || c == '\n' || c == ':' || c == '\0' ); +} + +void Abc_FrameCopyLTLDataBase( Abc_Frame_t *pAbc, Abc_Ntk_t * pNtk ) +{ + char *pLtlFormula, *tempFormula; + int i; + + if( pAbc->vLTLProperties_global != NULL ) + { +// printf("Deleting exisitng LTL database from the frame\n"); + Vec_PtrFree( pAbc->vLTLProperties_global ); + pAbc->vLTLProperties_global = NULL; + } + pAbc->vLTLProperties_global = Vec_PtrAlloc(Vec_PtrSize(pNtk->vLtlProperties)); + Vec_PtrForEachEntry( char *, pNtk->vLtlProperties, pLtlFormula, i ) + { + tempFormula = (char *)malloc( sizeof(char)*(strlen(pLtlFormula)+1) ); + sprintf( tempFormula, "%s", pLtlFormula ); + Vec_PtrPush( pAbc->vLTLProperties_global, tempFormula ); + } +} + +char *getVarName( char *suffixFormula, int startLoc, int *endLocation ) +{ + int i = startLoc, length; + char *name; + + if( isNotVarNameSymbol( suffixFormula[startLoc] ) ) + return NULL; + + while( !isNotVarNameSymbol( suffixFormula[i] ) ) + i++; + *endLocation = i; + length = i - startLoc; + name = (char *)malloc( sizeof(char) * (length + 1)); + for( i=0; i= (int)strlen( formula ) ) + { + printf("\nInvalid LTL formula: unexpected end of string..." ); + return 1; + } + return 0; +} + +int isTemporalOperator( char *formula, int index ) +{ + if( !(isUnexpectedEOS( formula, index ) || formula[ index ] == 'G' || formula[ index ] == 'F' || formula[ index ] == 'U' || formula[ index ] == 'X') ) + { + printf("\nInvalid LTL formula: expecting temporal operator at the position %d....\n", index); + return 0; + } + return 1; +} + +ltlNode *readLtlFormula( char *formula ) +{ + char ch; + char *varName; + int formulaLength, rememberEnd; + int i = startOfSuffixString; + ltlNode *curr_node, *temp_node_left, *temp_node_right; + char prevChar; + + formulaLength = strlen( formula ); + if( isUnexpectedEOS( formula, startOfSuffixString ) ) + { + printf("\nFAULTING POINT: formula = %s\nstartOfSuffixString = %d, formula[%d] = %c\n\n", formula, startOfSuffixString, startOfSuffixString - 1, formula[startOfSuffixString-1]); + return NULL; + } + + while( i < formulaLength ) + { + ch = formula[i]; + + switch(ch){ + case ' ': + case '\n': + case '\r': + case '\t': + case '\v': + case '\f': + i++; + startOfSuffixString = i; + break; + case ':': + i++; + if( !isTemporalOperator( formula, i ) ) + return NULL; + startOfSuffixString = i; + break; + case 'G': + prevChar = formula[i-1]; + if( prevChar == ':' ) //i.e. 'G' is a temporal operator + { + i++; + startOfSuffixString = i; + temp_node_left = readLtlFormula( formula ); + if( temp_node_left == NULL ) + return NULL; + else + { + curr_node = generateTypedNode(GLOBALLY); + curr_node->left = temp_node_left; + return curr_node; + } + } + else //i.e. 'G' must be starting a variable name + { + varName = getVarName( formula, i, &rememberEnd ); + if( !varName ) + { + printf("\nInvalid LTL formula: expecting valid variable name token...aborting" ); + return NULL; + } + curr_node = generateTypedNode(BOOL); + curr_node->name = varName; + i = rememberEnd; + startOfSuffixString = i; + return curr_node; + } + case 'F': + prevChar = formula[i-1]; + if( prevChar == ':' ) //i.e. 'F' is a temporal operator + { + i++; + startOfSuffixString = i; + temp_node_left = readLtlFormula( formula ); + if( temp_node_left == NULL ) + return NULL; + else + { + curr_node = generateTypedNode(EVENTUALLY); + curr_node->left = temp_node_left; + return curr_node; + } + } + else //i.e. 'F' must be starting a variable name + { + varName = getVarName( formula, i, &rememberEnd ); + if( !varName ) + { + printf("\nInvalid LTL formula: expecting valid variable name token...aborting" ); + return NULL; + } + curr_node = generateTypedNode(BOOL); + curr_node->name = varName; + i = rememberEnd; + startOfSuffixString = i; + return curr_node; + } + case 'X': + prevChar = formula[i-1]; + if( prevChar == ':' ) //i.e. 'X' is a temporal operator + { + i++; + startOfSuffixString = i; + temp_node_left = readLtlFormula( formula ); + if( temp_node_left == NULL ) + return NULL; + else + { + curr_node = generateTypedNode(NEXT); + curr_node->left = temp_node_left; + return curr_node; + } + } + else //i.e. 'X' must be starting a variable name + { + varName = getVarName( formula, i, &rememberEnd ); + if( !varName ) + { + printf("\nInvalid LTL formula: expecting valid variable name token...aborting" ); + return NULL; + } + curr_node = generateTypedNode(BOOL); + curr_node->name = varName; + i = rememberEnd; + startOfSuffixString = i; + return curr_node; + } + case 'U': + prevChar = formula[i-1]; + if( prevChar == ':' ) //i.e. 'X' is a temporal operator + { + i++; + startOfSuffixString = i; + temp_node_left = readLtlFormula( formula ); + if( temp_node_left == NULL ) + return NULL; + temp_node_right = readLtlFormula( formula ); + if( temp_node_right == NULL ) + { + //need to do memory management: if right subtree is NULL then left + //subtree must be freed. + return NULL; + } + curr_node = generateTypedNode(UNTIL); + curr_node->left = temp_node_left; + curr_node->right = temp_node_right; + return curr_node; + } + else //i.e. 'U' must be starting a variable name + { + varName = getVarName( formula, i, &rememberEnd ); + if( !varName ) + { + printf("\nInvalid LTL formula: expecting valid variable name token...aborting" ); + return NULL; + } + curr_node = generateTypedNode(BOOL); + curr_node->name = varName; + i = rememberEnd; + startOfSuffixString = i; + return curr_node; + } + case '+': + i++; + startOfSuffixString = i; + temp_node_left = readLtlFormula( formula ); + if( temp_node_left == NULL ) + return NULL; + temp_node_right = readLtlFormula( formula ); + if( temp_node_right == NULL ) + { + //need to do memory management: if right subtree is NULL then left + //subtree must be freed. + return NULL; + } + curr_node = generateTypedNode(OR); + curr_node->left = temp_node_left; + curr_node->right = temp_node_right; + return curr_node; + case '&': + i++; + startOfSuffixString = i; + temp_node_left = readLtlFormula( formula ); + if( temp_node_left == NULL ) + return NULL; + temp_node_right = readLtlFormula( formula ); + if( temp_node_right == NULL ) + { + //need to do memory management: if right subtree is NULL then left + //subtree must be freed. + return NULL; + } + curr_node = generateTypedNode(AND); + curr_node->left = temp_node_left; + curr_node->right = temp_node_right; + return curr_node; + case '!': + i++; + startOfSuffixString = i; + temp_node_left = readLtlFormula( formula ); + if( temp_node_left == NULL ) + return NULL; + else + { + curr_node = generateTypedNode(NOT); + curr_node->left = temp_node_left; + return curr_node; + } + default: + varName = getVarName( formula, i, &rememberEnd ); + if( !varName ) + { + printf("\nInvalid LTL formula: expecting valid variable name token...aborting" ); + return NULL; + } + curr_node = generateTypedNode(BOOL); + curr_node->name = varName; + i = rememberEnd; + startOfSuffixString = i; + return curr_node; + } + } + return NULL; +} + +void resetGlobalVar() +{ + startOfSuffixString = 0; +} + +ltlNode *parseFormulaCreateAST( char *inputFormula ) +{ + ltlNode *temp; + + temp = readLtlFormula( inputFormula ); + //if( temp == NULL ) + // printf("\nAST creation failed for formula %s", inputFormula ); + resetGlobalVar(); + return temp; +} + +void traverseAbstractSyntaxTree( ltlNode *node ) +{ + switch(node->type){ + case( AND ): + printf("& "); + assert( node->left != NULL ); + assert( node->right != NULL ); + traverseAbstractSyntaxTree( node->left ); + traverseAbstractSyntaxTree( node->right ); + return; + case( OR ): + printf("+ "); + assert( node->left != NULL ); + assert( node->right != NULL ); + traverseAbstractSyntaxTree( node->left ); + traverseAbstractSyntaxTree( node->right ); + return; + case( NOT ): + printf("~ "); + assert( node->left != NULL ); + traverseAbstractSyntaxTree( node->left ); + assert( node->right == NULL ); + return; + case( GLOBALLY ): + printf("G "); + assert( node->left != NULL ); + traverseAbstractSyntaxTree( node->left ); + assert( node->right == NULL ); + return; + case( EVENTUALLY ): + printf("F "); + assert( node->left != NULL ); + traverseAbstractSyntaxTree( node->left ); + assert( node->right == NULL ); + return; + case( NEXT ): + printf("X "); + assert( node->left != NULL ); + traverseAbstractSyntaxTree( node->left ); + assert( node->right == NULL ); + return; + case( UNTIL ): + printf("U "); + assert( node->left != NULL ); + assert( node->right != NULL ); + traverseAbstractSyntaxTree( node->left ); + traverseAbstractSyntaxTree( node->right ); + return; + case( BOOL ): + printf("%s ", node->name); + assert( node->left == NULL ); + assert( node->right == NULL ); + return; + default: + printf("\nUnsupported token type: Exiting execution\n"); + exit(0); + } +} + +void traverseAbstractSyntaxTree_postFix( ltlNode *node ) +{ + switch(node->type){ + case( AND ): + printf("( "); + assert( node->left != NULL ); + assert( node->right != NULL ); + traverseAbstractSyntaxTree_postFix( node->left ); + printf("& "); + traverseAbstractSyntaxTree_postFix( node->right ); + printf(") "); + return; + case( OR ): + printf("( "); + assert( node->left != NULL ); + assert( node->right != NULL ); + traverseAbstractSyntaxTree_postFix( node->left ); + printf("+ "); + traverseAbstractSyntaxTree_postFix( node->right ); + printf(") "); + return; + case( NOT ): + printf("~ "); + assert( node->left != NULL ); + traverseAbstractSyntaxTree_postFix( node->left ); + assert( node->right == NULL ); + return; + case( GLOBALLY ): + printf("G "); + //printf("( "); + assert( node->left != NULL ); + traverseAbstractSyntaxTree_postFix( node->left ); + assert( node->right == NULL ); + //printf(") "); + return; + case( EVENTUALLY ): + printf("F "); + //printf("( "); + assert( node->left != NULL ); + traverseAbstractSyntaxTree_postFix( node->left ); + assert( node->right == NULL ); + //printf(") "); + return; + case( NEXT ): + printf("X "); + assert( node->left != NULL ); + traverseAbstractSyntaxTree_postFix( node->left ); + assert( node->right == NULL ); + return; + case( UNTIL ): + printf("( "); + assert( node->left != NULL ); + assert( node->right != NULL ); + traverseAbstractSyntaxTree_postFix( node->left ); + printf("U "); + traverseAbstractSyntaxTree_postFix( node->right ); + printf(") "); + return; + case( BOOL ): + printf("%s ", node->name); + assert( node->left == NULL ); + assert( node->right == NULL ); + return; + default: + printf("\nUnsupported token type: Exiting execution\n"); + exit(0); + } +} + +void populateAigPointerUnitGF( Aig_Man_t *pAigNew, ltlNode *topASTNode, Vec_Ptr_t *vSignal, Vec_Vec_t *vAigGFMap ) +{ + ltlNode *nextNode, *nextToNextNode; + int serialNumSignal; + + switch( topASTNode->type ){ + case AND: + case OR: + case IMPLY: + populateAigPointerUnitGF( pAigNew, topASTNode->left, vSignal, vAigGFMap ); + populateAigPointerUnitGF( pAigNew, topASTNode->right, vSignal, vAigGFMap ); + return; + case NOT: + populateAigPointerUnitGF( pAigNew, topASTNode->left, vSignal, vAigGFMap ); + return; + case GLOBALLY: + nextNode = topASTNode->left; + assert( nextNode->type = EVENTUALLY ); + nextToNextNode = nextNode->left; + if( nextToNextNode->type == BOOL ) + { + assert( nextToNextNode->pObj ); + serialNumSignal = Vec_PtrFind( vSignal, nextToNextNode->pObj ); + if( serialNumSignal == -1 ) + { + Vec_PtrPush( vSignal, nextToNextNode->pObj ); + serialNumSignal = Vec_PtrFind( vSignal, nextToNextNode->pObj ); + } + //Vec_PtrPush( vGLOBALLY, topASTNode ); + Vec_VecPush( vAigGFMap, serialNumSignal, topASTNode ); + } + else + { + assert( nextToNextNode->pObj == NULL ); + buildLogicFromLTLNode_combinationalOnly( pAigNew, nextToNextNode ); + serialNumSignal = Vec_PtrFind( vSignal, nextToNextNode->pObj ); + if( serialNumSignal == -1 ) + { + Vec_PtrPush( vSignal, nextToNextNode->pObj ); + serialNumSignal = Vec_PtrFind( vSignal, nextToNextNode->pObj ); + } + //Vec_PtrPush( vGLOBALLY, topASTNode ); + Vec_VecPush( vAigGFMap, serialNumSignal, topASTNode ); + } + return; + case BOOL: + return; + default: + printf("\nINVALID situation: aborting...\n"); + exit(0); + } +} + +Aig_Obj_t *buildLogicFromLTLNode_combinationalOnly( Aig_Man_t *pAigNew, ltlNode *pLtlNode ) +{ + Aig_Obj_t *leftAigObj, *rightAigObj; + + if( pLtlNode->pObj != NULL ) + return pLtlNode->pObj; + else + { + assert( pLtlNode->type != BOOL ); + switch( pLtlNode->type ){ + case AND: + assert( pLtlNode->left ); assert( pLtlNode->right ); + leftAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->left ); + rightAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->right ); + assert( leftAigObj ); assert( rightAigObj ); + pLtlNode->pObj = Aig_And( pAigNew, leftAigObj, rightAigObj ); + return pLtlNode->pObj; + case OR: + assert( pLtlNode->left ); assert( pLtlNode->right ); + leftAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->left ); + rightAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->right ); + assert( leftAigObj ); assert( rightAigObj ); + pLtlNode->pObj = Aig_Or( pAigNew, leftAigObj, rightAigObj ); + return pLtlNode->pObj; + case NOT: + assert( pLtlNode->left ); assert( pLtlNode->right == NULL ); + leftAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->left ); + assert( leftAigObj ); + pLtlNode->pObj = Aig_Not( leftAigObj ); + return pLtlNode->pObj; + case GLOBALLY: + case EVENTUALLY: + case NEXT: + case UNTIL: + printf("FORBIDDEN node: ABORTING!!\n"); + exit(0); + default: + printf("\nSerious ERROR: attempting to create AIG node from a temporal node\n"); + exit(0); + } + } +} + +Aig_Obj_t *buildLogicFromLTLNode( Aig_Man_t *pAig, ltlNode *pLtlNode ) +{ + Aig_Obj_t *leftAigObj, *rightAigObj; + + if( pLtlNode->pObj != NULL ) + return pLtlNode->pObj; + else + { + assert( pLtlNode->type != BOOL ); + switch( pLtlNode->type ){ + case AND: + assert( pLtlNode->left ); assert( pLtlNode->right ); + leftAigObj = buildLogicFromLTLNode( pAig, pLtlNode->left ); + rightAigObj = buildLogicFromLTLNode( pAig, pLtlNode->right ); + assert( leftAigObj ); assert( rightAigObj ); + pLtlNode->pObj = Aig_And( pAig, leftAigObj, rightAigObj ); + return pLtlNode->pObj; + case OR: + assert( pLtlNode->left ); assert( pLtlNode->right ); + leftAigObj = buildLogicFromLTLNode( pAig, pLtlNode->left ); + rightAigObj = buildLogicFromLTLNode( pAig, pLtlNode->right ); + assert( leftAigObj ); assert( rightAigObj ); + pLtlNode->pObj = Aig_Or( pAig, leftAigObj, rightAigObj ); + return pLtlNode->pObj; + case NOT: + assert( pLtlNode->left ); assert( pLtlNode->right == NULL ); + leftAigObj = buildLogicFromLTLNode( pAig, pLtlNode->left ); + assert( leftAigObj ); + pLtlNode->pObj = Aig_Not( leftAigObj ); + return pLtlNode->pObj; + case GLOBALLY: + case EVENTUALLY: + case NEXT: + case UNTIL: + printf("\nAttempting to create circuit with missing AIG pointer in a TEMPORAL node: ABORTING!!\n"); + exit(0); + default: + printf("\nSerious ERROR: attempting to create AIG node from a temporal node\n"); + exit(0); + } + } +} + +int isNonTemporalSubformula( ltlNode *topNode ) +{ + switch( topNode->type ){ + case AND: + case OR: + case IMPLY: + return isNonTemporalSubformula( topNode->left) && isNonTemporalSubformula( topNode->right ) ; + case NOT: + assert( topNode->right == NULL ); + return isNonTemporalSubformula( topNode->left ); + case BOOL: + return 1; + default: + return 0; + } +} + +int isWellFormed( ltlNode *topNode ) +{ + ltlNode *nextNode; + + switch( topNode->type ){ + case AND: + case OR: + case IMPLY: + return isWellFormed( topNode->left) && isWellFormed( topNode->right ) ; + case NOT: + assert( topNode->right == NULL ); + return isWellFormed( topNode->left ); + case BOOL: + return 1; + case GLOBALLY: + nextNode = topNode->left; + assert( topNode->right == NULL ); + if( nextNode->type != EVENTUALLY ) + return 0; + else + { + assert( nextNode->right == NULL ); + return isNonTemporalSubformula( nextNode->left ); + } + default: + return 0; + } +} + +int checkBooleanConstant( char *targetName ) +{ + if( strcmp( targetName, "true" ) == 0 ) + return 1; + if( strcmp( targetName, "false" ) == 0 ) + return 0; + return -1; +} + +int checkSignalNameExistence( Abc_Ntk_t *pNtk, ltlNode *topASTNode ) +{ + char *targetName; + Abc_Obj_t * pNode; + int i; + + switch( topASTNode->type ){ + case BOOL: + targetName = topASTNode->name; + //printf("\nTrying to match name %s\n", targetName); + if( checkBooleanConstant( targetName ) != -1 ) + return 1; + Abc_NtkForEachPo( pNtk, pNode, i ) + { + if( strcmp( Abc_ObjName( pNode ), targetName ) == 0 ) + { + //printf("\nVariable name \"%s\" MATCHED\n", targetName); + return 1; + } + } + printf("\nVariable name \"%s\" not found in the PO name list\n", targetName); + return 0; + case AND: + case OR: + case IMPLY: + case UNTIL: + assert( topASTNode->left != NULL ); + assert( topASTNode->right != NULL ); + return checkSignalNameExistence( pNtk, topASTNode->left ) && checkSignalNameExistence( pNtk, topASTNode->right ); + + case NOT: + case NEXT: + case GLOBALLY: + case EVENTUALLY: + assert( topASTNode->left != NULL ); + assert( topASTNode->right == NULL ); + return checkSignalNameExistence( pNtk, topASTNode->left ); + default: + printf("\nUNSUPPORTED LTL NODE TYPE:: Aborting execution\n"); + exit(0); + } +} + +void populateBoolWithAigNodePtr( Abc_Ntk_t *pNtk, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, ltlNode *topASTNode ) +{ + char *targetName; + Abc_Obj_t * pNode; + int i; + Aig_Obj_t *pObj, *pDriverImage; + + switch( topASTNode->type ){ + case BOOL: + targetName = topASTNode->name; + if( checkBooleanConstant( targetName ) == 1 ) + { + topASTNode->pObj = Aig_ManConst1( pAigNew ); + return; + } + if( checkBooleanConstant( targetName ) == 0 ) + { + topASTNode->pObj = Aig_Not(topASTNode->pObj = Aig_ManConst1( pAigNew )); + return; + } + Abc_NtkForEachPo( pNtk, pNode, i ) + if( strcmp( Abc_ObjName( pNode ), targetName ) == 0 ) + { + pObj = Aig_ManPo( pAigOld, i ); + assert( Aig_ObjIsPo( pObj )); + pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); + topASTNode->pObj = pDriverImage; + return; + } + assert(0); + case AND: + case OR: + case IMPLY: + case UNTIL: + assert( topASTNode->left != NULL ); + assert( topASTNode->right != NULL ); + populateBoolWithAigNodePtr( pNtk, pAigOld, pAigNew, topASTNode->left ); + populateBoolWithAigNodePtr( pNtk, pAigOld, pAigNew, topASTNode->right ); + return; + case NOT: + case NEXT: + case GLOBALLY: + case EVENTUALLY: + assert( topASTNode->left != NULL ); + assert( topASTNode->right == NULL ); + populateBoolWithAigNodePtr( pNtk, pAigOld, pAigNew, topASTNode->left ); + return; + default: + printf("\nUNSUPPORTED LTL NODE TYPE:: Aborting execution\n"); + exit(0); + } +} + +int checkAllBoolHaveAIGPointer( ltlNode *topASTNode ) +{ + + switch( topASTNode->type ){ + case BOOL: + if( topASTNode->pObj != NULL ) + return 1; + else + { + printf("\nfaulting PODMANDYO topASTNode->name = %s\n", topASTNode->name); + return 0; + } + case AND: + case OR: + case IMPLY: + case UNTIL: + assert( topASTNode->left != NULL ); + assert( topASTNode->right != NULL ); + return checkAllBoolHaveAIGPointer( topASTNode->left ) && checkAllBoolHaveAIGPointer( topASTNode->right ); + + case NOT: + case NEXT: + case GLOBALLY: + case EVENTUALLY: + assert( topASTNode->left != NULL ); + assert( topASTNode->right == NULL ); + return checkAllBoolHaveAIGPointer( topASTNode->left ); + default: + printf("\nUNSUPPORTED LTL NODE TYPE:: Aborting execution\n"); + exit(0); + } +} + +void setAIGNodePtrOfGloballyNode( ltlNode *astNode, Aig_Obj_t *pObjLo ) +{ + astNode->pObj = pObjLo; +} + +Aig_Obj_t *retriveAIGPointerFromLTLNode( ltlNode *astNode ) +{ + return astNode->pObj; +} + + +ABC_NAMESPACE_IMPL_END diff --git a/src/proof/live/module.make b/src/proof/live/module.make new file mode 100644 index 00000000..55c70fc8 --- /dev/null +++ b/src/proof/live/module.make @@ -0,0 +1,3 @@ +SRC += src/proof/live/liveness.c \ + src/proof/live/liveness_sim.c \ + src/proof/live/ltl_parser.c diff --git a/src/proof/llb/llb.c b/src/proof/llb/llb.c new file mode 100644 index 00000000..348c0622 --- /dev/null +++ b/src/proof/llb/llb.c @@ -0,0 +1,52 @@ +/**CFile**************************************************************** + + FileName [llb.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/llb/llb.h b/src/proof/llb/llb.h new file mode 100644 index 00000000..a9bfd891 --- /dev/null +++ b/src/proof/llb/llb.h @@ -0,0 +1,96 @@ +/**CFile**************************************************************** + + FileName [llb.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD-based reachability.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 8, 2010.] + + Revision [$Id: llb.h,v 1.00 2010/05/08 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__llb__llb_h +#define ABC__aig__llb__llb_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Gia_ParLlb_t_ Gia_ParLlb_t; +struct Gia_ParLlb_t_ +{ + int nBddMax; // maximum BDD size + int nIterMax; // maximum iteration count + int nClusterMax; // maximum cluster size + int nHintDepth; // the number of times to cofactor + int HintFirst; // the number of first hint to use + int fUseFlow; // use flow computation + int nVolumeMax; // the largest volume + int nVolumeMin; // the smallest volume + int nPartValue; // partitioning value + int fBackward; // enable backward reachability + int fReorder; // enable dynamic variable reordering + int fIndConstr; // extract inductive constraints + int fUsePivots; // use internal pivot variables + int fCluster; // use partition clustering + int fSchedule; // use cluster scheduling + int fDumpReached; // dump reached states into a file + int fVerbose; // print verbose information + int fVeryVerbose; // print dependency matrices + int fSilent; // do not print any infomation + int fSkipReach; // skip reachability (preparation phase only) + int fSkipOutCheck; // does not check the property output + int TimeLimit; // time limit for one reachability run + int TimeLimitGlo; // time limit for all reachability runs + // internal parameters + int TimeTarget; // the time to stop + int iFrame; // explored up to this frame +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== llbCore.c ==========================================================*/ +extern void Llb_ManSetDefaultParams( Gia_ParLlb_t * pPars ); +/*=== llb4Nonlin.c ==========================================================*/ +extern int Llb_Nonlin4CoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/proof/llb/llb1Cluster.c b/src/proof/llb/llb1Cluster.c new file mode 100644 index 00000000..1356e484 --- /dev/null +++ b/src/proof/llb/llb1Cluster.c @@ -0,0 +1,356 @@ +/**CFile**************************************************************** + + FileName [llb1Cluster.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Clustering algorithm.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Cluster.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManComputeCommonQuant( Llb_Mtr_t * p, int iCol1, int iCol2 ) +{ + int iVar, Weight = 0; + for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ ) + { + // count each removed variable as 2 + if ( p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 1 && p->pRowSums[iVar] == 2 ) + Weight += 2; + // count each added variale as -1 + else if ( (p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 0) || + (p->pMatrix[iCol1][iVar] == 0 && p->pMatrix[iCol2][iVar] == 1) ) + Weight--; + } + return Weight; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManComputeBestQuant( Llb_Mtr_t * p ) +{ + int i, k, WeightBest = -100000, WeightCur, RetValue = -1; + for ( i = 1; i < p->nCols-1; i++ ) + for ( k = i+1; k < p->nCols-1; k++ ) + { + if ( p->pColSums[i] == 0 || p->pColSums[i] > p->pMan->pPars->nClusterMax ) + continue; + if ( p->pColSums[k] == 0 || p->pColSums[k] > p->pMan->pPars->nClusterMax ) + continue; + + WeightCur = Llb_ManComputeCommonQuant( p, i, k ); + if ( WeightCur <= 0 ) + continue; + if ( WeightBest < WeightCur ) + { + WeightBest = WeightCur; + RetValue = (i << 16) | k; + } + } +// printf( "Choosing best quant Weight %4d\n", WeightCur ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float ** Llb_ManComputeQuant( Llb_Mtr_t * p ) +{ + float ** pCosts; + int i, k; + // alloc and clean + pCosts = (float **)Extra_ArrayAlloc( p->nCols, p->nCols, sizeof(float) ); + for ( i = 0; i < p->nCols; i++ ) + for ( k = 0; k < p->nCols; k++ ) + pCosts[i][i] = 0.0; + // fill up + for ( i = 1; i < p->nCols-1; i++ ) + for ( k = i+1; k < p->nCols-1; k++ ) + pCosts[i][k] = pCosts[k][i] = Llb_ManComputeCommonQuant( p, i, k ); + return pCosts; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Llb_ManComputeCommonAttr( Llb_Mtr_t * p, int iCol1, int iCol2 ) +{ + int iVar, CountComm = 0, CountDiff = 0; + for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ ) + { + if ( p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 1 ) + CountComm++; + else if ( p->pMatrix[iCol1][iVar] == 1 || p->pMatrix[iCol2][iVar] == 1 ) + CountDiff++; + } +/* + printf( "Attr cost for %4d and %4d: %4d %4d (%5.2f)\n", + iCol1, iCol2, + CountDiff, CountComm, + -1.0 * CountDiff / ( CountComm + CountDiff ) ); +*/ + return -1.0 * CountDiff / ( CountComm + CountDiff ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManComputeBestAttr( Llb_Mtr_t * p ) +{ + float WeightBest = -100000, WeightCur; + int i, k, RetValue = -1; + for ( i = 1; i < p->nCols-1; i++ ) + for ( k = i+1; k < p->nCols-1; k++ ) + { + if ( p->pColSums[i] == 0 || p->pColSums[i] > p->pMan->pPars->nClusterMax ) + continue; + if ( p->pColSums[k] == 0 || p->pColSums[k] > p->pMan->pPars->nClusterMax ) + continue; + WeightCur = Llb_ManComputeCommonAttr( p, i, k ); + if ( WeightBest < WeightCur ) + { + WeightBest = WeightCur; + RetValue = (i << 16) | k; + } + } + return RetValue; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float ** Llb_ManComputeAttr( Llb_Mtr_t * p ) +{ + float ** pCosts; + int i, k; + // alloc and clean + pCosts = (float **)Extra_ArrayAlloc( p->nCols, p->nCols, sizeof(float) ); + for ( i = 0; i < p->nCols; i++ ) + for ( k = 0; k < p->nCols; k++ ) + pCosts[i][i] = 0.0; + // fill up + for ( i = 1; i < p->nCols-1; i++ ) + for ( k = i+1; k < p->nCols-1; k++ ) + pCosts[i][k] = pCosts[k][i] = Llb_ManComputeCommonAttr( p, i, k ); + return pCosts; +} + + +/**Function************************************************************* + + Synopsis [Returns the number of variables that will be saved.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrCombineSelectedColumns( Llb_Mtr_t * p, int iGrp1, int iGrp2 ) +{ + int iVar; + assert( iGrp1 >= 1 && iGrp1 < p->nCols - 1 ); + assert( iGrp2 >= 1 && iGrp2 < p->nCols - 1 ); + assert( p->pColGrps[iGrp1] != NULL ); + assert( p->pColGrps[iGrp2] != NULL ); + for ( iVar = 0; iVar < p->nRows; iVar++ ) + { + if ( p->pMatrix[iGrp1][iVar] == 1 && p->pMatrix[iGrp2][iVar] == 1 ) + p->pRowSums[iVar]--; + if ( p->pMatrix[iGrp1][iVar] == 0 && p->pMatrix[iGrp2][iVar] == 1 ) + { + p->pMatrix[iGrp1][iVar] = 1; + p->pColSums[iGrp1]++; + } + if ( p->pMatrix[iGrp2][iVar] == 1 ) + p->pMatrix[iGrp2][iVar] = 0; + } + p->pColSums[iGrp2] = 0; +} + + +/**Function************************************************************* + + Synopsis [Combines one pair of columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManClusterOne( Llb_Mtr_t * p, int iCol1, int iCol2 ) +{ + int fVerbose = 0; + Llb_Grp_t * pGrp; + int iVar; + + if ( fVerbose ) + { + printf( "Combining %d and %d\n", iCol1, iCol2 ); + for ( iVar = 0; iVar < p->nRows; iVar++ ) + { + if ( p->pMatrix[iCol1][iVar] == 0 && p->pMatrix[iCol2][iVar] == 0 ) + continue; + printf( "%3d : %c%c\n", iVar, + p->pMatrix[iCol1][iVar]? '*':' ', + p->pMatrix[iCol2][iVar]? '*':' ' ); + } + } + pGrp = Llb_ManGroupsCombine( p->pColGrps[iCol1], p->pColGrps[iCol2] ); + Llb_MtrCombineSelectedColumns( p, iCol1, iCol2 ); + p->pColGrps[iCol1] = pGrp; + p->pColGrps[iCol2] = NULL; +} + +/**Function************************************************************* + + Synopsis [Removes empty columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManClusterCompress( Llb_Mtr_t * p ) +{ + int i, k = 0; + for ( i = 0; i < p->nCols; i++ ) + { + if ( p->pColGrps[i] == NULL ) + { + assert( p->pColSums[i] == 0 ); + assert( p->pMatrix[i] != NULL ); + ABC_FREE( p->pMatrix[i] ); + continue; + } + p->pMatrix[k] = p->pMatrix[i]; + p->pColGrps[k] = p->pColGrps[i]; + p->pColSums[k] = p->pColSums[i]; + k++; + } + p->nCols = k; +} + +/**Function************************************************************* + + Synopsis [Combines one pair of columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManCluster( Llb_Mtr_t * p ) +{ + int RetValue; + do + { + do { + RetValue = Llb_ManComputeBestQuant( p ); + if ( RetValue > 0 ) + Llb_ManClusterOne( p, RetValue >> 16, RetValue & 0xffff ); + } + while ( RetValue > 0 ); + + RetValue = Llb_ManComputeBestAttr( p ); + if ( RetValue > 0 ) + Llb_ManClusterOne( p, RetValue >> 16, RetValue & 0xffff ); + + Llb_MtrVerifyMatrix( p ); + } + while ( RetValue > 0 ); + + Llb_ManClusterCompress( p ); + + Llb_MtrVerifyMatrix( p ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/llb/llb1Constr.c b/src/proof/llb/llb1Constr.c new file mode 100644 index 00000000..67fb30ba --- /dev/null +++ b/src/proof/llb/llb1Constr.c @@ -0,0 +1,313 @@ +/**CFile**************************************************************** + + FileName [llb1Constr.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Computing inductive constraints.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Constr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the array of constraint candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManCountEntries( Vec_Int_t * vCands ) +{ + int i, Entry, Counter = 0; + Vec_IntForEachEntry( vCands, Entry, i ) + Counter += ((Entry == 0) || (Entry == 1)); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns the array of constraint candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManPrintEntries( Aig_Man_t * p, Vec_Int_t * vCands ) +{ + int i, Entry; + if ( vCands == NULL ) + { + printf( "There is no hints.\n" ); + return; + } + Entry = Llb_ManCountEntries(vCands); + printf( "\n*** Using %d hint%s:\n", Entry, (Entry != 1 ? "s":"") ); + Vec_IntForEachEntry( vCands, Entry, i ) + { + if ( Entry != 0 && Entry != 1 ) + continue; + printf( "%c", Entry ? '+' : '-' ); + printf( "%-6d : ", i ); + Aig_ObjPrint( p, Aig_ManObj(p, i) ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Dereference BDD nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManDerefenceBdds( Aig_Man_t * p, DdManager * dd ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachObj( p, pObj, i ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); +} + +/**Function************************************************************* + + Synopsis [Returns the array of constraint candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManComputeIndCase_rec( Aig_Man_t * p, Aig_Obj_t * pObj, DdManager * dd, Vec_Ptr_t * vBdds ) +{ + DdNode * bBdd0, * bBdd1; + DdNode * bFunc = (DdNode *)Vec_PtrEntry( vBdds, Aig_ObjId(pObj) ); + if ( bFunc != NULL ) + return bFunc; + assert( Aig_ObjIsNode(pObj) ); + bBdd0 = Llb_ManComputeIndCase_rec( p, Aig_ObjFanin0(pObj), dd, vBdds ); + bBdd1 = Llb_ManComputeIndCase_rec( p, Aig_ObjFanin1(pObj), dd, vBdds ); + bBdd0 = Cudd_NotCond( bBdd0, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( bBdd1, Aig_ObjFaninC1(pObj) ); + bFunc = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bFunc ); + Vec_PtrWriteEntry( vBdds, Aig_ObjId(pObj), bFunc ); + return bFunc; +} + +/**Function************************************************************* + + Synopsis [Returns the array of constraint candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManComputeIndCase( Aig_Man_t * p, DdManager * dd, Vec_Int_t * vNodes ) +{ + Vec_Ptr_t * vBdds; + Aig_Obj_t * pObj; + DdNode * bFunc; + int i, Entry; + vBdds = Vec_PtrStart( Aig_ManObjNumMax(p) ); + bFunc = Cudd_ReadOne(dd); Cudd_Ref( bFunc ); + Vec_PtrWriteEntry( vBdds, Aig_ObjId(Aig_ManConst1(p)), bFunc ); + Saig_ManForEachPi( p, pObj, i ) + { + bFunc = Cudd_bddIthVar( dd, Aig_ManPiNum(p) + i ); Cudd_Ref( bFunc ); + Vec_PtrWriteEntry( vBdds, Aig_ObjId(pObj), bFunc ); + } + Saig_ManForEachLi( p, pObj, i ) + { + bFunc = (DdNode *)pObj->pData; Cudd_Ref( bFunc ); + Vec_PtrWriteEntry( vBdds, Aig_ObjId(Saig_ObjLiToLo(p, pObj)), bFunc ); + } + Vec_IntForEachEntry( vNodes, Entry, i ) + { + if ( Entry != 0 && Entry != 1 ) + continue; + pObj = Aig_ManObj( p, i ); + bFunc = Llb_ManComputeIndCase_rec( p, pObj, dd, vBdds ); + if ( Entry == 0 ) + { +// Extra_bddPrint( dd, Cudd_Not(pObj->pData) ); printf( "\n" ); +// Extra_bddPrint( dd, Cudd_Not(bFunc) ); printf( "\n" ); + if ( !Cudd_bddLeq( dd, Cudd_Not(pObj->pData), Cudd_Not(bFunc) ) ) + Vec_IntWriteEntry( vNodes, i, -1 ); + } + else if ( Entry == 1 ) + { +// Extra_bddPrint( dd, pObj->pData ); printf( "\n" ); +// Extra_bddPrint( dd, bFunc ); printf( "\n" ); + if ( !Cudd_bddLeq( dd, (DdNode *)pObj->pData, bFunc ) ) + Vec_IntWriteEntry( vNodes, i, -1 ); + } + } + Vec_PtrForEachEntry( DdNode *, vBdds, bFunc, i ) + if ( bFunc ) + Cudd_RecursiveDeref( dd, bFunc ); + Vec_PtrFree( vBdds ); +} + +/**Function************************************************************* + + Synopsis [Returns the array of constraint candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_ManComputeBaseCase( Aig_Man_t * p, DdManager * dd ) +{ + Vec_Int_t * vNodes; + Aig_Obj_t * pObj, * pRoot; + int i; + pRoot = Aig_ManPo( p, 0 ); + vNodes = Vec_IntStartFull( Aig_ManObjNumMax(p) ); + Aig_ManForEachObj( p, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) ) + continue; + if ( Cudd_bddLeq( dd, (DdNode *)pObj->pData, Cudd_Not(pRoot->pData) ) ) + Vec_IntWriteEntry( vNodes, i, 1 ); + else if ( Cudd_bddLeq( dd, Cudd_Not((DdNode *)pObj->pData), Cudd_Not(pRoot->pData) ) ) + Vec_IntWriteEntry( vNodes, i, 0 ); + } + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Constructs global BDDs for each object in the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdManager * Llb_ManConstructGlobalBdds( Aig_Man_t * p ) +{ + DdManager * dd; + DdNode * bBdd0, * bBdd1; + Aig_Obj_t * pObj; + int i; + dd = Cudd_Init( Aig_ManPiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + pObj = Aig_ManConst1(p); + pObj->pData = Cudd_ReadOne(dd); Cudd_Ref( (DdNode *)pObj->pData ); + Aig_ManForEachPi( p, pObj, i ) + { + pObj->pData = Cudd_bddIthVar(dd, i); Cudd_Ref( (DdNode *)pObj->pData ); + } + Aig_ManForEachNode( p, pObj, i ) + { + bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); + pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData ); + } + Aig_ManForEachPo( p, pObj, i ) + { + pObj->pData = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); Cudd_Ref( (DdNode *)pObj->pData ); + } + return dd; +} + +/**Function************************************************************* + + Synopsis [Derives inductive constraints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_ManDeriveConstraints( Aig_Man_t * p ) +{ + DdManager * dd; + Vec_Int_t * vNodes; + if ( Saig_ManPoNum(p) != 1 ) + { + printf( "The AIG has %d property outputs.\n", Saig_ManPoNum(p) ); + return NULL; + } + assert( Saig_ManPoNum(p) == 1 ); + dd = Llb_ManConstructGlobalBdds( p ); + vNodes = Llb_ManComputeBaseCase( p, dd ); + if ( Llb_ManCountEntries(vNodes) > 0 ) + Llb_ManComputeIndCase( p, dd, vNodes ); + if ( Llb_ManCountEntries(vNodes) == 0 ) + Vec_IntFreeP( &vNodes ); + Llb_ManDerefenceBdds( p, dd ); + Extra_StopManager( dd ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Tests derived constraints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManConstrTest( Aig_Man_t * p ) +{ + Vec_Int_t * vNodes; + vNodes = Llb_ManDeriveConstraints( p ); + Llb_ManPrintEntries( p, vNodes ); + Vec_IntFreeP( &vNodes ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/llb/llb1Core.c b/src/proof/llb/llb1Core.c new file mode 100644 index 00000000..ee697748 --- /dev/null +++ b/src/proof/llb/llb1Core.c @@ -0,0 +1,222 @@ +/**CFile**************************************************************** + + FileName [llb1Core.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Top-level procedure.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Core.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" +#include "src/aig/gia/gia.h" +#include "src/aig/gia/giaAig.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManSetDefaultParams( Gia_ParLlb_t * p ) +{ + memset( p, 0, sizeof(Gia_ParLlb_t) ); + p->nBddMax = 10000000; + p->nIterMax = 10000000; + p->nClusterMax = 20; + p->nHintDepth = 0; + p->HintFirst = 0; + p->fUseFlow = 0; // use flow + p->nVolumeMax = 100; // max volume + p->nVolumeMin = 30; // min volume + p->nPartValue = 5; // partitioning value + p->fBackward = 0; // forward by default + p->fReorder = 1; + p->fIndConstr = 0; + p->fUsePivots = 0; + p->fCluster = 0; + p->fSchedule = 0; + p->fDumpReached = 0; + p->fVerbose = 0; + p->fVeryVerbose = 0; + p->fSilent = 0; + p->TimeLimit = 0; +// p->TimeLimit = 0; + p->TimeLimitGlo = 0; + p->TimeTarget = 0; + p->iFrame = -1; +} + + +/**Function************************************************************* + + Synopsis [Prints statistics about MFFCs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManPrintAig( Llb_Man_t * p ) +{ + Abc_Print( 1, "pi =%3d ", Saig_ManPiNum(p->pAig) ); + Abc_Print( 1, "po =%3d ", Saig_ManPoNum(p->pAig) ); + Abc_Print( 1, "ff =%3d ", Saig_ManRegNum(p->pAig) ); + Abc_Print( 1, "int =%5d ", Vec_IntSize(p->vVar2Obj)-Aig_ManPiNum(p->pAig)-Saig_ManRegNum(p->pAig) ); + Abc_Print( 1, "var =%5d ", Vec_IntSize(p->vVar2Obj) ); + Abc_Print( 1, "part =%5d ", Vec_PtrSize(p->vGroups)-2 ); + Abc_Print( 1, "and =%5d ", Aig_ManNodeNum(p->pAig) ); + Abc_Print( 1, "lev =%4d ", Aig_ManLevelNum(p->pAig) ); +// Abc_Print( 1, "cut =%4d ", Llb_ManCrossCut(p->pAig) ); + Abc_Print( 1, "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManModelCheckAig( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars, Vec_Int_t * vHints, DdManager ** pddGlo ) +{ + Llb_Man_t * p = NULL; + Aig_Man_t * pAig; + int RetValue = -1; + int clk = clock(); + + if ( pPars->fIndConstr ) + { + assert( vHints == NULL ); + vHints = Llb_ManDeriveConstraints( pAigGlo ); + } + + // derive AIG for hints + if ( vHints == NULL ) + pAig = Aig_ManDupSimple( pAigGlo ); + else + { + if ( pPars->fVerbose ) + Llb_ManPrintEntries( pAigGlo, vHints ); + pAig = Aig_ManDupSimpleWithHints( pAigGlo, vHints ); + } + + + if ( pPars->fUseFlow ) + { +// p = Llb_ManStartFlow( pAigGlo, pAig, pPars ); + } + else + { + p = Llb_ManStart( pAigGlo, pAig, pPars ); + if ( pPars->fVerbose ) + { + Llb_ManPrintAig( p ); + printf( "Original matrix: " ); + Llb_MtrPrintMatrixStats( p->pMatrix ); + if ( pPars->fVeryVerbose ) + Llb_MtrPrint( p->pMatrix, 1 ); + } + if ( pPars->fCluster ) + { + Llb_ManCluster( p->pMatrix ); + if ( pPars->fVerbose ) + { + printf( "Matrix after clustering: " ); + Llb_MtrPrintMatrixStats( p->pMatrix ); + if ( pPars->fVeryVerbose ) + Llb_MtrPrint( p->pMatrix, 1 ); + } + } + if ( pPars->fSchedule ) + { + Llb_MtrSchedule( p->pMatrix ); + if ( pPars->fVerbose ) + { + printf( "Matrix after scheduling: " ); + Llb_MtrPrintMatrixStats( p->pMatrix ); + if ( pPars->fVeryVerbose ) + Llb_MtrPrint( p->pMatrix, 1 ); + } + } + } + + if ( !p->pPars->fSkipReach ) + RetValue = Llb_ManReachability( p, vHints, pddGlo ); + Llb_ManStop( p ); + + Abc_PrintTime( 1, "Time", clock() - clk ); + + if ( pPars->fIndConstr ) + Vec_IntFreeP( &vHints ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManModelCheckGia( Gia_Man_t * pGia, Gia_ParLlb_t * pPars ) +{ + Gia_Man_t * pGia2; + Aig_Man_t * pAig; + int RetValue = -1; + pGia2 = Gia_ManDupDfs( pGia ); + pAig = Gia_ManToAigSimple( pGia2 ); + Gia_ManStop( pGia2 ); +//Aig_ManShow( pAig, 0, NULL ); + + if ( pPars->nHintDepth == 0 ) + RetValue = Llb_ManModelCheckAig( pAig, pPars, NULL, NULL ); + else + RetValue = Llb_ManModelCheckAigWithHints( pAig, pPars ); + pGia->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL; + Aig_ManStop( pAig ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/llb/llb1Group.c b/src/proof/llb/llb1Group.c new file mode 100644 index 00000000..c61f3a30 --- /dev/null +++ b/src/proof/llb/llb1Group.c @@ -0,0 +1,474 @@ +/**CFile**************************************************************** + + FileName [llb1Group.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Initial partition computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Group.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Grp_t * Llb_ManGroupAlloc( Llb_Man_t * pMan ) +{ + Llb_Grp_t * p; + p = ABC_CALLOC( Llb_Grp_t, 1 ); + p->pMan = pMan; + p->vIns = Vec_PtrAlloc( 8 ); + p->vOuts = Vec_PtrAlloc( 8 ); + p->Id = Vec_PtrSize( pMan->vGroups ); + Vec_PtrPush( pMan->vGroups, p ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManGroupStop( Llb_Grp_t * p ) +{ + if ( p == NULL ) + return; + Vec_PtrWriteEntry( p->pMan->vGroups, p->Id, NULL ); + Vec_PtrFreeP( &p->vIns ); + Vec_PtrFreeP( &p->vOuts ); + Vec_PtrFreeP( &p->vNodes ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManGroupCollect_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + return; + Aig_ObjSetTravIdCurrent(pAig, pObj); + if ( Aig_ObjIsConst1(pObj) ) + return; + if ( Aig_ObjIsPo(pObj) ) + { + Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin0(pObj), vNodes ); + return; + } + assert( Aig_ObjIsAnd(pObj) ); + Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin0(pObj), vNodes ); + Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin1(pObj), vNodes ); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Collects the support of MFFC.] + + Description [Returns the number of internal nodes in the MFFC.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManGroupCollect( Llb_Grp_t * pGroup ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + vNodes = Vec_PtrAlloc( 100 ); + Aig_ManIncrementTravId( pGroup->pMan->pAig ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) + Aig_ObjSetTravIdCurrent( pGroup->pMan->pAig, pObj ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) + Aig_ObjSetTravIdPrevious( pGroup->pMan->pAig, pObj ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) + Llb_ManGroupCollect_rec( pGroup->pMan->pAig, pObj, vNodes ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManGroupCreate_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vSupp ) +{ + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + return; + Aig_ObjSetTravIdCurrent(pAig, pObj); + if ( Aig_ObjIsConst1(pObj) ) + return; + if ( pObj->fMarkA ) + { + Vec_PtrPush( vSupp, pObj ); + return; + } + assert( Aig_ObjIsAnd(pObj) ); + Llb_ManGroupCreate_rec( pAig, Aig_ObjFanin0(pObj), vSupp ); + Llb_ManGroupCreate_rec( pAig, Aig_ObjFanin1(pObj), vSupp ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Grp_t * Llb_ManGroupCreate( Llb_Man_t * pMan, Aig_Obj_t * pObj ) +{ + Llb_Grp_t * p; + assert( pObj->fMarkA == 1 ); + // derive group + p = Llb_ManGroupAlloc( pMan ); + Vec_PtrPush( p->vOuts, pObj ); + Aig_ManIncrementTravId( pMan->pAig ); + if ( Aig_ObjIsPo(pObj) ) + Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin0(pObj), p->vIns ); + else + { + Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin0(pObj), p->vIns ); + Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin1(pObj), p->vIns ); + } + // derive internal objects + assert( p->vNodes == NULL ); + p->vNodes = Llb_ManGroupCollect( p ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Grp_t * Llb_ManGroupCreateFirst( Llb_Man_t * pMan ) +{ + Llb_Grp_t * p; + Aig_Obj_t * pObj; + int i; + p = Llb_ManGroupAlloc( pMan ); + Saig_ManForEachLo( pMan->pAig, pObj, i ) + Vec_PtrPush( p->vOuts, pObj ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Grp_t * Llb_ManGroupCreateLast( Llb_Man_t * pMan ) +{ + Llb_Grp_t * p; + Aig_Obj_t * pObj; + int i; + p = Llb_ManGroupAlloc( pMan ); + Saig_ManForEachLi( pMan->pAig, pObj, i ) + Vec_PtrPush( p->vIns, pObj ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Grp_t * Llb_ManGroupsCombine( Llb_Grp_t * p1, Llb_Grp_t * p2 ) +{ + Llb_Grp_t * p; + Aig_Obj_t * pObj; + int i; + p = Llb_ManGroupAlloc( p1->pMan ); + // create inputs + Vec_PtrForEachEntry( Aig_Obj_t *, p1->vIns, pObj, i ) + Vec_PtrPush( p->vIns, pObj ); + Vec_PtrForEachEntry( Aig_Obj_t *, p2->vIns, pObj, i ) + Vec_PtrPushUnique( p->vIns, pObj ); + // create outputs + Vec_PtrForEachEntry( Aig_Obj_t *, p1->vOuts, pObj, i ) + Vec_PtrPush( p->vOuts, pObj ); + Vec_PtrForEachEntry( Aig_Obj_t *, p2->vOuts, pObj, i ) + Vec_PtrPushUnique( p->vOuts, pObj ); + + // derive internal objects + assert( p->vNodes == NULL ); + p->vNodes = Llb_ManGroupCollect( p ); + return p; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManGroupMarkNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + if ( Aig_ObjIsTravIdPrevious(p, pObj) ) + { + Aig_ObjSetTravIdCurrent(p, pObj); + return; + } + Aig_ObjSetTravIdCurrent(p, pObj); + assert( Aig_ObjIsNode(pObj) ); + Llb_ManGroupMarkNodes_rec( p, Aig_ObjFanin0(pObj) ); + Llb_ManGroupMarkNodes_rec( p, Aig_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Creates group from two cuts derived by the flow computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Grp_t * Llb_ManGroupCreateFromCuts( Llb_Man_t * pMan, Vec_Int_t * vCut1, Vec_Int_t * vCut2 ) +{ + Llb_Grp_t * p; + Aig_Obj_t * pObj; + int i; + p = Llb_ManGroupAlloc( pMan ); + + // mark Cut1 + Aig_ManIncrementTravId( pMan->pAig ); + Aig_ManForEachObjVec( vCut1, pMan->pAig, pObj, i ) + Aig_ObjSetTravIdCurrent( pMan->pAig, pObj ); + // collect unmarked Cut2 + Aig_ManForEachObjVec( vCut2, pMan->pAig, pObj, i ) + if ( !Aig_ObjIsTravIdCurrent( pMan->pAig, pObj ) ) + Vec_PtrPush( p->vOuts, pObj ); + + // mark nodes reachable from Cut2 + Aig_ManIncrementTravId( pMan->pAig ); + Aig_ManForEachObjVec( vCut2, pMan->pAig, pObj, i ) + Llb_ManGroupMarkNodes_rec( pMan->pAig, pObj ); + // collect marked Cut1 + Aig_ManForEachObjVec( vCut1, pMan->pAig, pObj, i ) + if ( Aig_ObjIsTravIdCurrent( pMan->pAig, pObj ) ) + Vec_PtrPush( p->vIns, pObj ); + + // derive internal objects + assert( p->vNodes == NULL ); + p->vNodes = Llb_ManGroupCollect( p ); + return p; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManPrepareGroups( Llb_Man_t * pMan ) +{ + Aig_Obj_t * pObj; + int i; + assert( pMan->vGroups == NULL ); + pMan->vGroups = Vec_PtrAlloc( 1000 ); + Llb_ManGroupCreateFirst( pMan ); + Aig_ManForEachNode( pMan->pAig, pObj, i ) + { + if ( pObj->fMarkA ) + Llb_ManGroupCreate( pMan, pObj ); + } + Saig_ManForEachLi( pMan->pAig, pObj, i ) + { + if ( pObj->fMarkA ) + Llb_ManGroupCreate( pMan, pObj ); + } + Llb_ManGroupCreateLast( pMan ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManPrintSpan( Llb_Man_t * p ) +{ + Llb_Grp_t * pGroup; + Aig_Obj_t * pVar; + int i, k, Span = 0, SpanMax = 0; + Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGroup, i ) + { + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) + if ( Vec_IntEntry(p->vVarBegs, pVar->Id) == i ) + Span++; + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) + if ( Vec_IntEntry(p->vVarBegs, pVar->Id) == i ) + Span++; + + SpanMax = Abc_MaxInt( SpanMax, Span ); +printf( "%d ", Span ); + + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) + if ( Vec_IntEntry(p->vVarEnds, pVar->Id) == i ) + Span--; + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) + if ( Vec_IntEntry(p->vVarEnds, pVar->Id) == i ) + Span--; + } +printf( "\n" ); +printf( "Max = %d\n", SpanMax ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManGroupHasVar( Llb_Man_t * p, int iGroup, int iVar ) +{ + Llb_Grp_t * pGroup = (Llb_Grp_t *)Vec_PtrEntry( p->vGroups, iGroup ); + Aig_Obj_t * pObj; + int i; + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) + if ( pObj->Id == iVar ) + return 1; + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) + if ( pObj->Id == iVar ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManPrintHisto( Llb_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, k; + Aig_ManForEachObj( p->pAig, pObj, i ) + { + if ( Vec_IntEntry(p->vObj2Var, i) < 0 ) + continue; + printf( "%3d :", i ); + for ( k = 0; k < Vec_IntEntry(p->vVarBegs, i); k++ ) + printf( " " ); + for ( ; k <= Vec_IntEntry(p->vVarEnds, i); k++ ) + printf( "%c", Llb_ManGroupHasVar(p, k, i)? '*':'-' ); + printf( "\n" ); + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/llb/llb1Hint.c b/src/proof/llb/llb1Hint.c new file mode 100644 index 00000000..f68030ff --- /dev/null +++ b/src/proof/llb/llb1Hint.c @@ -0,0 +1,226 @@ +/**CFile**************************************************************** + + FileName [llb1Hint.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Cofactors the circuit w.r.t. the high-fanout variables.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Hint.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns CI index with the largest number of fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManMaxFanoutCi( Aig_Man_t * pAig ) +{ + Aig_Obj_t * pObj; + int i, WeightMax = -ABC_INFINITY, iInput = -1; + Aig_ManForEachPi( pAig, pObj, i ) + if ( WeightMax < Aig_ObjRefs(pObj) ) + { + WeightMax = Aig_ObjRefs(pObj); + iInput = i; + } + assert( iInput >= 0 ); + return iInput; +} + +/**Function************************************************************* + + Synopsis [Derives AIG whose PI is substituted by a constant.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Llb_ManPerformHints( Aig_Man_t * pAig, int nHintDepth ) +{ + Aig_Man_t * pNew, * pTemp; + int i, iInput; + pNew = Aig_ManDupDfs( pAig ); + for ( i = 0; i < nHintDepth; i++ ) + { + iInput = Llb_ManMaxFanoutCi( pNew ); + Abc_Print( 1, "%d %3d\n", i, iInput ); + pNew = Aig_ManDupCof( pTemp = pNew, iInput, 1 ); + Aig_ManStop( pTemp ); + } + return pNew; +} + +/**Function************************************************************* + + Synopsis [Returns CI index with the largest number of fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_ManCollectHighFanoutObjects( Aig_Man_t * pAig, int nCandMax, int fCisOnly ) +{ + Vec_Int_t * vFanouts, * vResult; + Aig_Obj_t * pObj; + int i, fChanges, PivotValue; +// int Entry; + // collect fanout counts + vFanouts = Vec_IntAlloc( 100 ); + Aig_ManForEachObj( pAig, pObj, i ) + { +// if ( !Aig_ObjIsPi(pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) + if ( !Saig_ObjIsLo(pAig,pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) + continue; + Vec_IntPush( vFanouts, Aig_ObjRefs(pObj) ); + } + Vec_IntSort( vFanouts, 1 ); + // pick the separator + nCandMax = Abc_MinInt( nCandMax, Vec_IntSize(vFanouts) - 1 ); + PivotValue = Vec_IntEntry( vFanouts, nCandMax ); + Vec_IntFree( vFanouts ); + // collect obj satisfying the constraints + vResult = Vec_IntAlloc( 100 ); + Aig_ManForEachObj( pAig, pObj, i ) + { +// if ( !Aig_ObjIsPi(pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) + if ( !Saig_ObjIsLo(pAig,pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) + continue; + if ( Aig_ObjRefs(pObj) < PivotValue ) + continue; + Vec_IntPush( vResult, Aig_ObjId(pObj) ); + } + assert( Vec_IntSize(vResult) >= nCandMax ); + // order in the decreasing order of fanouts + do + { + fChanges = 0; + for ( i = 0; i < Vec_IntSize(vResult) - 1; i++ ) + if ( Aig_ObjRefs(Aig_ManObj(pAig, Vec_IntEntry(vResult, i))) < + Aig_ObjRefs(Aig_ManObj(pAig, Vec_IntEntry(vResult, i+1))) ) + { + int Temp = Vec_IntEntry( vResult, i ); + Vec_IntWriteEntry( vResult, i, Vec_IntEntry(vResult, i+1) ); + Vec_IntWriteEntry( vResult, i+1, Temp ); + fChanges = 1; + } + } + while ( fChanges ); +/* + Vec_IntForEachEntry( vResult, Entry, i ) + printf( "%d ", Aig_ObjRefs(Aig_ManObj(pAig, Entry)) ); +printf( "\n" ); +*/ + return vResult; +} + +/**Function************************************************************* + + Synopsis [Derives AIG whose PI is substituted by a constant.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManModelCheckAigWithHints( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars ) +{ + DdManager * ddGlo = NULL; + Vec_Int_t * vHints; + Vec_Int_t * vHFCands; + int i, Entry, RetValue = -1; + int clk = clock(); + assert( pPars->nHintDepth > 0 ); +/* + // perform reachability without hints + RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, NULL, NULL ); + if ( RetValue >= 0 ) + return RetValue; +*/ + // create hints representation + vHFCands = Llb_ManCollectHighFanoutObjects( pAigGlo, pPars->nHintDepth+pPars->HintFirst, 1 ); + vHints = Vec_IntStartFull( Aig_ManObjNumMax(pAigGlo) ); + // add one hint at a time till the problem is solved + Vec_IntForEachEntryStart( vHFCands, Entry, i, pPars->HintFirst ) + { + Vec_IntWriteEntry( vHints, Entry, 1 ); // change to 1 to start from zero cof!!! + // solve under hints + RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, vHints, &ddGlo ); + if ( RetValue == 0 ) + goto Finish; + if ( RetValue == 1 ) + break; + } + if ( RetValue == -1 ) + goto Finish; + // undo the hints one at a time + for ( ; i >= pPars->HintFirst; i-- ) + { + Entry = Vec_IntEntry( vHFCands, i ); + Vec_IntWriteEntry( vHints, Entry, -1 ); + // solve under relaxed hints + RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, vHints, &ddGlo ); + if ( RetValue == 0 ) + goto Finish; + if ( RetValue == 1 ) + continue; + break; + } +Finish: + if ( ddGlo ) + { + if ( ddGlo->bFunc ) + Cudd_RecursiveDeref( ddGlo, ddGlo->bFunc ); + Extra_StopManager( ddGlo ); + } + Vec_IntFreeP( &vHFCands ); + Vec_IntFreeP( &vHints ); + if ( pPars->fVerbose ) + Abc_PrintTime( 1, "Total runtime", clock() - clk ); + return RetValue; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/llb/llb1Man.c b/src/proof/llb/llb1Man.c new file mode 100644 index 00000000..f5de25e0 --- /dev/null +++ b/src/proof/llb/llb1Man.c @@ -0,0 +1,218 @@ +/**CFile**************************************************************** + + FileName [llb1Man.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Reachability manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Man.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManPrepareVarMap( Llb_Man_t * p ) +{ + Aig_Obj_t * pObjLi, * pObjLo; + int i, iVarLi, iVarLo; + assert( p->vNs2Glo == NULL ); + assert( p->vCs2Glo == NULL ); + assert( p->vGlo2Cs == NULL ); + assert( p->vGlo2Ns == NULL ); + p->vNs2Glo = Vec_IntStartFull( Vec_IntSize(p->vVar2Obj) ); + p->vCs2Glo = Vec_IntStartFull( Vec_IntSize(p->vVar2Obj) ); + p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); + p->vGlo2Ns = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); + Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) + { + iVarLi = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLi)); + iVarLo = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLo)); + assert( iVarLi >= 0 && iVarLi < Vec_IntSize(p->vVar2Obj) ); + assert( iVarLo >= 0 && iVarLo < Vec_IntSize(p->vVar2Obj) ); + Vec_IntWriteEntry( p->vNs2Glo, iVarLi, i ); + Vec_IntWriteEntry( p->vCs2Glo, iVarLo, i ); + Vec_IntWriteEntry( p->vGlo2Cs, i, iVarLo ); + Vec_IntWriteEntry( p->vGlo2Ns, i, iVarLi ); + } + // add mapping of the PIs + Saig_ManForEachPi( p->pAig, pObjLo, i ) + { + iVarLo = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLo)); + Vec_IntWriteEntry( p->vCs2Glo, iVarLo, Aig_ManRegNum(p->pAig)+i ); + Vec_IntWriteEntry( p->vNs2Glo, iVarLo, Aig_ManRegNum(p->pAig)+i ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManPrepareVarLimits( Llb_Man_t * p ) +{ + Llb_Grp_t * pGroup; + Aig_Obj_t * pVar; + int i, k; + assert( p->vVarBegs == NULL ); + assert( p->vVarEnds == NULL ); + p->vVarEnds = Vec_IntStart( Aig_ManObjNumMax(p->pAig) ); + p->vVarBegs = Vec_IntStart( Aig_ManObjNumMax(p->pAig) ); + Vec_IntFill( p->vVarBegs, Aig_ManObjNumMax(p->pAig), p->pMatrix->nCols ); + + for ( i = 0; i < p->pMatrix->nCols; i++ ) + { + pGroup = p->pMatrix->pColGrps[i]; + + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) + if ( Vec_IntEntry(p->vVarBegs, pVar->Id) > i ) + Vec_IntWriteEntry( p->vVarBegs, pVar->Id, i ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) + if ( Vec_IntEntry(p->vVarBegs, pVar->Id) > i ) + Vec_IntWriteEntry( p->vVarBegs, pVar->Id, i ); + + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) + if ( Vec_IntEntry(p->vVarEnds, pVar->Id) < i ) + Vec_IntWriteEntry( p->vVarEnds, pVar->Id, i ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) + if ( Vec_IntEntry(p->vVarEnds, pVar->Id) < i ) + Vec_IntWriteEntry( p->vVarEnds, pVar->Id, i ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManStop( Llb_Man_t * p ) +{ + Llb_Grp_t * pGrp; + DdNode * bTemp; + int i; + +// Vec_IntFreeP( &p->vMem ); +// Vec_PtrFreeP( &p->vTops ); +// Vec_PtrFreeP( &p->vBots ); +// Vec_VecFreeP( (Vec_Vec_t **)&p->vCuts ); + + if ( p->pMatrix ) + Llb_MtrFree( p->pMatrix ); + Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGrp, i ) + Llb_ManGroupStop( pGrp ); + if ( p->dd ) + { +// printf( "Manager dd\n" ); + Extra_StopManager( p->dd ); + } + if ( p->ddG ) + { +// printf( "Manager ddG\n" ); + if ( p->ddG->bFunc ) + Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc ); + Extra_StopManager( p->ddG ); + } + if ( p->ddR ) + { +// printf( "Manager ddR\n" ); + if ( p->ddR->bFunc ) + Cudd_RecursiveDeref( p->ddR, p->ddR->bFunc ); + Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i ) + Cudd_RecursiveDeref( p->ddR, bTemp ); + Extra_StopManager( p->ddR ); + } + Aig_ManStop( p->pAig ); + Vec_PtrFreeP( &p->vGroups ); + Vec_IntFreeP( &p->vVar2Obj ); + Vec_IntFreeP( &p->vObj2Var ); + Vec_IntFreeP( &p->vVarBegs ); + Vec_IntFreeP( &p->vVarEnds ); + Vec_PtrFreeP( &p->vRings ); + Vec_IntFreeP( &p->vNs2Glo ); + Vec_IntFreeP( &p->vCs2Glo ); + Vec_IntFreeP( &p->vGlo2Cs ); + Vec_IntFreeP( &p->vGlo2Ns ); +// Vec_IntFreeP( &p->vHints ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Man_t * Llb_ManStart( Aig_Man_t * pAigGlo, Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) +{ + Llb_Man_t * p; + Aig_ManCleanMarkA( pAig ); + p = ABC_CALLOC( Llb_Man_t, 1 ); + p->pAigGlo = pAigGlo; + p->pPars = pPars; + p->pAig = pAig; + p->vVar2Obj = Llb_ManMarkPivotNodes( p->pAig, pPars->fUsePivots ); + p->vObj2Var = Vec_IntInvert( p->vVar2Obj, -1 ); + p->vRings = Vec_PtrAlloc( 100 ); + Llb_ManPrepareVarMap( p ); + Llb_ManPrepareGroups( p ); + Aig_ManCleanMarkA( pAig ); + p->pMatrix = Llb_MtrCreate( p ); + p->pMatrix->pMan = p; + return p; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/llb/llb1Matrix.c b/src/proof/llb/llb1Matrix.c new file mode 100644 index 00000000..7aa9c744 --- /dev/null +++ b/src/proof/llb/llb1Matrix.c @@ -0,0 +1,430 @@ +/**CFile**************************************************************** + + FileName [llb1Matrix.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Partition clustering as a matrix problem.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Matrix.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// 0123 nCols +// +---------------------> +// pi 0 | 111 row0 pRowSums[0] +// pi 1 | 1 11 row1 pRowSums[1] +// pi 2 | 1 11 row2 pRowSums[2] +// CS |1 1 +// CS |1 111 +// CS |111 111 +// int | 11111 +// int | 111 +// int | 111 +// int | 111 +// NS | 11 11 +// NS | 11 1 +// NS | 111 +// nRows | +// v +// cccc pColSums[0] +// oooo pColSums[1] +// llll pColSums[2] +// 0123 pColSums[3] + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Verify columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrVerifyRowsAll( Llb_Mtr_t * p ) +{ + int iRow, iCol, Counter; + for ( iCol = 0; iCol < p->nCols; iCol++ ) + { + Counter = 0; + for ( iRow = 0; iRow < p->nRows; iRow++ ) + if ( p->pMatrix[iCol][iRow] == 1 ) + Counter++; + assert( Counter == p->pColSums[iCol] ); + } +} + +/**Function************************************************************* + + Synopsis [Verify columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrVerifyColumnsAll( Llb_Mtr_t * p ) +{ + int iRow, iCol, Counter; + for ( iRow = 0; iRow < p->nRows; iRow++ ) + { + Counter = 0; + for ( iCol = 0; iCol < p->nCols; iCol++ ) + if ( p->pMatrix[iCol][iRow] == 1 ) + Counter++; + assert( Counter == p->pRowSums[iRow] ); + } +} + +/**Function************************************************************* + + Synopsis [Verify columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrVerifyMatrix( Llb_Mtr_t * p ) +{ + Llb_MtrVerifyRowsAll( p ); + Llb_MtrVerifyColumnsAll( p ); +} + +/**Function************************************************************* + + Synopsis [Sort variables in the order of removal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Llb_MtrFindVarOrder( Llb_Mtr_t * p ) +{ + int * pOrder, * pLast; + int i, k, fChanges, Temp; + pOrder = ABC_CALLOC( int, p->nRows ); + pLast = ABC_CALLOC( int, p->nRows ); + for ( i = 0; i < p->nRows; i++ ) + { + pOrder[i] = i; + for ( k = p->nCols - 1; k >= 0; k-- ) + if ( p->pMatrix[k][i] ) + { + pLast[i] = k; + break; + } + } + do + { + fChanges = 0; + for ( i = 0; i < p->nRows - 1; i++ ) + if ( pLast[i] > pLast[i+1] ) + { + Temp = pOrder[i]; + pOrder[i] = pOrder[i+1]; + pOrder[i+1] = Temp; + + Temp = pLast[i]; + pLast[i] = pLast[i+1]; + pLast[i+1] = Temp; + + fChanges = 1; + } + } + while ( fChanges ); + ABC_FREE( pLast ); + return pOrder; +} + +/**Function************************************************************* + + Synopsis [Returns type of a variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Llb_MtrVarName( Llb_Mtr_t * p, int iVar ) +{ + static char Buffer[10]; + if ( iVar < p->nPis ) + strcpy( Buffer, "pi" ); + else if ( iVar < p->nPis + p->nFfs ) + strcpy( Buffer, "CS" ); + else if ( iVar >= p->nRows - p->nFfs ) + strcpy( Buffer, "NS" ); + else + strcpy( Buffer, "int" ); + return Buffer; +} + +/**Function************************************************************* + + Synopsis [Creates one column with vars in the array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrPrint( Llb_Mtr_t * p, int fOrder ) +{ + int * pOrder = NULL; + int i, iRow, iCol; + if ( fOrder ) + pOrder = Llb_MtrFindVarOrder( p ); + for ( i = 0; i < p->nRows; i++ ) + { + iRow = pOrder ? pOrder[i] : i; + printf( "%3d : ", iRow ); + printf( "%3d ", p->pRowSums[iRow] ); + printf( "%3s ", Llb_MtrVarName(p, iRow) ); + for ( iCol = 0; iCol < p->nCols; iCol++ ) + printf( "%c", p->pMatrix[iCol][iRow] ? '*' : ' ' ); + printf( "\n" ); + } + ABC_FREE( pOrder ); +} + +/**Function************************************************************* + + Synopsis [Verify columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrPrintMatrixStats( Llb_Mtr_t * p ) +{ + int iVar, iGrp, iGrp1, iGrp2, Span = 0, nCutSize = 0, nCutSizeMax = 0; + int * pGrp1 = ABC_CALLOC( int, p->nRows ); + int * pGrp2 = ABC_CALLOC( int, p->nRows ); + for ( iVar = 0; iVar < p->nRows; iVar++ ) + { + if ( p->pRowSums[iVar] == 0 ) + continue; + for ( iGrp1 = 0; iGrp1 < p->nCols; iGrp1++ ) + if ( p->pMatrix[iGrp1][iVar] == 1 ) + break; + for ( iGrp2 = p->nCols - 1; iGrp2 >= 0; iGrp2-- ) + if ( p->pMatrix[iGrp2][iVar] == 1 ) + break; + assert( iGrp1 <= iGrp2 ); + pGrp1[iVar] = iGrp1; + pGrp2[iVar] = iGrp2; + Span += iGrp2 - iGrp1; + } + // compute span + for ( iGrp = 0; iGrp < p->nCols; iGrp++ ) + { + for ( iVar = 0; iVar < p->nRows; iVar++ ) + if ( pGrp1[iVar] == iGrp ) + nCutSize++; + if ( nCutSizeMax < nCutSize ) + nCutSizeMax = nCutSize; + for ( iVar = 0; iVar < p->nRows; iVar++ ) + if ( pGrp2[iVar] == iGrp ) + nCutSize--; + } + ABC_FREE( pGrp1 ); + ABC_FREE( pGrp2 ); + printf( "[%4d x %4d] Life-span =%6.2f Max-cut =%5d\n", + p->nCols, p->nRows, 1.0*Span/p->nRows, nCutSizeMax ); + if ( nCutSize ) + Abc_Print( -1, "Cut size is not zero (%d).\n", nCutSize ); +} + + + +/**Function************************************************************* + + Synopsis [Starts the matrix representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Mtr_t * Llb_MtrAlloc( int nPis, int nFfs, int nCols, int nRows ) +{ + Llb_Mtr_t * p; + int i; + p = ABC_CALLOC( Llb_Mtr_t, 1 ); + p->nPis = nPis; + p->nFfs = nFfs; + p->nRows = nRows; + p->nCols = nCols; + p->pRowSums = ABC_CALLOC( int, nRows ); + p->pColSums = ABC_CALLOC( int, nCols ); + p->pColGrps = ABC_CALLOC( Llb_Grp_t *, nCols ); + p->pMatrix = ABC_CALLOC( char *, nCols ); + for ( i = 0; i < nCols; i++ ) + p->pMatrix[i] = ABC_CALLOC( char, nRows ); + // partial product + p->pProdVars = ABC_CALLOC( char, nRows ); // variables in the partial product + p->pProdNums = ABC_CALLOC( int, nRows ); // var counts in the remaining partitions + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the matrix representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrFree( Llb_Mtr_t * p ) +{ + int i; + ABC_FREE( p->pProdVars ); + ABC_FREE( p->pProdNums ); + for ( i = 0; i < p->nCols; i++ ) + ABC_FREE( p->pMatrix[i] ); + ABC_FREE( p->pRowSums ); + ABC_FREE( p->pColSums ); + ABC_FREE( p->pMatrix ); + ABC_FREE( p->pColGrps ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Creates one column with vars in the array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrAddColumn( Llb_Mtr_t * p, Llb_Grp_t * pGrp ) +{ + Aig_Obj_t * pVar; + int i, iRow, iCol = pGrp->Id; + assert( iCol >= 0 && iCol < p->nCols ); + p->pColGrps[iCol] = pGrp; + Vec_PtrForEachEntry( Aig_Obj_t *, pGrp->vIns, pVar, i ) + { + iRow = Vec_IntEntry( pGrp->pMan->vObj2Var, Aig_ObjId(pVar) ); + assert( iRow >= 0 && iRow < p->nRows ); + p->pMatrix[iCol][iRow] = 1; + p->pColSums[iCol]++; + p->pRowSums[iRow]++; + } + Vec_PtrForEachEntry( Aig_Obj_t *, pGrp->vOuts, pVar, i ) + { + iRow = Vec_IntEntry( pGrp->pMan->vObj2Var, Aig_ObjId(pVar) ); + assert( iRow >= 0 && iRow < p->nRows ); + p->pMatrix[iCol][iRow] = 1; + p->pColSums[iCol]++; + p->pRowSums[iRow]++; + } +} + +/**Function************************************************************* + + Synopsis [Matrix reduce.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrRemoveSingletonRows( Llb_Mtr_t * p ) +{ + int i, k; + for ( i = 0; i < p->nRows; i++ ) + if ( p->pRowSums[i] < 2 ) + { + p->pRowSums[i] = 0; + for ( k = 0; k < p->nCols; k++ ) + { + if ( p->pMatrix[k][i] == 1 ) + { + p->pMatrix[k][i] = 0; + p->pColSums[k]--; + } + } + } +} + +/**Function************************************************************* + + Synopsis [Matrix reduce.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Mtr_t * Llb_MtrCreate( Llb_Man_t * p ) +{ + Llb_Mtr_t * pMatrix; + Llb_Grp_t * pGroup; + int i; + pMatrix = Llb_MtrAlloc( Saig_ManPiNum(p->pAig), Saig_ManRegNum(p->pAig), + Vec_PtrSize(p->vGroups), Vec_IntSize(p->vVar2Obj) ); + Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGroup, i ) + Llb_MtrAddColumn( pMatrix, pGroup ); +// Llb_MtrRemoveSingletonRows( pMatrix ); + return pMatrix; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/llb/llb1Pivot.c b/src/proof/llb/llb1Pivot.c new file mode 100644 index 00000000..d42bf659 --- /dev/null +++ b/src/proof/llb/llb1Pivot.c @@ -0,0 +1,254 @@ +/**CFile**************************************************************** + + FileName [llb1Pivot.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Determining pivot variables.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Pivot.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManTracePaths_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pPivot ) +{ + Aig_Obj_t * pFanout; + int k, iFan; + if ( Aig_ObjIsTravIdPrevious(p, pObj) ) + return 0; + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return 1; + if ( Saig_ObjIsLi(p, pObj) ) + return 0; + if ( Saig_ObjIsPo(p, pObj) ) + return 0; + if ( pObj == pPivot ) + return 1; + assert( Aig_ObjIsCand(pObj) ); + Aig_ObjForEachFanout( p, pObj, pFanout, iFan, k ) + if ( !Llb_ManTracePaths_rec( p, pFanout, pPivot ) ) + { + Aig_ObjSetTravIdPrevious(p, pObj); + return 0; + } + Aig_ObjSetTravIdCurrent(p, pObj); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManTracePaths( Aig_Man_t * p, Aig_Obj_t * pPivot ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + Aig_ManIncrementTravId( p ); // prev = visited with path to LI (value 0) + Aig_ManIncrementTravId( p ); // cur = visited w/o path to LI (value 1) + Saig_ManForEachLo( p, pObj, i ) + Counter += Llb_ManTracePaths_rec( p, pObj, pPivot ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManTestCuts( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, Count; + Aig_ManFanoutStart( p ); + Aig_ManForEachNode( p, pObj, i ) + { + if ( Aig_ObjRefs(pObj) <= 1 ) + continue; + Count = Llb_ManTracePaths( p, pObj ); + printf( "Obj =%5d. Lev =%3d. Fanout =%5d. Count = %3d.\n", + i, Aig_ObjLevel(pObj), Aig_ObjRefs(pObj), Count ); + } + Aig_ManFanoutStop( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManLabelLiCones_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + if ( pObj->fMarkB ) + return; + pObj->fMarkB = 1; + assert( Aig_ObjIsNode(pObj) ); + Llb_ManLabelLiCones_rec( p, Aig_ObjFanin0(pObj) ); + Llb_ManLabelLiCones_rec( p, Aig_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Determine starting cut-points.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManLabelLiCones( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + // mark const and PIs + Aig_ManConst1(p)->fMarkB = 1; + Aig_ManForEachPi( p, pObj, i ) + pObj->fMarkB = 1; + // mark cones + Saig_ManForEachLi( p, pObj, i ) + Llb_ManLabelLiCones_rec( p, Aig_ObjFanin0(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Determine starting cut-points.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManMarkInternalPivots( Aig_Man_t * p ) +{ + Vec_Ptr_t * vMuxes; + Aig_Obj_t * pObj; + int i, Counter = 0; + + // remove refs due to MUXes + vMuxes = Aig_ManMuxesCollect( p ); + Aig_ManMuxesDeref( p, vMuxes ); + + // mark nodes feeding into LIs + Aig_ManCleanMarkB( p ); + Llb_ManLabelLiCones( p ); + + // mark internal nodes + Aig_ManFanoutStart( p ); + Aig_ManForEachNode( p, pObj, i ) + if ( pObj->fMarkB && pObj->nRefs > 1 ) + { + if ( Llb_ManTracePaths(p, pObj) > 0 ) + pObj->fMarkA = 1; + Counter++; + } + Aig_ManFanoutStop( p ); +// printf( "TracePath tried = %d.\n", Counter ); + + // mark nodes feeding into LIs + Aig_ManCleanMarkB( p ); + + // add refs due to MUXes + Aig_ManMuxesRef( p, vMuxes ); + Vec_PtrFree( vMuxes ); +} + +/**Function************************************************************* + + Synopsis [Determine starting cut-points.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_ManMarkPivotNodes( Aig_Man_t * p, int fUseInternal ) +{ + Vec_Int_t * vVar2Obj; + Aig_Obj_t * pObj; + int i; + // mark inputs/outputs + Aig_ManForEachPi( p, pObj, i ) + pObj->fMarkA = 1; + Saig_ManForEachLi( p, pObj, i ) + pObj->fMarkA = 1; + + // mark internal pivot nodes + if ( fUseInternal ) + Llb_ManMarkInternalPivots( p ); + + // assign variable numbers + Aig_ManConst1(p)->fMarkA = 0; + vVar2Obj = Vec_IntAlloc( 100 ); + Aig_ManForEachPi( p, pObj, i ) + Vec_IntPush( vVar2Obj, Aig_ObjId(pObj) ); + Aig_ManForEachNode( p, pObj, i ) + if ( pObj->fMarkA ) + Vec_IntPush( vVar2Obj, Aig_ObjId(pObj) ); + Saig_ManForEachLi( p, pObj, i ) + Vec_IntPush( vVar2Obj, Aig_ObjId(pObj) ); + return vVar2Obj; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/llb/llb1Reach.c b/src/proof/llb/llb1Reach.c new file mode 100644 index 00000000..fbf91351 --- /dev/null +++ b/src/proof/llb/llb1Reach.c @@ -0,0 +1,898 @@ +/**CFile**************************************************************** + + FileName [llb1Reach.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Reachability analysis.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Reach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Derives global BDD for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManConstructOutBdd( Aig_Man_t * pAig, Aig_Obj_t * pNode, DdManager * dd ) +{ + DdNode * bBdd0, * bBdd1, * bFunc; + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i, TimeStop; + if ( Aig_ObjFanin0(pNode) == Aig_ManConst1(pAig) ) + return Cudd_NotCond( Cudd_ReadOne(dd), Aig_ObjFaninC0(pNode) ); + TimeStop = dd->TimeStop; dd->TimeStop = 0; + vNodes = Aig_ManDfsNodes( pAig, &pNode, 1 ); + assert( Vec_PtrSize(vNodes) > 0 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) ) + continue; + bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); + pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData ); + } + bFunc = (DdNode *)pObj->pData; Cudd_Ref( bFunc ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) ) + continue; + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + } + Vec_PtrFree( vNodes ); + if ( Aig_ObjIsPo(pNode) ) + bFunc = Cudd_NotCond( bFunc, Aig_ObjFaninC0(pNode) ); + Cudd_Deref( bFunc ); + dd->TimeStop = TimeStop; + return bFunc; +} + +/**Function************************************************************* + + Synopsis [Derives BDD for the group.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManConstructGroupBdd( Llb_Man_t * p, Llb_Grp_t * pGroup ) +{ + Aig_Obj_t * pObj; + DdNode * bBdd0, * bBdd1, * bRes, * bXor, * bTemp; + int i, k; + Aig_ManConst1(p->pAig)->pData = Cudd_ReadOne( p->dd ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) + pObj->pData = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vNodes, pObj, i ) + { + bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); +// pObj->pData = Extra_bddAndTime( p->dd, bBdd0, bBdd1, p->pPars->TimeTarget ); + pObj->pData = Cudd_bddAnd( p->dd, bBdd0, bBdd1 ); + if ( pObj->pData == NULL ) + { + Vec_PtrForEachEntryStop( Aig_Obj_t *, pGroup->vNodes, pObj, k, i ) + if ( pObj->pData ) + Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData ); + return NULL; + } + Cudd_Ref( (DdNode *)pObj->pData ); + } + bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) + { + if ( Aig_ObjIsPo(pObj) ) + bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + else + bBdd0 = (DdNode *)pObj->pData; + bBdd1 = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + bXor = Cudd_bddXor( p->dd, bBdd0, bBdd1 ); Cudd_Ref( bXor ); +// bRes = Extra_bddAndTime( p->dd, bTemp = bRes, Cudd_Not(bXor), p->pPars->TimeTarget ); + bRes = Cudd_bddAnd( p->dd, bTemp = bRes, Cudd_Not(bXor) ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bXor ); + Vec_PtrForEachEntryStop( Aig_Obj_t *, pGroup->vNodes, pObj, k, i ) + if ( pObj->pData ) + Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData ); + return NULL; + } + Cudd_Ref( bRes ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bXor ); + } + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vNodes, pObj, i ) + Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData ); + Cudd_Deref( bRes ); + return bRes; +} + +/**Function************************************************************* + + Synopsis [Derives quantification cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManConstructQuantCubeIntern( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace, int fBackward ) +{ + Aig_Obj_t * pObj; + DdNode * bRes, * bTemp, * bVar; + int i, iGroupFirst, iGroupLast; + int TimeStop; + TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; + bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) + { + if ( fBackward && Saig_ObjIsPi(p->pAig, pObj) ) + continue; + iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj)); + iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); + assert( iGroupFirst <= iGroupLast ); + if ( iGroupFirst < iGroupLast ) + continue; + bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) + { + if ( fBackward && Saig_ObjIsPi(p->pAig, pObj) ) + continue; + iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj)); + iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); + assert( iGroupFirst <= iGroupLast ); + if ( iGroupFirst < iGroupLast ) + continue; + bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + Cudd_Deref( bRes ); + p->dd->TimeStop = TimeStop; + return bRes; +} + +/**Function************************************************************* + + Synopsis [Derives quantification cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManConstructQuantCubeFwd( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace ) +{ + Aig_Obj_t * pObj; + DdNode * bRes, * bTemp, * bVar; + int i, iGroupLast, TimeStop; + TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; + bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) + { + iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); + assert( iGroupLast >= iGrpPlace ); + if ( iGroupLast > iGrpPlace ) + continue; + bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) + { + iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); + assert( iGroupLast >= iGrpPlace ); + if ( iGroupLast > iGrpPlace ) + continue; + bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + Cudd_Deref( bRes ); + p->dd->TimeStop = TimeStop; + return bRes; +} + +/**Function************************************************************* + + Synopsis [Derives quantification cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManConstructQuantCubeBwd( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace ) +{ + Aig_Obj_t * pObj; + DdNode * bRes, * bTemp, * bVar; + int i, iGroupFirst, TimeStop; + TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; + bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) + { + if ( Saig_ObjIsPi(p->pAig, pObj) ) + continue; + iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj)); + assert( iGroupFirst <= iGrpPlace ); + if ( iGroupFirst < iGrpPlace ) + continue; + bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) + { + if ( Saig_ObjIsPi(p->pAig, pObj) ) + continue; + iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj)); + assert( iGroupFirst <= iGrpPlace ); + if ( iGroupFirst < iGrpPlace ) + continue; + bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + Cudd_Deref( bRes ); + p->dd->TimeStop = TimeStop; + return bRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManComputeInitState( Llb_Man_t * p, DdManager * dd ) +{ + Aig_Obj_t * pObj; + DdNode * bRes, * bVar, * bTemp; + int i, iVar, TimeStop; + TimeStop = dd->TimeStop; dd->TimeStop = 0; + bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); + Saig_ManForEachLo( p->pAig, pObj, i ) + { + iVar = (dd == p->ddG) ? i : Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)); + bVar = Cudd_bddIthVar( dd, iVar ); + bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bRes ); + dd->TimeStop = TimeStop; + return bRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManComputeImage( Llb_Man_t * p, DdNode * bInit, int fBackward ) +{ + int fCheckSupport = 0; + Llb_Grp_t * pGroup; + DdNode * bImage, * bGroup, * bCube, * bTemp; + int k, Index; + bImage = bInit; Cudd_Ref( bImage ); + for ( k = 1; k < p->pMatrix->nCols-1; k++ ) + { + if ( fBackward ) + Index = p->pMatrix->nCols - 1 - k; + else + Index = k; + + // compute group BDD + pGroup = p->pMatrix->pColGrps[Index]; + bGroup = Llb_ManConstructGroupBdd( p, pGroup ); + if ( bGroup == NULL ) + { + Cudd_RecursiveDeref( p->dd, bImage ); + return NULL; + } + Cudd_Ref( bGroup ); + // quantify variables appearing only in this group + bCube = Llb_ManConstructQuantCubeIntern( p, pGroup, Index, fBackward ); Cudd_Ref( bCube ); + bGroup = Cudd_bddExistAbstract( p->dd, bTemp = bGroup, bCube ); + if ( bGroup == NULL ) + { + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bCube ); + return NULL; + } + Cudd_Ref( bGroup ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bCube ); + // perform partial product + if ( fBackward ) + bCube = Llb_ManConstructQuantCubeBwd( p, pGroup, Index ); + else + bCube = Llb_ManConstructQuantCubeFwd( p, pGroup, Index ); + Cudd_Ref( bCube ); +// bImage = Extra_bddAndAbstractTime( p->dd, bTemp = bImage, bGroup, bCube, p->pPars->TimeTarget ); + bImage = Cudd_bddAndAbstract( p->dd, bTemp = bImage, bGroup, bCube ); + if ( bImage == NULL ) + { + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bGroup ); + Cudd_RecursiveDeref( p->dd, bCube ); + return NULL; + } + Cudd_Ref( bImage ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bGroup ); + Cudd_RecursiveDeref( p->dd, bCube ); + } + + // make sure image depends on next state vars + if ( fCheckSupport ) + { + bCube = Cudd_Support( p->dd, bImage ); Cudd_Ref( bCube ); + for ( bTemp = bCube; bTemp != p->dd->one; bTemp = cuddT(bTemp) ) + { + int ObjId = Vec_IntEntry( p->vVar2Obj, bTemp->index ); + Aig_Obj_t * pObj = Aig_ManObj( p->pAig, ObjId ); + if ( !Saig_ObjIsLi(p->pAig, pObj) ) + printf( "Var %d assigned to obj %d that is not LI\n", bTemp->index, ObjId ); + } + Cudd_RecursiveDeref( p->dd, bCube ); + } + Cudd_Deref( bImage ); + return bImage; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManCreateConstraints( Llb_Man_t * p, Vec_Int_t * vHints, int fUseNsVars ) +{ + DdNode * bConstr, * bFunc, * bTemp; + Aig_Obj_t * pObj; + int i, Entry, TimeStop; + if ( vHints == NULL ) + return Cudd_ReadOne( p->dd ); + TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; + assert( Aig_ManPiNum(p->pAig) == Aig_ManPiNum(p->pAigGlo) ); + // assign const and PI nodes to the original AIG + Aig_ManCleanData( p->pAig ); + Aig_ManConst1( p->pAig )->pData = Cudd_ReadOne( p->dd ); + Saig_ManForEachPi( p->pAig, pObj, i ) + pObj->pData = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var,Aig_ObjId(pObj)) ); + Saig_ManForEachLo( p->pAig, pObj, i ) + { + if ( fUseNsVars ) + Entry = Vec_IntEntry( p->vObj2Var, Aig_ObjId(Saig_ObjLoToLi(p->pAig, pObj)) ); + else + Entry = Vec_IntEntry( p->vObj2Var, Aig_ObjId(pObj) ); + pObj->pData = Cudd_bddIthVar( p->dd, Entry ); + } + // transfer them to the global AIG + Aig_ManCleanData( p->pAigGlo ); + Aig_ManConst1( p->pAigGlo )->pData = Cudd_ReadOne( p->dd ); + Aig_ManForEachPi( p->pAigGlo, pObj, i ) + pObj->pData = Aig_ManPi(p->pAig, i)->pData; + // derive consraints + bConstr = Cudd_ReadOne( p->dd ); Cudd_Ref( bConstr ); + Vec_IntForEachEntry( vHints, Entry, i ) + { + if ( Entry != 0 && Entry != 1 ) + continue; + bFunc = Llb_ManConstructOutBdd( p->pAigGlo, Aig_ManObj(p->pAigGlo, i), p->dd ); Cudd_Ref( bFunc ); + bFunc = Cudd_NotCond( bFunc, Entry ); // restrict to not constraint + // make the product + bConstr = Cudd_bddAnd( p->dd, bTemp = bConstr, bFunc ); Cudd_Ref( bConstr ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bFunc ); + } + Cudd_Deref( bConstr ); + p->dd->TimeStop = TimeStop; + return bConstr; +} + +/**Function************************************************************* + + Synopsis [Perform reachability with hints and returns reached states in ppGlo.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Llb_ManReachDeriveCex( Llb_Man_t * p ) +{ + Abc_Cex_t * pCex; + Aig_Obj_t * pObj; + DdNode * bState, * bImage, * bOneCube, * bTemp, * bRing; + int i, v, RetValue, nPiOffset; + char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) ); + assert( Vec_PtrSize(p->vRings) > 0 ); + + p->dd->TimeStop = 0; + p->ddR->TimeStop = 0; + +/* + Saig_ManForEachLo( p->pAig, pObj, i ) + printf( "%d ", pObj->Id ); + printf( "\n" ); + Saig_ManForEachLi( p->pAig, pObj, i ) + printf( "%d(%d) ", pObj->Id, Aig_ObjFaninId0(pObj) ); + printf( "\n" ); +*/ + // allocate room for the counter-example + pCex = Abc_CexAlloc( Saig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Vec_PtrSize(p->vRings) ); + pCex->iFrame = Vec_PtrSize(p->vRings) - 1; + pCex->iPo = -1; + + // get the last cube + bOneCube = Cudd_bddIntersect( p->ddR, (DdNode *)Vec_PtrEntryLast(p->vRings), p->ddR->bFunc ); Cudd_Ref( bOneCube ); + RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); + Cudd_RecursiveDeref( p->ddR, bOneCube ); + assert( RetValue ); + + // write PIs of counter-example + nPiOffset = Saig_ManRegNum(p->pAig) + Saig_ManPiNum(p->pAig) * (Vec_PtrSize(p->vRings) - 1); + Saig_ManForEachPi( p->pAig, pObj, i ) + if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) + Abc_InfoSetBit( pCex->pData, nPiOffset + i ); + + // write state in terms of NS variables + if ( Vec_PtrSize(p->vRings) > 1 ) + { + bState = Llb_CoreComputeCube( p->dd, p->vGlo2Ns, 1, pValues ); Cudd_Ref( bState ); + } + // perform backward analysis + Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v ) + { + if ( v == Vec_PtrSize(p->vRings) - 1 ) + continue; +//Extra_bddPrintSupport( p->dd, bState ); printf( "\n" ); +//Extra_bddPrintSupport( p->dd, bRing ); printf( "\n" ); + // compute the next states + bImage = Llb_ManComputeImage( p, bState, 1 ); + assert( bImage != NULL ); + Cudd_Ref( bImage ); + Cudd_RecursiveDeref( p->dd, bState ); +//Extra_bddPrintSupport( p->dd, bImage ); printf( "\n" ); + + // move reached states into ring manager + bImage = Extra_TransferPermute( p->dd, p->ddR, bTemp = bImage, Vec_IntArray(p->vCs2Glo) ); Cudd_Ref( bImage ); + Cudd_RecursiveDeref( p->dd, bTemp ); +//Extra_bddPrintSupport( p->ddR, bImage ); printf( "\n" ); + + // intersect with the previous set + bOneCube = Cudd_bddIntersect( p->ddR, bImage, bRing ); Cudd_Ref( bOneCube ); + Cudd_RecursiveDeref( p->ddR, bImage ); + + // find any assignment of the BDD + RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); + Cudd_RecursiveDeref( p->ddR, bOneCube ); + assert( RetValue ); +/* + for ( i = 0; i < p->ddR->size; i++ ) + printf( "%d ", pValues[i] ); + printf( "\n" ); +*/ + // write PIs of counter-example + nPiOffset -= Saig_ManPiNum(p->pAig); + Saig_ManForEachPi( p->pAig, pObj, i ) + if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) + Abc_InfoSetBit( pCex->pData, nPiOffset + i ); + + // check that we get the init state + if ( v == 0 ) + { + Saig_ManForEachLo( p->pAig, pObj, i ) + assert( pValues[i] == 0 ); + break; + } + + // write state in terms of NS variables + bState = Llb_CoreComputeCube( p->dd, p->vGlo2Ns, 1, pValues ); Cudd_Ref( bState ); + } + assert( nPiOffset == Saig_ManRegNum(p->pAig) ); + // update the output number +//Abc_CexPrint( pCex ); + RetValue = Saig_ManFindFailedPoCex( p->pAigGlo, pCex ); + assert( RetValue >= 0 && RetValue < Saig_ManPoNum(p->pAigGlo) ); // invalid CEX!!! + pCex->iPo = RetValue; + // cleanup + ABC_FREE( pValues ); + return pCex; +} + +/**Function************************************************************* + + Synopsis [Perform reachability with hints and returns reached states in ppGlo.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManReachability( Llb_Man_t * p, Vec_Int_t * vHints, DdManager ** pddGlo ) +{ + int * pNs2Glo = Vec_IntArray( p->vNs2Glo ); + int * pCs2Glo = Vec_IntArray( p->vCs2Glo ); + int * pGlo2Cs = Vec_IntArray( p->vGlo2Cs ); + DdNode * bCurrent, * bReached, * bNext, * bTemp, * bCube; + DdNode * bConstrCs, * bConstrNs; + int clk2, clk = clock(), nIters, nBddSize = 0; + int nThreshold = 10000; + + // compute time to stop + p->pPars->TimeTarget = p->pPars->TimeLimit ? time(NULL) + p->pPars->TimeLimit : 0; + + // define variable limits + Llb_ManPrepareVarLimits( p ); + + // start the managers + assert( p->dd == NULL ); + assert( p->ddG == NULL ); + assert( p->ddR == NULL ); + p->dd = Cudd_Init( Vec_IntSize(p->vVar2Obj), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + p->ddR = Cudd_Init( Aig_ManPiNum(p->pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + if ( pddGlo && *pddGlo ) + p->ddG = *pddGlo, *pddGlo = NULL; + else + p->ddG = Cudd_Init( Aig_ManRegNum(p->pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + + if ( p->pPars->fReorder ) + { + Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); + Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT ); + Cudd_AutodynEnable( p->ddR, CUDD_REORDER_SYMM_SIFT ); + } + else + { + Cudd_AutodynDisable( p->dd ); + Cudd_AutodynDisable( p->ddG ); + Cudd_AutodynDisable( p->ddR ); + } + + // set the stop time parameter + p->dd->TimeStop = p->pPars->TimeTarget; + p->ddG->TimeStop = p->pPars->TimeTarget; + p->ddR->TimeStop = p->pPars->TimeTarget; + + // create bad state in the ring manager + p->ddR->bFunc = Llb_BddComputeBad( p->pAigGlo, p->ddR, p->pPars->TimeTarget ); + if ( p->ddR->bFunc == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = -1; + return -1; + } + Cudd_Ref( p->ddR->bFunc ); + + // derive constraints + bConstrCs = Llb_ManCreateConstraints( p, vHints, 0 ); Cudd_Ref( bConstrCs ); + bConstrNs = Llb_ManCreateConstraints( p, vHints, 1 ); Cudd_Ref( bConstrNs ); +//Extra_bddPrint( p->dd, bConstrCs ); printf( "\n" ); +//Extra_bddPrint( p->dd, bConstrNs ); printf( "\n" ); + + // perform reachability analysis + // compute the starting set of states + if ( p->ddG->bFunc ) + { + bReached = p->ddG->bFunc; p->ddG->bFunc = NULL; + bCurrent = Extra_TransferPermute( p->ddG, p->dd, bReached, pGlo2Cs ); Cudd_Ref( bCurrent ); + } + else + { + bReached = Llb_ManComputeInitState( p, p->ddG ); Cudd_Ref( bReached ); + bCurrent = Llb_ManComputeInitState( p, p->dd ); Cudd_Ref( bCurrent ); + } +//Extra_bddPrintSupport( p->ddG, bReached ); printf( "\n" ); +//Extra_bddPrintSupport( p->dd, bCurrent ); printf( "\n" ); + +//Extra_bddPrintSupport( p->dd, bCurrent ); printf( "\n" ); + for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ ) + { + clk2 = clock(); + // check the runtime limit + if ( p->pPars->TimeLimit && time(NULL) > p->pPars->TimeTarget ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout during image computation (%d seconds).\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; + Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + + // save the onion ring + bTemp = Extra_TransferPermute( p->dd, p->ddR, bCurrent, pCs2Glo ); + if ( bTemp == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during ring transfer.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; + Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + Cudd_Ref( bTemp ); + Vec_PtrPush( p->vRings, bTemp ); + + // check it for bad states + if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->ddR, bTemp, Cudd_Not(p->ddR->bFunc) ) ) + { + assert( p->pAigGlo->pSeqModel == NULL ); + if ( !p->pPars->fBackward ) + p->pAigGlo->pSeqModel = Llb_ManReachDeriveCex( p ); + if ( !p->pPars->fSilent ) + { + if ( !p->pPars->fBackward ) + printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump a witness). ", p->pAigGlo->pSeqModel->iPo, nIters ); + else + printf( "Output ??? was asserted in frame %d (counter-example is not produced). ", nIters ); + Abc_PrintTime( 1, "Time", clock() - clk ); + } + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; + Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return 0; + } + + // restrict reachable states using constraints + if ( vHints ) + { + bCurrent = Cudd_bddAnd( p->dd, bTemp = bCurrent, bConstrCs ); Cudd_Ref( bCurrent ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + + // quantify variables appearing only in the init state + bCube = Llb_ManConstructQuantCubeIntern( p, (Llb_Grp_t *)Vec_PtrEntry(p->vGroups,0), 0, 0 ); Cudd_Ref( bCube ); + bCurrent = Cudd_bddExistAbstract( p->dd, bTemp = bCurrent, bCube ); Cudd_Ref( bCurrent ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bCube ); + + // compute the next states + bNext = Llb_ManComputeImage( p, bCurrent, 0 ); + if ( bNext == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; + Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + Cudd_Ref( bNext ); + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + + // restrict reachable states using constraints + if ( vHints ) + { + bNext = Cudd_bddAnd( p->dd, bTemp = bNext, bConstrNs ); Cudd_Ref( bNext ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } +//Extra_bddPrintSupport( p->dd, bNext ); printf( "\n" ); + + // remap these states into the current state vars +// bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pNs2Glo ); Cudd_Ref( bNext ); +// Cudd_RecursiveDeref( p->dd, bTemp ); +// bNext = Extra_TransferPermuteTime( p->dd, p->ddG, bTemp = bNext, pNs2Glo, p->pPars->TimeTarget ); + bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pNs2Glo ); + if ( bNext == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; + Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + Cudd_Ref( bNext ); + Cudd_RecursiveDeref( p->dd, bTemp ); + + + // check if there are any new states + if ( Cudd_bddLeq( p->ddG, bNext, bReached ) ) // implication = no new states + { + Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; + break; + } + + // check the BDD size + nBddSize = Cudd_DagSize(bNext); + if ( nBddSize > p->pPars->nBddMax ) + { + Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; + break; + } + + // get the new states + bCurrent = Cudd_bddAnd( p->ddG, bNext, Cudd_Not(bReached) ); + if ( bCurrent == NULL ) + { + Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + break; + } + Cudd_Ref( bCurrent ); + // minimize the new states with the reached states +// bCurrent = Cudd_bddConstrain( p->ddG, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); +// bCurrent = Cudd_bddRestrict( p->ddG, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); +// Cudd_RecursiveDeref( p->ddG, bTemp ); +//printf( "Initial BDD =%7d. Constrained BDD =%7d.\n", Cudd_DagSize(bTemp), Cudd_DagSize(bCurrent) ); + + // remap these states into the current state vars +// bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs ); Cudd_Ref( bCurrent ); +// Cudd_RecursiveDeref( p->ddG, bTemp ); +// bCurrent = Extra_TransferPermuteTime( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs, p->pPars->TimeTarget ); + bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs ); + if ( bCurrent == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->ddG, bTemp ); + Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; + Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + Cudd_Ref( bCurrent ); + Cudd_RecursiveDeref( p->ddG, bTemp ); + + + // add to the reached states + bReached = Cudd_bddOr( p->ddG, bTemp = bReached, bNext ); + if ( bReached == NULL ) + { + Cudd_RecursiveDeref( p->ddG, bTemp ); bTemp = NULL; + Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; + break; + } + Cudd_Ref( bReached ); + Cudd_RecursiveDeref( p->ddG, bTemp ); + Cudd_RecursiveDeref( p->ddG, bNext ); + bNext = NULL; + + if ( p->pPars->fVerbose ) + { + fprintf( stdout, "F =%5d : ", nIters ); + fprintf( stdout, "Im =%6d ", nBddSize ); + fprintf( stdout, "(%4d %3d) ", Cudd_ReadReorderings(p->dd), Cudd_ReadGarbageCollections(p->dd) ); + fprintf( stdout, "Rea =%6d ", Cudd_DagSize(bReached) ); + fprintf( stdout, "(%4d%4d) ", Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) ); + Abc_PrintTime( 1, "Time", clock() - clk2 ); + } +/* + if ( p->pPars->fVerbose ) + { + double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) ); +// Extra_bddPrint( p->ddG, bReached );printf( "\n" ); + fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); + fflush( stdout ); + } +*/ + } + Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; + Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; + if ( bReached == NULL ) + { + p->pPars->iFrame = nIters - 1; + return 0; // reachable + } +// assert( bCurrent == NULL ); + if ( bCurrent ) + Cudd_RecursiveDeref( p->dd, bCurrent ); + // report the stats + if ( p->pPars->fVerbose ) + { + double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) ); + if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax ) + fprintf( stdout, "Reachability analysis is stopped after %d frames.\n", nIters ); + else + fprintf( stdout, "Reachability analysis completed after %d frames.\n", nIters ); + fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); + fflush( stdout ); + } + if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax ) + { + if ( !p->pPars->fSilent ) + printf( "Verified only for states reachable in %d frames. ", nIters ); + p->pPars->iFrame = p->pPars->nIterMax; + Cudd_RecursiveDeref( p->ddG, bReached ); + return -1; // undecided + } + if ( pddGlo ) + { + assert( p->ddG->bFunc == NULL ); + p->ddG->bFunc = bReached; bReached = NULL; + assert( *pddGlo == NULL ); + *pddGlo = p->ddG; p->ddG = NULL; + } + else + Cudd_RecursiveDeref( p->ddG, bReached ); + if ( !p->pPars->fSilent ) + printf( "The miter is proved unreachable after %d iterations. ", nIters ); + p->pPars->iFrame = nIters - 1; + return 1; // unreachable +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/llb/llb1Sched.c b/src/proof/llb/llb1Sched.c new file mode 100644 index 00000000..6bdae42e --- /dev/null +++ b/src/proof/llb/llb1Sched.c @@ -0,0 +1,257 @@ +/**CFile**************************************************************** + + FileName [llb1Sched.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Partition scheduling algorithm.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Sched.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Swaps two rows.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrSwapColumns( Llb_Mtr_t * p, int iCol1, int iCol2 ) +{ + Llb_Grp_t * pGemp; + char * pTemp; + int iTemp; + assert( iCol1 >= 0 && iCol1 < p->nCols ); + assert( iCol2 >= 0 && iCol2 < p->nCols ); + if ( iCol1 == iCol2 ) + return; + assert( iCol1 != iCol2 ); + // swap col groups + pGemp = p->pColGrps[iCol1]; + p->pColGrps[iCol1] = p->pColGrps[iCol2]; + p->pColGrps[iCol2] = pGemp; + // swap col vectors + pTemp = p->pMatrix[iCol1]; + p->pMatrix[iCol1] = p->pMatrix[iCol2]; + p->pMatrix[iCol2] = pTemp; + // swap col sums + iTemp = p->pColSums[iCol1]; + p->pColSums[iCol1] = p->pColSums[iCol2]; + p->pColSums[iCol2] = iTemp; +} + +/**Function************************************************************* + + Synopsis [Find columns which brings as few vars as possible.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_MtrFindBestColumn( Llb_Mtr_t * p, int iGrpStart ) +{ + int Cost, Cost2, CostBest = ABC_INFINITY, Cost2Best = ABC_INFINITY; + int WeightCur, WeightBest = -ABC_INFINITY, iGrp, iGrpBest = -1; + int k, c, iVar, Counter; + // find partition that reduces partial product as much as possible + for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ ) + { + if ( p->pRowSums[iVar] < 2 ) + continue; + // look at present variables that can be quantified + if ( !(p->pProdVars[iVar] == 1 && p->pProdNums[iVar] == 1) ) + continue; + // check that it appears in one partition only + Counter = 0; + for ( c = iGrpStart; c < p->nCols-1; c++ ) + if ( p->pMatrix[c][iVar] == 1 ) + { + iGrp = c; + Counter++; + } + assert( Counter == 1 ); + if ( Counter != 1 ) + Abc_Print( -1, "Llb_MtrFindBestColumn() Internal error!\n" ); + // find weight of this column + WeightCur = 0; + for ( k = 0; k < p->nRows; k++ ) + { + // increase weight if variable k will be quantified from partial product + if ( p->pProdVars[k] == 1 && p->pMatrix[iGrp][k] == 1 && p->pProdNums[k] == 1 ) + WeightCur += 2; + // decrease weight if variable k will be added to partial product + if ( p->pProdVars[k] == 0 && p->pMatrix[iGrp][k] == 1 ) + WeightCur--; + } + if ( WeightCur > 0 && WeightBest < WeightCur ) + { + WeightBest = WeightCur; + iGrpBest = iGrp; + } + } + if ( iGrpBest >= 0 ) + return iGrpBest; + // could not find the group with any vars to quantify + // select the group that contains as few extra variables as possible + // if there is a tie, select variables that appear in less groups than others + for ( iGrp = iGrpStart; iGrp < p->nCols-1; iGrp++ ) + { + Cost = Cost2 = 0; + for ( k = 0; k < p->nRows; k++ ) + if ( p->pProdVars[k] == 0 && p->pMatrix[iGrp][k] == 1 ) + { + Cost++; + Cost2 += p->pProdNums[k]; + } + if ( CostBest > Cost || + (CostBest == Cost && Cost2 > Cost2Best) ) + { + CostBest = Cost; + Cost2Best = Cost2; + iGrpBest = iGrp; + } + } + return iGrpBest; +} + +/**Function************************************************************* + + Synopsis [Returns the number of variables that will be saved.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrUseSelectedColumn( Llb_Mtr_t * p, int iCol ) +{ + int iVar; + assert( iCol >= 1 && iCol < p->nCols - 1 ); + for ( iVar = 0; iVar < p->nRows; iVar++ ) + { + if ( p->pMatrix[iCol][iVar] == 0 ) + continue; + if ( p->pProdVars[iVar] == 1 && p->pProdNums[iVar] == 1 ) + { + p->pProdVars[iVar] = 0; + p->pProdNums[iVar] = 0; + continue; + } + if ( p->pProdVars[iVar] == 0 ) + { + p->pProdVars[iVar] = 1; + p->pProdNums[iVar] = p->pRowSums[iVar]; + } + p->pProdNums[iVar]--; + assert( p->pProdNums[iVar] >= 0 ); + if ( p->pProdNums[iVar] < 0 ) + Abc_Print( -1, "Llb_MtrUseSelectedColumn() Internal error!\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Verify columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrVerifyColumns( Llb_Mtr_t * p, int iGrpStart ) +{ + int iVar, iGrp, Counter; + for ( iVar = 0; iVar < p->nRows; iVar++ ) + { + if ( p->pProdVars[iVar] == 0 ) + continue; + Counter = 0; + for ( iGrp = iGrpStart; iGrp < p->nCols; iGrp++ ) + if ( p->pMatrix[iGrp][iVar] == 1 ) + Counter++; + assert( Counter == p->pProdNums[iVar] ); + if ( Counter != p->pProdNums[iVar] ) + Abc_Print( -1, "Llb_MtrVerifyColumns(): Internal error.\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Matrix reduce.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrSchedule( Llb_Mtr_t * p ) +{ + int iGrp, iGrpBest, i; + // start partial product + for ( i = 0; i < p->nRows; i++ ) + { + if ( i >= p->nPis && i < p->nPis + p->nFfs ) + { + p->pProdVars[i] = 1; + p->pProdNums[i] = p->pRowSums[i] - 1; + } + else + { + p->pProdVars[i] = 0; + p->pProdNums[i] = p->pRowSums[i]; + } + } + // order the partitions + Llb_MtrVerifyMatrix( p ); + for ( iGrp = 1; iGrp < p->nCols-1; iGrp++ ) + { + Llb_MtrVerifyColumns( p, iGrp ); + iGrpBest = Llb_MtrFindBestColumn( p, iGrp ); + Llb_MtrUseSelectedColumn( p, iGrpBest ); + Llb_MtrSwapColumns( p, iGrp, iGrpBest ); + } + Llb_MtrVerifyMatrix( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/llb/llb2Bad.c b/src/proof/llb/llb2Bad.c new file mode 100644 index 00000000..9aecb9ff --- /dev/null +++ b/src/proof/llb/llb2Bad.c @@ -0,0 +1,137 @@ +/**CFile**************************************************************** + + FileName [llb2Bad.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Computing bad states.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Bad.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes bad in working manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_BddComputeBad( Aig_Man_t * pInit, DdManager * dd, int TimeOut ) +{ + Vec_Ptr_t * vNodes; + DdNode * bBdd0, * bBdd1, * bTemp, * bResult; + Aig_Obj_t * pObj; + int i, k; + assert( Cudd_ReadSize(dd) == Aig_ManPiNum(pInit) ); + // initialize elementary variables + Aig_ManConst1(pInit)->pData = Cudd_ReadOne( dd ); + Saig_ManForEachLo( pInit, pObj, i ) + pObj->pData = Cudd_bddIthVar( dd, i ); + Saig_ManForEachPi( pInit, pObj, i ) + pObj->pData = Cudd_bddIthVar( dd, Aig_ManRegNum(pInit) + i ); + // compute internal nodes + vNodes = Aig_ManDfsNodes( pInit, (Aig_Obj_t **)Vec_PtrArray(pInit->vPos), Saig_ManPoNum(pInit) ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) ) + continue; + bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); +// pObj->pData = Extra_bddAndTime( dd, bBdd0, bBdd1, TimeOut ); + pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); + if ( pObj->pData == NULL ) + { + Vec_PtrForEachEntryStop( Aig_Obj_t *, vNodes, pObj, k, i ) + if ( pObj->pData ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + Vec_PtrFree( vNodes ); + return NULL; + } + Cudd_Ref( (DdNode *)pObj->pData ); + } + // quantify PIs of each PO + bResult = Cudd_ReadLogicZero( dd ); Cudd_Ref( bResult ); + Saig_ManForEachPo( pInit, pObj, i ) + { + bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bResult = Cudd_bddOr( dd, bTemp = bResult, bBdd0 ); Cudd_Ref( bResult ); + Cudd_RecursiveDeref( dd, bTemp ); + } + // deref + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) ) + continue; + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + } + Vec_PtrFree( vNodes ); + Cudd_Deref( bResult ); + return bResult; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_BddQuantifyPis( Aig_Man_t * pInit, DdManager * dd, DdNode * bFunc ) +{ + DdNode * bVar, * bCube, * bTemp; + Aig_Obj_t * pObj; + int i, TimeStop; + assert( Cudd_ReadSize(dd) == Aig_ManPiNum(pInit) ); + TimeStop = dd->TimeStop; dd->TimeStop = 0; + // create PI cube + bCube = Cudd_ReadOne( dd ); Cudd_Ref( bCube ); + Saig_ManForEachPi( pInit, pObj, i ) { + bVar = Cudd_bddIthVar( dd, Aig_ManRegNum(pInit) + i ); + bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( dd, bTemp ); + } + // quantify PI cube + bFunc = Cudd_bddExistAbstract( dd, bFunc, bCube ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( dd, bCube ); + Cudd_Deref( bFunc ); + dd->TimeStop = TimeStop; + return bFunc; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/llb/llb2Core.c b/src/proof/llb/llb2Core.c new file mode 100644 index 00000000..c15574c2 --- /dev/null +++ b/src/proof/llb/llb2Core.c @@ -0,0 +1,775 @@ +/**CFile**************************************************************** + + FileName [llb2Core.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Core procedure.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Core.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Llb_Img_t_ Llb_Img_t; +struct Llb_Img_t_ +{ + Aig_Man_t * pInit; // AIG manager + Aig_Man_t * pAig; // AIG manager + Gia_ParLlb_t * pPars; // parameters + + DdManager * dd; // BDD manager + DdManager * ddG; // BDD manager + DdManager * ddR; // BDD manager + Vec_Ptr_t * vDdMans; // BDD managers for each partition + Vec_Ptr_t * vRings; // onion rings in ddR + + Vec_Int_t * vDriRefs; // driver references + Vec_Int_t * vVarsCs; // cur state variables + Vec_Int_t * vVarsNs; // next state variables + + Vec_Int_t * vCs2Glo; // cur state variables into global variables + Vec_Int_t * vNs2Glo; // next state variables into global variables + Vec_Int_t * vGlo2Cs; // global variables into cur state variables + Vec_Int_t * vGlo2Ns; // global variables into next state variables +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes cube composed of given variables with given values.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_CoreComputeCube( DdManager * dd, Vec_Int_t * vVars, int fUseVarIndex, char * pValues ) +{ + DdNode * bRes, * bVar, * bTemp; + int i, iVar, Index, TimeStop; + TimeStop = dd->TimeStop; dd->TimeStop = 0; + bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); + Vec_IntForEachEntry( vVars, Index, i ) + { + iVar = fUseVarIndex ? Index : i; + bVar = Cudd_NotCond( Cudd_bddIthVar(dd, iVar), (int)(pValues == NULL || pValues[i] != 1) ); + bRes = Cudd_bddAnd( dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bRes ); + dd->TimeStop = TimeStop; + return bRes; +} + +/**Function************************************************************* + + Synopsis [Derives counter-example by backward reachability.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Llb_CoreDeriveCex( Llb_Img_t * p ) +{ + Abc_Cex_t * pCex; + Aig_Obj_t * pObj; + Vec_Ptr_t * vSupps, * vQuant0, * vQuant1; + DdNode * bState, * bImage, * bOneCube, * bTemp, * bRing; + int i, v, RetValue, nPiOffset; + char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) ); + assert( Vec_PtrSize(p->vRings) > 0 ); + + p->dd->TimeStop = 0; + p->ddR->TimeStop = 0; + + // get supports and quantified variables + Vec_PtrReverseOrder( p->vDdMans ); + vSupps = Llb_ImgSupports( p->pAig, p->vDdMans, p->vVarsNs, p->vVarsCs, 1, 0 ); + Llb_ImgSchedule( vSupps, &vQuant0, &vQuant1, 0 ); + Vec_VecFree( (Vec_Vec_t *)vSupps ); + Llb_ImgQuantifyReset( p->vDdMans ); +// Llb_ImgQuantifyFirst( p->pAig, p->vDdMans, vQuant0 ); + + // allocate room for the counter-example + pCex = Abc_CexAlloc( Saig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Vec_PtrSize(p->vRings) ); + pCex->iFrame = Vec_PtrSize(p->vRings) - 1; + pCex->iPo = -1; + + // get the last cube + bOneCube = Cudd_bddIntersect( p->ddR, (DdNode *)Vec_PtrEntryLast(p->vRings), p->ddR->bFunc ); Cudd_Ref( bOneCube ); + RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); + Cudd_RecursiveDeref( p->ddR, bOneCube ); + assert( RetValue ); + + // write PIs of counter-example + nPiOffset = Saig_ManRegNum(p->pAig) + Saig_ManPiNum(p->pAig) * (Vec_PtrSize(p->vRings) - 1); + Saig_ManForEachPi( p->pAig, pObj, i ) + if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) + Abc_InfoSetBit( pCex->pData, nPiOffset + i ); + + // write state in terms of NS variables + if ( Vec_PtrSize(p->vRings) > 1 ) + { + bState = Llb_CoreComputeCube( p->dd, p->vVarsNs, 1, pValues ); Cudd_Ref( bState ); + } + // perform backward analysis + Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v ) + { + if ( v == Vec_PtrSize(p->vRings) - 1 ) + continue; + // compute the next states + bImage = Llb_ImgComputeImage( p->pAig, p->vDdMans, p->dd, bState, + vQuant0, vQuant1, p->vDriRefs, p->pPars->TimeTarget, 1, 0, 0 ); + assert( bImage != NULL ); + Cudd_Ref( bImage ); + Cudd_RecursiveDeref( p->dd, bState ); +//Extra_bddPrintSupport( p->dd, bImage ); printf( "\n" ); + + // move reached states into ring manager + bImage = Extra_TransferPermute( p->dd, p->ddR, bTemp = bImage, Vec_IntArray(p->vCs2Glo) ); Cudd_Ref( bImage ); + Cudd_RecursiveDeref( p->dd, bTemp ); + + // intersect with the previous set + bOneCube = Cudd_bddIntersect( p->ddR, bImage, bRing ); Cudd_Ref( bOneCube ); + Cudd_RecursiveDeref( p->ddR, bImage ); + + // find any assignment of the BDD + RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); + Cudd_RecursiveDeref( p->ddR, bOneCube ); + assert( RetValue ); + + // write PIs of counter-example + nPiOffset -= Saig_ManPiNum(p->pAig); + Saig_ManForEachPi( p->pAig, pObj, i ) + if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) + Abc_InfoSetBit( pCex->pData, nPiOffset + i ); + + // check that we get the init state + if ( v == 0 ) + { + Saig_ManForEachLo( p->pAig, pObj, i ) + assert( pValues[i] == 0 ); + break; + } + + // write state in terms of NS variables + bState = Llb_CoreComputeCube( p->dd, p->vVarsNs, 1, pValues ); Cudd_Ref( bState ); + } + assert( nPiOffset == Saig_ManRegNum(p->pAig) ); + // update the output number + RetValue = Saig_ManFindFailedPoCex( p->pInit, pCex ); + assert( RetValue >= 0 && RetValue < Saig_ManPoNum(p->pInit) ); // invalid CEX!!! + pCex->iPo = RetValue; + // cleanup + ABC_FREE( pValues ); + Vec_VecFree( (Vec_Vec_t *)vQuant0 ); + Vec_VecFree( (Vec_Vec_t *)vQuant1 ); + return pCex; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_CoreReachability_int( Llb_Img_t * p, Vec_Ptr_t * vQuant0, Vec_Ptr_t * vQuant1 ) +{ + int * pLoc2Glo = p->pPars->fBackward? Vec_IntArray( p->vCs2Glo ) : Vec_IntArray( p->vNs2Glo ); + int * pLoc2GloR = p->pPars->fBackward? Vec_IntArray( p->vNs2Glo ) : Vec_IntArray( p->vCs2Glo ); + int * pGlo2Loc = p->pPars->fBackward? Vec_IntArray( p->vGlo2Ns ) : Vec_IntArray( p->vGlo2Cs ); + DdNode * bCurrent, * bReached, * bNext, * bTemp; + int clk2, clk = clock(), nIters, nBddSize, iOutFail = -1; +/* + // compute time to stop + if ( p->pPars->TimeLimit ) + p->pPars->TimeTarget = clock() + p->pPars->TimeLimit * CLOCKS_PER_SEC; + else + p->pPars->TimeTarget = 0; +*/ + + if ( time(NULL) > p->pPars->TimeTarget ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) before image computation.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = -1; + return -1; + } + + // set the stop time parameter + p->dd->TimeStop = p->pPars->TimeTarget; + p->ddG->TimeStop = p->pPars->TimeTarget; + p->ddR->TimeStop = p->pPars->TimeTarget; + + // compute initial states + if ( p->pPars->fBackward ) + { + // create init state in the global manager + bTemp = Llb_BddComputeBad( p->pInit, p->ddR, p->pPars->TimeTarget ); + if ( bTemp == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) while computing bad states.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = -1; + return -1; + } + Cudd_Ref( bTemp ); + // create bad state in the ring manager + p->ddR->bFunc = Llb_CoreComputeCube( p->ddR, p->vVarsCs, 0, NULL ); Cudd_Ref( p->ddR->bFunc ); + bCurrent = Llb_BddQuantifyPis( p->pInit, p->ddR, bTemp ); Cudd_Ref( bCurrent ); + Cudd_RecursiveDeref( p->ddR, bTemp ); + bReached = Cudd_bddTransfer( p->ddR, p->ddG, bCurrent ); Cudd_Ref( bReached ); + Cudd_RecursiveDeref( p->ddR, bCurrent ); + // move init state to the working manager + bCurrent = Extra_TransferPermute( p->ddG, p->dd, bReached, pGlo2Loc ); + if ( bCurrent == NULL ) + { + Cudd_RecursiveDeref( p->ddG, bReached ); + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during transfer 0.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = -1; + return -1; + } + Cudd_Ref( bCurrent ); + } + else + { + // create bad state in the ring manager + p->ddR->bFunc = Llb_BddComputeBad( p->pInit, p->ddR, p->pPars->TimeTarget ); + if ( p->ddR->bFunc == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) while computing bad states.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = -1; + return -1; + } + Cudd_Ref( p->ddR->bFunc ); + // create init state in the working and global manager + bCurrent = Llb_CoreComputeCube( p->dd, p->vVarsCs, 1, NULL ); Cudd_Ref( bCurrent ); + bReached = Llb_CoreComputeCube( p->ddG, p->vVarsCs, 0, NULL ); Cudd_Ref( bReached ); +//Extra_bddPrint( p->dd, bCurrent ); printf( "\n" ); +//Extra_bddPrint( p->ddG, bReached ); printf( "\n" ); + } + + // compute onion rings + for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ ) + { + clk2 = clock(); + // check the runtime limit + if ( p->pPars->TimeLimit && time(NULL) > p->pPars->TimeTarget ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + + // save the onion ring + bTemp = Extra_TransferPermute( p->dd, p->ddR, bCurrent, pLoc2GloR ); + if ( bTemp == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + Cudd_Ref( bTemp ); + Vec_PtrPush( p->vRings, bTemp ); + + // check it for bad states + if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->ddR, bTemp, Cudd_Not(p->ddR->bFunc) ) ) + { + assert( p->pInit->pSeqModel == NULL ); + if ( !p->pPars->fBackward ) + p->pInit->pSeqModel = Llb_CoreDeriveCex( p ); + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + if ( !p->pPars->fSilent ) + { + if ( !p->pPars->fBackward ) + printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump a witness). ", p->pInit->pSeqModel->iPo, nIters ); + else + printf( "Output ??? was asserted in frame %d (counter-example is not produced). ", nIters ); + Abc_PrintTime( 1, "Time", clock() - clk ); + } + p->pPars->iFrame = nIters - 1; + return 0; + } + + // compute the next states + bNext = Llb_ImgComputeImage( p->pAig, p->vDdMans, p->dd, bCurrent, + vQuant0, vQuant1, p->vDriRefs, p->pPars->TimeTarget, + p->pPars->fBackward, p->pPars->fReorder, p->pPars->fVeryVerbose ); + if ( bNext == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + Cudd_Ref( bNext ); + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; +//Extra_bddPrintSupport( p->dd, bNext ); printf( "\n" ); + + // remap these states into the global manager +// bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pLoc2Glo ); Cudd_Ref( bNext ); +// Cudd_RecursiveDeref( p->dd, bTemp ); + +// bNext = Extra_TransferPermuteTime( p->dd, p->ddG, bTemp = bNext, pLoc2Glo, p->pPars->TimeTarget ); + bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pLoc2Glo ); + if ( bNext == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + Cudd_Ref( bNext ); + Cudd_RecursiveDeref( p->dd, bTemp ); + + nBddSize = Cudd_DagSize(bNext); + // check if there are any new states + if ( Cudd_bddLeq( p->ddG, bNext, bReached ) ) // implication = no new states + { + Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; + break; + } + + // get the new states + bCurrent = Cudd_bddAnd( p->ddG, bNext, Cudd_Not(bReached) ); + if ( bCurrent == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->ddG, bNext ); + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + Cudd_Ref( bCurrent ); + + // remap these states into the current state vars +// bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Loc ); Cudd_Ref( bCurrent ); +// Cudd_RecursiveDeref( p->ddG, bTemp ); + +// bCurrent = Extra_TransferPermuteTime( p->ddG, p->dd, bTemp = bCurrent, pGlo2Loc, p->pPars->TimeTarget ); + bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Loc ); + if ( bCurrent == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->ddG, bTemp ); + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + Cudd_Ref( bCurrent ); + Cudd_RecursiveDeref( p->ddG, bTemp ); + + // add to the reached states + bReached = Cudd_bddOr( p->ddG, bTemp = bReached, bNext ); Cudd_Ref( bReached ); + Cudd_RecursiveDeref( p->ddG, bTemp ); + Cudd_RecursiveDeref( p->ddG, bNext ); + bNext = NULL; + + if ( p->pPars->fVeryVerbose ) + { + double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) ); +// Extra_bddPrint( p->ddG, bReached );printf( "\n" ); + fprintf( stdout, " Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); + fflush( stdout ); + } + if ( p->pPars->fVerbose ) + { + fprintf( stdout, "F =%3d : ", nIters ); + fprintf( stdout, "Image =%6d ", nBddSize ); + fprintf( stdout, "(%4d%4d) ", + Cudd_ReadReorderings(p->dd), Cudd_ReadGarbageCollections(p->dd) ); + fprintf( stdout, "Reach =%6d ", Cudd_DagSize(bReached) ); + fprintf( stdout, "(%4d%4d) ", + Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) ); + Abc_PrintTime( 1, "Time", clock() - clk2 ); + } + + // check timeframe limit + if ( nIters == p->pPars->nIterMax - 1 ) + { + if ( !p->pPars->fSilent ) + printf( "Reached limit on the number of timeframes (%d).\n", p->pPars->nIterMax ); + p->pPars->iFrame = nIters; + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + } + if ( bReached == NULL ) + { + p->pPars->iFrame = nIters - 1; + return 0; // reachable + } + if ( bCurrent ) + Cudd_RecursiveDeref( p->dd, bCurrent ); + // report the stats + if ( p->pPars->fVerbose ) + { + double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) ); + if ( nIters >= p->pPars->nIterMax ) + fprintf( stdout, "Reachability analysis is stopped after %d frames.\n", nIters ); + else + fprintf( stdout, "Reachability analysis completed after %d frames.\n", nIters ); + fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); + fflush( stdout ); + } + if ( p->pPars->fDumpReached ) + { + Llb_ManDumpReached( p->ddG, bReached, p->pAig->pName, "reached.blif" ); + printf( "Reached states with %d BDD nodes are dumpted into file \"reached.blif\".\n", Cudd_DagSize(bReached) ); + } + Cudd_RecursiveDeref( p->ddG, bReached ); + if ( nIters >= p->pPars->nIterMax ) + { + if ( !p->pPars->fSilent ) + { + printf( "Verified only for states reachable in %d frames. ", nIters ); + Abc_PrintTime( 1, "Time", clock() - clk ); + } + p->pPars->iFrame = p->pPars->nIterMax; + return -1; // undecided + } + if ( !p->pPars->fSilent ) + { + printf( "The miter is proved unreachable after %d iterations. ", nIters ); + Abc_PrintTime( 1, "Time", clock() - clk ); + } + p->pPars->iFrame = nIters - 1; + return 1; // unreachable +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_CoreReachability( Llb_Img_t * p ) +{ + Vec_Ptr_t * vSupps, * vQuant0, * vQuant1; + int RetValue; + // get supports and quantified variables + if ( p->pPars->fBackward ) + { + Vec_PtrReverseOrder( p->vDdMans ); + vSupps = Llb_ImgSupports( p->pAig, p->vDdMans, p->vVarsNs, p->vVarsCs, 0, p->pPars->fVeryVerbose ); + } + else + vSupps = Llb_ImgSupports( p->pAig, p->vDdMans, p->vVarsCs, p->vVarsNs, 0, p->pPars->fVeryVerbose ); + Llb_ImgSchedule( vSupps, &vQuant0, &vQuant1, p->pPars->fVeryVerbose ); + Vec_VecFree( (Vec_Vec_t *)vSupps ); + // remove variables + Llb_ImgQuantifyFirst( p->pAig, p->vDdMans, vQuant0, p->pPars->fVeryVerbose ); + // perform reachability + RetValue = Llb_CoreReachability_int( p, vQuant0, vQuant1 ); + Vec_VecFree( (Vec_Vec_t *)vQuant0 ); + Vec_VecFree( (Vec_Vec_t *)vQuant1 ); + return RetValue; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_CoreConstructAll( Aig_Man_t * p, Vec_Ptr_t * vResult, Vec_Int_t * vVarsNs, int TimeTarget ) +{ + DdManager * dd; + Vec_Ptr_t * vDdMans; + Vec_Ptr_t * vLower, * vUpper; + int i; + vDdMans = Vec_PtrStart( Vec_PtrSize(vResult) ); + Vec_PtrForEachEntryReverse( Vec_Ptr_t *, vResult, vLower, i ) + { + if ( i < Vec_PtrSize(vResult) - 1 ) + dd = Llb_ImgPartition( p, vLower, vUpper, TimeTarget ); + else + dd = Llb_DriverLastPartition( p, vVarsNs, TimeTarget ); + if ( dd == NULL ) + { + Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i ) + { + if ( dd == NULL ) + continue; + if ( dd->bFunc ) + Cudd_RecursiveDeref( dd, dd->bFunc ); + Extra_StopManager( dd ); + } + Vec_PtrFree( vDdMans ); + return NULL; + } + Vec_PtrWriteEntry( vDdMans, i, dd ); + vUpper = vLower; + } + return vDdMans; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_CoreSetVarMaps( Llb_Img_t * p ) +{ + Aig_Obj_t * pObj; + int i, iVarCs, iVarNs; + assert( p->vVarsCs != NULL ); + assert( p->vVarsNs != NULL ); + assert( p->vCs2Glo == NULL ); + assert( p->vNs2Glo == NULL ); + assert( p->vGlo2Cs == NULL ); + assert( p->vGlo2Ns == NULL ); + p->vCs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) ); + p->vNs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) ); + p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); + p->vGlo2Ns = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); + for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ ) + { + iVarCs = Vec_IntEntry( p->vVarsCs, i ); + iVarNs = Vec_IntEntry( p->vVarsNs, i ); + assert( iVarCs >= 0 && iVarCs < Aig_ManObjNumMax(p->pAig) ); + assert( iVarNs >= 0 && iVarNs < Aig_ManObjNumMax(p->pAig) ); + Vec_IntWriteEntry( p->vCs2Glo, iVarCs, i ); + Vec_IntWriteEntry( p->vNs2Glo, iVarNs, i ); + Vec_IntWriteEntry( p->vGlo2Cs, i, iVarCs ); + Vec_IntWriteEntry( p->vGlo2Ns, i, iVarNs ); + } + // add mapping of the PIs + Saig_ManForEachPi( p->pAig, pObj, i ) + Vec_IntWriteEntry( p->vCs2Glo, Aig_ObjId(pObj), Aig_ManRegNum(p->pAig)+i ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Img_t * Llb_CoreStart( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) +{ + Llb_Img_t * p; + p = ABC_CALLOC( Llb_Img_t, 1 ); + p->pInit = pInit; + p->pAig = pAig; + p->pPars = pPars; + p->dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + p->ddG = Cudd_Init( Aig_ManRegNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + p->ddR = Cudd_Init( Aig_ManPiNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); + Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT ); + Cudd_AutodynEnable( p->ddR, CUDD_REORDER_SYMM_SIFT ); + p->vRings = Vec_PtrAlloc( 100 ); + p->vDriRefs = Llb_DriverCountRefs( pAig ); + p->vVarsCs = Llb_DriverCollectCs( pAig ); + p->vVarsNs = Llb_DriverCollectNs( pAig, p->vDriRefs ); + Llb_CoreSetVarMaps( p ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_CoreStop( Llb_Img_t * p ) +{ + DdManager * dd; + DdNode * bTemp; + int i; + if ( p->vDdMans ) + Vec_PtrForEachEntry( DdManager *, p->vDdMans, dd, i ) + { + if ( dd->bFunc ) + Cudd_RecursiveDeref( dd, dd->bFunc ); + if ( dd->bFunc2 ) + Cudd_RecursiveDeref( dd, dd->bFunc2 ); + Extra_StopManager( dd ); + } + Vec_PtrFreeP( &p->vDdMans ); + if ( p->ddR->bFunc ) + Cudd_RecursiveDeref( p->ddR, p->ddR->bFunc ); + Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i ) + Cudd_RecursiveDeref( p->ddR, bTemp ); + Vec_PtrFree( p->vRings ); + Extra_StopManager( p->dd ); + Extra_StopManager( p->ddG ); + Extra_StopManager( p->ddR ); + Vec_IntFreeP( &p->vDriRefs ); + Vec_IntFreeP( &p->vVarsCs ); + Vec_IntFreeP( &p->vVarsNs ); + Vec_IntFreeP( &p->vCs2Glo ); + Vec_IntFreeP( &p->vNs2Glo ); + Vec_IntFreeP( &p->vGlo2Cs ); + Vec_IntFreeP( &p->vGlo2Ns ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_CoreExperiment( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars, Vec_Ptr_t * vResult, int TimeTarget ) +{ + int RetValue; + Llb_Img_t * p; +// printf( "\n" ); +// pPars->fVerbose = 1; + p = Llb_CoreStart( pInit, pAig, pPars ); + p->vDdMans = Llb_CoreConstructAll( pAig, vResult, p->vVarsNs, TimeTarget ); + if ( p->vDdMans == NULL ) + { + if ( !pPars->fSilent ) + printf( "Reached timeout (%d seconds) while deriving the partitions.\n", pPars->TimeLimit ); + Llb_CoreStop( p ); + return -1; + } + RetValue = Llb_CoreReachability( p ); + Llb_CoreStop( p ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManReachMinCut( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) +{ + extern Vec_Ptr_t * Llb_ManComputeCuts( Aig_Man_t * p, int Num, int fVerbose, int fVeryVerbose ); + Vec_Ptr_t * vResult; + Aig_Man_t * p; + int RetValue = -1; + int clk = clock(); + + // compute time to stop + pPars->TimeTarget = pPars->TimeLimit ? time(NULL) + pPars->TimeLimit : 0; + + p = Aig_ManDupFlopsOnly( pAig ); +//Aig_ManShow( p, 0, NULL ); + if ( pPars->fVerbose ) + Aig_ManPrintStats( pAig ); + if ( pPars->fVerbose ) + Aig_ManPrintStats( p ); + Aig_ManFanoutStart( p ); + + vResult = Llb_ManComputeCuts( p, pPars->nPartValue, pPars->fVerbose, pPars->fVeryVerbose ); + + if ( pPars->TimeLimit && time(NULL) > pPars->TimeTarget ) + { + if ( !pPars->fSilent ) + printf( "Reached timeout (%d seconds) after partitioning.\n", pPars->TimeLimit ); + + Vec_VecFree( (Vec_Vec_t *)vResult ); + Aig_ManFanoutStop( p ); + Aig_ManCleanMarkAB( p ); + Aig_ManStop( p ); + return RetValue; + } + + if ( !pPars->fSkipReach ) + RetValue = Llb_CoreExperiment( pAig, p, pPars, vResult, pPars->TimeTarget ); + + Vec_VecFree( (Vec_Vec_t *)vResult ); + Aig_ManFanoutStop( p ); + Aig_ManCleanMarkAB( p ); + Aig_ManStop( p ); + + if ( RetValue == -1 ) + Abc_PrintTime( 1, "Total runtime of the min-cut-based reachability engine", clock() - clk ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/llb/llb2Driver.c b/src/proof/llb/llb2Driver.c new file mode 100644 index 00000000..041a39d5 --- /dev/null +++ b/src/proof/llb/llb2Driver.c @@ -0,0 +1,221 @@ +/**CFile**************************************************************** + + FileName [llb2Driver.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Procedures working with flop drivers.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Driver.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// driver issue:arises when creating +// - driver ref-counter array +// - Ns2Glo maps +// - final partition +// - change-phase cube + +// LI variable is used when +// - driver drives more than one LI +// - driver is a PI +// - driver is a constant + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the array of times each flop driver is referenced.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_DriverCountRefs( Aig_Man_t * p ) +{ + Vec_Int_t * vCounts; + Aig_Obj_t * pObj; + int i; + vCounts = Vec_IntStart( Aig_ManObjNumMax(p) ); + Saig_ManForEachLi( p, pObj, i ) + Vec_IntAddToEntry( vCounts, Aig_ObjFaninId0(pObj), 1 ); + return vCounts; +} + +/**Function************************************************************* + + Synopsis [Returns array of NS variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_DriverCollectNs( Aig_Man_t * pAig, Vec_Int_t * vDriRefs ) +{ + Vec_Int_t * vVars; + Aig_Obj_t * pObj, * pDri; + int i; + vVars = Vec_IntAlloc( Aig_ManRegNum(pAig) ); + Saig_ManForEachLi( pAig, pObj, i ) + { + pDri = Aig_ObjFanin0(pObj); + if ( Vec_IntEntry( vDriRefs, Aig_ObjId(pDri) ) != 1 || Saig_ObjIsPi(pAig, pDri) || Aig_ObjIsConst1(pDri) ) + Vec_IntPush( vVars, Aig_ObjId(pObj) ); + else + Vec_IntPush( vVars, Aig_ObjId(pDri) ); + } + return vVars; +} + +/**Function************************************************************* + + Synopsis [Returns array of CS variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_DriverCollectCs( Aig_Man_t * pAig ) +{ + Vec_Int_t * vVars; + Aig_Obj_t * pObj; + int i; + vVars = Vec_IntAlloc( Aig_ManRegNum(pAig) ); + Saig_ManForEachLo( pAig, pObj, i ) + Vec_IntPush( vVars, Aig_ObjId(pObj) ); + return vVars; +} + +/**Function************************************************************* + + Synopsis [Create cube for phase swapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_DriverPhaseCube( Aig_Man_t * pAig, Vec_Int_t * vDriRefs, DdManager * dd ) +{ + DdNode * bCube, * bVar, * bTemp; + Aig_Obj_t * pObj; + int i, TimeStop; + TimeStop = dd->TimeStop; dd->TimeStop = 0; + bCube = Cudd_ReadOne( dd ); Cudd_Ref( bCube ); + Saig_ManForEachLi( pAig, pObj, i ) + { + assert( Vec_IntEntry( vDriRefs, Aig_ObjFaninId0(pObj) ) >= 1 ); + if ( Vec_IntEntry( vDriRefs, Aig_ObjFaninId0(pObj) ) != 1 ) + continue; + if ( !Aig_ObjFaninC0(pObj) ) + continue; + bVar = Cudd_bddIthVar( dd, Aig_ObjFaninId0(pObj) ); + bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bCube ); + dd->TimeStop = TimeStop; + return bCube; +} + +/**Function************************************************************* + + Synopsis [Compute the last partition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdManager * Llb_DriverLastPartition( Aig_Man_t * p, Vec_Int_t * vVarsNs, int TimeTarget ) +{ + int fVerbose = 1; + DdManager * dd; + DdNode * bVar1, * bVar2, * bProd, * bRes, * bTemp; + Aig_Obj_t * pObj; + int i; + dd = Cudd_Init( Aig_ManObjNumMax(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + dd->TimeStop = TimeTarget; + bRes = Cudd_ReadOne(dd); Cudd_Ref( bRes ); + + // mark the duplicated flop inputs + Aig_ManForEachObjVec( vVarsNs, p, pObj, i ) + { + if ( !Saig_ObjIsLi(p, pObj) ) + continue; + bVar1 = Cudd_bddIthVar( dd, Aig_ObjId(pObj) ); + bVar2 = Cudd_bddIthVar( dd, Aig_ObjFaninId0(pObj) ); + if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) + bVar2 = Cudd_ReadOne(dd); + bVar2 = Cudd_NotCond( bVar2, Aig_ObjFaninC0(pObj) ); + bProd = Cudd_bddXnor( dd, bVar1, bVar2 ); Cudd_Ref( bProd ); +// bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd ); Cudd_Ref( bRes ); +// bRes = Extra_bddAndTime( dd, bTemp = bRes, bProd, TimeTarget ); + bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bProd ); + return NULL; + } + Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bProd ); + } + +/* + Saig_ManForEachLi( p, pObj, i ) + printf( "%d ", Aig_ObjId(pObj) ); + printf( "\n" ); + Saig_ManForEachLi( p, pObj, i ) + printf( "%c%d ", Aig_ObjFaninC0(pObj)? '-':'+', Aig_ObjFaninId0(pObj) ); + printf( "\n" ); +*/ + Cudd_AutodynDisable( dd ); +// Cudd_RecursiveDeref( dd, bRes ); +// Extra_StopManager( dd ); + dd->bFunc = bRes; + dd->TimeStop = 0; + return dd; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/llb/llb2Dump.c b/src/proof/llb/llb2Dump.c new file mode 100644 index 00000000..74f07922 --- /dev/null +++ b/src/proof/llb/llb2Dump.c @@ -0,0 +1,104 @@ +/**CFile**************************************************************** + + FileName [llb2Dump.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Dumps the BDD of reached states into a file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Dump.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns a dummy name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Llb_ManGetDummyName( char * pPrefix, int Num, int nDigits ) +{ + static char Buffer[2000]; + sprintf( Buffer, "%s%0*d", pPrefix, nDigits, Num ); + return Buffer; +} + +/**Function************************************************************* + + Synopsis [Writes reached state BDD into a BLIF file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManDumpReached( DdManager * ddG, DdNode * bReached, char * pModel, char * pFileName ) +{ + FILE * pFile; + Vec_Ptr_t * vNamesIn, * vNamesOut; + char * pName; + int i, nDigits; + // reorder the BDD + Cudd_ReduceHeap( ddG, CUDD_REORDER_SYMM_SIFT, 1 ); + + // create input names + nDigits = Abc_Base10Log( Cudd_ReadSize(ddG) ); + vNamesIn = Vec_PtrAlloc( Cudd_ReadSize(ddG) ); + for ( i = 0; i < Cudd_ReadSize(ddG); i++ ) + { + pName = Llb_ManGetDummyName( "ff", i, nDigits ); + Vec_PtrPush( vNamesIn, Extra_UtilStrsav(pName) ); + } + // create output names + vNamesOut = Vec_PtrAlloc( 1 ); + Vec_PtrPush( vNamesOut, Extra_UtilStrsav("Reached") ); + + // write the file + pFile = fopen( pFileName, "wb" ); + Cudd_DumpBlif( ddG, 1, &bReached, (char **)Vec_PtrArray(vNamesIn), (char **)Vec_PtrArray(vNamesOut), pModel, pFile, 0 ); + fclose( pFile ); + + // cleanup + Vec_PtrForEachEntry( char *, vNamesIn, pName, i ) + ABC_FREE( pName ); + Vec_PtrForEachEntry( char *, vNamesOut, pName, i ) + ABC_FREE( pName ); + Vec_PtrFree( vNamesIn ); + Vec_PtrFree( vNamesOut ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/llb/llb2Flow.c b/src/proof/llb/llb2Flow.c new file mode 100644 index 00000000..ebb4e038 --- /dev/null +++ b/src/proof/llb/llb2Flow.c @@ -0,0 +1,1374 @@ +/**CFile**************************************************************** + + FileName [llb2Flow.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Flow computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Flow.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Llb_ObjSetPath( Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { pObj->pData = (void *)pNext; return 1; } +static inline Aig_Obj_t * Llb_ObjGetPath( Aig_Obj_t * pObj ) { return (Aig_Obj_t *)pObj->pData; } +static inline Aig_Obj_t * Llb_ObjGetFanoutPath( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pFanout; + int i, iFanout; + assert( Llb_ObjGetPath(pObj) ); + Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) + if ( Llb_ObjGetPath(pFanout) == pObj ) + return pFanout; + return NULL; +} + +extern Vec_Ptr_t * Llb_ManCutSupp( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +/**Function************************************************************* + + Synopsis [For each cut, returns PIs that can be quantified.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManCutSupps( Aig_Man_t * p, Vec_Ptr_t * vResult ) +{ + Vec_Ptr_t * vSupps, * vOne, * vLower, * vUpper; + int i; + vSupps = Vec_PtrAlloc( 100 ); + Vec_PtrPush( vSupps, Vec_PtrAlloc(0) ); + vLower = (Vec_Ptr_t *)Vec_PtrEntry( vResult, 0 ); + Vec_PtrForEachEntryStart( Vec_Ptr_t *, vResult, vUpper, i, 1 ) + { + vOne = Llb_ManCutSupp( p, vLower, vUpper ); + Vec_PtrPush( vSupps, vOne ); + vLower = vUpper; + } + assert( Vec_PtrSize(vSupps) == Vec_PtrSize(vResult) ); + return vSupps; +} + +/**Function************************************************************* + + Synopsis [For each cut, returns PIs that can be quantified.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManCutMap( Aig_Man_t * p, Vec_Ptr_t * vResult, Vec_Ptr_t * vSupps ) +{ + int fShowMatrix = 1; + Vec_Ptr_t * vMaps, * vOne; + Vec_Int_t * vMap, * vPrev, * vNext; + Aig_Obj_t * pObj; + int * piFirst, * piLast; + int i, k, CounterPlus, CounterMinus, Counter; + + vMaps = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( Vec_Ptr_t *, vResult, vOne, i ) + { + vMap = Vec_IntStart( Aig_ManObjNumMax(p) ); + Vec_PtrForEachEntry( Aig_Obj_t *, vOne, pObj, k ) + { + if ( !Saig_ObjIsPi(p, pObj) ) + Vec_IntWriteEntry( vMap, pObj->Id, 1 ); +// else +//printf( "*" ); +//printf( "%d ", pObj->Id ); + } + Vec_PtrPush( vMaps, vMap ); +//printf( "\n" ); + } + Vec_PtrPush( vMaps, Vec_IntStart( Aig_ManObjNumMax(p) ) ); + assert( Vec_PtrSize(vMaps) == Vec_PtrSize(vResult)+1 ); + + // collect the first and last PIs + piFirst = ABC_ALLOC( int, Saig_ManPiNum(p) ); + piLast = ABC_ALLOC( int, Saig_ManPiNum(p) ); + Saig_ManForEachPi( p, pObj, i ) + piFirst[i] = piLast[i] = -1; + Vec_PtrForEachEntry( Vec_Ptr_t *, vSupps, vOne, i ) + { + Vec_PtrForEachEntry( Aig_Obj_t *, vOne, pObj, k ) + { + if ( !Saig_ObjIsPi(p, pObj) ) + continue; + if ( piFirst[Aig_ObjPioNum(pObj)] == -1 ) + piFirst[Aig_ObjPioNum(pObj)] = i; + piLast[Aig_ObjPioNum(pObj)] = i; + } + } + // PIs feeding into the flops should be extended to the last frame + Saig_ManForEachLi( p, pObj, i ) + { + if ( !Saig_ObjIsPi(p, Aig_ObjFanin0(pObj)) ) + continue; + piLast[Aig_ObjPioNum(Aig_ObjFanin0(pObj))] = Vec_PtrSize(vMaps)-1; + } + + // set the PI map + Saig_ManForEachPi( p, pObj, i ) + { + if ( piFirst[i] == -1 ) + continue; + if ( piFirst[i] == piLast[i] ) + { + vMap = (Vec_Int_t *)Vec_PtrEntry( vMaps, piFirst[i] ); + Vec_IntWriteEntry( vMap, pObj->Id, 2 ); + continue; + } + + // set support for all in between + for ( k = piFirst[i]; k <= piLast[i]; k++ ) + { + vMap = (Vec_Int_t *)Vec_PtrEntry( vMaps, k ); + Vec_IntWriteEntry( vMap, pObj->Id, 1 ); + } + } + ABC_FREE( piFirst ); + ABC_FREE( piLast ); + + + // find all that will appear here + Counter = Aig_ManRegNum(p); + printf( "%d ", Counter ); + Vec_PtrForEachEntryStart( Vec_Int_t *, vMaps, vMap, i, 1 ) + { + vPrev = (Vec_Int_t *)Vec_PtrEntry( vMaps, i-1 ); + vNext = (i == Vec_PtrSize(vMaps)-1)? NULL: (Vec_Int_t *)Vec_PtrEntry( vMaps, i+1 ); + + CounterPlus = CounterMinus = 0; + Aig_ManForEachObj( p, pObj, k ) + { + if ( Saig_ObjIsPi(p, pObj) ) + { + if ( Vec_IntEntry(vPrev, k) == 0 && Vec_IntEntry(vMap, k) == 1 ) + CounterPlus++; + if ( Vec_IntEntry(vMap, k) == 1 && (vNext == NULL || Vec_IntEntry(vNext, k) == 0) ) + CounterMinus++; + } + else + { + if ( Vec_IntEntry(vPrev, k) == 0 && Vec_IntEntry(vMap, k) == 1 ) + CounterPlus++; + if ( Vec_IntEntry(vPrev, k) == 1 && Vec_IntEntry(vMap, k) == 0 ) + CounterMinus++; + } + } + Counter = Counter + CounterPlus - CounterMinus; + printf( "%d=%d ", i, Counter ); + } + printf( "\n" ); + + if ( fShowMatrix ) + Aig_ManForEachObj( p, pObj, i ) + { + if ( !Aig_ObjIsPi(pObj) && !Aig_ObjIsNode(pObj) ) + continue; + Vec_PtrForEachEntry( Vec_Int_t *, vMaps, vMap, k ) + if ( Vec_IntEntry(vMap, i) ) + break; + if ( k == Vec_PtrSize(vMaps) ) + continue; + printf( "Obj = %4d : ", i ); + if ( Saig_ObjIsPi(p,pObj) ) + printf( "pi " ); + else if ( Saig_ObjIsLo(p,pObj) ) + printf( "lo " ); + else if ( Aig_ObjIsNode(pObj) ) + printf( "and " ); + + Vec_PtrForEachEntry( Vec_Int_t *, vMaps, vMap, k ) + printf( "%d", Vec_IntEntry(vMap, i) ); + printf( "\n" ); + } + return vMaps; +} + +/**Function************************************************************* + + Synopsis [Counts the number of PIs in the cut] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManCutPiNum( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) + if ( Saig_ObjIsPi(p,pObj) ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of LOs in the cut] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManCutLoNum( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) + if ( Saig_ObjIsLo(p,pObj) ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of LIs in the cut] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManCutLiNum( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) +{ + Aig_Obj_t * pFanout; + Aig_Obj_t * pObj; + int i, k, iFanout, Counter = 0; + Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) + { + if ( Aig_ObjIsPi(pObj) ) + continue; + Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, k ) + { + if ( Saig_ObjIsLi(p, pFanout) ) + { + Counter++; + break; + } + } + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManCutVolume_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return 0; + Aig_ObjSetTravIdCurrent(p, pObj); + assert( Aig_ObjIsNode(pObj) ); + return 1 + Llb_ManCutVolume_rec(p, Aig_ObjFanin0(pObj)) + + Llb_ManCutVolume_rec(p, Aig_ObjFanin1(pObj)); +} + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManCutVolume( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + // mark the lower cut with the traversal ID + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + // count the upper cut + Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) + Counter += Llb_ManCutVolume_rec( p, pObj ); + return Counter; +} + + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManCutNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + assert( Aig_ObjIsNode(pObj) ); + Llb_ManCutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); + Llb_ManCutNodes_rec(p, Aig_ObjFanin1(pObj), vNodes); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManCutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + // mark the lower cut with the traversal ID + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + // count the upper cut + vNodes = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) + Llb_ManCutNodes_rec( p, pObj, vNodes ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManCutSupp( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) +{ + Vec_Ptr_t * vNodes, * vSupp; + Aig_Obj_t * pObj; + int i; + vNodes = Llb_ManCutNodes( p, vLower, vUpper ); + // mark support of the nodes + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + assert( Aig_ObjIsNode(pObj) ); + Aig_ObjSetTravIdCurrent( p, Aig_ObjFanin0(pObj) ); + Aig_ObjSetTravIdCurrent( p, Aig_ObjFanin1(pObj) ); + } + Vec_PtrFree( vNodes ); + // collect the support nodes + vSupp = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + Vec_PtrPush( vSupp, pObj ); + return vSupp; + +} + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManCutRange( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) +{ + Vec_Ptr_t * vRange; + Aig_Obj_t * pObj; + int i; + // mark the lower cut with the traversal ID + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + // collect the upper ones that are not marked + vRange = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) + if ( !Aig_ObjIsTravIdCurrent(p, pObj) ) + Vec_PtrPush( vRange, pObj ); + return vRange; +} + + + + +/**Function************************************************************* + + Synopsis [Prints the given cluster.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManCutPrint( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) +{ + Vec_Ptr_t * vSupp, * vRange; + int Pis, Ffs, And; + + Pis = Llb_ManCutPiNum(p, vLower); + Ffs = Llb_ManCutLoNum(p, vLower); + And = Vec_PtrSize(vLower) - Pis - Ffs; + printf( "Leaf: %3d=%3d+%3d+%3d ", Vec_PtrSize(vLower), Pis, Ffs, And ); + + Pis = Llb_ManCutPiNum(p, vUpper); + Ffs = Llb_ManCutLiNum(p, vUpper); + And = Vec_PtrSize(vUpper) - Pis - Ffs; + printf( "Root: %3d=%3d+%3d+%3d ", Vec_PtrSize(vUpper), Pis, Ffs, And ); + + vSupp = Llb_ManCutSupp( p, vLower, vUpper ); + Pis = Llb_ManCutPiNum(p, vSupp); + Ffs = Llb_ManCutLoNum(p, vSupp); + And = Vec_PtrSize(vSupp) - Pis - Ffs; + printf( "Supp: %3d=%3d+%3d+%3d ", Vec_PtrSize(vSupp), Pis, Ffs, And ); + + vRange = Llb_ManCutRange( p, vLower, vUpper ); + Pis = Llb_ManCutPiNum(p, vRange); + Ffs = Llb_ManCutLiNum(p, vRange); + And = Vec_PtrSize(vRange) - Pis - Ffs; + printf( "Range: %3d=%3d+%3d+%3d ", Vec_PtrSize(vRange), Pis, Ffs, And ); + + printf( "S =%3d. V =%3d.\n", + Vec_PtrSize(vSupp)+Vec_PtrSize(vRange), Llb_ManCutVolume(p, vLower, vUpper) ); + Vec_PtrFree( vSupp ); + Vec_PtrFree( vRange ); +/* + { + Aig_Obj_t * pObj; + int i; + printf( "Lower: " ); + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + printf( " %d", pObj->Id ); + printf( " " ); + printf( "Upper: " ); + Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) + printf( " %d", pObj->Id ); + printf( "\n" ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Prints the given cluster.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManResultPrint( Aig_Man_t * p, Vec_Ptr_t * vResult ) +{ + Vec_Ptr_t * vLower, * vUpper; + int i; + Vec_PtrForEachEntryReverse( Vec_Ptr_t *, vResult, vLower, i ) + { + if ( i < Vec_PtrSize(vResult) - 1 ) + Llb_ManCutPrint( p, vLower, vUpper ); + vUpper = vLower; + } +} + +/**Function************************************************************* + + Synopsis [Tries to find an augmenting path originating in this node.] + + Description [This procedure works for directed graphs only!] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManFlowBwdPath2_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pFanout; + assert( Aig_ObjIsNode(pObj) || Aig_ObjIsPi(pObj) || Aig_ObjIsConst1(pObj) ); + // skip visited nodes + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return 0; + Aig_ObjSetTravIdCurrent(p, pObj); + // process node without flow + if ( !Llb_ObjGetPath(pObj) ) + { + // start the path if we reached a terminal node + if ( pObj->fMarkA ) + return Llb_ObjSetPath( pObj, (Aig_Obj_t *)1 ); + // explore the fanins +// Abc_ObjForEachFanin( pObj, pFanin, i ) +// if ( Abc_NtkMaxFlowBwdPath2_rec(pFanin) ) +// return Abc_ObjSetPath( pObj, pFanin ); + if ( Aig_ObjIsNode(pObj) ) + { + if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ) ) + return Llb_ObjSetPath( pObj, Aig_ObjFanin0(pObj) ); + if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ) ) + return Llb_ObjSetPath( pObj, Aig_ObjFanin1(pObj) ); + } + return 0; + } + // pObj has flow - find the fanout with flow + pFanout = Llb_ObjGetFanoutPath( p, 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 ); + assert( Aig_ObjIsNode(pFanout) ); + if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pFanout) ) ) + return Llb_ObjSetPath( pFanout, Aig_ObjFanin0(pFanout) ); + if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pFanout) ) ) + return Llb_ObjSetPath( pFanout, Aig_ObjFanin1(pFanout) ); + // try the fanout + if ( Llb_ManFlowBwdPath2_rec( p, pFanout ) ) + return Llb_ObjSetPath( pFanout, NULL ); + return 0; +} + + +/**Function************************************************************* + + Synopsis [Cleans markB.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManFlowLabelTfi_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Aig_ObjIsPi(pObj) || Aig_ObjIsConst1(pObj) ) + return; + assert( Aig_ObjIsNode(pObj) ); + Llb_ManFlowLabelTfi_rec( p, Aig_ObjFanin0(pObj) ); + Llb_ManFlowLabelTfi_rec( p, Aig_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManFlowUpdateCut( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) +{ + Aig_Obj_t * pObj; + int i; + // label the TFI of the cut nodes + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) + Llb_ManFlowLabelTfi_rec( p, pObj ); + // collect labeled fanins of non-labeled nodes + Vec_PtrClear( vMinCut ); + Aig_ManIncrementTravId(p); + Aig_ManForEachObj( p, pObj, i ) + { + if ( !Aig_ObjIsPo(pObj) && !Aig_ObjIsNode(pObj) ) + continue; + if ( Aig_ObjIsTravIdCurrent(p, pObj) || Aig_ObjIsTravIdPrevious(p, pObj) ) + continue; + if ( Aig_ObjIsTravIdPrevious(p, Aig_ObjFanin0(pObj)) ) + { + Aig_ObjSetTravIdCurrent(p, Aig_ObjFanin0(pObj)); + Vec_PtrPush( vMinCut, Aig_ObjFanin0(pObj) ); + } + if ( Aig_ObjIsNode(pObj) && Aig_ObjIsTravIdPrevious(p, Aig_ObjFanin1(pObj)) ) + { + Aig_ObjSetTravIdCurrent(p, Aig_ObjFanin1(pObj)); + Vec_PtrPush( vMinCut, Aig_ObjFanin1(pObj) ); + } + } +} + +/**Function************************************************************* + + Synopsis [Find minimum-volume minumum cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManFlowMinCut( Aig_Man_t * p ) +{ + Vec_Ptr_t * vMinCut; + Aig_Obj_t * pObj; + int i; + // collect the cut nodes + vMinCut = Vec_PtrAlloc( Aig_ManRegNum(p) ); + Aig_ManForEachObj( p, pObj, i ) + { + // node without flow is not a cut node + if ( !Llb_ObjGetPath(pObj) ) + continue; + // unvisited node is below the cut + if ( !Aig_ObjIsTravIdCurrent(p, pObj) ) + continue; + // add terminal with flow or node whose path is not visited + if ( pObj->fMarkA || !Aig_ObjIsTravIdCurrent( p, Llb_ObjGetPath(pObj) ) ) + Vec_PtrPush( vMinCut, pObj ); + } + return vMinCut; +} + +/**Function************************************************************* + + Synopsis [Verifies the min-cut is indeed a cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManFlowVerifyCut_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + // skip visited nodes + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return 1; + Aig_ObjSetTravIdCurrent(p, pObj); + // visit the node + if ( Aig_ObjIsConst1(pObj) ) + return 1; + if ( Aig_ObjIsPi(pObj) ) + return 0; + // explore the fanins + assert( Aig_ObjIsNode(pObj) ); + if ( !Llb_ManFlowVerifyCut_rec(p, Aig_ObjFanin0(pObj)) ) + return 0; + if ( !Llb_ManFlowVerifyCut_rec(p, Aig_ObjFanin1(pObj)) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Verifies the min-cut is indeed a cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManFlowVerifyCut( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) +{ + Aig_Obj_t * pObj; + int i; + // mark the cut with the current traversal ID + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + // search from the latches for a path to the COs/CIs + Saig_ManForEachLi( p, pObj, i ) + { + if ( !Llb_ManFlowVerifyCut_rec( p, Aig_ObjFanin0(pObj) ) ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Implementation of max-flow/min-cut computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManFlow( Aig_Man_t * p, Vec_Ptr_t * vSources, int * pnFlow ) +{ + Vec_Ptr_t * vMinCut; + Aig_Obj_t * pObj; + int Flow, FlowCur, RetValue, i; + // find the max-flow + Flow = 0; + Aig_ManCleanData( p ); + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vSources, pObj, i ) + { + assert( !pObj->fMarkA && pObj->fMarkB ); + if ( !Aig_ObjFanin0(pObj)->fMarkB ) + { + FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ); + Flow += FlowCur; + if ( FlowCur ) + Aig_ManIncrementTravId(p); + } + if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB ) + { + FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ); + Flow += FlowCur; + if ( FlowCur ) + Aig_ManIncrementTravId(p); + } + } + if ( pnFlow ) + *pnFlow = Flow; + + // mark the nodes reachable from the latches + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vSources, pObj, i ) + { + assert( !pObj->fMarkA && pObj->fMarkB ); + if ( !Aig_ObjFanin0(pObj)->fMarkB ) + { + RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ); + assert( RetValue == 0 ); + } + if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB ) + { + RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ); + assert( RetValue == 0 ); + } + } + + // find the min-cut with the smallest volume + vMinCut = Llb_ManFlowMinCut( p ); + assert( Vec_PtrSize(vMinCut) == Flow ); + // verify the cut + if ( !Llb_ManFlowVerifyCut(p, vMinCut) ) + printf( "Llb_ManFlow() error! The computed min-cut is not a cut!\n" ); +// Llb_ManFlowPrintCut( p, vMinCut ); + return vMinCut; +} + +/**Function************************************************************* + + Synopsis [Implementation of max-flow/min-cut computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManFlowCompute( Aig_Man_t * p ) +{ + Vec_Ptr_t * vMinCut; + Aig_Obj_t * pObj; + int Flow, FlowCur, RetValue, i; + // find the max-flow + Flow = 0; + Aig_ManCleanData( p ); + Aig_ManIncrementTravId(p); + Aig_ManForEachObj( p, pObj, i ) + { + if ( !pObj->fMarkB ) + continue; + assert( !pObj->fMarkA ); + if ( !Aig_ObjFanin0(pObj)->fMarkB ) + { +//printf( "%d ", Aig_ObjFanin0(pObj)->Id ); + FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ); + Flow += FlowCur; + if ( FlowCur ) + Aig_ManIncrementTravId(p); + } + if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB ) + { +//printf( "%d ", Aig_ObjFanin1(pObj)->Id ); + FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ); + Flow += FlowCur; + if ( FlowCur ) + Aig_ManIncrementTravId(p); + } + } +//printf( "\n" ); + + // mark the nodes reachable from the latches + Aig_ManIncrementTravId(p); + Aig_ManForEachObj( p, pObj, i ) + { + if ( !pObj->fMarkB ) + continue; + assert( !pObj->fMarkA ); + if ( !Aig_ObjFanin0(pObj)->fMarkB ) + { + RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ); + assert( RetValue == 0 ); + } + if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB ) + { + RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ); + assert( RetValue == 0 ); + } + } + // find the min-cut with the smallest volume + vMinCut = Llb_ManFlowMinCut( p ); + assert( Vec_PtrSize(vMinCut) == Flow ); +//printf( "%d ", Vec_PtrSize(vMinCut) ); + Llb_ManFlowUpdateCut( p, vMinCut ); +//printf( "%d ", Vec_PtrSize(vMinCut) ); + // verify the cut + if ( !Llb_ManFlowVerifyCut(p, vMinCut) ) + printf( "Llb_ManFlow() error! The computed min-cut is not a cut!\n" ); +// Llb_ManFlowPrintCut( p, vMinCut ); + return vMinCut; +} + + + + +/**Function************************************************************* + + Synopsis [Cleans markB.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManFlowCleanMarkB_rec( Aig_Obj_t * pObj ) +{ + if ( pObj->fMarkB == 0 ) + return; + pObj->fMarkB = 0; + assert( Aig_ObjIsNode(pObj) ); + Llb_ManFlowCleanMarkB_rec( Aig_ObjFanin0(pObj) ); + Llb_ManFlowCleanMarkB_rec( Aig_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Cleans markB.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManFlowSetMarkA_rec( Aig_Obj_t * pObj ) +{ + if ( pObj->fMarkA ) + return; + pObj->fMarkA = 1; + if ( Aig_ObjIsPi(pObj) || Aig_ObjIsConst1(pObj) ) + return; + assert( Aig_ObjIsNode(pObj) ); + Llb_ManFlowSetMarkA_rec( Aig_ObjFanin0(pObj) ); + Llb_ManFlowSetMarkA_rec( Aig_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Prepares flow computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManFlowPrepareCut( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) +{ + Aig_Obj_t * pObj; + int i; + // reset marks + Aig_ManForEachObj( p, pObj, i ) + { + pObj->fMarkA = 0; + pObj->fMarkB = 1; + } + // clean PIs and const + Aig_ManConst1(p)->fMarkB = 0; + Aig_ManForEachPi( p, pObj, i ) + pObj->fMarkB = 0; + // clean upper cut +//printf( "Upper: "); + Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) + { + Llb_ManFlowCleanMarkB_rec( pObj ); +//printf( "%d ", pObj->Id ); + } +//printf( "\n" ); + // set lower cut +//printf( "Lower: "); + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + { +//printf( "%d ", pObj->Id ); + assert( pObj->fMarkB == 0 ); + Llb_ManFlowSetMarkA_rec( pObj ); + } +//printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Prepares flow computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManFlowUnmarkCone( Aig_Man_t * p, Vec_Ptr_t * vCone ) +{ + Aig_Obj_t * pObj; + int i; + Vec_PtrForEachEntry( Aig_Obj_t *, vCone, pObj, i ) + { + assert( Aig_ObjIsNode(pObj) ); + assert( pObj->fMarkB == 1 ); + pObj->fMarkB = 0; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManFlowCollectAndMarkCone_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vCone ) +{ + Aig_Obj_t * pFanout; + int i, iFanout; + if ( Saig_ObjIsLi(p, pObj) ) + return; + if ( pObj->fMarkB ) + return; + if ( pObj->fMarkA == 0 ) + { + assert( Aig_ObjIsNode(pObj) ); + pObj->fMarkB = 1; + if ( Aig_ObjIsNode(pObj) ) + Vec_PtrPush( vCone, pObj ); + } + Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) + Llb_ManFlowCollectAndMarkCone_rec( p, pFanout, vCone ); +} + +/**Function************************************************************* + + Synopsis [Collects the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManFlowCollectAndMarkCone( Aig_Man_t * p, Vec_Ptr_t * vStarts, Vec_Ptr_t * vCone ) +{ + Aig_Obj_t * pObj; + int i; + Vec_PtrClear( vCone ); + Vec_PtrForEachEntry( Aig_Obj_t *, vStarts, pObj, i ) + { + assert( pObj->fMarkA && !pObj->fMarkB ); + Llb_ManFlowCollectAndMarkCone_rec( p, pObj, vCone ); + } +} + + + + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManComputeCutLo( Aig_Man_t * p ) +{ + Vec_Ptr_t * vMinCut; + Aig_Obj_t * pObj; + int i; + vMinCut = Vec_PtrAlloc( 100 ); + Aig_ManForEachPi( p, pObj, i ) + Vec_PtrPush( vMinCut, pObj ); + return vMinCut; +} + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManComputeCutLi( Aig_Man_t * p ) +{ + Vec_Ptr_t * vMinCut; + Aig_Obj_t * pObj; + int i; + assert( Saig_ManPoNum(p) == 0 ); + vMinCut = Vec_PtrAlloc( 100 ); + Aig_ManIncrementTravId(p); + Saig_ManForEachLi( p, pObj, i ) + { + pObj = Aig_ObjFanin0(pObj); + if ( Aig_ObjIsConst1(pObj) ) + continue; + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + continue; + Aig_ObjSetTravIdCurrent(p, pObj); + Vec_PtrPush( vMinCut, pObj ); + } + return vMinCut; +} + + + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManFlowGetObjSet( Aig_Man_t * p, Vec_Ptr_t * vLower, int iStart, int nSize, Vec_Ptr_t * vSet ) +{ + Aig_Obj_t * pObj; + int i; + Vec_PtrClear( vSet ); + for ( i = 0; i < nSize; i++ ) + { + pObj = (Aig_Obj_t *)Vec_PtrEntry( vLower, (iStart + i) % Vec_PtrSize(vLower) ); + Vec_PtrPush( vSet, pObj ); + } +} + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManFlowFindBestCut( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, int Num ) +{ + int nVolMin = Aig_ManNodeNum(p) / Num / 2; + Vec_Ptr_t * vMinCut; + Vec_Ptr_t * vCone, * vSet; + Aig_Obj_t * pObj; + int i, s, Vol, VolLower, VolUpper, VolCmp; + int iBest = -1, iMinCut = ABC_INFINITY, iVolBest = 0; + + Vol = Llb_ManCutVolume( p, vLower, vUpper ); + assert( Vol > nVolMin ); + VolCmp = Abc_MinInt( nVolMin, Vol - nVolMin ); + vCone = Vec_PtrAlloc( 100 ); + vSet = Vec_PtrAlloc( 100 ); + Llb_ManFlowPrepareCut( p, vLower, vUpper ); + for ( s = 1; s < Aig_ManRegNum(p); s += 5 ) + { + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + { + Llb_ManFlowGetObjSet( p, vLower, i, s, vSet ); + Llb_ManFlowCollectAndMarkCone( p, vSet, vCone ); + if ( Vec_PtrSize(vCone) == 0 ) + continue; + vMinCut = Llb_ManFlowCompute( p ); + Llb_ManFlowUnmarkCone( p, vCone ); + + VolLower = Llb_ManCutVolume( p, vLower, vMinCut ); + VolUpper = Llb_ManCutVolume( p, vMinCut, vUpper ); + Vol = Abc_MinInt( VolLower, VolUpper ); + if ( Vol >= VolCmp && (iMinCut == -1 || + iMinCut > Vec_PtrSize(vMinCut) || + (iMinCut == Vec_PtrSize(vMinCut) && iVolBest < Vol)) ) + { + iBest = i; + iMinCut = Vec_PtrSize(vMinCut); + iVolBest = Vol; + } + Vec_PtrFree( vMinCut ); + } + if ( iBest >= 0 ) + break; + } + if ( iBest == -1 ) + { + // cleanup + Vec_PtrFree( vCone ); + Vec_PtrFree( vSet ); + return NULL; + } + // get the best cut + assert( iBest >= 0 ); + Llb_ManFlowGetObjSet( p, vLower, iBest, s, vSet ); + Llb_ManFlowCollectAndMarkCone( p, vSet, vCone ); + vMinCut = Llb_ManFlowCompute( p ); + Llb_ManFlowUnmarkCone( p, vCone ); + // cleanup + Vec_PtrFree( vCone ); + Vec_PtrFree( vSet ); + return vMinCut; +} + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManComputeCuts( Aig_Man_t * p, int Num, int fVerbose, int fVeryVerbose ) +{ + int nVolMax = Aig_ManNodeNum(p) / Num; + Vec_Ptr_t * vResult, * vMinCut, * vLower, * vUpper; + int i, k, nVol, clk = clock(); + vResult = Vec_PtrAlloc( 100 ); + Vec_PtrPush( vResult, Llb_ManComputeCutLo(p) ); + Vec_PtrPush( vResult, Llb_ManComputeCutLi(p) ); + while ( 1 ) + { + // find a place to insert new cut + vLower = (Vec_Ptr_t *)Vec_PtrEntry( vResult, 0 ); + Vec_PtrForEachEntryStart( Vec_Ptr_t *, vResult, vUpper, i, 1 ) + { + nVol = Llb_ManCutVolume( p, vLower, vUpper ); + if ( nVol <= nVolMax ) + { + vLower = vUpper; + continue; + } + + if ( fVeryVerbose ) + Llb_ManCutPrint( p, vLower, vUpper ); + vMinCut = Llb_ManFlowFindBestCut( p, vLower, vUpper, Num ); + if ( vMinCut == NULL ) + { + if ( fVeryVerbose ) + printf( "Could not break the cut.\n" ); + if ( fVeryVerbose ) + printf( "\n" ); + vLower = vUpper; + continue; + } + + if ( fVeryVerbose ) + Llb_ManCutPrint( p, vMinCut, vUpper ); + if ( fVeryVerbose ) + Llb_ManCutPrint( p, vLower, vMinCut ); + if ( fVeryVerbose ) + printf( "\n" ); + + break; + } + if ( i == Vec_PtrSize(vResult) ) + break; + // insert vMinCut before vUpper + Vec_PtrPush( vResult, NULL ); + for ( k = Vec_PtrSize(vResult) - 1; k > i; k-- ) + Vec_PtrWriteEntry( vResult, k, Vec_PtrEntry(vResult, k-1) ); + Vec_PtrWriteEntry( vResult, i, vMinCut ); + } + if ( fVerbose ) + { + printf( "Finished computing %d partitions. ", Vec_PtrSize(vResult) - 1 ); + Abc_PrintTime( 1, "Time", clock() - clk ); + Llb_ManResultPrint( p, vResult ); + } + return vResult; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_BddSetDefaultParams( Gia_ParLlb_t * p ) +{ + memset( p, 0, sizeof(Gia_ParLlb_t) ); + p->nBddMax = 1000000; + p->nIterMax = 10000000; + p->nClusterMax = 20; + p->nHintDepth = 0; + p->HintFirst = 0; + p->fUseFlow = 0; // use flow + p->nVolumeMax = 100; // max volume + p->nVolumeMin = 30; // min volume + p->fReorder = 1; + p->fIndConstr = 0; + p->fUsePivots = 0; + p->fCluster = 0; + p->fSchedule = 0; + p->fVerbose = 0; + p->fVeryVerbose = 0; + p->fSilent = 0; + p->TimeLimit = 0; +// p->TimeLimit = 0; + p->TimeLimitGlo = 0; + p->TimeTarget = 0; + p->iFrame = -1; +} + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManMinCutTest( Aig_Man_t * pAig, int Num ) +{ + extern void Llb_BddConstructTest( Aig_Man_t * p, Vec_Ptr_t * vResult ); + extern void Llb_BddExperiment( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars, Vec_Ptr_t * vResult, Vec_Ptr_t * vMaps ); + + + int fVerbose = 1; + Gia_ParLlb_t Pars, * pPars = &Pars; + Vec_Ptr_t * vResult;//, * vSupps, * vMaps; + Aig_Man_t * p; + + Llb_BddSetDefaultParams( pPars ); + + p = Aig_ManDupFlopsOnly( pAig ); +//Aig_ManShow( p, 0, NULL ); + Aig_ManPrintStats( pAig ); + Aig_ManPrintStats( p ); + Aig_ManFanoutStart( p ); + + vResult = Llb_ManComputeCuts( p, Num, 1, 0 ); +// vSupps = Llb_ManCutSupps( p, vResult ); +// vMaps = Llb_ManCutMap( p, vResult, vSupps ); + +// Llb_BddExperiment( pAig, p, pPars, vResult, vMaps ); + Llb_CoreExperiment( pAig, p, pPars, vResult, 0 ); + +// Vec_VecFree( (Vec_Vec_t *)vMaps ); +// Vec_VecFree( (Vec_Vec_t *)vSupps ); + Vec_VecFree( (Vec_Vec_t *)vResult ); + + Aig_ManFanoutStop( p ); + Aig_ManCleanMarkAB( p ); + Aig_ManStop( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/llb/llb2Image.c b/src/proof/llb/llb2Image.c new file mode 100644 index 00000000..5baa5c57 --- /dev/null +++ b/src/proof/llb/llb2Image.c @@ -0,0 +1,478 @@ +/**CFile**************************************************************** + + FileName [llb2Image.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Computes image using partitioned structure.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Image.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern Vec_Ptr_t * Llb_ManCutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ); +extern Vec_Ptr_t * Llb_ManCutRange( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes supports of the partitions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ImgSupports( Aig_Man_t * p, Vec_Ptr_t * vDdMans, Vec_Int_t * vStart, Vec_Int_t * vStop, int fAddPis, int fVerbose ) +{ + Vec_Ptr_t * vSupps; + Vec_Int_t * vOne; + Aig_Obj_t * pObj; + DdManager * dd; + DdNode * bSupp, * bTemp; + int i, Entry, nSize; + nSize = Cudd_ReadSize( (DdManager *)Vec_PtrEntry( vDdMans, 0 ) ); + vSupps = Vec_PtrAlloc( 100 ); + // create initial + vOne = Vec_IntStart( nSize ); + Vec_IntForEachEntry( vStart, Entry, i ) + Vec_IntWriteEntry( vOne, Entry, 1 ); + Vec_PtrPush( vSupps, vOne ); + // create intermediate + Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i ) + { + vOne = Vec_IntStart( nSize ); + bSupp = Cudd_Support( dd, dd->bFunc ); Cudd_Ref( bSupp ); + for ( bTemp = bSupp; bTemp != Cudd_ReadOne(dd); bTemp = cuddT(bTemp) ) + Vec_IntWriteEntry( vOne, bTemp->index, 1 ); + Cudd_RecursiveDeref( dd, bSupp ); + Vec_PtrPush( vSupps, vOne ); + } + // create final + vOne = Vec_IntStart( nSize ); + Vec_IntForEachEntry( vStop, Entry, i ) + Vec_IntWriteEntry( vOne, Entry, 1 ); + if ( fAddPis ) + Saig_ManForEachPi( p, pObj, i ) + Vec_IntWriteEntry( vOne, Aig_ObjId(pObj), 1 ); + Vec_PtrPush( vSupps, vOne ); + + // print supports + assert( nSize == Aig_ManObjNumMax(p) ); + if ( fVerbose ) + Aig_ManForEachObj( p, pObj, i ) + { + int k, Counter = 0; + Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k ) + Counter += Vec_IntEntry(vOne, i); + if ( Counter == 0 ) + continue; + printf( "Obj = %4d : ", i ); + if ( Saig_ObjIsPi(p,pObj) ) + printf( "pi " ); + else if ( Saig_ObjIsLo(p,pObj) ) + printf( "lo " ); + else if ( Saig_ObjIsLi(p,pObj) ) + printf( "li " ); + else if ( Aig_ObjIsNode(pObj) ) + printf( "and " ); + Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k ) + printf( "%d", Vec_IntEntry(vOne, i) ); + printf( "\n" ); + } + return vSupps; +} + +/**Function************************************************************* + + Synopsis [Computes quantification schedule.] + + Description [Input array contains supports: 0=starting, ... intermediate... + N-1=final. Output arrays contain immediately quantifiable vars (vQuant0) + and vars that should be quantified after conjunction (vQuant1).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ImgSchedule( Vec_Ptr_t * vSupps, Vec_Ptr_t ** pvQuant0, Vec_Ptr_t ** pvQuant1, int fVerbose ) +{ + Vec_Int_t * vOne; + int nVarsAll, Counter, iSupp, Entry, i, k; + // start quantification arrays + *pvQuant0 = Vec_PtrAlloc( Vec_PtrSize(vSupps) ); + *pvQuant1 = Vec_PtrAlloc( Vec_PtrSize(vSupps) ); + Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k ) + { + Vec_PtrPush( *pvQuant0, Vec_IntAlloc(16) ); + Vec_PtrPush( *pvQuant1, Vec_IntAlloc(16) ); + } + // count how many times each var appears + nVarsAll = Vec_IntSize( (Vec_Int_t *)Vec_PtrEntry(vSupps, 0) ); + for ( i = 0; i < nVarsAll; i++ ) + { + Counter = 0; + Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k ) + if ( Vec_IntEntry(vOne, i) ) + { + iSupp = k; + Counter++; + } + if ( Counter == 0 ) + continue; + if ( Counter == 1 ) + Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(*pvQuant0, iSupp), i ); + else // if ( Counter > 1 ) + Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(*pvQuant1, iSupp), i ); + } + + if ( fVerbose ) + for ( i = 0; i < Vec_PtrSize(vSupps); i++ ) + { + printf( "%2d : Quant0 = ", i ); + Vec_IntForEachEntry( (Vec_Int_t *)Vec_PtrEntry(*pvQuant0, i), Entry, k ) + printf( "%d ", Entry ); + printf( "\n" ); + } + + if ( fVerbose ) + for ( i = 0; i < Vec_PtrSize(vSupps); i++ ) + { + printf( "%2d : Quant1 = ", i ); + Vec_IntForEachEntry( (Vec_Int_t *)Vec_PtrEntry(*pvQuant1, i), Entry, k ) + printf( "%d ", Entry ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Computes one partition in a separate BDD manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdManager * Llb_ImgPartition( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, int TimeTarget ) +{ + Vec_Ptr_t * vNodes, * vRange; + Aig_Obj_t * pObj; + DdManager * dd; + DdNode * bBdd0, * bBdd1, * bProd, * bRes, * bTemp; + int i; + + dd = Cudd_Init( Aig_ManObjNumMax(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + dd->TimeStop = TimeTarget; + + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + pObj->pData = Cudd_bddIthVar( dd, Aig_ObjId(pObj) ); + + vNodes = Llb_ManCutNodes( p, vLower, vUpper ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); +// pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData ); +// pObj->pData = Extra_bddAndTime( dd, bBdd0, bBdd1, TimeTarget ); + pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); + if ( pObj->pData == NULL ) + { + Cudd_Quit( dd ); + Vec_PtrFree( vNodes ); + return NULL; + } + Cudd_Ref( (DdNode *)pObj->pData ); + } + + vRange = Llb_ManCutRange( p, vLower, vUpper ); + bRes = Cudd_ReadOne(dd); Cudd_Ref( bRes ); + Vec_PtrForEachEntry( Aig_Obj_t *, vRange, pObj, i ) + { + assert( Aig_ObjIsNode(pObj) ); + bProd = Cudd_bddXnor( dd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)), (DdNode *)pObj->pData ); Cudd_Ref( bProd ); +// bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd ); Cudd_Ref( bRes ); +// bRes = Extra_bddAndTime( dd, bTemp = bRes, bProd, TimeTarget ); + bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd ); + if ( bRes == NULL ) + { + Cudd_Quit( dd ); + Vec_PtrFree( vRange ); + Vec_PtrFree( vNodes ); + return NULL; + } + Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bProd ); + } + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + + Vec_PtrFree( vRange ); + Vec_PtrFree( vNodes ); + Cudd_AutodynDisable( dd ); +// Cudd_RecursiveDeref( dd, bRes ); +// Extra_StopManager( dd ); + dd->bFunc = bRes; + dd->TimeStop = 0; + return dd; +} + +/**Function************************************************************* + + Synopsis [Derives positive cube composed of nodes IDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ImgComputeCube( Aig_Man_t * pAig, Vec_Int_t * vNodeIds, DdManager * dd ) +{ + DdNode * bProd, * bTemp; + Aig_Obj_t * pObj; + int i, TimeStop; + TimeStop = dd->TimeStop; dd->TimeStop = 0; + bProd = Cudd_ReadOne(dd); Cudd_Ref( bProd ); + Aig_ManForEachObjVec( vNodeIds, pAig, pObj, i ) + { + bProd = Cudd_bddAnd( dd, bTemp = bProd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)) ); Cudd_Ref( bProd ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bProd ); + dd->TimeStop = TimeStop; + return bProd; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ImgQuantifyFirst( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, Vec_Ptr_t * vQuant0, int fVerbose ) +{ + DdManager * dd; + DdNode * bProd, * bRes, * bTemp; + int i, clk = clock(); + Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i ) + { + // remember unquantified ones + assert( dd->bFunc2 == NULL ); + dd->bFunc2 = dd->bFunc; Cudd_Ref( dd->bFunc2 ); + + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + + bRes = dd->bFunc; + if ( fVerbose ) + Abc_Print( 1, "Part %2d : Init =%5d. ", i, Cudd_DagSize(bRes) ); + bProd = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant0, i+1), dd ); Cudd_Ref( bProd ); + bRes = Cudd_bddExistAbstract( dd, bTemp = bRes, bProd ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bProd ); + dd->bFunc = bRes; + + Cudd_AutodynDisable( dd ); + + if ( fVerbose ) + Abc_Print( 1, "Quant =%5d. ", Cudd_DagSize(bRes) ); + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); + if ( fVerbose ) + Abc_Print( 1, "Reo = %5d. ", Cudd_DagSize(bRes) ); + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); + if ( fVerbose ) + Abc_Print( 1, "Reo = %5d. ", Cudd_DagSize(bRes) ); + if ( fVerbose ) + Abc_Print( 1, "Supp = %3d. ", Cudd_SupportSize(dd, bRes) ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", clock() - clk ); + + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ImgQuantifyReset( Vec_Ptr_t * vDdMans ) +{ + DdManager * dd; + int i; + Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i ) + { + assert( dd->bFunc2 != NULL ); + Cudd_RecursiveDeref( dd, dd->bFunc ); + dd->bFunc = dd->bFunc2; + dd->bFunc2 = NULL; + } +} + +/**Function************************************************************* + + Synopsis [Computes image of the initial set of states.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ImgComputeImage( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, DdManager * dd, DdNode * bInit, + Vec_Ptr_t * vQuant0, Vec_Ptr_t * vQuant1, Vec_Int_t * vDriRefs, + int TimeTarget, int fBackward, int fReorder, int fVerbose ) +{ + int fCheckSupport = 0; + DdManager * ddPart; + DdNode * bImage, * bGroup, * bCube, * bTemp; + int i, clk, clk0 = clock(); + + bImage = bInit; Cudd_Ref( bImage ); + if ( fBackward ) + { + // change polarity + bCube = Llb_DriverPhaseCube( pAig, vDriRefs, dd ); Cudd_Ref( bCube ); + bImage = Extra_bddChangePolarity( dd, bTemp = bImage, bCube ); Cudd_Ref( bImage ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + } + else + { + // quantify unique vriables + bCube = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant0, 0), dd ); Cudd_Ref( bCube ); + bImage = Cudd_bddExistAbstract( dd, bTemp = bImage, bCube ); + if ( bImage == NULL ) + { + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + return NULL; + } + Cudd_Ref( bImage ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + } + // perform image computation + Vec_PtrForEachEntry( DdManager *, vDdMans, ddPart, i ) + { + clk = clock(); +if ( fVerbose ) +printf( " %2d : ", i ); + // transfer the BDD from the group manager to the main manager + bGroup = Cudd_bddTransfer( ddPart, dd, ddPart->bFunc ); + if ( bGroup == NULL ) + return NULL; + Cudd_Ref( bGroup ); +if ( fVerbose ) +printf( "Pt0 =%6d. Pt1 =%6d. ", Cudd_DagSize(ddPart->bFunc), Cudd_DagSize(bGroup) ); + // perform partial product + bCube = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant1, i+1), dd ); Cudd_Ref( bCube ); +// bImage = Cudd_bddAndAbstract( dd, bTemp = bImage, bGroup, bCube ); +// bImage = Extra_bddAndAbstractTime( dd, bTemp = bImage, bGroup, bCube, TimeTarget ); + bImage = Cudd_bddAndAbstract( dd, bTemp = bImage, bGroup, bCube ); + if ( bImage == NULL ) + { + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + Cudd_RecursiveDeref( dd, bGroup ); + return NULL; + } + Cudd_Ref( bImage ); + +if ( fVerbose ) +printf( "Im0 =%6d. Im1 =%6d. ", Cudd_DagSize(bTemp), Cudd_DagSize(bImage) ); +//printf("\n"); Extra_bddPrintSupport(dd, bImage); printf("\n"); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + Cudd_RecursiveDeref( dd, bGroup ); + +// Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); +// Abc_Print( 1, "Reo =%6d. ", Cudd_DagSize(bImage) ); + +if ( fVerbose ) +printf( "Supp =%3d. ", Cudd_SupportSize(dd, bImage) ); +if ( fVerbose ) +Abc_PrintTime( 1, "T", clock() - clk ); + } + + if ( !fBackward ) + { + // change polarity + bCube = Llb_DriverPhaseCube( pAig, vDriRefs, dd ); Cudd_Ref( bCube ); + bImage = Extra_bddChangePolarity( dd, bTemp = bImage, bCube ); Cudd_Ref( bImage ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + } + else + { + // quantify unique vriables + bCube = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant0, 0), dd ); Cudd_Ref( bCube ); + bImage = Cudd_bddExistAbstract( dd, bTemp = bImage, bCube ); Cudd_Ref( bImage ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + } + + if ( fReorder ) + { + if ( fVerbose ) + Abc_Print( 1, " Reordering... Before =%5d. ", Cudd_DagSize(bImage) ); + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); + if ( fVerbose ) + Abc_Print( 1, "After =%5d. ", Cudd_DagSize(bImage) ); +// Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); +// Abc_Print( 1, "After =%5d. ", Cudd_DagSize(bImage) ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", clock() - clk0 ); +// Abc_Print( 1, "\n" ); + } + + Cudd_Deref( bImage ); + return bImage; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/llb/llb3Image.c b/src/proof/llb/llb3Image.c new file mode 100644 index 00000000..f674d4b1 --- /dev/null +++ b/src/proof/llb/llb3Image.c @@ -0,0 +1,1093 @@ +/**CFile**************************************************************** + + FileName [llb3Image.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Computes image using partitioned structure.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb3Image.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Llb_Var_t_ Llb_Var_t; +struct Llb_Var_t_ +{ + int iVar; // variable number + int nScore; // variable score + Vec_Int_t * vParts; // partitions +}; + +typedef struct Llb_Prt_t_ Llb_Prt_t; +struct Llb_Prt_t_ +{ + int iPart; // partition number + int nSize; // the number of BDD nodes + DdNode * bFunc; // the partition + Vec_Int_t * vVars; // support +}; + +typedef struct Llb_Mgr_t_ Llb_Mgr_t; +struct Llb_Mgr_t_ +{ + Aig_Man_t * pAig; // AIG manager + Vec_Ptr_t * vLeaves; // leaves in the AIG manager + Vec_Ptr_t * vRoots; // roots in the AIG manager + DdManager * dd; // working BDD manager + int * pVars2Q; // variables to quantify + // internal + Llb_Prt_t ** pParts; // partitions + Llb_Var_t ** pVars; // variables + int iPartFree; // next free partition + int nVars; // the number of BDD variables + int nSuppMax; // maximum support size + // temporary + int * pSupp; // temporary support storage +}; + +static inline Llb_Var_t * Llb_MgrVar( Llb_Mgr_t * p, int i ) { return p->pVars[i]; } +static inline Llb_Prt_t * Llb_MgrPart( Llb_Mgr_t * p, int i ) { return p->pParts[i]; } + +// iterator over vars +#define Llb_MgrForEachVar( p, pVar, i ) \ + for ( i = 0; (i < p->nVars) && (((pVar) = Llb_MgrVar(p, i)), 1); i++ ) if ( pVar == NULL ) {} else +// iterator over parts +#define Llb_MgrForEachPart( p, pPart, i ) \ + for ( i = 0; (i < p->iPartFree) && (((pPart) = Llb_MgrPart(p, i)), 1); i++ ) if ( pPart == NULL ) {} else + +// iterator over vars of one partition +#define Llb_PartForEachVar( p, pPart, pVar, i ) \ + for ( i = 0; (i < Vec_IntSize(pPart->vVars)) && (((pVar) = Llb_MgrVar(p, Vec_IntEntry(pPart->vVars,i))), 1); i++ ) +// iterator over parts of one variable +#define Llb_VarForEachPart( p, pVar, pPart, i ) \ + for ( i = 0; (i < Vec_IntSize(pVar->vParts)) && (((pPart) = Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,i))), 1); i++ ) + +// statistics +int timeBuild, timeAndEx, timeOther; +int nSuppMax; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Removes one variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinRemoveVar( Llb_Mgr_t * p, Llb_Var_t * pVar ) +{ + assert( p->pVars[pVar->iVar] == pVar ); + p->pVars[pVar->iVar] = NULL; + Vec_IntFree( pVar->vParts ); + ABC_FREE( pVar ); +} + +/**Function************************************************************* + + Synopsis [Removes one partition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinRemovePart( Llb_Mgr_t * p, Llb_Prt_t * pPart ) +{ + assert( p->pParts[pPart->iPart] == pPart ); + p->pParts[pPart->iPart] = NULL; + Vec_IntFree( pPart->vVars ); + Cudd_RecursiveDeref( p->dd, pPart->bFunc ); + ABC_FREE( pPart ); +} + +/**Function************************************************************* + + Synopsis [Create cube with singleton variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_NonlinCreateCube1( Llb_Mgr_t * p, Llb_Prt_t * pPart ) +{ + DdNode * bCube, * bTemp; + Llb_Var_t * pVar; + int i, TimeStop; + TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; + bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube ); + Llb_PartForEachVar( p, pPart, pVar, i ) + { + assert( Vec_IntSize(pVar->vParts) > 0 ); + if ( Vec_IntSize(pVar->vParts) != 1 ) + continue; + assert( Vec_IntEntry(pVar->vParts, 0) == pPart->iPart ); + bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + Cudd_Deref( bCube ); + p->dd->TimeStop = TimeStop; + return bCube; +} + +/**Function************************************************************* + + Synopsis [Create cube of variables appearing only in two partitions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_NonlinCreateCube2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 ) +{ + DdNode * bCube, * bTemp; + Llb_Var_t * pVar; + int i, TimeStop; + TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; + bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube ); + Llb_PartForEachVar( p, pPart1, pVar, i ) + { + assert( Vec_IntSize(pVar->vParts) > 0 ); + if ( Vec_IntSize(pVar->vParts) != 2 ) + continue; + if ( (Vec_IntEntry(pVar->vParts, 0) == pPart1->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart2->iPart) || + (Vec_IntEntry(pVar->vParts, 0) == pPart2->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart1->iPart) ) + { + bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + } + Cudd_Deref( bCube ); + p->dd->TimeStop = TimeStop; + return bCube; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if partition has singleton variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinHasSingletonVars( Llb_Mgr_t * p, Llb_Prt_t * pPart ) +{ + Llb_Var_t * pVar; + int i; + Llb_PartForEachVar( p, pPart, pVar, i ) + if ( Vec_IntSize(pVar->vParts) == 1 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if partition has singleton variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinPrint( Llb_Mgr_t * p ) +{ + Llb_Prt_t * pPart; + Llb_Var_t * pVar; + int i, k; + printf( "\n" ); + Llb_MgrForEachVar( p, pVar, i ) + { + printf( "Var %3d : ", i ); + Llb_VarForEachPart( p, pVar, pPart, k ) + printf( "%d ", pPart->iPart ); + printf( "\n" ); + } + Llb_MgrForEachPart( p, pPart, i ) + { + printf( "Part %3d : ", i ); + Llb_PartForEachVar( p, pPart, pVar, k ) + printf( "%d ", pVar->iVar ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Quantifies singles belonging to one partition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinQuantify1( Llb_Mgr_t * p, Llb_Prt_t * pPart, int fSubset ) +{ + Llb_Var_t * pVar; + Llb_Prt_t * pTemp; + Vec_Ptr_t * vSingles; + DdNode * bCube, * bTemp; + int i, RetValue, nSizeNew; + if ( fSubset ) + { + int Length; +// int nSuppSize = Cudd_SupportSize( p->dd, pPart->bFunc ); +// pPart->bFunc = Cudd_SubsetHeavyBranch( p->dd, bTemp = pPart->bFunc, nSuppSize, 3*pPart->nSize/4 ); Cudd_Ref( pPart->bFunc ); + pPart->bFunc = Cudd_LargestCube( p->dd, bTemp = pPart->bFunc, &Length ); Cudd_Ref( pPart->bFunc ); + + printf( "Subsetting %3d : ", pPart->iPart ); + printf( "(Supp =%3d Node =%5d) -> ", Cudd_SupportSize(p->dd, bTemp), Cudd_DagSize(bTemp) ); + printf( "(Supp =%3d Node =%5d)\n", Cudd_SupportSize(p->dd, pPart->bFunc), Cudd_DagSize(pPart->bFunc) ); + + RetValue = (Cudd_DagSize(bTemp) == Cudd_DagSize(pPart->bFunc)); + + Cudd_RecursiveDeref( p->dd, bTemp ); + + if ( RetValue ) + return 1; + } + else + { + // create cube to be quantified + bCube = Llb_NonlinCreateCube1( p, pPart ); Cudd_Ref( bCube ); +// assert( !Cudd_IsConstant(bCube) ); + // derive new function + pPart->bFunc = Cudd_bddExistAbstract( p->dd, bTemp = pPart->bFunc, bCube ); Cudd_Ref( pPart->bFunc ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bCube ); + } + // get support + vSingles = Vec_PtrAlloc( 0 ); + nSizeNew = Cudd_DagSize(pPart->bFunc); + Extra_SupportArray( p->dd, pPart->bFunc, p->pSupp ); + Llb_PartForEachVar( p, pPart, pVar, i ) + if ( p->pSupp[pVar->iVar] ) + { + assert( Vec_IntSize(pVar->vParts) > 1 ); + pVar->nScore -= pPart->nSize - nSizeNew; + } + else + { + RetValue = Vec_IntRemove( pVar->vParts, pPart->iPart ); + assert( RetValue ); + pVar->nScore -= pPart->nSize; + if ( Vec_IntSize(pVar->vParts) == 0 ) + Llb_NonlinRemoveVar( p, pVar ); + else if ( Vec_IntSize(pVar->vParts) == 1 ) + Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); + } + + // update partition + pPart->nSize = nSizeNew; + Vec_IntClear( pPart->vVars ); + for ( i = 0; i < p->nVars; i++ ) + if ( p->pSupp[i] && p->pVars2Q[i] ) + Vec_IntPush( pPart->vVars, i ); + // remove other variables + Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i ) + Llb_NonlinQuantify1( p, pTemp, 0 ); + Vec_PtrFree( vSingles ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Quantifies singles belonging to one partition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinQuantify2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2, int Limit, int TimeOut ) +{ + int fVerbose = 0; + Llb_Var_t * pVar; + Llb_Prt_t * pTemp; + Vec_Ptr_t * vSingles; + DdNode * bCube, * bFunc; + int i, RetValue, nSuppSize; + int iPart1 = pPart1->iPart; + int iPart2 = pPart2->iPart; + + // create cube to be quantified + bCube = Llb_NonlinCreateCube2( p, pPart1, pPart2 ); Cudd_Ref( bCube ); +if ( fVerbose ) +{ +printf( "\n" ); +printf( "\n" ); +Llb_NonlinPrint( p ); +printf( "Conjoining partitions %d and %d.\n", pPart1->iPart, pPart2->iPart ); +Extra_bddPrintSupport( p->dd, bCube ); printf( "\n" ); +} + + // derive new function +// bFunc = Cudd_bddAndAbstract( p->dd, pPart1->bFunc, pPart2->bFunc, bCube ); Cudd_Ref( bFunc ); +/* + bFunc = Cudd_bddAndAbstractLimit( p->dd, pPart1->bFunc, pPart2->bFunc, bCube, Limit ); + if ( bFunc == NULL ) + { + int RetValue; + Cudd_RecursiveDeref( p->dd, bCube ); + if ( pPart1->nSize < pPart2->nSize ) + RetValue = Llb_NonlinQuantify1( p, pPart1, 1 ); + else + RetValue = Llb_NonlinQuantify1( p, pPart2, 1 ); + if ( RetValue ) + Limit = Limit + 1000; + Llb_NonlinQuantify2( p, pPart1, pPart2, Limit, TimeOut ); + return 0; + } + Cudd_Ref( bFunc ); +*/ + +// bFunc = Extra_bddAndAbstractTime( p->dd, pPart1->bFunc, pPart2->bFunc, bCube, TimeOut ); + bFunc = Cudd_bddAndAbstract( p->dd, pPart1->bFunc, pPart2->bFunc, bCube ); + if ( bFunc == NULL ) + { + Cudd_RecursiveDeref( p->dd, bCube ); + return 0; + } + Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( p->dd, bCube ); + + // create new partition + pTemp = p->pParts[p->iPartFree] = ABC_CALLOC( Llb_Prt_t, 1 ); + pTemp->iPart = p->iPartFree++; + pTemp->nSize = Cudd_DagSize(bFunc); + pTemp->bFunc = bFunc; + pTemp->vVars = Vec_IntAlloc( 8 ); + // update variables + Llb_PartForEachVar( p, pPart1, pVar, i ) + { + RetValue = Vec_IntRemove( pVar->vParts, pPart1->iPart ); + assert( RetValue ); + pVar->nScore -= pPart1->nSize; + } + // update variables + Llb_PartForEachVar( p, pPart2, pVar, i ) + { + RetValue = Vec_IntRemove( pVar->vParts, pPart2->iPart ); + assert( RetValue ); + pVar->nScore -= pPart2->nSize; + } + // add variables to the new partition + nSuppSize = 0; + Extra_SupportArray( p->dd, bFunc, p->pSupp ); + for ( i = 0; i < p->nVars; i++ ) + { + nSuppSize += p->pSupp[i]; + if ( p->pSupp[i] && p->pVars2Q[i] ) + { + pVar = Llb_MgrVar( p, i ); + pVar->nScore += pTemp->nSize; + Vec_IntPush( pVar->vParts, pTemp->iPart ); + Vec_IntPush( pTemp->vVars, i ); + } + } + p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize ); + // remove variables and collect partitions with singleton variables + vSingles = Vec_PtrAlloc( 0 ); + Llb_PartForEachVar( p, pPart1, pVar, i ) + { + if ( Vec_IntSize(pVar->vParts) == 0 ) + Llb_NonlinRemoveVar( p, pVar ); + else if ( Vec_IntSize(pVar->vParts) == 1 ) + { + if ( fVerbose ) + printf( "Adding partition %d because of var %d.\n", + Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar ); + Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); + } + } + Llb_PartForEachVar( p, pPart2, pVar, i ) + { + if ( pVar == NULL ) + continue; + if ( Vec_IntSize(pVar->vParts) == 0 ) + Llb_NonlinRemoveVar( p, pVar ); + else if ( Vec_IntSize(pVar->vParts) == 1 ) + { + if ( fVerbose ) + printf( "Adding partition %d because of var %d.\n", + Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar ); + Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); + } + } + // remove partitions + Llb_NonlinRemovePart( p, pPart1 ); + Llb_NonlinRemovePart( p, pPart2 ); + // remove other variables +if ( fVerbose ) +Llb_NonlinPrint( p ); + Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i ) + { +if ( fVerbose ) +printf( "Updating partitiong %d with singlton vars.\n", pTemp->iPart ); + Llb_NonlinQuantify1( p, pTemp, 0 ); + } +if ( fVerbose ) +Llb_NonlinPrint( p ); + Vec_PtrFree( vSingles ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinCutNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Saig_ObjIsLi(p, pObj) ) + { + Llb_NonlinCutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); + return; + } + if ( Aig_ObjIsConst1(pObj) ) + return; + assert( Aig_ObjIsNode(pObj) ); + Llb_NonlinCutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); + Llb_NonlinCutNodes_rec(p, Aig_ObjFanin1(pObj), vNodes); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_NonlinCutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + // mark the lower cut with the traversal ID + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + // count the upper cut + vNodes = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) + Llb_NonlinCutNodes_rec( p, pObj, vNodes ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Returns array of BDDs for the roots in terms of the leaves.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_NonlinBuildBdds( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, DdManager * dd, int TimeOut ) +{ + Vec_Ptr_t * vNodes, * vResult; + Aig_Obj_t * pObj; + DdNode * bBdd0, * bBdd1, * bProd; + int i, k; + + Aig_ManConst1(p)->pData = Cudd_ReadOne( dd ); + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + pObj->pData = Cudd_bddIthVar( dd, Aig_ObjId(pObj) ); + + vNodes = Llb_NonlinCutNodes( p, vLower, vUpper ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); +// pObj->pData = Extra_bddAndTime( dd, bBdd0, bBdd1, TimeOut ); + pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); + if ( pObj->pData == NULL ) + { + Vec_PtrForEachEntryStop( Aig_Obj_t *, vNodes, pObj, k, i ) + if ( pObj->pData ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + Vec_PtrFree( vNodes ); + return NULL; + } + Cudd_Ref( (DdNode *)pObj->pData ); + } + + vResult = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) + { + if ( Aig_ObjIsNode(pObj) ) + { + bProd = Cudd_bddXnor( dd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)), (DdNode *)pObj->pData ); Cudd_Ref( bProd ); + } + else + { + assert( Saig_ObjIsLi(p, pObj) ); + bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bProd = Cudd_bddXnor( dd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)), bBdd0 ); Cudd_Ref( bProd ); + } + Vec_PtrPush( vResult, bProd ); + } + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + + Vec_PtrFree( vNodes ); + return vResult; +} + +/**Function************************************************************* + + Synopsis [Starts non-linear quantification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinAddPair( Llb_Mgr_t * p, DdNode * bFunc, int iPart, int iVar ) +{ + if ( p->pVars[iVar] == NULL ) + { + p->pVars[iVar] = ABC_CALLOC( Llb_Var_t, 1 ); + p->pVars[iVar]->iVar = iVar; + p->pVars[iVar]->nScore = 0; + p->pVars[iVar]->vParts = Vec_IntAlloc( 8 ); + } + Vec_IntPush( p->pVars[iVar]->vParts, iPart ); + Vec_IntPush( p->pParts[iPart]->vVars, iVar ); +} + +/**Function************************************************************* + + Synopsis [Starts non-linear quantification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinAddPartition( Llb_Mgr_t * p, int i, DdNode * bFunc ) +{ + int k, nSuppSize; + assert( !Cudd_IsConstant(bFunc) ); + // create partition + p->pParts[i] = ABC_CALLOC( Llb_Prt_t, 1 ); + p->pParts[i]->iPart = i; + p->pParts[i]->bFunc = bFunc; + p->pParts[i]->vVars = Vec_IntAlloc( 8 ); + // add support dependencies + nSuppSize = 0; + Extra_SupportArray( p->dd, bFunc, p->pSupp ); + for ( k = 0; k < p->nVars; k++ ) + { + nSuppSize += p->pSupp[k]; + if ( p->pSupp[k] && p->pVars2Q[k] ) + Llb_NonlinAddPair( p, bFunc, i, k ); + } + p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize ); +} + +/**Function************************************************************* + + Synopsis [Starts non-linear quantification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinStart( Llb_Mgr_t * p, int TimeOut ) +{ + Vec_Ptr_t * vRootBdds; + DdNode * bFunc; + int i; + // create and collect BDDs + vRootBdds = Llb_NonlinBuildBdds( p->pAig, p->vLeaves, p->vRoots, p->dd, TimeOut ); // come referenced + if ( vRootBdds == NULL ) + return 0; + // add pairs (refs are consumed inside) + Vec_PtrForEachEntry( DdNode *, vRootBdds, bFunc, i ) + Llb_NonlinAddPartition( p, i, bFunc ); + Vec_PtrFree( vRootBdds ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Checks that each var appears in at least one partition.] + + Description [] + + SideEffects [] + + SeeAlso [] +**********************************************************************/ +void Llb_NonlinCheckVars( Llb_Mgr_t * p ) +{ + Llb_Var_t * pVar; + int i; + Llb_MgrForEachVar( p, pVar, i ) + assert( Vec_IntSize(pVar->vParts) > 1 ); +} + +/**Function************************************************************* + + Synopsis [Find next partition to quantify] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinNextPartitions( Llb_Mgr_t * p, Llb_Prt_t ** ppPart1, Llb_Prt_t ** ppPart2 ) +{ + Llb_Var_t * pVar, * pVarBest = NULL; + Llb_Prt_t * pPart, * pPart1Best = NULL, * pPart2Best = NULL; + int i; + Llb_NonlinCheckVars( p ); + // find variable with minimum score + Llb_MgrForEachVar( p, pVar, i ) + if ( pVarBest == NULL || pVarBest->nScore > pVar->nScore ) + pVarBest = pVar; + if ( pVarBest == NULL ) + return 0; + // find two partitions with minimum size + Llb_VarForEachPart( p, pVarBest, pPart, i ) + { + if ( pPart1Best == NULL ) + pPart1Best = pPart; + else if ( pPart2Best == NULL ) + pPart2Best = pPart; + else if ( pPart1Best->nSize > pPart->nSize || pPart2Best->nSize > pPart->nSize ) + { + if ( pPart1Best->nSize > pPart2Best->nSize ) + pPart1Best = pPart; + else + pPart2Best = pPart; + } + } + *ppPart1 = pPart1Best; + *ppPart2 = pPart2Best; + return 1; +} + +/**Function************************************************************* + + Synopsis [Reorders BDDs in the working manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinReorder( DdManager * dd, int fTwice, int fVerbose ) +{ + int clk = clock(); + if ( fVerbose ) + Abc_Print( 1, "Reordering... Before =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); + if ( fVerbose ) + Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + if ( fTwice ) + { + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); + if ( fVerbose ) + Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + } + if ( fVerbose ) + Abc_PrintTime( 1, "Time", clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [Recomputes scores after variable reordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinRecomputeScores( Llb_Mgr_t * p ) +{ + Llb_Prt_t * pPart; + Llb_Var_t * pVar; + int i, k; + Llb_MgrForEachPart( p, pPart, i ) + pPart->nSize = Cudd_DagSize(pPart->bFunc); + Llb_MgrForEachVar( p, pVar, i ) + { + pVar->nScore = 0; + Llb_VarForEachPart( p, pVar, pPart, k ) + pVar->nScore += pPart->nSize; + } +} + +/**Function************************************************************* + + Synopsis [Recomputes scores after variable reordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinVerifyScores( Llb_Mgr_t * p ) +{ + Llb_Prt_t * pPart; + Llb_Var_t * pVar; + int i, k, nScore; + Llb_MgrForEachPart( p, pPart, i ) + assert( pPart->nSize == Cudd_DagSize(pPart->bFunc) ); + Llb_MgrForEachVar( p, pVar, i ) + { + nScore = 0; + Llb_VarForEachPart( p, pVar, pPart, k ) + nScore += pPart->nSize; + assert( nScore == pVar->nScore ); + } +} + +/**Function************************************************************* + + Synopsis [Starts non-linear quantification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Mgr_t * Llb_NonlinAlloc( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, DdManager * dd ) +{ + Llb_Mgr_t * p; + p = ABC_CALLOC( Llb_Mgr_t, 1 ); + p->pAig = pAig; + p->vLeaves = vLeaves; + p->vRoots = vRoots; + p->dd = dd; + p->pVars2Q = pVars2Q; + p->nVars = Cudd_ReadSize(dd); + p->iPartFree = Vec_PtrSize(vRoots); + p->pVars = ABC_CALLOC( Llb_Var_t *, p->nVars ); + p->pParts = ABC_CALLOC( Llb_Prt_t *, 2 * p->iPartFree + 2 ); + p->pSupp = ABC_ALLOC( int, Cudd_ReadSize(dd) ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops non-linear quantification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinFree( Llb_Mgr_t * p ) +{ + Llb_Prt_t * pPart; + Llb_Var_t * pVar; + int i; + Llb_MgrForEachVar( p, pVar, i ) + Llb_NonlinRemoveVar( p, pVar ); + Llb_MgrForEachPart( p, pPart, i ) + Llb_NonlinRemovePart( p, pPart ); + ABC_FREE( p->pVars ); + ABC_FREE( p->pParts ); + ABC_FREE( p->pSupp ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Performs image computation.] + + Description [Computes image of BDDs (vFuncs).] + + SideEffects [BDDs in vFuncs are derefed inside. The result is refed.] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_NonlinImage( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, + DdManager * dd, DdNode * bCurrent, int fReorder, int fVerbose, int * pOrder, int Limit, int TimeOut ) +{ + Llb_Prt_t * pPart, * pPart1, * pPart2; + Llb_Mgr_t * p; + DdNode * bFunc, * bTemp; + int i, nReorders, timeInside; + int clk = clock(), clk2; + // start the manager + clk2 = clock(); + p = Llb_NonlinAlloc( pAig, vLeaves, vRoots, pVars2Q, dd ); + if ( !Llb_NonlinStart( p, TimeOut ) ) + { + Llb_NonlinFree( p ); + return NULL; + } + // add partition + Llb_NonlinAddPartition( p, p->iPartFree++, bCurrent ); + // remove singles + Llb_MgrForEachPart( p, pPart, i ) + if ( Llb_NonlinHasSingletonVars(p, pPart) ) + Llb_NonlinQuantify1( p, pPart, 0 ); + timeBuild += clock() - clk2; + timeInside = clock() - clk2; + // compute scores + Llb_NonlinRecomputeScores( p ); + // save permutation + if ( pOrder ) + memcpy( pOrder, dd->invperm, sizeof(int) * dd->size ); + // iteratively quantify variables + while ( Llb_NonlinNextPartitions(p, &pPart1, &pPart2) ) + { + clk2 = clock(); + nReorders = Cudd_ReadReorderings(dd); + if ( !Llb_NonlinQuantify2( p, pPart1, pPart2, Limit, TimeOut ) ) + { + Llb_NonlinFree( p ); + return NULL; + } + timeAndEx += clock() - clk2; + timeInside += clock() - clk2; + if ( nReorders < Cudd_ReadReorderings(dd) ) + Llb_NonlinRecomputeScores( p ); +// else +// Llb_NonlinVerifyScores( p ); + } + // load partitions + bFunc = Cudd_ReadOne(p->dd); Cudd_Ref( bFunc ); + Llb_MgrForEachPart( p, pPart, i ) + { + bFunc = Cudd_bddAnd( p->dd, bTemp = bFunc, pPart->bFunc ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + nSuppMax = p->nSuppMax; + Llb_NonlinFree( p ); + // reorder variables + if ( fReorder ) + Llb_NonlinReorder( dd, 0, fVerbose ); + timeOther += clock() - clk - timeInside; + // return + Cudd_Deref( bFunc ); + return bFunc; +} + + + +static Llb_Mgr_t * p = NULL; + +/**Function************************************************************* + + Synopsis [Starts image computation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdManager * Llb_NonlinImageStart( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, int * pOrder, int fFirst, int TimeTarget ) +{ + DdManager * dd; + int clk = clock(); + assert( p == NULL ); + // start a new manager (disable reordering) + dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + dd->TimeStop = TimeTarget; + Cudd_ShuffleHeap( dd, pOrder ); +// if ( fFirst ) + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + // start the manager + p = Llb_NonlinAlloc( pAig, vLeaves, vRoots, pVars2Q, dd ); + if ( !Llb_NonlinStart( p, 0 ) ) + { + Llb_NonlinFree( p ); + p = NULL; + return NULL; + } + timeBuild += clock() - clk; +// if ( !fFirst ) +// Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + return dd; +} + +/**Function************************************************************* + + Synopsis [Performs image computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_NonlinImageCompute( DdNode * bCurrent, int fReorder, int fDrop, int fVerbose, int * pOrder ) +{ + Llb_Prt_t * pPart, * pPart1, * pPart2; + DdNode * bFunc, * bTemp; + int i, nReorders, timeInside = 0; + int clk = clock(), clk2; + + // add partition + Llb_NonlinAddPartition( p, p->iPartFree++, bCurrent ); + // remove singles + Llb_MgrForEachPart( p, pPart, i ) + if ( Llb_NonlinHasSingletonVars(p, pPart) ) + Llb_NonlinQuantify1( p, pPart, 0 ); + // reorder + if ( fReorder ) + Llb_NonlinReorder( p->dd, 0, 0 ); + // save permutation + memcpy( pOrder, p->dd->invperm, sizeof(int) * p->dd->size ); + + // compute scores + Llb_NonlinRecomputeScores( p ); + // iteratively quantify variables + while ( Llb_NonlinNextPartitions(p, &pPart1, &pPart2) ) + { + clk2 = clock(); + nReorders = Cudd_ReadReorderings(p->dd); + if ( !Llb_NonlinQuantify2( p, pPart1, pPart2, 0, 0 ) ) + { + Llb_NonlinFree( p ); + return NULL; + } + timeAndEx += clock() - clk2; + timeInside += clock() - clk2; + if ( nReorders < Cudd_ReadReorderings(p->dd) ) + Llb_NonlinRecomputeScores( p ); +// else +// Llb_NonlinVerifyScores( p ); + } + // load partitions + bFunc = Cudd_ReadOne(p->dd); Cudd_Ref( bFunc ); + Llb_MgrForEachPart( p, pPart, i ) + { + bFunc = Cudd_bddAnd( p->dd, bTemp = bFunc, pPart->bFunc ); + if ( bFunc == NULL ) + { + Cudd_RecursiveDeref( p->dd, bTemp ); + Llb_NonlinFree( p ); + return NULL; + } + Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + nSuppMax = p->nSuppMax; + // reorder variables +// if ( fReorder ) +// Llb_NonlinReorder( p->dd, 0, fVerbose ); + // save permutation +// memcpy( pOrder, p->dd->invperm, sizeof(int) * Cudd_ReadSize(p->dd) ); + + timeOther += clock() - clk - timeInside; + // return + Cudd_Deref( bFunc ); + return bFunc; +} + +/**Function************************************************************* + + Synopsis [Quits image computation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinImageQuit() +{ + DdManager * dd; + if ( p == NULL ) + return; + dd = p->dd; + Llb_NonlinFree( p ); + if ( dd->bFunc ) + Cudd_RecursiveDeref( dd, dd->bFunc ); + Extra_StopManager( dd ); +// Cudd_Quit ( dd ); + p = NULL; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/llb/llb3Nonlin.c b/src/proof/llb/llb3Nonlin.c new file mode 100644 index 00000000..45f6f11e --- /dev/null +++ b/src/proof/llb/llb3Nonlin.c @@ -0,0 +1,871 @@ +/**CFile**************************************************************** + + FileName [llb2Nonlin.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Non-linear quantification scheduling.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Nonlin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Llb_Mnn_t_ Llb_Mnn_t; +struct Llb_Mnn_t_ +{ + Aig_Man_t * pInit; // AIG manager + Aig_Man_t * pAig; // AIG manager + Gia_ParLlb_t * pPars; // parameters + + DdManager * dd; // BDD manager + DdManager * ddG; // BDD manager + DdManager * ddR; // BDD manager + Vec_Ptr_t * vRings; // onion rings in ddR + + Vec_Ptr_t * vLeaves; + Vec_Ptr_t * vRoots; + int * pVars2Q; + int * pOrderL; + int * pOrderL2; + int * pOrderG; + + Vec_Int_t * vCs2Glo; // cur state variables into global variables + Vec_Int_t * vNs2Glo; // next state variables into global variables + Vec_Int_t * vGlo2Cs; // global variables into cur state variables + Vec_Int_t * vGlo2Ns; // global variables into next state variables + + int ddLocReos; + int ddLocGrbs; + + int timeImage; + int timeTran1; + int timeTran2; + int timeGloba; + int timeOther; + int timeTotal; + int timeReo; + int timeReoG; + +}; + +extern int timeBuild, timeAndEx, timeOther; +extern int nSuppMax; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Finds variable whose 0-cofactor is the smallest.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinFindBestVar( DdManager * dd, DdNode * bFunc, Aig_Man_t * pAig ) +{ + int fVerbose = 0; + Aig_Obj_t * pObj; + DdNode * bCof, * bVar; + int i, iVar, iVarBest = -1, iValue, iValueBest = ABC_INFINITY, Size0Best = -1; + int Size, Size0, Size1; + int clk = clock(); + Size = Cudd_DagSize(bFunc); +// printf( "Original = %6d. SuppSize = %3d. Vars = %3d.\n", +// Size = Cudd_DagSize(bFunc), Cudd_SupportSize(dd, bFunc), Aig_ManRegNum(pAig) ); + Saig_ManForEachLo( pAig, pObj, i ) + { + iVar = Aig_ObjId(pObj); + +if ( fVerbose ) +printf( "Var =%3d : ", iVar ); + bVar = Cudd_bddIthVar(dd, iVar); + + bCof = Cudd_bddAnd( dd, bFunc, Cudd_Not(bVar) ); Cudd_Ref( bCof ); + Size0 = Cudd_DagSize(bCof); +if ( fVerbose ) +printf( "Supp0 =%3d ", Cudd_SupportSize(dd, bCof) ); +if ( fVerbose ) +printf( "Size0 =%6d ", Size0 ); + Cudd_RecursiveDeref( dd, bCof ); + + bCof = Cudd_bddAnd( dd, bFunc, bVar ); Cudd_Ref( bCof ); + Size1 = Cudd_DagSize(bCof); +if ( fVerbose ) +printf( "Supp1 =%3d ", Cudd_SupportSize(dd, bCof) ); +if ( fVerbose ) +printf( "Size1 =%6d ", Size1 ); + Cudd_RecursiveDeref( dd, bCof ); + + iValue = Abc_MaxInt(Size0, Size1) - Abc_MinInt(Size0, Size1) + Size0 + Size1 - Size; +if ( fVerbose ) +printf( "D =%6d ", Size0 + Size1 - Size ); +if ( fVerbose ) +printf( "B =%6d ", Abc_MaxInt(Size0, Size1) - Abc_MinInt(Size0, Size1) ); +if ( fVerbose ) +printf( "S =%6d\n", iValue ); + if ( Size0 > 1 && Size1 > 1 && iValueBest > iValue ) + { + iValueBest = iValue; + iVarBest = i; + Size0Best = Size0; + } + } + printf( "BestVar = %4d/%4d. Value =%6d. Orig =%6d. Size0 =%6d. ", + iVarBest, Aig_ObjId(Saig_ManLo(pAig,iVarBest)), iValueBest, Size, Size0Best ); + Abc_PrintTime( 1, "Time", clock() - clk ); + return iVarBest; +} + + +/**Function************************************************************* + + Synopsis [Finds variable whose 0-cofactor is the smallest.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinTrySubsetting( DdManager * dd, DdNode * bFunc ) +{ + DdNode * bNew; + printf( "Original = %6d. SuppSize = %3d. ", + Cudd_DagSize(bFunc), Cudd_SupportSize(dd, bFunc) ); + bNew = Cudd_SubsetHeavyBranch( dd, bFunc, Cudd_SupportSize(dd, bFunc), 1000 ); Cudd_Ref( bNew ); + printf( "Result = %6d. SuppSize = %3d.\n", + Cudd_DagSize(bNew), Cudd_SupportSize(dd, bNew) ); + Cudd_RecursiveDeref( dd, bNew ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinPrepareVarMap( Llb_Mnn_t * p ) +{ + Aig_Obj_t * pObjLi, * pObjLo, * pObj; + int i, iVarLi, iVarLo; + p->vCs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) ); + p->vNs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) ); + p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); + p->vGlo2Ns = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); + Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) + { + iVarLi = Aig_ObjId(pObjLi); + iVarLo = Aig_ObjId(pObjLo); + assert( iVarLi >= 0 && iVarLi < Aig_ManObjNumMax(p->pAig) ); + assert( iVarLo >= 0 && iVarLo < Aig_ManObjNumMax(p->pAig) ); + Vec_IntWriteEntry( p->vCs2Glo, iVarLo, i ); + Vec_IntWriteEntry( p->vNs2Glo, iVarLi, i ); + Vec_IntWriteEntry( p->vGlo2Cs, i, iVarLo ); + Vec_IntWriteEntry( p->vGlo2Ns, i, iVarLi ); + } + // add mapping of the PIs + Saig_ManForEachPi( p->pAig, pObj, i ) + { + Vec_IntWriteEntry( p->vCs2Glo, Aig_ObjId(pObj), Aig_ManRegNum(p->pAig)+i ); + Vec_IntWriteEntry( p->vNs2Glo, Aig_ObjId(pObj), Aig_ManRegNum(p->pAig)+i ); + } +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_NonlinComputeInitState( Aig_Man_t * pAig, DdManager * dd ) +{ + Aig_Obj_t * pObj; + DdNode * bRes, * bVar, * bTemp; + int i, iVar, TimeStop; + TimeStop = dd->TimeStop; dd->TimeStop = 0; + bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); + Saig_ManForEachLo( pAig, pObj, i ) + { + iVar = (Cudd_ReadSize(dd) == Aig_ManRegNum(pAig)) ? i : Aig_ObjId(pObj); + bVar = Cudd_bddIthVar( dd, iVar ); + bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bRes ); + dd->TimeStop = TimeStop; + return bRes; +} + + +/**Function************************************************************* + + Synopsis [Derives counter-example by backward reachability.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Llb_NonlinDeriveCex( Llb_Mnn_t * p ) +{ + Abc_Cex_t * pCex; + Aig_Obj_t * pObj; + Vec_Int_t * vVarsNs; + DdNode * bState, * bImage, * bOneCube, * bTemp, * bRing; + int i, v, RetValue, nPiOffset; + char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) ); + assert( Vec_PtrSize(p->vRings) > 0 ); + + p->dd->TimeStop = 0; + p->ddR->TimeStop = 0; + + // update quantifiable vars + memset( p->pVars2Q, 0, sizeof(int) * Cudd_ReadSize(p->dd) ); + vVarsNs = Vec_IntAlloc( Aig_ManRegNum(p->pAig) ); + Saig_ManForEachLi( p->pAig, pObj, i ) + { + p->pVars2Q[Aig_ObjId(pObj)] = 1; + Vec_IntPush( vVarsNs, Aig_ObjId(pObj) ); + } +/* + Saig_ManForEachLo( p->pAig, pObj, i ) + printf( "%d ", pObj->Id ); + printf( "\n" ); + Saig_ManForEachLi( p->pAig, pObj, i ) + printf( "%d(%d) ", pObj->Id, Aig_ObjFaninId0(pObj) ); + printf( "\n" ); +*/ + // allocate room for the counter-example + pCex = Abc_CexAlloc( Saig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Vec_PtrSize(p->vRings) ); + pCex->iFrame = Vec_PtrSize(p->vRings) - 1; + pCex->iPo = -1; + + // get the last cube + bOneCube = Cudd_bddIntersect( p->ddR, (DdNode *)Vec_PtrEntryLast(p->vRings), p->ddR->bFunc ); Cudd_Ref( bOneCube ); + RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); + Cudd_RecursiveDeref( p->ddR, bOneCube ); + assert( RetValue ); + + // write PIs of counter-example + nPiOffset = Saig_ManRegNum(p->pAig) + Saig_ManPiNum(p->pAig) * (Vec_PtrSize(p->vRings) - 1); + Saig_ManForEachPi( p->pAig, pObj, i ) + if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) + Abc_InfoSetBit( pCex->pData, nPiOffset + i ); + + // write state in terms of NS variables + if ( Vec_PtrSize(p->vRings) > 1 ) + { + bState = Llb_CoreComputeCube( p->dd, vVarsNs, 1, pValues ); Cudd_Ref( bState ); + } + // perform backward analysis + Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v ) + { + if ( v == Vec_PtrSize(p->vRings) - 1 ) + continue; +//Extra_bddPrintSupport( p->dd, bState ); printf( "\n" ); +//Extra_bddPrintSupport( p->dd, bRing ); printf( "\n" ); + // compute the next states + bImage = Llb_NonlinImage( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->dd, bState, + p->pPars->fReorder, p->pPars->fVeryVerbose, NULL, ABC_INFINITY, ABC_INFINITY ); // consumed reference + assert( bImage != NULL ); + Cudd_Ref( bImage ); +//Extra_bddPrintSupport( p->dd, bImage ); printf( "\n" ); + + // move reached states into ring manager + bImage = Extra_TransferPermute( p->dd, p->ddR, bTemp = bImage, Vec_IntArray(p->vCs2Glo) ); Cudd_Ref( bImage ); + Cudd_RecursiveDeref( p->dd, bTemp ); + + // intersect with the previous set + bOneCube = Cudd_bddIntersect( p->ddR, bImage, bRing ); Cudd_Ref( bOneCube ); + Cudd_RecursiveDeref( p->ddR, bImage ); + + // find any assignment of the BDD + RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); + Cudd_RecursiveDeref( p->ddR, bOneCube ); + assert( RetValue ); + + // write PIs of counter-example + nPiOffset -= Saig_ManPiNum(p->pAig); + Saig_ManForEachPi( p->pAig, pObj, i ) + if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) + Abc_InfoSetBit( pCex->pData, nPiOffset + i ); + + // check that we get the init state + if ( v == 0 ) + { + Saig_ManForEachLo( p->pAig, pObj, i ) + assert( pValues[i] == 0 ); + break; + } + + // write state in terms of NS variables + bState = Llb_CoreComputeCube( p->dd, vVarsNs, 1, pValues ); Cudd_Ref( bState ); + } + assert( nPiOffset == Saig_ManRegNum(p->pAig) ); + // update the output number +//Abc_CexPrint( pCex ); + RetValue = Saig_ManFindFailedPoCex( p->pInit, pCex ); + assert( RetValue >= 0 && RetValue < Saig_ManPoNum(p->pInit) ); // invalid CEX!!! + pCex->iPo = RetValue; + // cleanup + ABC_FREE( pValues ); + Vec_IntFree( vVarsNs ); + return pCex; +} + + +/**Function************************************************************* + + Synopsis [Perform reachability with hints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinReoHook( DdManager * dd, char * Type, void * Method ) +{ + Aig_Man_t * pAig = (Aig_Man_t *)dd->bFunc; + Aig_Obj_t * pObj; + int i; + printf( "Order: " ); + for ( i = 0; i < Cudd_ReadSize(dd); i++ ) + { + pObj = Aig_ManObj( pAig, i ); + if ( pObj == NULL ) + continue; + if ( Saig_ObjIsPi(pAig, pObj) ) + printf( "pi" ); + else if ( Saig_ObjIsLo(pAig, pObj) ) + printf( "lo" ); + else if ( Saig_ObjIsPo(pAig, pObj) ) + printf( "po" ); + else if ( Saig_ObjIsLi(pAig, pObj) ) + printf( "li" ); + else continue; + printf( "%d=%d ", i, dd->perm[i] ); + } + printf( "\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Perform reachability with hints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinCompPerms( DdManager * dd, int * pVar2Lev ) +{ + DdSubtable * pSubt; + int i, Sum = 0, Entry; + for ( i = 0; i < dd->size; i++ ) + { + pSubt = &(dd->subtables[dd->perm[i]]); + if ( pSubt->keys == pSubt->dead + 1 ) + continue; + Entry = Abc_MaxInt(dd->perm[i], pVar2Lev[i]) - Abc_MinInt(dd->perm[i], pVar2Lev[i]); + Sum += Entry; +//printf( "%d-%d(%d) ", dd->perm[i], pV2L[i], Entry ); + } + return Sum; +} + +/**Function************************************************************* + + Synopsis [Perform reachability with hints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinReachability( Llb_Mnn_t * p ) +{ + DdNode * bTemp, * bNext; + int nIters, nBddSize0, nBddSize, NumCmp, Limit = p->pPars->nBddMax; + int clk2, clk3, clk = clock(); + assert( Aig_ManRegNum(p->pAig) > 0 ); + + // compute time to stop + p->pPars->TimeTarget = p->pPars->TimeLimit ? time(NULL) + p->pPars->TimeLimit : 0; + + // set the stop time parameter + p->dd->TimeStop = p->pPars->TimeTarget; + p->ddG->TimeStop = p->pPars->TimeTarget; + p->ddR->TimeStop = p->pPars->TimeTarget; + + // set reordering hooks + assert( p->dd->bFunc == NULL ); +// p->dd->bFunc = (DdNode *)p->pAig; +// Cudd_AddHook( p->dd, Llb_NonlinReoHook, CUDD_POST_REORDERING_HOOK ); + + // create bad state in the ring manager + p->ddR->bFunc = Llb_BddComputeBad( p->pInit, p->ddR, p->pPars->TimeTarget ); + if ( p->ddR->bFunc == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = -1; + return -1; + } + Cudd_Ref( p->ddR->bFunc ); + // compute the starting set of states + Cudd_Quit( p->dd ); + p->dd = Llb_NonlinImageStart( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->pOrderL, 1, p->pPars->TimeTarget ); + if ( p->dd == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = -1; + return -1; + } + p->dd->bFunc = Llb_NonlinComputeInitState( p->pAig, p->dd ); Cudd_Ref( p->dd->bFunc ); // current + p->ddG->bFunc = Llb_NonlinComputeInitState( p->pAig, p->ddG ); Cudd_Ref( p->ddG->bFunc ); // reached + p->ddG->bFunc2 = Llb_NonlinComputeInitState( p->pAig, p->ddG ); Cudd_Ref( p->ddG->bFunc2 ); // frontier + for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ ) + { + // check the runtime limit + clk2 = clock(); + if ( p->pPars->TimeLimit && time(NULL) > p->pPars->TimeTarget ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Llb_NonlinImageQuit(); + return -1; + } + + // save the onion ring + bTemp = Extra_TransferPermute( p->dd, p->ddR, p->dd->bFunc, Vec_IntArray(p->vCs2Glo) ); + if ( bTemp == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during ring transfer.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Llb_NonlinImageQuit(); + return -1; + } + Cudd_Ref( bTemp ); + Vec_PtrPush( p->vRings, bTemp ); + + // check it for bad states + if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->ddR, bTemp, Cudd_Not(p->ddR->bFunc) ) ) + { + assert( p->pInit->pSeqModel == NULL ); + if ( !p->pPars->fBackward ) + p->pInit->pSeqModel = Llb_NonlinDeriveCex( p ); + if ( !p->pPars->fSilent ) + { + if ( !p->pPars->fBackward ) + printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump a witness). ", p->pInit->pSeqModel->iPo, nIters ); + else + printf( "Output ??? was asserted in frame %d (counter-example is not produced). ", nIters ); + Abc_PrintTime( 1, "Time", clock() - clk ); + } + p->pPars->iFrame = nIters - 1; + Llb_NonlinImageQuit(); + return 0; + } + + // compute the next states + clk3 = clock(); + nBddSize0 = Cudd_DagSize( p->dd->bFunc ); + bNext = Llb_NonlinImageCompute( p->dd->bFunc, p->pPars->fReorder, 0, 1, p->pOrderL ); // consumes ref +// bNext = Llb_NonlinImage( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->dd, bCurrent, +// p->pPars->fReorder, p->pPars->fVeryVerbose, NULL, ABC_INFINITY, p->pPars->TimeTarget ); + if ( bNext == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in quantification.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Llb_NonlinImageQuit(); + return -1; + } + Cudd_Ref( bNext ); + nBddSize = Cudd_DagSize( bNext ); + p->timeImage += clock() - clk3; + + + // transfer to the state manager + clk3 = clock(); + Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc2 ); + p->ddG->bFunc2 = Extra_TransferPermute( p->dd, p->ddG, bNext, Vec_IntArray(p->vNs2Glo) ); +// p->ddG->bFunc2 = Extra_bddAndPermute( p->ddG, Cudd_Not(p->ddG->bFunc), p->dd, bNext, Vec_IntArray(p->vNs2Glo) ); + if ( p->ddG->bFunc2 == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bNext ); + Llb_NonlinImageQuit(); + return -1; + } + Cudd_Ref( p->ddG->bFunc2 ); + Cudd_RecursiveDeref( p->dd, bNext ); + p->timeTran1 += clock() - clk3; + + // save permutation + NumCmp = Llb_NonlinCompPerms( p->dd, p->pOrderL2 ); + // save order before image computation + memcpy( p->pOrderL2, p->dd->perm, sizeof(int) * p->dd->size ); + // update the image computation manager + p->timeReo += Cudd_ReadReorderingTime(p->dd); + p->ddLocReos += Cudd_ReadReorderings(p->dd); + p->ddLocGrbs += Cudd_ReadGarbageCollections(p->dd); + Llb_NonlinImageQuit(); + p->dd = Llb_NonlinImageStart( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->pOrderL, 0, p->pPars->TimeTarget ); + if ( p->dd == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + return -1; + } + //Extra_TestAndPerm( p->ddG, Cudd_Not(p->ddG->bFunc), p->ddG->bFunc2 ); + + // derive new states + clk3 = clock(); + p->ddG->bFunc2 = Cudd_bddAnd( p->ddG, bTemp = p->ddG->bFunc2, Cudd_Not(p->ddG->bFunc) ); + if ( p->ddG->bFunc2 == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->ddG, bTemp ); + Llb_NonlinImageQuit(); + return -1; + } + Cudd_Ref( p->ddG->bFunc2 ); + Cudd_RecursiveDeref( p->ddG, bTemp ); + p->timeGloba += clock() - clk3; + + if ( Cudd_IsConstant(p->ddG->bFunc2) ) + break; + // add to the reached set + clk3 = clock(); + p->ddG->bFunc = Cudd_bddOr( p->ddG, bTemp = p->ddG->bFunc, p->ddG->bFunc2 ); + if ( p->ddG->bFunc == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->ddG, bTemp ); + Llb_NonlinImageQuit(); + return -1; + } + Cudd_Ref( p->ddG->bFunc ); + Cudd_RecursiveDeref( p->ddG, bTemp ); + p->timeGloba += clock() - clk3; + + // reset permutation +// RetValue = Cudd_CheckZeroRef( dd ); +// assert( RetValue == 0 ); +// Cudd_ShuffleHeap( dd, pOrderG ); + + // move new states to the working manager + clk3 = clock(); + p->dd->bFunc = Extra_TransferPermute( p->ddG, p->dd, p->ddG->bFunc2, Vec_IntArray(p->vGlo2Cs) ); + if ( p->dd->bFunc == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Llb_NonlinImageQuit(); + return -1; + } + Cudd_Ref( p->dd->bFunc ); + p->timeTran2 += clock() - clk3; + + // report the results + if ( p->pPars->fVerbose ) + { + printf( "I =%3d : ", nIters ); + printf( "Fr =%7d ", nBddSize0 ); + printf( "Im =%7d ", nBddSize ); + printf( "(%4d %4d) ", p->ddLocReos, p->ddLocGrbs ); + printf( "Rea =%6d ", Cudd_DagSize(p->ddG->bFunc) ); + printf( "(%4d %4d) ", Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) ); + printf( "S =%4d ", nSuppMax ); + printf( "cL =%5d ", NumCmp ); + printf( "cG =%5d ", Llb_NonlinCompPerms( p->ddG, p->pOrderG ) ); + Abc_PrintTime( 1, "T", clock() - clk2 ); + memcpy( p->pOrderG, p->ddG->perm, sizeof(int) * p->ddG->size ); + } +/* + if ( pPars->fVerbose ) + { + double nMints = Cudd_CountMinterm(ddG, bReached, Saig_ManRegNum(pAig) ); +// Extra_bddPrint( ddG, bReached );printf( "\n" ); + printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(pAig)) ); + fflush( stdout ); + } +*/ + if ( nIters == p->pPars->nIterMax - 1 ) + { + if ( !p->pPars->fSilent ) + printf( "Reached limit on the number of timeframes (%d).\n", p->pPars->nIterMax ); + p->pPars->iFrame = nIters; + Llb_NonlinImageQuit(); + return -1; + } + } + Llb_NonlinImageQuit(); + + // report the stats + if ( p->pPars->fVerbose ) + { + double nMints = Cudd_CountMinterm(p->ddG, p->ddG->bFunc, Saig_ManRegNum(p->pAig) ); + if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax ) + printf( "Reachability analysis is stopped after %d frames.\n", nIters ); + else + printf( "Reachability analysis completed after %d frames.\n", nIters ); + printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); + fflush( stdout ); + } + if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax ) + { + if ( !p->pPars->fSilent ) + printf( "Verified only for states reachable in %d frames. ", nIters ); + p->pPars->iFrame = p->pPars->nIterMax; + return -1; // undecided + } + // report + if ( !p->pPars->fSilent ) + printf( "The miter is proved unreachable after %d iterations. ", nIters ); + p->pPars->iFrame = nIters - 1; + Abc_PrintTime( 1, "Time", clock() - clk ); + return 1; // unreachable +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Mnn_t * Llb_MnnStart( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) +{ + Llb_Mnn_t * p; + Aig_Obj_t * pObj; + int i; + p = ABC_CALLOC( Llb_Mnn_t, 1 ); + p->pInit = pInit; + p->pAig = pAig; + p->pPars = pPars; + p->dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + p->ddG = Cudd_Init( Aig_ManRegNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + p->ddR = Cudd_Init( Aig_ManPiNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); + Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT ); + Cudd_AutodynEnable( p->ddR, CUDD_REORDER_SYMM_SIFT ); + p->vRings = Vec_PtrAlloc( 100 ); + // create leaves + p->vLeaves = Vec_PtrAlloc( Aig_ManPiNum(pAig) ); + Aig_ManForEachPi( pAig, pObj, i ) + Vec_PtrPush( p->vLeaves, pObj ); + // create roots + p->vRoots = Vec_PtrAlloc( Aig_ManPoNum(pAig) ); + Saig_ManForEachLi( pAig, pObj, i ) + Vec_PtrPush( p->vRoots, pObj ); + // variables to quantify + p->pOrderL = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); + p->pOrderL2= ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); + p->pOrderG = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); + p->pVars2Q = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); + Aig_ManForEachPi( pAig, pObj, i ) + p->pVars2Q[Aig_ObjId(pObj)] = 1; + for ( i = 0; i < Aig_ManObjNumMax(pAig); i++ ) + p->pOrderL[i] = p->pOrderL2[i] = p->pOrderG[i] = i; + Llb_NonlinPrepareVarMap( p ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MnnStop( Llb_Mnn_t * p ) +{ + DdNode * bTemp; + int i; + if ( p->pPars->fVerbose ) + { + p->timeOther = p->timeTotal - p->timeImage - p->timeTran1 - p->timeTran2 - p->timeGloba; + p->timeReoG = Cudd_ReadReorderingTime(p->ddG); + ABC_PRTP( "Image ", p->timeImage, p->timeTotal ); + ABC_PRTP( " build ", timeBuild, p->timeTotal ); + ABC_PRTP( " and-ex ", timeAndEx, p->timeTotal ); + ABC_PRTP( " other ", timeOther, p->timeTotal ); + ABC_PRTP( "Transfer1", p->timeTran1, p->timeTotal ); + ABC_PRTP( "Transfer2", p->timeTran2, p->timeTotal ); + ABC_PRTP( "Global ", p->timeGloba, p->timeTotal ); + ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); + ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); + ABC_PRTP( " reo ", p->timeReo, p->timeTotal ); + ABC_PRTP( " reoG ", p->timeReoG, p->timeTotal ); + } + if ( p->ddR->bFunc ) + Cudd_RecursiveDeref( p->ddR, p->ddR->bFunc ); + Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i ) + Cudd_RecursiveDeref( p->ddR, bTemp ); + Vec_PtrFree( p->vRings ); + if ( p->ddG->bFunc ) + Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc ); + if ( p->ddG->bFunc2 ) + Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc2 ); +// printf( "manager1\n" ); +// Extra_StopManager( p->dd ); +// printf( "manager2\n" ); + Extra_StopManager( p->ddG ); +// printf( "manager3\n" ); + Extra_StopManager( p->ddR ); + Vec_IntFreeP( &p->vCs2Glo ); + Vec_IntFreeP( &p->vNs2Glo ); + Vec_IntFreeP( &p->vGlo2Cs ); + Vec_IntFreeP( &p->vGlo2Ns ); + Vec_PtrFree( p->vLeaves ); + Vec_PtrFree( p->vRoots ); + ABC_FREE( p->pVars2Q ); + ABC_FREE( p->pOrderL ); + ABC_FREE( p->pOrderL2 ); + ABC_FREE( p->pOrderG ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinExperiment( Aig_Man_t * pAig, int Num ) +{ + Llb_Mnn_t * pMnn; + Gia_ParLlb_t Pars, * pPars = &Pars; + Aig_Man_t * p; + int clk = clock(); + + Llb_ManSetDefaultParams( pPars ); + pPars->fVerbose = 1; + + p = Aig_ManDupFlopsOnly( pAig ); +//Aig_ManShow( p, 0, NULL ); + Aig_ManPrintStats( pAig ); + Aig_ManPrintStats( p ); + + pMnn = Llb_MnnStart( pAig, p, pPars ); + Llb_NonlinReachability( pMnn ); + pMnn->timeTotal = clock() - clk; + Llb_MnnStop( pMnn ); + + Aig_ManStop( p ); +} + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinCoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) +{ + Llb_Mnn_t * pMnn; + Aig_Man_t * p; + int RetValue = -1; + + p = Aig_ManDupFlopsOnly( pAig ); +//Aig_ManShow( p, 0, NULL ); + if ( pPars->fVerbose ) + Aig_ManPrintStats( pAig ); + if ( pPars->fVerbose ) + Aig_ManPrintStats( p ); + + if ( !pPars->fSkipReach ) + { + int clk = clock(); + pMnn = Llb_MnnStart( pAig, p, pPars ); + RetValue = Llb_NonlinReachability( pMnn ); + pMnn->timeTotal = clock() - clk; + Llb_MnnStop( pMnn ); + } + + Aig_ManStop( p ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/llb/llb4Cex.c b/src/proof/llb/llb4Cex.c new file mode 100644 index 00000000..a68be711 --- /dev/null +++ b/src/proof/llb/llb4Cex.c @@ -0,0 +1,320 @@ +/**CFile**************************************************************** + + FileName [llb2Cex.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Non-linear quantification scheduling.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Cex.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" +#include "src/sat/cnf/cnf.h" +#include "src/sat/bsat/satSolver.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Translates a sequence of states into a counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Llb4_Nonlin4TransformCex( Aig_Man_t * pAig, Vec_Ptr_t * vStates, int iCexPo, int fVerbose ) +{ + Abc_Cex_t * pCex; + Cnf_Dat_t * pCnf; + Vec_Int_t * vAssumps; + sat_solver * pSat; + Aig_Obj_t * pObj; + unsigned * pNext, * pThis; + int i, k, iBit, status, nRegs, clk = clock(); +/* + Vec_PtrForEachEntry( unsigned *, vStates, pNext, i ) + { + printf( "%4d : ", i ); + Extra_PrintBinary( stdout, pNext, Aig_ManRegNum(pAig) ); + printf( "\n" ); + } +*/ + // derive SAT solver + nRegs = Aig_ManRegNum(pAig); pAig->nRegs = 0; + pCnf = Cnf_Derive( pAig, Aig_ManPoNum(pAig) ); + pAig->nRegs = nRegs; +// Cnf_DataTranformPolarity( pCnf, 0 ); + // convert into SAT solver + pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + if ( pSat == NULL ) + { + printf( "Llb4_Nonlin4TransformCex(): Counter-example generation has failed.\n" ); + Cnf_DataFree( pCnf ); + return NULL; + } + // simplify the problem + status = sat_solver_simplify(pSat); + if ( status == 0 ) + { + printf( "Llb4_Nonlin4TransformCex(): SAT solver is invalid.\n" ); + sat_solver_delete( pSat ); + Cnf_DataFree( pCnf ); + return NULL; + } + // start the counter-example + pCex = Abc_CexAlloc( Saig_ManRegNum(pAig), Saig_ManPiNum(pAig), Vec_PtrSize(vStates) ); + pCex->iFrame = Vec_PtrSize(vStates)-1; + pCex->iPo = -1; + + // solve each time frame + iBit = Saig_ManRegNum(pAig); + pThis = (unsigned *)Vec_PtrEntry( vStates, 0 ); + vAssumps = Vec_IntAlloc( 2 * Aig_ManRegNum(pAig) ); + Vec_PtrForEachEntryStart( unsigned *, vStates, pNext, i, 1 ) + { + // create assumptions + Vec_IntClear( vAssumps ); + Saig_ManForEachLo( pAig, pObj, k ) + Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !Abc_InfoHasBit(pThis,k) ) ); + Saig_ManForEachLi( pAig, pObj, k ) + Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !Abc_InfoHasBit(pNext,k) ) ); + // solve SAT problem + status = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), + (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + // if the problem is SAT, get the counterexample + if ( status != l_True ) + { + printf( "Llb4_Nonlin4TransformCex(): There is no transition between state %d and %d.\n", i-1, i ); + Vec_IntFree( vAssumps ); + sat_solver_delete( pSat ); + Cnf_DataFree( pCnf ); + ABC_FREE( pCex ); + return NULL; + } + // get the assignment of PIs + Saig_ManForEachPi( pAig, pObj, k ) + if ( sat_solver_var_value(pSat, pCnf->pVarNums[Aig_ObjId(pObj)]) ) + Abc_InfoSetBit( pCex->pData, iBit + k ); + // update the counter + iBit += Saig_ManPiNum(pAig); + pThis = pNext; + } + + // add the last frame when the property fails + Vec_IntClear( vAssumps ); + if ( iCexPo >= 0 ) + { + Saig_ManForEachPo( pAig, pObj, k ) + if ( k == iCexPo ) + Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 ) ); + } + else + { + Saig_ManForEachPo( pAig, pObj, k ) + Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 ) ); + } + + // add clause + status = sat_solver_addclause( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps) ); + if ( status == 0 ) + { + printf( "Llb4_Nonlin4TransformCex(): The SAT solver is unsat after adding last clause.\n" ); + Vec_IntFree( vAssumps ); + sat_solver_delete( pSat ); + Cnf_DataFree( pCnf ); + ABC_FREE( pCex ); + return NULL; + } + // create assumptions + Vec_IntClear( vAssumps ); + Saig_ManForEachLo( pAig, pObj, k ) + Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !Abc_InfoHasBit(pThis,k) ) ); + // solve the last frame + status = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), + (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + if ( status != l_True ) + { + printf( "Llb4_Nonlin4TransformCex(): There is no last transition that makes the property fail.\n" ); + Vec_IntFree( vAssumps ); + sat_solver_delete( pSat ); + Cnf_DataFree( pCnf ); + ABC_FREE( pCex ); + return NULL; + } + // get the assignment of PIs + Saig_ManForEachPi( pAig, pObj, k ) + if ( sat_solver_var_value(pSat, pCnf->pVarNums[Aig_ObjId(pObj)]) ) + Abc_InfoSetBit( pCex->pData, iBit + k ); + iBit += Saig_ManPiNum(pAig); + assert( iBit == pCex->nBits ); + + // free the sat_solver + Vec_IntFree( vAssumps ); + sat_solver_delete( pSat ); + Cnf_DataFree( pCnf ); + + // verify counter-example + status = Saig_ManFindFailedPoCex( pAig, pCex ); + if ( status >= 0 && status < Saig_ManPoNum(pAig) ) + pCex->iPo = status; + else + { + printf( "Llb4_Nonlin4TransformCex(): Counter-example verification has FAILED.\n" ); + ABC_FREE( pCex ); + return NULL; + } + // report the results +// if ( fVerbose ) +// Abc_PrintTime( 1, "SAT-based cex generation time", clock() - clk ); + return pCex; +} + + +/**Function************************************************************* + + Synopsis [Resimulates the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb4_Nonlin4VerifyCex( Aig_Man_t * pAig, Abc_Cex_t * p ) +{ + Vec_Ptr_t * vStates; + Aig_Obj_t * pObj, * pObjRi, * pObjRo; + int i, k, iBit = 0; + // create storage for states + vStates = Vec_PtrAllocSimInfo( p->iFrame+1, Abc_BitWordNum(Aig_ManRegNum(pAig)) ); + Vec_PtrCleanSimInfo( vStates, 0, Abc_BitWordNum(Aig_ManRegNum(pAig)) ); + // verify counter-example + Aig_ManCleanMarkB(pAig); + Aig_ManConst1(pAig)->fMarkB = 1; + Saig_ManForEachLo( pAig, pObj, i ) + pObj->fMarkB = 0; //Abc_InfoHasBit(p->pData, iBit++); + // do not require equal flop count in the AIG and in the CEX + iBit = p->nRegs; + for ( i = 0; i <= p->iFrame; i++ ) + { + // save current state + Saig_ManForEachLo( pAig, pObj, k ) + if ( pObj->fMarkB ) + Abc_InfoSetBit( (unsigned *)Vec_PtrEntry(vStates, i), k ); + // compute new state + Saig_ManForEachPi( pAig, pObj, k ) + pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++); + Aig_ManForEachNode( pAig, pObj, k ) + pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) & + (Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj)); + Aig_ManForEachPo( pAig, pObj, k ) + pObj->fMarkB = Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj); + if ( i == p->iFrame ) + break; + Saig_ManForEachLiLo( pAig, pObjRi, pObjRo, k ) + pObjRo->fMarkB = pObjRi->fMarkB; + } +/* + { + unsigned * pNext; + Vec_PtrForEachEntry( unsigned *, vStates, pNext, i ) + { + printf( "%4d : ", i ); + Extra_PrintBinary( stdout, pNext, Aig_ManRegNum(pAig) ); + printf( "\n" ); + } + } +*/ + assert( iBit == p->nBits ); +// if ( Aig_ManPo(pAig, p->iPo)->fMarkB == 0 ) +// Vec_PtrFreeP( &vStates ); + for ( i = Saig_ManPoNum(pAig) - 1; i >= 0; i-- ) + { + if ( Aig_ManPo(pAig, i)->fMarkB ) + { + p->iPo = i; + break; + } + } + if ( i == -1 ) + Vec_PtrFreeP( &vStates ); + Aig_ManCleanMarkB(pAig); + return vStates; +} + +/**Function************************************************************* + + Synopsis [Translates a sequence of states into a counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Llb4_Nonlin4NormalizeCex( Aig_Man_t * pAigOrg, Aig_Man_t * pAigRpm, Abc_Cex_t * pCexRpm ) +{ + Abc_Cex_t * pCexOrg; + Vec_Ptr_t * vStates; + // check parameters of the AIG + if ( Saig_ManRegNum(pAigOrg) != Saig_ManRegNum(pAigRpm) ) + { + printf( "Llb4_Nonlin4NormalizeCex(): The number of flops in the original and reparametrized AIGs do not agree.\n" ); + return NULL; + } +/* + if ( Saig_ManRegNum(pAigRpm) != pCexRpm->nRegs ) + { + printf( "Llb4_Nonlin4NormalizeCex(): The number of flops in the reparametrized AIG and in the CEX do not agree.\n" ); + return NULL; + } +*/ + if ( Saig_ManPiNum(pAigRpm) != pCexRpm->nPis ) + { + printf( "Llb4_Nonlin4NormalizeCex(): The number of PIs in the reparametrized AIG and in the CEX do not agree.\n" ); + return NULL; + } + // get the sequence of states + vStates = Llb4_Nonlin4VerifyCex( pAigRpm, pCexRpm ); + if ( vStates == NULL ) + { + Abc_Print( 1, "Llb4_Nonlin4NormalizeCex(): The given CEX does not fail outputs of pAigRpm.\n" ); + return NULL; + } + // derive updated counter-example + pCexOrg = Llb4_Nonlin4TransformCex( pAigOrg, vStates, pCexRpm->iPo, 0 ); + Vec_PtrFree( vStates ); + return pCexOrg; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/llb/llb4Cluster.c b/src/proof/llb/llb4Cluster.c new file mode 100644 index 00000000..8d29eed4 --- /dev/null +++ b/src/proof/llb/llb4Cluster.c @@ -0,0 +1,452 @@ +/**CFile**************************************************************** + + FileName [llb2Cluster.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Non-linear quantification scheduling.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Cluster.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Find good static variable ordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4FindOrder_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vOrder, int * pCounter ) +{ + Aig_Obj_t * pFanin0, * pFanin1; + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + return; + Aig_ObjSetTravIdCurrent( pAig, pObj ); + assert( Llb_ObjBddVar(vOrder, pObj) < 0 ); + if ( Aig_ObjIsPi(pObj) ) + { + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); + return; + } + // try fanins with higher level first + pFanin0 = Aig_ObjFanin0(pObj); + pFanin1 = Aig_ObjFanin1(pObj); +// if ( pFanin0->Level > pFanin1->Level || (pFanin0->Level == pFanin1->Level && pFanin0->Id < pFanin1->Id) ) + if ( pFanin0->Level > pFanin1->Level ) + { + Llb_Nonlin4FindOrder_rec( pAig, pFanin0, vOrder, pCounter ); + Llb_Nonlin4FindOrder_rec( pAig, pFanin1, vOrder, pCounter ); + } + else + { + Llb_Nonlin4FindOrder_rec( pAig, pFanin1, vOrder, pCounter ); + Llb_Nonlin4FindOrder_rec( pAig, pFanin0, vOrder, pCounter ); + } + if ( pObj->fMarkA ) + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); +} + +/**Function************************************************************* + + Synopsis [Find good static variable ordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_Nonlin4FindOrder( Aig_Man_t * pAig, int * pCounter ) +{ + Vec_Int_t * vNodes = NULL; + Vec_Int_t * vOrder; + Aig_Obj_t * pObj; + int i, Counter = 0; + // mark nodes to exclude: AND with low level and CO drivers + Aig_ManCleanMarkA( pAig ); + Aig_ManForEachNode( pAig, pObj, i ) + if ( Aig_ObjLevel(pObj) > 3 ) + pObj->fMarkA = 1; + Aig_ManForEachPo( pAig, pObj, i ) + Aig_ObjFanin0(pObj)->fMarkA = 0; + + // collect nodes in the order + vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) ); + Aig_ManIncrementTravId( pAig ); + Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) ); +// Aig_ManForEachPo( pAig, pObj, i ) + Saig_ManForEachLi( pAig, pObj, i ) + { + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); + Llb_Nonlin4FindOrder_rec( pAig, Aig_ObjFanin0(pObj), vOrder, &Counter ); + } + Aig_ManForEachPi( pAig, pObj, i ) + if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); + Aig_ManCleanMarkA( pAig ); + Vec_IntFreeP( &vNodes ); +// assert( Counter == Aig_ManObjNum(pAig) - 1 ); + +/* + Saig_ManForEachPi( pAig, pObj, i ) + printf( "pi%d ", Llb_ObjBddVar(vOrder, pObj) ); + printf( "\n" ); + Saig_ManForEachLo( pAig, pObj, i ) + printf( "lo%d ", Llb_ObjBddVar(vOrder, pObj) ); + printf( "\n" ); + Saig_ManForEachPo( pAig, pObj, i ) + printf( "po%d ", Llb_ObjBddVar(vOrder, pObj) ); + printf( "\n" ); + Saig_ManForEachLi( pAig, pObj, i ) + printf( "li%d ", Llb_ObjBddVar(vOrder, pObj) ); + printf( "\n" ); + Aig_ManForEachNode( pAig, pObj, i ) + printf( "n%d ", Llb_ObjBddVar(vOrder, pObj) ); + printf( "\n" ); +*/ + if ( pCounter ) + *pCounter = Counter; + return vOrder; +} + +/**Function************************************************************* + + Synopsis [Derives BDDs for the partitions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_Nonlin4FindPartitions_rec( DdManager * dd, Aig_Obj_t * pObj, Vec_Int_t * vOrder, Vec_Ptr_t * vRoots ) +{ + DdNode * bBdd, * bBdd0, * bBdd1, * bPart, * vVar; + if ( Aig_ObjIsConst1(pObj) ) + return Cudd_ReadOne(dd); + if ( Aig_ObjIsPi(pObj) ) + return Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + if ( pObj->pData ) + return (DdNode *)pObj->pData; + if ( Aig_ObjIsPo(pObj) ) + { + bBdd0 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) ); + bPart = Cudd_bddXnor( dd, Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ), bBdd0 ); Cudd_Ref( bPart ); + Vec_PtrPush( vRoots, bPart ); + return NULL; + } + bBdd0 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin1(pObj), vOrder, vRoots), Aig_ObjFaninC1(pObj) ); + bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bBdd ); + if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) + { + vVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + bPart = Cudd_bddXnor( dd, vVar, bBdd ); Cudd_Ref( bPart ); + Vec_PtrPush( vRoots, bPart ); + Cudd_RecursiveDeref( dd, bBdd ); + bBdd = vVar; Cudd_Ref( vVar ); + } + pObj->pData = bBdd; + return bBdd; +} + +/**Function************************************************************* + + Synopsis [Derives BDDs for the partitions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_Nonlin4FindPartitions( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fOutputs ) +{ + Vec_Ptr_t * vRoots; + Aig_Obj_t * pObj; + int i; + Aig_ManCleanData( pAig ); + vRoots = Vec_PtrAlloc( 100 ); + if ( fOutputs ) + { + Saig_ManForEachPo( pAig, pObj, i ) + Llb_Nonlin4FindPartitions_rec( dd, pObj, vOrder, vRoots ); + } + else + { + Saig_ManForEachLi( pAig, pObj, i ) + Llb_Nonlin4FindPartitions_rec( dd, pObj, vOrder, vRoots ); + } + Aig_ManForEachNode( pAig, pObj, i ) + if ( pObj->pData ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + return vRoots; +} + +/**Function************************************************************* + + Synopsis [Creates quantifiable variables for both types of traversal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_Nonlin4FindVars2Q( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder ) +{ + Vec_Int_t * vVars2Q; + Aig_Obj_t * pObj; + int i; + vVars2Q = Vec_IntAlloc( 0 ); + Vec_IntFill( vVars2Q, Cudd_ReadSize(dd), 1 ); + Saig_ManForEachLo( pAig, pObj, i ) + Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 ); +// Aig_ManForEachPo( pAig, pObj, i ) + Saig_ManForEachLi( pAig, pObj, i ) + Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 ); + return vVars2Q; +} + +/**Function************************************************************* + + Synopsis [Creates quantifiable variables for both types of traversal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_Nonlin4CountTerms( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, DdNode * bFunc, int fCo, int fFlop ) +{ + DdNode * bSupp; + Aig_Obj_t * pObj; + int i, Counter = 0; + bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); + if ( !fCo && !fFlop ) + { + Saig_ManForEachPi( pAig, pObj, i ) + if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) + Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) ); + } + else if ( fCo && !fFlop ) + { + Saig_ManForEachPo( pAig, pObj, i ) + if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) + Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) ); + } + else if ( !fCo && fFlop ) + { + Saig_ManForEachLo( pAig, pObj, i ) + if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) + Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) ); + } + else if ( fCo && fFlop ) + { + Saig_ManForEachLi( pAig, pObj, i ) + if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) + Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) ); + } + Cudd_RecursiveDeref( dd, bSupp ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Creates quantifiable variables for both types of traversal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4PrintGroups( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups ) +{ + DdNode * bTemp; + int i, nSuppAll, nSuppPi, nSuppPo, nSuppLi, nSuppLo, nSuppAnd; + Vec_PtrForEachEntry( DdNode *, vGroups, bTemp, i ) + { +//Extra_bddPrintSupport(dd, bTemp); printf("\n" ); + nSuppAll = Cudd_SupportSize(dd,bTemp); + nSuppPi = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 0, 0); + nSuppPo = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 1, 0); + nSuppLi = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 0, 1); + nSuppLo = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 1, 1); + nSuppAnd = nSuppAll - (nSuppPi+nSuppPo+nSuppLi+nSuppLo); + + if ( Cudd_DagSize(bTemp) <= 10 ) + continue; + + printf( "%4d : bdd =%6d supp =%3d ", i, Cudd_DagSize(bTemp), nSuppAll ); + printf( "pi =%3d ", nSuppPi ); + printf( "po =%3d ", nSuppPo ); + printf( "lo =%3d ", nSuppLo ); + printf( "li =%3d ", nSuppLi ); + printf( "and =%3d", nSuppAnd ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Creates quantifiable variables for both types of traversal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4PrintSuppProfile( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups ) +{ + Aig_Obj_t * pObj; + int i, * pSupp; + int nSuppAll = 0, nSuppPi = 0, nSuppPo = 0, nSuppLi = 0, nSuppLo = 0, nSuppAnd = 0; + + pSupp = ABC_CALLOC( int, Cudd_ReadSize(dd) ); + Extra_VectorSupportArray( dd, (DdNode **)Vec_PtrArray(vGroups), Vec_PtrSize(vGroups), pSupp ); + + Aig_ManForEachObj( pAig, pObj, i ) + { + if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) + continue; + // remove variables that do not participate + if ( pSupp[Llb_ObjBddVar(vOrder, pObj)] == 0 ) + { + if ( Aig_ObjIsNode(pObj) ) + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), -1 ); + continue; + } + nSuppAll++; + if ( Saig_ObjIsPi(pAig, pObj) ) + nSuppPi++; + else if ( Saig_ObjIsLo(pAig, pObj) ) + nSuppLo++; + else if ( Saig_ObjIsPo(pAig, pObj) ) + nSuppPo++; + else if ( Saig_ObjIsLi(pAig, pObj) ) + nSuppLi++; + else + nSuppAnd++; + } + ABC_FREE( pSupp ); + + printf( "Groups =%3d ", Vec_PtrSize(vGroups) ); + printf( "Variables: all =%4d ", nSuppAll ); + printf( "pi =%4d ", nSuppPi ); + printf( "po =%4d ", nSuppPo ); + printf( "lo =%4d ", nSuppLo ); + printf( "li =%4d ", nSuppLi ); + printf( "and =%4d", nSuppAnd ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4Cluster( Aig_Man_t * pAig, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int nBddMax, int fVerbose ) +{ + DdManager * dd; + Vec_Int_t * vOrder, * vVars2Q; + Vec_Ptr_t * vParts, * vGroups; + DdNode * bTemp; + int i, nVarNum; + + // create the BDD manager + vOrder = Llb_Nonlin4FindOrder( pAig, &nVarNum ); + dd = Cudd_Init( nVarNum, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); +// Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + + vVars2Q = Llb_Nonlin4FindVars2Q( dd, pAig, vOrder ); + vParts = Llb_Nonlin4FindPartitions( dd, pAig, vOrder, 0 ); + + vGroups = Llb_Nonlin4Group( dd, vParts, vVars2Q, nBddMax ); + Vec_IntFree( vVars2Q ); + + Vec_PtrForEachEntry( DdNode *, vParts, bTemp, i ) + Cudd_RecursiveDeref( dd, bTemp ); + Vec_PtrFree( vParts ); + + +// if ( fVerbose ) + Llb_Nonlin4PrintSuppProfile( dd, pAig, vOrder, vGroups ); + if ( fVerbose ) + printf( "Before reordering\n" ); + if ( fVerbose ) + Llb_Nonlin4PrintGroups( dd, pAig, vOrder, vGroups ); + +// Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 ); +// printf( "After reordering\n" ); +// Llb_Nonlin4PrintGroups( dd, pAig, vOrder, vGroups ); + + if ( pvOrder ) + *pvOrder = vOrder; + else + Vec_IntFree( vOrder ); + + if ( pvGroups ) + *pvGroups = vGroups; + else + { + Vec_PtrForEachEntry( DdNode *, vGroups, bTemp, i ) + Cudd_RecursiveDeref( dd, bTemp ); + Vec_PtrFree( vGroups ); + } + + if ( pdd ) + *pdd = dd; + else + Extra_StopManager( dd ); +// Cudd_Quit( dd ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/llb/llb4Image.c b/src/proof/llb/llb4Image.c new file mode 100644 index 00000000..91eb62f8 --- /dev/null +++ b/src/proof/llb/llb4Image.c @@ -0,0 +1,861 @@ +/**CFile**************************************************************** + + FileName [llb3Image.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Computes image using partitioned structure.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb3Image.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Llb_Var_t_ Llb_Var_t; +struct Llb_Var_t_ +{ + int iVar; // variable number + int nScore; // variable score + Vec_Int_t * vParts; // partitions +}; + +typedef struct Llb_Prt_t_ Llb_Prt_t; +struct Llb_Prt_t_ +{ + int iPart; // partition number + int nSize; // the number of BDD nodes + DdNode * bFunc; // the partition + Vec_Int_t * vVars; // support +}; + +typedef struct Llb_Mgr_t_ Llb_Mgr_t; +struct Llb_Mgr_t_ +{ + DdManager * dd; // working BDD manager + Vec_Int_t * vVars2Q; // variables to quantify + int nSizeMax; // maximum size of the cluster + // internal + Llb_Prt_t ** pParts; // partitions + Llb_Var_t ** pVars; // variables + int iPartFree; // next free partition + int nVars; // the number of BDD variables + int nSuppMax; // maximum support size + // temporary + int * pSupp; // temporary support storage +}; + +static inline Llb_Var_t * Llb_MgrVar( Llb_Mgr_t * p, int i ) { return p->pVars[i]; } +static inline Llb_Prt_t * Llb_MgrPart( Llb_Mgr_t * p, int i ) { return p->pParts[i]; } + +// iterator over vars +#define Llb_MgrForEachVar( p, pVar, i ) \ + for ( i = 0; (i < p->nVars) && (((pVar) = Llb_MgrVar(p, i)), 1); i++ ) if ( pVar == NULL ) {} else +// iterator over parts +#define Llb_MgrForEachPart( p, pPart, i ) \ + for ( i = 0; (i < p->iPartFree) && (((pPart) = Llb_MgrPart(p, i)), 1); i++ ) if ( pPart == NULL ) {} else + +// iterator over vars of one partition +#define Llb_PartForEachVar( p, pPart, pVar, i ) \ + for ( i = 0; (i < Vec_IntSize(pPart->vVars)) && (((pVar) = Llb_MgrVar(p, Vec_IntEntry(pPart->vVars,i))), 1); i++ ) +// iterator over parts of one variable +#define Llb_VarForEachPart( p, pVar, pPart, i ) \ + for ( i = 0; (i < Vec_IntSize(pVar->vParts)) && (((pPart) = Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,i))), 1); i++ ) + +// statistics +//int timeBuild, timeAndEx, timeOther; +//int nSuppMax; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Removes one variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4RemoveVar( Llb_Mgr_t * p, Llb_Var_t * pVar ) +{ + assert( p->pVars[pVar->iVar] == pVar ); + p->pVars[pVar->iVar] = NULL; + Vec_IntFree( pVar->vParts ); + ABC_FREE( pVar ); +} + +/**Function************************************************************* + + Synopsis [Removes one partition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4RemovePart( Llb_Mgr_t * p, Llb_Prt_t * pPart ) +{ +//printf( "Removing %d\n", pPart->iPart ); + assert( p->pParts[pPart->iPart] == pPart ); + p->pParts[pPart->iPart] = NULL; + Vec_IntFree( pPart->vVars ); + Cudd_RecursiveDeref( p->dd, pPart->bFunc ); + ABC_FREE( pPart ); +} + +/**Function************************************************************* + + Synopsis [Create cube with singleton variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_Nonlin4CreateCube1( Llb_Mgr_t * p, Llb_Prt_t * pPart ) +{ + DdNode * bCube, * bTemp; + Llb_Var_t * pVar; + int i, TimeStop; + TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; + bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube ); + Llb_PartForEachVar( p, pPart, pVar, i ) + { + assert( Vec_IntSize(pVar->vParts) > 0 ); + if ( Vec_IntSize(pVar->vParts) != 1 ) + continue; + assert( Vec_IntEntry(pVar->vParts, 0) == pPart->iPart ); + bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + Cudd_Deref( bCube ); + p->dd->TimeStop = TimeStop; + return bCube; +} + +/**Function************************************************************* + + Synopsis [Create cube of variables appearing only in two partitions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_Nonlin4CreateCube2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 ) +{ + DdNode * bCube, * bTemp; + Llb_Var_t * pVar; + int i, TimeStop; + TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; + bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube ); + Llb_PartForEachVar( p, pPart1, pVar, i ) + { + assert( Vec_IntSize(pVar->vParts) > 0 ); + if ( Vec_IntSize(pVar->vParts) != 2 ) + continue; + if ( (Vec_IntEntry(pVar->vParts, 0) == pPart1->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart2->iPart) || + (Vec_IntEntry(pVar->vParts, 0) == pPart2->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart1->iPart) ) + { + bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + } + Cudd_Deref( bCube ); + p->dd->TimeStop = TimeStop; + return bCube; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if partition has singleton variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_Nonlin4HasSingletonVars( Llb_Mgr_t * p, Llb_Prt_t * pPart ) +{ + Llb_Var_t * pVar; + int i; + Llb_PartForEachVar( p, pPart, pVar, i ) + if ( Vec_IntSize(pVar->vParts) == 1 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if partition has singleton variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4Print( Llb_Mgr_t * p ) +{ + Llb_Prt_t * pPart; + Llb_Var_t * pVar; + int i, k; + printf( "\n" ); + Llb_MgrForEachVar( p, pVar, i ) + { + printf( "Var %3d : ", i ); + Llb_VarForEachPart( p, pVar, pPart, k ) + printf( "%d ", pPart->iPart ); + printf( "\n" ); + } + Llb_MgrForEachPart( p, pPart, i ) + { + printf( "Part %3d : ", i ); + Llb_PartForEachVar( p, pPart, pVar, k ) + printf( "%d ", pVar->iVar ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Quantifies singles belonging to one partition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_Nonlin4Quantify1( Llb_Mgr_t * p, Llb_Prt_t * pPart ) +{ + Llb_Var_t * pVar; + Llb_Prt_t * pTemp; + Vec_Ptr_t * vSingles; + DdNode * bCube, * bTemp; + int i, RetValue, nSizeNew; + // create cube to be quantified + bCube = Llb_Nonlin4CreateCube1( p, pPart ); Cudd_Ref( bCube ); +// assert( !Cudd_IsConstant(bCube) ); + // derive new function + pPart->bFunc = Cudd_bddExistAbstract( p->dd, bTemp = pPart->bFunc, bCube ); Cudd_Ref( pPart->bFunc ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bCube ); + // get support + vSingles = Vec_PtrAlloc( 0 ); + nSizeNew = Cudd_DagSize(pPart->bFunc); + Extra_SupportArray( p->dd, pPart->bFunc, p->pSupp ); + Llb_PartForEachVar( p, pPart, pVar, i ) + if ( p->pSupp[pVar->iVar] ) + { + assert( Vec_IntSize(pVar->vParts) > 1 ); + pVar->nScore -= pPart->nSize - nSizeNew; + } + else + { + RetValue = Vec_IntRemove( pVar->vParts, pPart->iPart ); + assert( RetValue ); + pVar->nScore -= pPart->nSize; + if ( Vec_IntSize(pVar->vParts) == 0 ) + Llb_Nonlin4RemoveVar( p, pVar ); + else if ( Vec_IntSize(pVar->vParts) == 1 ) + Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); + } + + // update partition + pPart->nSize = nSizeNew; + Vec_IntClear( pPart->vVars ); + for ( i = 0; i < p->nVars; i++ ) + if ( p->pSupp[i] && Vec_IntEntry(p->vVars2Q, i) ) + Vec_IntPush( pPart->vVars, i ); + // remove other variables + Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i ) + Llb_Nonlin4Quantify1( p, pTemp ); + Vec_PtrFree( vSingles ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Quantifies singles belonging to one partition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_Nonlin4Quantify2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 ) +{ + int fVerbose = 0; + Llb_Var_t * pVar; + Llb_Prt_t * pTemp; + Vec_Ptr_t * vSingles; + DdNode * bCube, * bFunc; + int i, RetValue, nSuppSize; + int iPart1 = pPart1->iPart; + int iPart2 = pPart2->iPart; + int liveBeg, liveEnd; + + // create cube to be quantified + bCube = Llb_Nonlin4CreateCube2( p, pPart1, pPart2 ); Cudd_Ref( bCube ); + +//printf( "Quantifying " ); Extra_bddPrintSupport( p->dd, bCube ); printf( "\n" ); + +if ( fVerbose ) +{ +printf( "\n" ); +printf( "\n" ); +Llb_Nonlin4Print( p ); +printf( "Conjoining partitions %d and %d.\n", pPart1->iPart, pPart2->iPart ); +Extra_bddPrintSupport( p->dd, bCube ); printf( "\n" ); +} +liveBeg = p->dd->keys - p->dd->dead; + bFunc = Cudd_bddAndAbstract( p->dd, pPart1->bFunc, pPart2->bFunc, bCube ); +liveEnd = p->dd->keys - p->dd->dead; +//printf( "%d ", liveEnd-liveBeg ); + + if ( bFunc == NULL ) + { + Cudd_RecursiveDeref( p->dd, bCube ); + return 0; + } + Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( p->dd, bCube ); + +//printf( "Creating part %d ", p->iPartFree ); Extra_bddPrintSupport( p->dd, bFunc ); printf( "\n" ); + +//printf( "Creating %d\n", p->iPartFree ); + + // create new partition + pTemp = p->pParts[p->iPartFree] = ABC_CALLOC( Llb_Prt_t, 1 ); + pTemp->iPart = p->iPartFree++; + pTemp->nSize = Cudd_DagSize(bFunc); + pTemp->bFunc = bFunc; + pTemp->vVars = Vec_IntAlloc( 8 ); + // update variables + Llb_PartForEachVar( p, pPart1, pVar, i ) + { + RetValue = Vec_IntRemove( pVar->vParts, pPart1->iPart ); + assert( RetValue ); + pVar->nScore -= pPart1->nSize; + } + // update variables + Llb_PartForEachVar( p, pPart2, pVar, i ) + { + RetValue = Vec_IntRemove( pVar->vParts, pPart2->iPart ); + assert( RetValue ); + pVar->nScore -= pPart2->nSize; + } + // add variables to the new partition + nSuppSize = 0; + Extra_SupportArray( p->dd, bFunc, p->pSupp ); + for ( i = 0; i < p->nVars; i++ ) + { + nSuppSize += p->pSupp[i]; + if ( p->pSupp[i] && Vec_IntEntry(p->vVars2Q, i) ) + { + pVar = Llb_MgrVar( p, i ); + pVar->nScore += pTemp->nSize; + Vec_IntPush( pVar->vParts, pTemp->iPart ); + Vec_IntPush( pTemp->vVars, i ); + } + } + p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize ); + // remove variables and collect partitions with singleton variables + vSingles = Vec_PtrAlloc( 0 ); + Llb_PartForEachVar( p, pPart1, pVar, i ) + { + if ( Vec_IntSize(pVar->vParts) == 0 ) + Llb_Nonlin4RemoveVar( p, pVar ); + else if ( Vec_IntSize(pVar->vParts) == 1 ) + { + if ( fVerbose ) + printf( "Adding partition %d because of var %d.\n", + Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar ); + Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); + } + } + Llb_PartForEachVar( p, pPart2, pVar, i ) + { + if ( pVar == NULL ) + continue; + if ( Vec_IntSize(pVar->vParts) == 0 ) + Llb_Nonlin4RemoveVar( p, pVar ); + else if ( Vec_IntSize(pVar->vParts) == 1 ) + { + if ( fVerbose ) + printf( "Adding partition %d because of var %d.\n", + Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar ); + Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); + } + } + // remove partitions + Llb_Nonlin4RemovePart( p, pPart1 ); + Llb_Nonlin4RemovePart( p, pPart2 ); + // remove other variables +if ( fVerbose ) +Llb_Nonlin4Print( p ); + Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i ) + { +if ( fVerbose ) +printf( "Updating partitiong %d with singlton vars.\n", pTemp->iPart ); + Llb_Nonlin4Quantify1( p, pTemp ); + } +if ( fVerbose ) +Llb_Nonlin4Print( p ); + Vec_PtrFree( vSingles ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4CutNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Saig_ObjIsLi(p, pObj) ) + { + Llb_Nonlin4CutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); + return; + } + if ( Aig_ObjIsConst1(pObj) ) + return; + assert( Aig_ObjIsNode(pObj) ); + Llb_Nonlin4CutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); + Llb_Nonlin4CutNodes_rec(p, Aig_ObjFanin1(pObj), vNodes); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_Nonlin4CutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + // mark the lower cut with the traversal ID + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + // count the upper cut + vNodes = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) + Llb_Nonlin4CutNodes_rec( p, pObj, vNodes ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Starts non-linear quantification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4AddPair( Llb_Mgr_t * p, int iPart, int iVar ) +{ + if ( p->pVars[iVar] == NULL ) + { + p->pVars[iVar] = ABC_CALLOC( Llb_Var_t, 1 ); + p->pVars[iVar]->iVar = iVar; + p->pVars[iVar]->nScore = 0; + p->pVars[iVar]->vParts = Vec_IntAlloc( 8 ); + } + Vec_IntPush( p->pVars[iVar]->vParts, iPart ); + Vec_IntPush( p->pParts[iPart]->vVars, iVar ); +} + +/**Function************************************************************* + + Synopsis [Starts non-linear quantification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4AddPartition( Llb_Mgr_t * p, int i, DdNode * bFunc ) +{ + int k, nSuppSize; + assert( !Cudd_IsConstant(bFunc) ); +//printf( "Creating init %d\n", i ); + // create partition + p->pParts[i] = ABC_CALLOC( Llb_Prt_t, 1 ); + p->pParts[i]->iPart = i; + p->pParts[i]->bFunc = bFunc; Cudd_Ref( bFunc ); + p->pParts[i]->vVars = Vec_IntAlloc( 8 ); + // add support dependencies + nSuppSize = 0; + Extra_SupportArray( p->dd, bFunc, p->pSupp ); + for ( k = 0; k < p->nVars; k++ ) + { + nSuppSize += p->pSupp[k]; + if ( p->pSupp[k] && Vec_IntEntry(p->vVars2Q, k) ) + Llb_Nonlin4AddPair( p, i, k ); + } + p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize ); +} + +/**Function************************************************************* + + Synopsis [Checks that each var appears in at least one partition.] + + Description [] + + SideEffects [] + + SeeAlso [] +**********************************************************************/ +void Llb_Nonlin4CheckVars( Llb_Mgr_t * p ) +{ + Llb_Var_t * pVar; + int i; + Llb_MgrForEachVar( p, pVar, i ) + assert( Vec_IntSize(pVar->vParts) > 1 ); +} + +/**Function************************************************************* + + Synopsis [Find next partition to quantify] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_Nonlin4NextPartitions( Llb_Mgr_t * p, Llb_Prt_t ** ppPart1, Llb_Prt_t ** ppPart2 ) +{ + Llb_Var_t * pVar, * pVarBest = NULL; + Llb_Prt_t * pPart, * pPart1Best = NULL, * pPart2Best = NULL; + int i; + Llb_Nonlin4CheckVars( p ); + // find variable with minimum score + Llb_MgrForEachVar( p, pVar, i ) + { + if ( p->nSizeMax && pVar->nScore > p->nSizeMax ) + continue; +// if ( pVarBest == NULL || Vec_IntSize(pVarBest->vParts) * pVarBest->nScore > Vec_IntSize(pVar->vParts) * pVar->nScore ) + if ( pVarBest == NULL || pVarBest->nScore > pVar->nScore ) + pVarBest = pVar; +// printf( "%d ", pVar->nScore ); + } +//printf( "\n" ); + if ( pVarBest == NULL ) + return 0; + // find two partitions with minimum size + Llb_VarForEachPart( p, pVarBest, pPart, i ) + { + if ( pPart1Best == NULL ) + pPart1Best = pPart; + else if ( pPart2Best == NULL ) + pPart2Best = pPart; + else if ( pPart1Best->nSize > pPart->nSize || pPart2Best->nSize > pPart->nSize ) + { + if ( pPart1Best->nSize > pPart2Best->nSize ) + pPart1Best = pPart; + else + pPart2Best = pPart; + } + } +//printf( "Selecting %d and parts %d and %d\n", pVarBest->iVar, pPart1Best->nSize, pPart2Best->nSize ); +//Extra_bddPrintSupport( p->dd, pPart1Best->bFunc ); printf( "\n" ); +//Extra_bddPrintSupport( p->dd, pPart2Best->bFunc ); printf( "\n" ); + + *ppPart1 = pPart1Best; + *ppPart2 = pPart2Best; + return 1; +} + +/**Function************************************************************* + + Synopsis [Recomputes scores after variable reordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4RecomputeScores( Llb_Mgr_t * p ) +{ + Llb_Prt_t * pPart; + Llb_Var_t * pVar; + int i, k; + Llb_MgrForEachPart( p, pPart, i ) + pPart->nSize = Cudd_DagSize(pPart->bFunc); + Llb_MgrForEachVar( p, pVar, i ) + { + pVar->nScore = 0; + Llb_VarForEachPart( p, pVar, pPart, k ) + pVar->nScore += pPart->nSize; + } +} + +/**Function************************************************************* + + Synopsis [Recomputes scores after variable reordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4VerifyScores( Llb_Mgr_t * p ) +{ + Llb_Prt_t * pPart; + Llb_Var_t * pVar; + int i, k, nScore; + Llb_MgrForEachPart( p, pPart, i ) + assert( pPart->nSize == Cudd_DagSize(pPart->bFunc) ); + Llb_MgrForEachVar( p, pVar, i ) + { + nScore = 0; + Llb_VarForEachPart( p, pVar, pPart, k ) + nScore += pPart->nSize; + assert( nScore == pVar->nScore ); + } +} + +/**Function************************************************************* + + Synopsis [Starts non-linear quantification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Mgr_t * Llb_Nonlin4Alloc( DdManager * dd, Vec_Ptr_t * vParts, DdNode * bCurrent, Vec_Int_t * vVars2Q, int nSizeMax ) +{ + Llb_Mgr_t * p; + DdNode * bFunc; + int i; + p = ABC_CALLOC( Llb_Mgr_t, 1 ); + p->dd = dd; + p->nSizeMax = nSizeMax; + p->vVars2Q = vVars2Q; + p->nVars = Cudd_ReadSize(dd); + p->iPartFree = Vec_PtrSize(vParts); + p->pVars = ABC_CALLOC( Llb_Var_t *, p->nVars ); + p->pParts = ABC_CALLOC( Llb_Prt_t *, 2 * p->iPartFree + 2 ); + p->pSupp = ABC_ALLOC( int, Cudd_ReadSize(dd) ); + // add pairs (refs are consumed inside) + Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i ) + Llb_Nonlin4AddPartition( p, i, bFunc ); + // add partition + if ( bCurrent ) + Llb_Nonlin4AddPartition( p, p->iPartFree++, bCurrent ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops non-linear quantification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4Free( Llb_Mgr_t * p ) +{ + Llb_Prt_t * pPart; + Llb_Var_t * pVar; + int i; + Llb_MgrForEachVar( p, pVar, i ) + Llb_Nonlin4RemoveVar( p, pVar ); + Llb_MgrForEachPart( p, pPart, i ) + Llb_Nonlin4RemovePart( p, pPart ); + ABC_FREE( p->pVars ); + ABC_FREE( p->pParts ); + ABC_FREE( p->pSupp ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_Nonlin4Image( DdManager * dd, Vec_Ptr_t * vParts, DdNode * bCurrent, Vec_Int_t * vVars2Q ) +{ + Llb_Prt_t * pPart, * pPart1, * pPart2; + Llb_Mgr_t * p; + DdNode * bFunc, * bTemp; + int i, nReorders; + // start the manager + p = Llb_Nonlin4Alloc( dd, vParts, bCurrent, vVars2Q, 0 ); + // remove singles + Llb_MgrForEachPart( p, pPart, i ) + if ( Llb_Nonlin4HasSingletonVars(p, pPart) ) + Llb_Nonlin4Quantify1( p, pPart ); + // compute scores + Llb_Nonlin4RecomputeScores( p ); + // iteratively quantify variables + while ( Llb_Nonlin4NextPartitions(p, &pPart1, &pPart2) ) + { + nReorders = Cudd_ReadReorderings(dd); + if ( !Llb_Nonlin4Quantify2( p, pPart1, pPart2 ) ) + { + Llb_Nonlin4Free( p ); + return NULL; + } + if ( nReorders < Cudd_ReadReorderings(dd) ) + Llb_Nonlin4RecomputeScores( p ); +// else +// Llb_Nonlin4VerifyScores( p ); + } + // load partitions + bFunc = Cudd_ReadOne(p->dd); Cudd_Ref( bFunc ); + Llb_MgrForEachPart( p, pPart, i ) + { + bFunc = Cudd_bddAnd( p->dd, bTemp = bFunc, pPart->bFunc ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } +// nSuppMax = p->nSuppMax; + Llb_Nonlin4Free( p ); +//printf( "\n" ); + // return + Cudd_Deref( bFunc ); + return bFunc; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_Nonlin4Group( DdManager * dd, Vec_Ptr_t * vParts, Vec_Int_t * vVars2Q, int nSizeMax ) +{ + Vec_Ptr_t * vGroups; + Llb_Prt_t * pPart, * pPart1, * pPart2; + Llb_Mgr_t * p; + int i, nReorders, clk = clock(); + // start the manager + p = Llb_Nonlin4Alloc( dd, vParts, NULL, vVars2Q, nSizeMax ); + // remove singles + Llb_MgrForEachPart( p, pPart, i ) + if ( Llb_Nonlin4HasSingletonVars(p, pPart) ) + Llb_Nonlin4Quantify1( p, pPart ); + // compute scores + Llb_Nonlin4RecomputeScores( p ); + // iteratively quantify variables + while ( Llb_Nonlin4NextPartitions(p, &pPart1, &pPart2) ) + { + nReorders = Cudd_ReadReorderings(dd); + if ( !Llb_Nonlin4Quantify2( p, pPart1, pPart2 ) ) + { + Llb_Nonlin4Free( p ); + return NULL; + } + if ( nReorders < Cudd_ReadReorderings(dd) ) + Llb_Nonlin4RecomputeScores( p ); +// else +// Llb_Nonlin4VerifyScores( p ); + } + // load partitions + vGroups = Vec_PtrAlloc( 1000 ); + Llb_MgrForEachPart( p, pPart, i ) + { +//printf( "Iteration %d ", pPart->iPart ); + if ( Cudd_IsConstant(pPart->bFunc) ) + { +//printf( "Constant\n" ); + assert( !Cudd_IsComplement(pPart->bFunc) ); + continue; + } +//printf( "\n" ); + Vec_PtrPush( vGroups, pPart->bFunc ); + Cudd_Ref( pPart->bFunc ); +//printf( "Part %d ", pPart->iPart ); +//Extra_bddPrintSupport( p->dd, pPart->bFunc ); printf( "\n" ); + } + Llb_Nonlin4Free( p ); +//Abc_PrintTime( 1, "Reparametrization time", clock() - clk ); + return vGroups; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/llb/llb4Map.c b/src/proof/llb/llb4Map.c new file mode 100644 index 00000000..b1442699 --- /dev/null +++ b/src/proof/llb/llb4Map.c @@ -0,0 +1,123 @@ +/**CFile**************************************************************** + + FileName [llb2Map.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Non-linear quantification scheduling.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Map.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" +#include "src/base/abc/abc.h" +#include "src/map/if/if.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns internal nodes used in the mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_AigMap( Aig_Man_t * pAig, int nLutSize, int nLutMin ) +{ + extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); + extern If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); + extern void Gia_ManSetIfParsDefault( If_Par_t * pPars ); + If_Par_t Pars, * pPars = &Pars; + If_Man_t * pIfMan; + If_Obj_t * pAnd; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode; + Vec_Int_t * vNodes; + Aig_Obj_t * pObj; + int i; + + // create ABC network + pNtk = Abc_NtkFromAigPhase( pAig ); + assert( Abc_NtkIsStrash(pNtk) ); + + // derive mapping parameters + Gia_ManSetIfParsDefault( pPars ); + pPars->nLutSize = nLutSize; + + // get timing information + pPars->pTimesArr = Abc_NtkGetCiArrivalFloats(pNtk); + pPars->pTimesReq = NULL; + + // perform LUT mapping + pIfMan = Abc_NtkToIf( pNtk, pPars ); + if ( pIfMan == NULL ) + { + Abc_NtkDelete( pNtk ); + return NULL; + } + if ( !If_ManPerformMapping( pIfMan ) ) + { + Abc_NtkDelete( pNtk ); + If_ManStop( pIfMan ); + return NULL; + } + + // mark nodes in the AIG used in the mapping + Aig_ManCleanMarkA( pAig ); + Aig_ManForEachNode( pAig, pObj, i ) + { + pNode = (Abc_Obj_t *)pObj->pData; + if ( pNode == NULL ) + continue; + pAnd = (If_Obj_t *)pNode->pCopy; + if ( pAnd == NULL ) + continue; + if ( pAnd->nRefs > 0 && (int)If_ObjCutBest(pAnd)->nLeaves >= nLutMin ) + pObj->fMarkA = 1; + } + Abc_NtkDelete( pNtk ); + If_ManStop( pIfMan ); + + // unmark flop drivers + Saig_ManForEachLi( pAig, pObj, i ) + Aig_ObjFanin0(pObj)->fMarkA = 0; + + // collect mapping + vNodes = Vec_IntAlloc( 100 ); + Aig_ManForEachNode( pAig, pObj, i ) + if ( pObj->fMarkA ) + Vec_IntPush( vNodes, Aig_ObjId(pObj) ); + Aig_ManCleanMarkA( pAig ); + return vNodes; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/llb/llb4Nonlin.c b/src/proof/llb/llb4Nonlin.c new file mode 100644 index 00000000..33c6b3f7 --- /dev/null +++ b/src/proof/llb/llb4Nonlin.c @@ -0,0 +1,1080 @@ +/**CFile**************************************************************** + + FileName [llb2Nonlin.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Non-linear quantification scheduling.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Nonlin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Llb_Mnx_t_ Llb_Mnx_t; +struct Llb_Mnx_t_ +{ + // user info + Aig_Man_t * pAig; // AIG manager + Gia_ParLlb_t * pPars; // parameters + + // intermediate BDDs + DdManager * dd; // BDD manager + DdNode * bBad; // bad states in terms of CIs + DdNode * bReached; // reached states + DdNode * bCurrent; // from states + DdNode * bNext; // to states + Vec_Ptr_t * vRings; // onion rings in ddR + Vec_Ptr_t * vRoots; // BDDs for partitions + + // structural info + Vec_Int_t * vOrder; // for each object ID, its BDD variable number or -1 + Vec_Int_t * vVars2Q; // 1 if variable is quantifiable; 0 othervise + + int timeImage; + int timeRemap; + int timeReo; + int timeOther; + int timeTotal; +}; + +//extern int timeBuild, timeAndEx, timeOther; +//extern int nSuppMax; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes bad in working manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_Nonlin4ComputeBad( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder ) +{ + Vec_Ptr_t * vNodes; + DdNode * bBdd, * bBdd0, * bBdd1, * bTemp, * bResult, * bCube; + Aig_Obj_t * pObj; + int i; + Aig_ManCleanData( pAig ); + // assign elementary variables + Aig_ManConst1(pAig)->pData = Cudd_ReadOne(dd); + Aig_ManForEachPi( pAig, pObj, i ) + pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + // compute internal nodes + vNodes = Aig_ManDfsNodes( pAig, (Aig_Obj_t **)Vec_PtrArray(pAig->vPos), Saig_ManPoNum(pAig) ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) ) + continue; + bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); + bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); + if ( bBdd == NULL ) + { + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + if ( Aig_ObjIsNode(pObj) && pObj->pData != NULL ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + Vec_PtrFree( vNodes ); + return NULL; + } + Cudd_Ref( bBdd ); + pObj->pData = bBdd; + } + // quantify PIs of each PO + bResult = Cudd_ReadLogicZero( dd ); Cudd_Ref( bResult ); + Saig_ManForEachPo( pAig, pObj, i ) + { + bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bResult = Cudd_bddOr( dd, bTemp = bResult, bBdd0 ); + if ( bResult == NULL ) + { + Cudd_RecursiveDeref( dd, bTemp ); + break; + } + Cudd_Ref( bResult ); + Cudd_RecursiveDeref( dd, bTemp ); + } + // deref + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + if ( Aig_ObjIsNode(pObj) && pObj->pData != NULL ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + Vec_PtrFree( vNodes ); + if ( bResult ) + { + bCube = Cudd_ReadOne(dd); Cudd_Ref( bCube ); + Saig_ManForEachPi( pAig, pObj, i ) + { + bCube = Cudd_bddAnd( dd, bTemp = bCube, (DdNode *)pObj->pData ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( dd, bTemp ); + } + bResult = Cudd_bddExistAbstract( dd, bTemp = bResult, bCube ); Cudd_Ref( bResult ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + Cudd_Deref( bResult ); + } +//if ( bResult ) +//printf( "Bad state = %d.\n", Cudd_DagSize(bResult) ); + return bResult; +} + +/**Function************************************************************* + + Synopsis [Derives BDDs for the partitions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_Nonlin4DerivePartitions( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder ) +{ + Vec_Ptr_t * vRoots; + Aig_Obj_t * pObj; + DdNode * bBdd, * bBdd0, * bBdd1, * bPart; + int i; + Aig_ManCleanData( pAig ); + // assign elementary variables + Aig_ManConst1(pAig)->pData = Cudd_ReadOne(dd); + Aig_ManForEachPi( pAig, pObj, i ) + pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + Aig_ManForEachNode( pAig, pObj, i ) + if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) + { + pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + Cudd_Ref( (DdNode *)pObj->pData ); + } + Saig_ManForEachLi( pAig, pObj, i ) + pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + // compute intermediate BDDs + vRoots = Vec_PtrAlloc( 100 ); + Aig_ManForEachNode( pAig, pObj, i ) + { + bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); + bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); + if ( bBdd == NULL ) + goto finish; + Cudd_Ref( bBdd ); + if ( pObj->pData == NULL ) + { + pObj->pData = bBdd; + continue; + } + // create new partition + bPart = Cudd_bddXnor( dd, (DdNode *)pObj->pData, bBdd ); + if ( bPart == NULL ) + goto finish; + Cudd_Ref( bPart ); + Cudd_RecursiveDeref( dd, bBdd ); + Vec_PtrPush( vRoots, bPart ); +//printf( "%d ", Cudd_DagSize(bPart) ); + } + // compute register output BDDs + Saig_ManForEachLi( pAig, pObj, i ) + { + bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bPart = Cudd_bddXnor( dd, (DdNode *)pObj->pData, bBdd0 ); + if ( bPart == NULL ) + goto finish; + Cudd_Ref( bPart ); + Vec_PtrPush( vRoots, bPart ); +//printf( "%d ", Cudd_DagSize(bPart) ); + } +//printf( "\n" ); + Aig_ManForEachNode( pAig, pObj, i ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + return vRoots; + // early termination +finish: + Aig_ManForEachNode( pAig, pObj, i ) + if ( pObj->pData ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + Vec_PtrForEachEntry( DdNode *, vRoots, bPart, i ) + Cudd_RecursiveDeref( dd, bPart ); + Vec_PtrFree( vRoots ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Find simple variable ordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_Nonlin4CreateOrderSimple( Aig_Man_t * pAig ) +{ + Vec_Int_t * vOrder; + Aig_Obj_t * pObj; + int i, Counter = 0; + vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) ); + Aig_ManForEachPi( pAig, pObj, i ) + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); + Saig_ManForEachLi( pAig, pObj, i ) + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); + return vOrder; +} + +/**Function************************************************************* + + Synopsis [Find good static variable ordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4CreateOrder_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vOrder, int * pCounter ) +{ + Aig_Obj_t * pFanin0, * pFanin1; + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + return; + Aig_ObjSetTravIdCurrent( pAig, pObj ); + assert( Llb_ObjBddVar(vOrder, pObj) < 0 ); + if ( Aig_ObjIsPi(pObj) ) + { +// if ( Saig_ObjIsLo(pAig, pObj) ) +// Vec_IntWriteEntry( vOrder, Aig_ObjId(Saig_ObjLoToLi(pAig, pObj)), (*pCounter)++ ); + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); + return; + } + // try fanins with higher level first + pFanin0 = Aig_ObjFanin0(pObj); + pFanin1 = Aig_ObjFanin1(pObj); +// if ( pFanin0->Level > pFanin1->Level || (pFanin0->Level == pFanin1->Level && pFanin0->Id < pFanin1->Id) ) + if ( pFanin0->Level > pFanin1->Level ) + { + Llb_Nonlin4CreateOrder_rec( pAig, pFanin0, vOrder, pCounter ); + Llb_Nonlin4CreateOrder_rec( pAig, pFanin1, vOrder, pCounter ); + } + else + { + Llb_Nonlin4CreateOrder_rec( pAig, pFanin1, vOrder, pCounter ); + Llb_Nonlin4CreateOrder_rec( pAig, pFanin0, vOrder, pCounter ); + } + if ( pObj->fMarkA ) + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); +} + +/**Function************************************************************* + + Synopsis [Collect nodes with the given fanout count.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_Nonlin4CollectHighRefNodes( Aig_Man_t * pAig, int nFans ) +{ + Vec_Int_t * vNodes; + Aig_Obj_t * pObj; + int i; + Aig_ManCleanMarkA( pAig ); + Aig_ManForEachNode( pAig, pObj, i ) + if ( Aig_ObjRefs(pObj) >= nFans ) + pObj->fMarkA = 1; + // unmark flop drivers + Saig_ManForEachLi( pAig, pObj, i ) + Aig_ObjFanin0(pObj)->fMarkA = 0; + // collect mapping + vNodes = Vec_IntAlloc( 100 ); + Aig_ManForEachNode( pAig, pObj, i ) + if ( pObj->fMarkA ) + Vec_IntPush( vNodes, Aig_ObjId(pObj) ); + Aig_ManCleanMarkA( pAig ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Find good static variable ordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_Nonlin4CreateOrder( Aig_Man_t * pAig ) +{ + Vec_Int_t * vNodes = NULL; + Vec_Int_t * vOrder; + Aig_Obj_t * pObj; + int i, Counter = 0; +/* + // mark internal nodes to be used + Aig_ManCleanMarkA( pAig ); + vNodes = Llb_Nonlin4CollectHighRefNodes( pAig, 4 ); + Aig_ManForEachObjVec( vNodes, pAig, pObj, i ) + pObj->fMarkA = 1; +printf( "Techmapping added %d pivots.\n", Vec_IntSize(vNodes) ); +*/ + // collect nodes in the order + vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) ); + Aig_ManIncrementTravId( pAig ); + Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) ); + Saig_ManForEachLi( pAig, pObj, i ) + { + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); + Llb_Nonlin4CreateOrder_rec( pAig, Aig_ObjFanin0(pObj), vOrder, &Counter ); + } + Aig_ManForEachPi( pAig, pObj, i ) + if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) + { +// if ( Saig_ObjIsLo(pAig, pObj) ) +// Vec_IntWriteEntry( vOrder, Aig_ObjId(Saig_ObjLoToLi(pAig, pObj)), Counter++ ); + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); + } + assert( Counter <= Aig_ManPiNum(pAig) + Aig_ManRegNum(pAig) + (vNodes?Vec_IntSize(vNodes):0) ); + Aig_ManCleanMarkA( pAig ); + Vec_IntFreeP( &vNodes ); + return vOrder; +} + + +/**Function************************************************************* + + Synopsis [Creates quantifiable varaibles for both types of traversal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_Nonlin4CreateVars2Q( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fBackward ) +{ + Vec_Int_t * vVars2Q; + Aig_Obj_t * pObjLi, * pObjLo; + int i; + vVars2Q = Vec_IntAlloc( 0 ); + Vec_IntFill( vVars2Q, Cudd_ReadSize(dd), 1 ); + Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) + Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, fBackward ? pObjLo : pObjLi), 0 ); + return vVars2Q; +} + +/**Function************************************************************* + + Synopsis [Compute initial state in terms of current state variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4SetupVarMap( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder ) +{ + DdNode ** pVarsX, ** pVarsY; + Aig_Obj_t * pObjLo, * pObjLi; + int i; + pVarsX = ABC_ALLOC( DdNode *, Cudd_ReadSize(dd) ); + pVarsY = ABC_ALLOC( DdNode *, Cudd_ReadSize(dd) ); + Saig_ManForEachLiLo( pAig, pObjLo, pObjLi, i ) + { + assert( Llb_ObjBddVar(vOrder, pObjLo) >= 0 ); + assert( Llb_ObjBddVar(vOrder, pObjLi) >= 0 ); + pVarsX[i] = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObjLo) ); + pVarsY[i] = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObjLi) ); + } + Cudd_SetVarMap( dd, pVarsX, pVarsY, Aig_ManRegNum(pAig) ); + ABC_FREE( pVarsX ); + ABC_FREE( pVarsY ); +} + +/**Function************************************************************* + + Synopsis [Compute initial state in terms of current state variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_Nonlin4ComputeInitState( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fBackward ) +{ + Aig_Obj_t * pObjLi, * pObjLo; + DdNode * bRes, * bVar, * bTemp; + int i, TimeStop; + TimeStop = dd->TimeStop; dd->TimeStop = 0; + bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); + Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) + { + bVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, fBackward? pObjLi : pObjLo) ); + bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bRes ); + dd->TimeStop = TimeStop; + return bRes; +} + +/**Function************************************************************* + + Synopsis [Compute initial state in terms of current state variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_Nonlin4ComputeCube( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, char * pValues, int Flag ) +{ + Aig_Obj_t * pObjLo, * pObjLi, * pObjTemp; + DdNode * bRes, * bVar, * bTemp; + int i, TimeStop; + TimeStop = dd->TimeStop; dd->TimeStop = 0; + bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); + Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) + { + if ( Flag ) + pObjTemp = pObjLo, pObjLo = pObjLi, pObjLi = pObjTemp; + // get the correspoding flop input variable + bVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObjLi) ); + if ( pValues[Llb_ObjBddVar(vOrder, pObjLo)] != 1 ) + bVar = Cudd_Not(bVar); + // create cube + bRes = Cudd_bddAnd( dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bRes ); + dd->TimeStop = TimeStop; + return bRes; +} + +/**Function************************************************************* + + Synopsis [Compute initial state in terms of current state variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4RecordState( Aig_Man_t * pAig, Vec_Int_t * vOrder, unsigned * pState, char * pValues, int fBackward ) +{ + Aig_Obj_t * pObjLo, * pObjLi; + int i; + Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) + if ( pValues[Llb_ObjBddVar(vOrder, fBackward? pObjLi : pObjLo)] == 1 ) + Abc_InfoSetBit( pState, i ); +} + +/**Function************************************************************* + + Synopsis [Multiply every partition by the cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_Nonlin4Multiply( DdManager * dd, DdNode * bCube, Vec_Ptr_t * vParts ) +{ + Vec_Ptr_t * vNew; + DdNode * bTemp, * bFunc; + int i; + vNew = Vec_PtrAlloc( Vec_PtrSize(vParts) ); + Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i ) + { + bTemp = Cudd_bddAnd( dd, bFunc, bCube ); Cudd_Ref( bTemp ); + Vec_PtrPush( vNew, bTemp ); + } + return vNew; +} + +/**Function************************************************************* + + Synopsis [Multiply every partition by the cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4Deref( DdManager * dd, Vec_Ptr_t * vParts ) +{ + DdNode * bFunc; + int i; + Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i ) + Cudd_RecursiveDeref( dd, bFunc ); + Vec_PtrFree( vParts ); +} + +/**Function************************************************************* + + Synopsis [Derives counter-example by backward reachability.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_Nonlin4DeriveCex( Llb_Mnx_t * p, int fBackward, int fVerbose ) +{ + Vec_Int_t * vVars2Q; + Vec_Ptr_t * vStates, * vRootsNew; + Aig_Obj_t * pObj; + DdNode * bState, * bImage, * bOneCube, * bRing; + int i, v, RetValue, clk = clock(); + char * pValues; + assert( Vec_PtrSize(p->vRings) > 0 ); + // disable the timeout + p->dd->TimeStop = 0; + + // start the state set + vStates = Vec_PtrAllocSimInfo( Vec_PtrSize(p->vRings), Abc_BitWordNum(Aig_ManRegNum(p->pAig)) ); + Vec_PtrCleanSimInfo( vStates, 0, Abc_BitWordNum(Aig_ManRegNum(p->pAig)) ); + if ( fBackward ) + Vec_PtrReverseOrder( vStates ); + + // get the last cube + pValues = ABC_ALLOC( char, Cudd_ReadSize(p->dd) ); + bOneCube = Cudd_bddIntersect( p->dd, (DdNode *)Vec_PtrEntryLast(p->vRings), p->bBad ); Cudd_Ref( bOneCube ); + RetValue = Cudd_bddPickOneCube( p->dd, bOneCube, pValues ); + Cudd_RecursiveDeref( p->dd, bOneCube ); + assert( RetValue ); + + // record the cube + Llb_Nonlin4RecordState( p->pAig, p->vOrder, (unsigned *)Vec_PtrEntryLast(vStates), pValues, fBackward ); + + // write state in terms of NS variables + if ( Vec_PtrSize(p->vRings) > 1 ) + { + bState = Llb_Nonlin4ComputeCube( p->dd, p->pAig, p->vOrder, pValues, fBackward ); Cudd_Ref( bState ); + } + // perform backward analysis + vVars2Q = Llb_Nonlin4CreateVars2Q( p->dd, p->pAig, p->vOrder, !fBackward ); + Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v ) + { + if ( v == Vec_PtrSize(p->vRings) - 1 ) + continue; + + // preprocess partitions + vRootsNew = Llb_Nonlin4Multiply( p->dd, bState, p->vRoots ); + Cudd_RecursiveDeref( p->dd, bState ); + + // compute the next states + bImage = Llb_Nonlin4Image( p->dd, vRootsNew, NULL, vVars2Q ); Cudd_Ref( bImage ); + Llb_Nonlin4Deref( p->dd, vRootsNew ); + + // intersect with the previous set + bOneCube = Cudd_bddIntersect( p->dd, bImage, bRing ); Cudd_Ref( bOneCube ); + Cudd_RecursiveDeref( p->dd, bImage ); + + // find any assignment of the BDD + RetValue = Cudd_bddPickOneCube( p->dd, bOneCube, pValues ); + Cudd_RecursiveDeref( p->dd, bOneCube ); + assert( RetValue ); + + // record the cube + Llb_Nonlin4RecordState( p->pAig, p->vOrder, (unsigned *)Vec_PtrEntry(vStates, v), pValues, fBackward ); + + // check that we get the init state + if ( v == 0 ) + { + Saig_ManForEachLo( p->pAig, pObj, i ) + assert( fBackward || pValues[Llb_ObjBddVar(p->vOrder, pObj)] == 0 ); + break; + } + + // write state in terms of NS variables + bState = Llb_Nonlin4ComputeCube( p->dd, p->pAig, p->vOrder, pValues, fBackward ); Cudd_Ref( bState ); + } + Vec_IntFree( vVars2Q ); + ABC_FREE( pValues ); + if ( fBackward ) + Vec_PtrReverseOrder( vStates ); +// if ( fVerbose ) +// Abc_PrintTime( 1, "BDD-based cex generation time", clock() - clk ); + return vStates; +} + + +/**Function************************************************************* + + Synopsis [Perform reachability with hints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_Nonlin4Reachability( Llb_Mnx_t * p ) +{ + DdNode * bAux; + int nIters, nBddSizeFr, nBddSizeTo, nBddSizeTo2; + int clkTemp, clkIter, clk = clock(); + assert( Aig_ManRegNum(p->pAig) > 0 ); + + if ( p->pPars->fBackward ) + { + // create bad state in the ring manager + if ( !p->pPars->fSkipOutCheck ) + { + p->bBad = Llb_Nonlin4ComputeInitState( p->dd, p->pAig, p->vOrder, p->pPars->fBackward ); Cudd_Ref( p->bBad ); + } + // create init state + if ( p->pPars->fCluster ) + p->bCurrent = p->dd->bFunc, p->dd->bFunc = NULL; + else + { + p->bCurrent = Llb_Nonlin4ComputeBad( p->dd, p->pAig, p->vOrder ); + if ( p->bCurrent == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = -1; + return -1; + } + Cudd_Ref( p->bCurrent ); + } + // remap into the next states + p->bCurrent = Cudd_bddVarMap( p->dd, bAux = p->bCurrent ); + if ( p->bCurrent == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during remapping bad states.\n", p->pPars->TimeLimit ); + Cudd_RecursiveDeref( p->dd, bAux ); + p->pPars->iFrame = -1; + return -1; + } + Cudd_Ref( p->bCurrent ); + Cudd_RecursiveDeref( p->dd, bAux ); + } + else + { + // create bad state in the ring manager + if ( !p->pPars->fSkipOutCheck ) + { + if ( p->pPars->fCluster ) + p->bBad = p->dd->bFunc, p->dd->bFunc = NULL; + else + { + p->bBad = Llb_Nonlin4ComputeBad( p->dd, p->pAig, p->vOrder ); + if ( p->bBad == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = -1; + return -1; + } + Cudd_Ref( p->bBad ); + } + } + else if ( p->dd->bFunc ) + Cudd_RecursiveDeref( p->dd, p->dd->bFunc ), p->dd->bFunc = NULL; + // compute the starting set of states + p->bCurrent = Llb_Nonlin4ComputeInitState( p->dd, p->pAig, p->vOrder, p->pPars->fBackward ); Cudd_Ref( p->bCurrent ); + } + // perform iterations + p->bReached = p->bCurrent; Cudd_Ref( p->bReached ); + for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ ) + { + clkIter = clock(); + // check the runtime limit + if ( p->pPars->TimeLimit && time(NULL) > p->pPars->TimeTarget ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + return -1; + } + + // save the onion ring + Vec_PtrPush( p->vRings, p->bCurrent ); Cudd_Ref( p->bCurrent ); + + // check it for bad states + if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->dd, p->bCurrent, Cudd_Not(p->bBad) ) ) + { + Vec_Ptr_t * vStates; + assert( p->pAig->pSeqModel == NULL ); + vStates = Llb_Nonlin4DeriveCex( p, p->pPars->fBackward, p->pPars->fVerbose ); + p->pAig->pSeqModel = Llb4_Nonlin4TransformCex( p->pAig, vStates, -1, p->pPars->fVerbose ); + Vec_PtrFreeP( &vStates ); + if ( !p->pPars->fSilent ) + { + printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump a witness). ", p->pAig->pSeqModel->iPo, nIters ); + Abc_PrintTime( 1, "Time", clock() - clk ); + } + p->pPars->iFrame = nIters - 1; + return 0; + } + + // compute the next states + clkTemp = clock(); + p->bNext = Llb_Nonlin4Image( p->dd, p->vRoots, p->bCurrent, p->vVars2Q ); + if ( p->bNext == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in quantification.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + return -1; + } + Cudd_Ref( p->bNext ); + p->timeImage += clock() - clkTemp; + + // remap into current states + clkTemp = clock(); + p->bNext = Cudd_bddVarMap( p->dd, bAux = p->bNext ); + if ( p->bNext == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during remapping next states.\n", p->pPars->TimeLimit ); + Cudd_RecursiveDeref( p->dd, bAux ); + p->pPars->iFrame = nIters - 1; + return -1; + } + Cudd_Ref( p->bNext ); + Cudd_RecursiveDeref( p->dd, bAux ); + p->timeRemap += clock() - clkTemp; + + // collect statistics + if ( p->pPars->fVerbose ) + { + nBddSizeFr = Cudd_DagSize( p->bCurrent ); + nBddSizeTo = Cudd_DagSize( bAux ); + nBddSizeTo2 = Cudd_DagSize( p->bNext ); + } + Cudd_RecursiveDeref( p->dd, p->bCurrent ); p->bCurrent = NULL; + + // derive new states + p->bCurrent = Cudd_bddAnd( p->dd, p->bNext, Cudd_Not(p->bReached) ); + if ( p->bCurrent == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + return -1; + } + Cudd_Ref( p->bCurrent ); + Cudd_RecursiveDeref( p->dd, p->bNext ); p->bNext = NULL; + if ( Cudd_IsConstant(p->bCurrent) ) + break; +/* + // reduce BDD size using constrain // Cudd_bddRestrict + p->bCurrent = Cudd_bddRestrict( p->dd, bAux = p->bCurrent, Cudd_Not(p->bReached) ); + Cudd_Ref( p->bCurrent ); +printf( "Before = %d. After = %d.\n", Cudd_DagSize(bAux), Cudd_DagSize(p->bCurrent) ); + Cudd_RecursiveDeref( p->dd, bAux ); +*/ + + // add to the reached set + p->bReached = Cudd_bddOr( p->dd, bAux = p->bReached, p->bCurrent ); + if ( p->bReached == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bAux ); + return -1; + } + Cudd_Ref( p->bReached ); + Cudd_RecursiveDeref( p->dd, bAux ); + + + // report the results + if ( p->pPars->fVerbose ) + { + printf( "I =%5d : ", nIters ); + printf( "Fr =%7d ", nBddSizeFr ); + printf( "ImNs =%7d ", nBddSizeTo ); + printf( "ImCs =%7d ", nBddSizeTo2 ); + printf( "Rea =%7d ", Cudd_DagSize(p->bReached) ); + printf( "(%4d %4d) ", Cudd_ReadReorderings(p->dd), Cudd_ReadGarbageCollections(p->dd) ); + Abc_PrintTime( 1, "T", clock() - clkIter ); + } +/* + if ( pPars->fVerbose ) + { + double nMints = Cudd_CountMinterm(p->dd, bReached, Saig_ManRegNum(p->pAig) ); +// Extra_bddPrint( p->dd, bReached );printf( "\n" ); + printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); + fflush( stdout ); + } +*/ + if ( nIters == p->pPars->nIterMax - 1 ) + { + if ( !p->pPars->fSilent ) + printf( "Reached limit on the number of timeframes (%d).\n", p->pPars->nIterMax ); + p->pPars->iFrame = nIters; + return -1; + } + } + + // report the stats + if ( p->pPars->fVerbose ) + { + double nMints = Cudd_CountMinterm(p->dd, p->bReached, Saig_ManRegNum(p->pAig) ); + if ( p->bCurrent && Cudd_IsConstant(p->bCurrent) ) + printf( "Reachability analysis completed after %d frames.\n", nIters ); + else + printf( "Reachability analysis is stopped after %d frames.\n", nIters ); + printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); + fflush( stdout ); + } + if ( p->bCurrent == NULL || !Cudd_IsConstant(p->bCurrent) ) + { + if ( !p->pPars->fSilent ) + printf( "Verified only for states reachable in %d frames. ", nIters ); + p->pPars->iFrame = p->pPars->nIterMax; + return -1; // undecided + } + // report + if ( !p->pPars->fSilent ) + printf( "The miter is proved unreachable after %d iterations. ", nIters ); + p->pPars->iFrame = nIters - 1; + Abc_PrintTime( 1, "Time", clock() - clk ); + return 1; // unreachable +} + +/**Function************************************************************* + + Synopsis [Reorders BDDs in the working manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4Reorder( DdManager * dd, int fTwice, int fVerbose ) +{ + int clk = clock(); + if ( fVerbose ) + Abc_Print( 1, "Reordering... Before =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); + if ( fVerbose ) + Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + if ( fTwice ) + { + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); + if ( fVerbose ) + Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + } + if ( fVerbose ) + Abc_PrintTime( 1, "Time", clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Mnx_t * Llb_MnxStart( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) +{ + Llb_Mnx_t * p; + + p = ABC_CALLOC( Llb_Mnx_t, 1 ); + p->pAig = pAig; + p->pPars = pPars; + + // compute time to stop + p->pPars->TimeTarget = p->pPars->TimeLimit ? time(NULL) + p->pPars->TimeLimit : 0; + + if ( pPars->fCluster ) + { +// Llb_Nonlin4Cluster( p->pAig, &p->dd, &p->vOrder, &p->vRoots, pPars->nBddMax, pPars->fVerbose ); +// Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); + Llb4_Nonlin4Sweep( p->pAig, pPars->nBddMax, pPars->nClusterMax, &p->dd, &p->vOrder, &p->vRoots, pPars->fVerbose ); + // set the stop time parameter + p->dd->TimeStop = p->pPars->TimeTarget; + } + else + { +// p->vOrder = Llb_Nonlin4CreateOrderSimple( pAig ); + p->vOrder = Llb_Nonlin4CreateOrder( pAig ); + p->dd = Cudd_Init( Vec_IntCountPositive(p->vOrder) + 1, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); + Cudd_SetMaxGrowth( p->dd, 1.05 ); + // set the stop time parameter + p->dd->TimeStop = p->pPars->TimeTarget; + p->vRoots = Llb_Nonlin4DerivePartitions( p->dd, pAig, p->vOrder ); + } + + Llb_Nonlin4SetupVarMap( p->dd, pAig, p->vOrder ); + p->vVars2Q = Llb_Nonlin4CreateVars2Q( p->dd, pAig, p->vOrder, p->pPars->fBackward ); + p->vRings = Vec_PtrAlloc( 100 ); + + if ( pPars->fReorder ) + Llb_Nonlin4Reorder( p->dd, 0, 1 ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MnxStop( Llb_Mnx_t * p ) +{ + DdNode * bTemp; + int i; + if ( p->pPars->fVerbose ) + { + p->timeReo = Cudd_ReadReorderingTime(p->dd); + p->timeOther = p->timeTotal - p->timeImage - p->timeRemap; + ABC_PRTP( "Image ", p->timeImage, p->timeTotal ); + ABC_PRTP( "Remap ", p->timeRemap, p->timeTotal ); + ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); + ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); + ABC_PRTP( " reo ", p->timeReo, p->timeTotal ); + } + // remove BDDs + if ( p->bBad ) + Cudd_RecursiveDeref( p->dd, p->bBad ); + if ( p->bReached ) + Cudd_RecursiveDeref( p->dd, p->bReached ); + if ( p->bCurrent ) + Cudd_RecursiveDeref( p->dd, p->bCurrent ); + if ( p->bNext ) + Cudd_RecursiveDeref( p->dd, p->bNext ); + if ( p->vRings ) + Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i ) + Cudd_RecursiveDeref( p->dd, bTemp ); + if ( p->vRoots ) + Vec_PtrForEachEntry( DdNode *, p->vRoots, bTemp, i ) + Cudd_RecursiveDeref( p->dd, bTemp ); + // remove arrays + Vec_PtrFreeP( &p->vRings ); + Vec_PtrFreeP( &p->vRoots ); +//Cudd_PrintInfo( p->dd, stdout ); + Extra_StopManager( p->dd ); + Vec_IntFreeP( &p->vOrder ); + Vec_IntFreeP( &p->vVars2Q ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MnxCheckNextStateVars( Llb_Mnx_t * p ) +{ + Aig_Obj_t * pObj; + int i, Counter0 = 0, Counter1 = 0; + Saig_ManForEachLi( p->pAig, pObj, i ) + if ( Saig_ObjIsLo(p->pAig, Aig_ObjFanin0(pObj)) ) + { + if ( Aig_ObjFaninC0(pObj) ) + Counter0++; + else + Counter1++; + } + printf( "Total = %d. Direct LO = %d. Compl LO = %d.\n", Aig_ManRegNum(p->pAig), Counter1, Counter0 ); +} + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_Nonlin4CoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) +{ + Llb_Mnx_t * pMnn; + int RetValue = -1; + if ( pPars->fVerbose ) + Aig_ManPrintStats( pAig ); + if ( pPars->fCluster && Aig_ManObjNum(pAig) >= (1 << 15) ) + { + printf( "The number of objects is more than 2^15. Clustering cannot be used.\n" ); + return RetValue; + } + { + int clk = clock(); + pMnn = Llb_MnxStart( pAig, pPars ); +//Llb_MnxCheckNextStateVars( pMnn ); + if ( !pPars->fSkipReach ) + RetValue = Llb_Nonlin4Reachability( pMnn ); + pMnn->timeTotal = clock() - clk; + Llb_MnxStop( pMnn ); + } + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/llb/llb4Sweep.c b/src/proof/llb/llb4Sweep.c new file mode 100644 index 00000000..d13c366f --- /dev/null +++ b/src/proof/llb/llb4Sweep.c @@ -0,0 +1,588 @@ +/**CFile**************************************************************** + + FileName [llb2Sweep.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Non-linear quantification scheduling.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Sweep.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Find good static variable ordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4SweepOrder_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vOrder, int * pCounter, int fSaveAll ) +{ + Aig_Obj_t * pFanin0, * pFanin1; + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + return; + Aig_ObjSetTravIdCurrent( pAig, pObj ); + assert( Llb_ObjBddVar(vOrder, pObj) < 0 ); + if ( Aig_ObjIsPi(pObj) ) + { + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); + return; + } + // try fanins with higher level first + pFanin0 = Aig_ObjFanin0(pObj); + pFanin1 = Aig_ObjFanin1(pObj); +// if ( pFanin0->Level > pFanin1->Level || (pFanin0->Level == pFanin1->Level && pFanin0->Id < pFanin1->Id) ) + if ( pFanin0->Level > pFanin1->Level ) + { + Llb_Nonlin4SweepOrder_rec( pAig, pFanin0, vOrder, pCounter, fSaveAll ); + Llb_Nonlin4SweepOrder_rec( pAig, pFanin1, vOrder, pCounter, fSaveAll ); + } + else + { + Llb_Nonlin4SweepOrder_rec( pAig, pFanin1, vOrder, pCounter, fSaveAll ); + Llb_Nonlin4SweepOrder_rec( pAig, pFanin0, vOrder, pCounter, fSaveAll ); + } + if ( fSaveAll || pObj->fMarkA ) + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); +} + +/**Function************************************************************* + + Synopsis [Find good static variable ordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_Nonlin4SweepOrder( Aig_Man_t * pAig, int * pCounter, int fSaveAll ) +{ + Vec_Int_t * vOrder; + Aig_Obj_t * pObj; + int i, Counter = 0; + // collect nodes in the order + vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) ); + Aig_ManIncrementTravId( pAig ); + Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) ); + Aig_ManForEachPo( pAig, pObj, i ) + { + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); + Llb_Nonlin4SweepOrder_rec( pAig, Aig_ObjFanin0(pObj), vOrder, &Counter, fSaveAll ); + } + Aig_ManForEachPi( pAig, pObj, i ) + if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); +// assert( Counter == Aig_ManObjNum(pAig) - 1 ); // no dangling nodes + if ( pCounter ) + *pCounter = Counter - Aig_ManPiNum(pAig) - Aig_ManPoNum(pAig); + return vOrder; +} + + +/**Function************************************************************* + + Synopsis [Performs BDD sweep on the netlist.] + + Description [Returns AIG with internal cut points labeled with fMarkA.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb4_Nonlin4SweepCutpoints( Aig_Man_t * pAig, Vec_Int_t * vOrder, int nBddLimit, int fVerbose ) +{ + DdManager * dd; + DdNode * bFunc0, * bFunc1, * bFunc; + Aig_Obj_t * pObj; + int i, Counter = 0, Counter1 = 0; + dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + // assign elementary variables + Aig_ManCleanData( pAig ); + Aig_ManForEachPi( pAig, pObj, i ) + pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + // sweep internal nodes + Aig_ManForEachNode( pAig, pObj, i ) + { +/* + if ( pObj->nRefs >= 4 ) + { + bFunc = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); Cudd_Ref( bFunc ); + pObj->pData = bFunc; + Counter1++; + continue; + } +*/ + bFunc0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bFunc1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); + bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); + if ( Cudd_DagSize(bFunc) > nBddLimit ) + { +// if ( fVerbose ) +// printf( "Node %5d : Beg =%5d. ", i, Cudd_DagSize(bFunc) ); + + // add cutpoint at a larger one + Cudd_RecursiveDeref( dd, bFunc ); + if ( Cudd_DagSize(bFunc0) >= Cudd_DagSize(bFunc1) ) + { + Cudd_RecursiveDeref( dd, (DdNode *)Aig_ObjFanin0(pObj)->pData ); + bFunc = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, Aig_ObjFanin0(pObj)) ); + Aig_ObjFanin0(pObj)->pData = bFunc; Cudd_Ref( bFunc ); + Aig_ObjFanin0(pObj)->fMarkA = 1; + +// if ( fVerbose ) +// printf( "Ref =%3d ", Aig_ObjFanin0(pObj)->nRefs ); + } + else + { + Cudd_RecursiveDeref( dd, (DdNode *)Aig_ObjFanin1(pObj)->pData ); + bFunc = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, Aig_ObjFanin1(pObj)) ); + Aig_ObjFanin1(pObj)->pData = bFunc; Cudd_Ref( bFunc ); + Aig_ObjFanin1(pObj)->fMarkA = 1; + +// if ( fVerbose ) +// printf( "Ref =%3d ", Aig_ObjFanin1(pObj)->nRefs ); + } + // perform new operation + bFunc0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bFunc1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); + bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); +// assert( Cudd_DagSize(bFunc) <= nBddLimit ); + +// if ( fVerbose ) +// printf( "End =%5d.\n", Cudd_DagSize(bFunc) ); + Counter++; + } + pObj->pData = bFunc; +//printf( "%d ", Cudd_DagSize(bFunc) ); + } +//printf( "\n" ); + // clean up + Aig_ManForEachNode( pAig, pObj, i ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + Extra_StopManager( dd ); +// Aig_ManCleanMarkA( pAig ); + if ( fVerbose ) + printf( "Added %d cut points. Used %d high fanout points.\n", Counter, Counter1 ); + return Counter + Counter1; +} + +/**Function************************************************************* + + Synopsis [Derives BDDs for the partitions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_Nonlin4SweepPartitions_rec( DdManager * dd, Aig_Obj_t * pObj, Vec_Int_t * vOrder, Vec_Ptr_t * vRoots ) +{ + DdNode * bBdd, * bBdd0, * bBdd1, * bPart, * vVar; + if ( Aig_ObjIsConst1(pObj) ) + return Cudd_ReadOne(dd); + if ( Aig_ObjIsPi(pObj) ) + return Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + if ( pObj->pData ) + return (DdNode *)pObj->pData; + if ( Aig_ObjIsPo(pObj) ) + { + bBdd0 = Cudd_NotCond( Llb_Nonlin4SweepPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) ); + bPart = Cudd_bddXnor( dd, Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ), bBdd0 ); Cudd_Ref( bPart ); + Vec_PtrPush( vRoots, bPart ); + return NULL; + } + bBdd0 = Cudd_NotCond( Llb_Nonlin4SweepPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( Llb_Nonlin4SweepPartitions_rec(dd, Aig_ObjFanin1(pObj), vOrder, vRoots), Aig_ObjFaninC1(pObj) ); + bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bBdd ); + if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) + { + vVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + bPart = Cudd_bddXnor( dd, vVar, bBdd ); Cudd_Ref( bPart ); + Vec_PtrPush( vRoots, bPart ); + Cudd_RecursiveDeref( dd, bBdd ); + bBdd = vVar; Cudd_Ref( vVar ); + } + pObj->pData = bBdd; + return bBdd; +} + +/**Function************************************************************* + + Synopsis [Derives BDDs for the partitions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_Nonlin4SweepPartitions( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fTransition ) +{ + Vec_Ptr_t * vRoots; + Aig_Obj_t * pObj; + int i; + Aig_ManCleanData( pAig ); + vRoots = Vec_PtrAlloc( 100 ); + if ( fTransition ) + { + Saig_ManForEachLi( pAig, pObj, i ) + Llb_Nonlin4SweepPartitions_rec( dd, pObj, vOrder, vRoots ); + } + else + { + Saig_ManForEachPo( pAig, pObj, i ) + Llb_Nonlin4SweepPartitions_rec( dd, pObj, vOrder, vRoots ); + } + Aig_ManForEachNode( pAig, pObj, i ) + if ( pObj->pData ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + return vRoots; +} + +/**Function************************************************************* + + Synopsis [Get bad state monitor.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb4_Nonlin4SweepBadMonitor( Aig_Man_t * pAig, Vec_Int_t * vOrder, DdManager * dd ) +{ + Aig_Obj_t * pObj; + DdNode * bRes, * bVar, * bTemp; + int i, TimeStop; + TimeStop = dd->TimeStop; dd->TimeStop = 0; + bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); + Saig_ManForEachPo( pAig, pObj, i ) + { + bVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bRes ); + dd->TimeStop = TimeStop; + return Cudd_Not(bRes); +} + +/**Function************************************************************* + + Synopsis [Creates quantifiable variables for both types of traversal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_Nonlin4SweepVars2Q( Aig_Man_t * pAig, Vec_Int_t * vOrder, int fAddLis ) +{ + Vec_Int_t * vVars2Q; + Aig_Obj_t * pObj; + int i; + vVars2Q = Vec_IntAlloc( 0 ); + Vec_IntFill( vVars2Q, Aig_ManObjNumMax(pAig), 1 ); + // add flop outputs + Saig_ManForEachLo( pAig, pObj, i ) + Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 ); + // add flop inputs + if ( fAddLis ) + Saig_ManForEachLi( pAig, pObj, i ) + Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 ); + return vVars2Q; +} + +/**Function************************************************************* + + Synopsis [Multiply every partition by the cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4SweepDeref( DdManager * dd, Vec_Ptr_t * vParts ) +{ + DdNode * bFunc; + int i; + Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i ) + Cudd_RecursiveDeref( dd, bFunc ); + Vec_PtrFree( vParts ); +} + +/**Function************************************************************* + + Synopsis [Multiply every partition by the cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4SweepPrint( Vec_Ptr_t * vFuncs ) +{ + DdNode * bFunc; + int i; + printf( "(%d) ", Vec_PtrSize(vFuncs) ); + Vec_PtrForEachEntry( DdNode *, vFuncs, bFunc, i ) + printf( "%d ", Cudd_DagSize(bFunc) ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Computes bad states.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdManager * Llb4_Nonlin4SweepBadStates( Aig_Man_t * pAig, Vec_Int_t * vOrder, int nVars ) +{ + DdManager * dd; + Vec_Ptr_t * vParts; + Vec_Int_t * vVars2Q; + DdNode * bMonitor, * bImage; + // get quantifiable variables + vVars2Q = Llb_Nonlin4SweepVars2Q( pAig, vOrder, 0 ); + // start BDD manager and create partitions + dd = Cudd_Init( nVars, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + vParts = Llb_Nonlin4SweepPartitions( dd, pAig, vOrder, 0 ); +//printf( "Outputs: " ); +//Llb_Nonlin4SweepPrint( vParts ); + // compute image of the partitions + bMonitor = Llb4_Nonlin4SweepBadMonitor( pAig, vOrder, dd ); Cudd_Ref( bMonitor ); + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + bImage = Llb_Nonlin4Image( dd, vParts, bMonitor, vVars2Q ); Cudd_Ref( bImage ); + Cudd_RecursiveDeref( dd, bMonitor ); + Llb_Nonlin4SweepDeref( dd, vParts ); + Vec_IntFree( vVars2Q ); + // save image and return + dd->bFunc = bImage; + return dd; +} + +/**Function************************************************************* + + Synopsis [Computes clusters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdManager * Llb4_Nonlin4SweepGroups( Aig_Man_t * pAig, Vec_Int_t * vOrder, int nVars, Vec_Ptr_t ** pvGroups, int nBddLimitClp, int fVerbose ) +{ + DdManager * dd; + Vec_Ptr_t * vParts; + Vec_Int_t * vVars2Q; + // get quantifiable variables + vVars2Q = Llb_Nonlin4SweepVars2Q( pAig, vOrder, 1 ); + // start BDD manager and create partitions + dd = Cudd_Init( nVars, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + vParts = Llb_Nonlin4SweepPartitions( dd, pAig, vOrder, 1 ); +//printf( "Transitions: " ); +//Llb_Nonlin4SweepPrint( vParts ); + // compute image of the partitions + + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + *pvGroups = Llb_Nonlin4Group( dd, vParts, vVars2Q, nBddLimitClp ); + Llb_Nonlin4SweepDeref( dd, vParts ); +// *pvGroups = vParts; + +if ( fVerbose ) +{ +printf( "Groups: " ); +Llb_Nonlin4SweepPrint( *pvGroups ); +} + + Vec_IntFree( vVars2Q ); + return dd; +} + + +/**Function************************************************************* + + Synopsis [Creates quantifiable variables for both types of traversal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4SweepPrintSuppProfile( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups, int fVerbose ) +{ + Aig_Obj_t * pObj; + int i, * pSupp; + int nSuppAll = 0, nSuppPi = 0, nSuppPo = 0, nSuppLi = 0, nSuppLo = 0, nSuppAnd = 0; + + pSupp = ABC_CALLOC( int, Cudd_ReadSize(dd) ); + Extra_VectorSupportArray( dd, (DdNode **)Vec_PtrArray(vGroups), Vec_PtrSize(vGroups), pSupp ); + + Aig_ManForEachObj( pAig, pObj, i ) + { + if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) + continue; + // remove variables that do not participate + if ( pSupp[Llb_ObjBddVar(vOrder, pObj)] == 0 ) + { + if ( Aig_ObjIsNode(pObj) ) + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), -1 ); + continue; + } + nSuppAll++; + if ( Saig_ObjIsPi(pAig, pObj) ) + nSuppPi++; + else if ( Saig_ObjIsLo(pAig, pObj) ) + nSuppLo++; + else if ( Saig_ObjIsPo(pAig, pObj) ) + nSuppPo++; + else if ( Saig_ObjIsLi(pAig, pObj) ) + nSuppLi++; + else + nSuppAnd++; + } + ABC_FREE( pSupp ); + + if ( fVerbose ) + { + printf( "Groups =%3d ", Vec_PtrSize(vGroups) ); + printf( "Variables: all =%4d ", nSuppAll ); + printf( "pi =%4d ", nSuppPi ); + printf( "po =%4d ", nSuppPo ); + printf( "lo =%4d ", nSuppLo ); + printf( "li =%4d ", nSuppLi ); + printf( "and =%4d", nSuppAnd ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Performs BDD sweep on the netlist.] + + Description [Returns BDD manager, ordering, clusters, and bad states + inside dd->bFunc.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb4_Nonlin4Sweep( Aig_Man_t * pAig, int nSweepMax, int nClusterMax, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int fVerbose ) +{ + DdManager * ddBad, * ddWork; + Vec_Ptr_t * vGroups; + Vec_Int_t * vOrder; + int Counter, nCutPoints; + + // get the original ordering + Aig_ManCleanMarkA( pAig ); + vOrder = Llb_Nonlin4SweepOrder( pAig, &Counter, 1 ); + assert( Counter == Aig_ManNodeNum(pAig) ); + // mark the nodes + nCutPoints = Llb4_Nonlin4SweepCutpoints( pAig, vOrder, nSweepMax, fVerbose ); + Vec_IntFree( vOrder ); + // get better ordering + vOrder = Llb_Nonlin4SweepOrder( pAig, &Counter, 0 ); + assert( Counter == nCutPoints ); + Aig_ManCleanMarkA( pAig ); + // compute the BAD states + ddBad = Llb4_Nonlin4SweepBadStates( pAig, vOrder, nCutPoints + Aig_ManPiNum(pAig) + Aig_ManPoNum(pAig) ); + // compute the clusters + ddWork = Llb4_Nonlin4SweepGroups( pAig, vOrder, nCutPoints + Aig_ManPiNum(pAig) + Aig_ManPoNum(pAig), &vGroups, nClusterMax, fVerbose ); + // transfer the result from the Bad manager +//printf( "Bad before = %d.\n", Cudd_DagSize(ddBad->bFunc) ); + ddWork->bFunc = Cudd_bddTransfer( ddBad, ddWork, ddBad->bFunc ); Cudd_Ref( ddWork->bFunc ); + Cudd_RecursiveDeref( ddBad, ddBad->bFunc ); ddBad->bFunc = NULL; + Extra_StopManager( ddBad ); + // update ordering to exclude quantified variables +//printf( "Bad after = %d.\n", Cudd_DagSize(ddWork->bFunc) ); + + Llb_Nonlin4SweepPrintSuppProfile( ddWork, pAig, vOrder, vGroups, fVerbose ); + + // return the result + *pdd = ddWork; + *pvOrder = vOrder; + *pvGroups = vGroups; +} + +/**Function************************************************************* + + Synopsis [Performs BDD sweep on the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb4_Nonlin4SweepExperiment( Aig_Man_t * pAig ) +{ + DdManager * dd; + Vec_Int_t * vOrder; + Vec_Ptr_t * vGroups; + Llb4_Nonlin4Sweep( pAig, 100, 500, &dd, &vOrder, &vGroups, 1 ); + + Llb_Nonlin4SweepDeref( dd, vGroups ); + + Cudd_RecursiveDeref( dd, dd->bFunc ); + Extra_StopManager( dd ); + Vec_IntFree( vOrder ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/llb/llbInt.h b/src/proof/llb/llbInt.h new file mode 100644 index 00000000..d81aadcf --- /dev/null +++ b/src/proof/llb/llbInt.h @@ -0,0 +1,211 @@ +/**CFile**************************************************************** + + FileName [llbInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD-based reachability.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 8, 2010.] + + Revision [$Id: llbInt.h,v 1.00 2010/05/08 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__llb__llbInt_h +#define ABC__aig__llb__llbInt_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include "src/aig/aig/aig.h" +#include "src/aig/saig/saig.h" +#include "src/proof/ssw/ssw.h" +#include "src/misc/extra/extraBdd.h" +#include "llb.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_HEADER_START + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Llb_Man_t_ Llb_Man_t; +typedef struct Llb_Mtr_t_ Llb_Mtr_t; +typedef struct Llb_Grp_t_ Llb_Grp_t; + +struct Llb_Man_t_ +{ + Gia_ParLlb_t * pPars; // parameters + Aig_Man_t * pAigGlo; // initial AIG manager (owned by the caller) + Aig_Man_t * pAig; // derived AIG manager (created in this package) + DdManager * dd; // BDD manager + DdManager * ddG; // BDD manager + DdManager * ddR; // BDD manager + Vec_Int_t * vObj2Var; // mapping AIG ObjId into BDD var index + Vec_Int_t * vVar2Obj; // mapping BDD var index into AIG ObjId + Vec_Ptr_t * vGroups; // group Id into group pointer + Llb_Mtr_t * pMatrix; // dependency matrix + // image computation + Vec_Ptr_t * vRings; // onion rings + Vec_Int_t * vVarBegs; // the first group where the var appears + Vec_Int_t * vVarEnds; // the last group where the var appears + // variable mapping + Vec_Int_t * vNs2Glo; // next state variables into global variables + Vec_Int_t * vCs2Glo; // next state variables into global variables + Vec_Int_t * vGlo2Cs; // global variables into current state variables + Vec_Int_t * vGlo2Ns; // global variables into current state variables + // flow computation +// Vec_Int_t * vMem; +// Vec_Ptr_t * vTops; +// Vec_Ptr_t * vBots; +// Vec_Ptr_t * vCuts; +}; + +struct Llb_Mtr_t_ +{ + int nPis; // number of primary inputs + int nFfs; // number of flip-flops + int nRows; // number of rows + int nCols; // number of columns + int * pColSums; // sum of values in a column + Llb_Grp_t ** pColGrps; // group structure for each col + int * pRowSums; // sum of values in a row + char ** pMatrix; // dependency matrix + Llb_Man_t * pMan; // manager + // partial product + char * pProdVars; // variables in the partial product + int * pProdNums; // var counts in the remaining partitions +}; + +struct Llb_Grp_t_ +{ + int Id; // group ID + Vec_Ptr_t * vIns; // input AIG objs + Vec_Ptr_t * vOuts; // output AIG objs + Vec_Ptr_t * vNodes; // internal AIG objs + Llb_Man_t * pMan; // manager + Llb_Grp_t * pPrev; // previous group + Llb_Grp_t * pNext; // next group +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Llb_ObjBddVar( Vec_Int_t * vOrder, Aig_Obj_t * pObj ) { return Vec_IntEntry(vOrder, Aig_ObjId(pObj)); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== llbConstr.c ======================================================*/ +extern Vec_Int_t * Llb_ManDeriveConstraints( Aig_Man_t * p ); +extern void Llb_ManPrintEntries( Aig_Man_t * p, Vec_Int_t * vCands ); +/*=== llbCore.c ======================================================*/ +extern int Llb_ManModelCheckAig( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars, Vec_Int_t * vHints, DdManager ** pddGlo ); +/*=== llbCluster.c ======================================================*/ +extern void Llb_ManCluster( Llb_Mtr_t * p ); +/*=== llbDump.c ======================================================*/ +extern void Llb_ManDumpReached( DdManager * ddG, DdNode * bReached, char * pModel, char * pFileName ); +/*=== llbFlow.c ======================================================*/ +extern Vec_Ptr_t * Llb_ManFlow( Aig_Man_t * p, Vec_Ptr_t * vSources, int * pnFlow ); +/*=== llbHint.c ======================================================*/ +extern int Llb_ManReachabilityWithHints( Llb_Man_t * p ); +extern int Llb_ManModelCheckAigWithHints( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars ); +/*=== llbMan.c =======================================================*/ +extern void Llb_ManPrepareVarMap( Llb_Man_t * p ); +extern Llb_Man_t * Llb_ManStart( Aig_Man_t * pAigGlo, Aig_Man_t * pAig, Gia_ParLlb_t * pPars ); +extern void Llb_ManStop( Llb_Man_t * p ); +/*=== llbMatrix.c ====================================================*/ +extern void Llb_MtrVerifyMatrix( Llb_Mtr_t * p ); +extern Llb_Mtr_t * Llb_MtrCreate( Llb_Man_t * p ); +extern void Llb_MtrFree( Llb_Mtr_t * p ); +extern void Llb_MtrPrint( Llb_Mtr_t * p, int fOrder ); +extern void Llb_MtrPrintMatrixStats( Llb_Mtr_t * p ); +/*=== llbPart.c ======================================================*/ +extern Llb_Grp_t * Llb_ManGroupAlloc( Llb_Man_t * pMan ); +extern void Llb_ManGroupStop( Llb_Grp_t * p ); +extern void Llb_ManPrepareGroups( Llb_Man_t * pMan ); +extern Llb_Grp_t * Llb_ManGroupsCombine( Llb_Grp_t * p1, Llb_Grp_t * p2 ); +extern Llb_Grp_t * Llb_ManGroupCreateFromCuts( Llb_Man_t * pMan, Vec_Int_t * vCut1, Vec_Int_t * vCut2 ); +extern void Llb_ManPrepareVarLimits( Llb_Man_t * p ); +/*=== llbPivot.c =====================================================*/ +extern int Llb_ManTracePaths( Aig_Man_t * p, Aig_Obj_t * pPivot ); +extern Vec_Int_t * Llb_ManMarkPivotNodes( Aig_Man_t * p, int fUseInternal ); +/*=== llbReach.c =====================================================*/ +extern int Llb_ManReachability( Llb_Man_t * p, Vec_Int_t * vHints, DdManager ** pddGlo ); +/*=== llbSched.c =====================================================*/ +extern void Llb_MtrSchedule( Llb_Mtr_t * p ); + +/*=== llb2Bad.c ======================================================*/ +extern DdNode * Llb_BddComputeBad( Aig_Man_t * pInit, DdManager * dd, int TimeOut ); +extern DdNode * Llb_BddQuantifyPis( Aig_Man_t * pInit, DdManager * dd, DdNode * bFunc ); +/*=== llb2Core.c ======================================================*/ +extern DdNode * Llb_CoreComputeCube( DdManager * dd, Vec_Int_t * vVars, int fUseVarIndex, char * pValues ); +extern int Llb_CoreExperiment( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars, Vec_Ptr_t * vResult, int TimeTarget ); +/*=== llb2Driver.c ======================================================*/ +extern Vec_Int_t * Llb_DriverCountRefs( Aig_Man_t * p ); +extern Vec_Int_t * Llb_DriverCollectNs( Aig_Man_t * pAig, Vec_Int_t * vDriRefs ); +extern Vec_Int_t * Llb_DriverCollectCs( Aig_Man_t * pAig ); +extern DdNode * Llb_DriverPhaseCube( Aig_Man_t * pAig, Vec_Int_t * vDriRefs, DdManager * dd ); +extern DdManager * Llb_DriverLastPartition( Aig_Man_t * p, Vec_Int_t * vVarsNs, int TimeTarget ); +/*=== llb2Image.c ======================================================*/ +extern Vec_Ptr_t * Llb_ImgSupports( Aig_Man_t * p, Vec_Ptr_t * vDdMans, Vec_Int_t * vStart, Vec_Int_t * vStop, int fAddPis, int fVerbose ); +extern void Llb_ImgSchedule( Vec_Ptr_t * vSupps, Vec_Ptr_t ** pvQuant0, Vec_Ptr_t ** pvQuant1, int fVerbose ); +extern DdManager * Llb_ImgPartition( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, int TimeTarget ); +extern void Llb_ImgQuantifyFirst( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, Vec_Ptr_t * vQuant0, int fVerbose ); +extern void Llb_ImgQuantifyReset( Vec_Ptr_t * vDdMans ); +extern DdNode * Llb_ImgComputeImage( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, DdManager * dd, DdNode * bInit, + Vec_Ptr_t * vQuant0, Vec_Ptr_t * vQuant1, Vec_Int_t * vDriRefs, + int TimeTarget, int fBackward, int fReorder, int fVerbose ); + +extern DdManager * Llb_NonlinImageStart( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, int * pOrder, int fFirst, int TimeTarget ); +extern DdNode * Llb_NonlinImageCompute( DdNode * bCurrent, int fReorder, int fDrop, int fVerbose, int * pOrder ); +extern void Llb_NonlinImageQuit(); + +/*=== llb3Image.c =======================================================*/ +extern DdNode * Llb_NonlinImage( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, + DdManager * dd, DdNode * bCurrent, int fReorder, int fVerbose, int * pOrder, int Limit, int TimeTarget ); +/*=== llb3Nonlin.c ======================================================*/ +extern DdNode * Llb_NonlinComputeInitState( Aig_Man_t * pAig, DdManager * dd ); + + +/*=== llb4Cex.c =======================================================*/ +extern Abc_Cex_t * Llb4_Nonlin4TransformCex( Aig_Man_t * pAig, Vec_Ptr_t * vStates, int iCexPo, int fVerbose ); +/*=== llb4Cluster.c =======================================================*/ +//extern void Llb_Nonlin4Cluster( Aig_Man_t * pAig, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int nBddMax, int fVerbose ); +/*=== llb4Image.c =======================================================*/ +extern DdNode * Llb_Nonlin4Image( DdManager * dd, Vec_Ptr_t * vParts, DdNode * bCurrent, Vec_Int_t * vVars2Q ); +extern Vec_Ptr_t * Llb_Nonlin4Group( DdManager * dd, Vec_Ptr_t * vParts, Vec_Int_t * vVars2Q, int nSizeMax ); +/*=== llb4Map.c =========================================================*/ +//extern Vec_Int_t * Llb_AigMap( Aig_Man_t * pAig, int nLutSize, int nLutMin ); +/*=== llb4Nonlin.c ======================================================*/ +//extern int Llb_Nonlin4CoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ); +/*=== llb4Sweep.c ======================================================*/ +extern void Llb4_Nonlin4Sweep( Aig_Man_t * pAig, int nSweepMax, int nClusterMax, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int fVerbose ); + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/proof/llb/module.make b/src/proof/llb/module.make new file mode 100644 index 00000000..849a9e0e --- /dev/null +++ b/src/proof/llb/module.make @@ -0,0 +1,23 @@ +SRC += src/proof/llb/llb.c \ + src/proof/llb/llb1Cluster.c \ + src/proof/llb/llb1Constr.c \ + src/proof/llb/llb1Core.c \ + src/proof/llb/llb1Group.c \ + src/proof/llb/llb1Hint.c \ + src/proof/llb/llb1Man.c \ + src/proof/llb/llb1Matrix.c \ + src/proof/llb/llb1Pivot.c \ + src/proof/llb/llb1Reach.c \ + src/proof/llb/llb1Sched.c \ + src/proof/llb/llb2Bad.c \ + src/proof/llb/llb2Core.c \ + src/proof/llb/llb2Driver.c \ + src/proof/llb/llb2Dump.c \ + src/proof/llb/llb2Flow.c \ + src/proof/llb/llb2Image.c \ + src/proof/llb/llb3Image.c \ + src/proof/llb/llb3Nonlin.c \ + src/proof/llb/llb4Cex.c \ + src/proof/llb/llb4Image.c \ + src/proof/llb/llb4Nonlin.c \ + src/proof/llb/llb4Sweep.c diff --git a/src/proof/pdr/module.make b/src/proof/pdr/module.make new file mode 100644 index 00000000..93fd8071 --- /dev/null +++ b/src/proof/pdr/module.make @@ -0,0 +1,8 @@ +SRC += src/proof/pdr/pdr.c \ + src/proof/pdr/pdrCnf.c \ + src/proof/pdr/pdrCore.c \ + src/proof/pdr/pdrInv.c \ + src/proof/pdr/pdrMan.c \ + src/proof/pdr/pdrSat.c \ + src/proof/pdr/pdrTsim.c \ + src/proof/pdr/pdrUtil.c diff --git a/src/proof/pdr/pdr.c b/src/proof/pdr/pdr.c new file mode 100644 index 00000000..6bdf75b5 --- /dev/null +++ b/src/proof/pdr/pdr.c @@ -0,0 +1,53 @@ +/**CFile**************************************************************** + + FileName [pdr.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Netlist representation.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 20, 2010.] + + Revision [$Id: pdr.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "pdrInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/pdr/pdr.h b/src/proof/pdr/pdr.h new file mode 100644 index 00000000..4f0f769e --- /dev/null +++ b/src/proof/pdr/pdr.h @@ -0,0 +1,79 @@ +/**CFile**************************************************************** + + FileName [pdr.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Property driven reachability.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 20, 2010.] + + Revision [$Id: pdr.h,v 1.00 2010/11/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__sat__pdr__pdr_h +#define ABC__sat__pdr__pdr_h + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Pdr_Par_t_ Pdr_Par_t; +struct Pdr_Par_t_ +{ + int iOutput; // zero-based number of primary output to solve + int nRecycle; // limit on vars for recycling + int nFrameMax; // limit on frame count + int nConfLimit; // limit on SAT solver conflicts + int nTimeOut; // timeout in seconds + int fTwoRounds; // use two rounds for generalization + int fMonoCnf; // monolythic CNF + int fDumpInv; // dump inductive invariant + int fShortest; // forces bug traces to be shortest + int fSkipGeneral; // skips expensive generalization step + int fVerbose; // verbose output + int fVeryVerbose; // very verbose output + int iFrame; // explored up to this frame +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== pdrCore.c ==========================================================*/ +extern void Pdr_ManSetDefaultParams( Pdr_Par_t * pPars ); +extern int Pdr_ManSolve( Aig_Man_t * p, Pdr_Par_t * pPars, Abc_Cex_t ** ppCex ); + + +ABC_NAMESPACE_HEADER_END + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/proof/pdr/pdrClass.c b/src/proof/pdr/pdrClass.c new file mode 100644 index 00000000..519384c5 --- /dev/null +++ b/src/proof/pdr/pdrClass.c @@ -0,0 +1,223 @@ +/**CFile**************************************************************** + + FileName [pdrClass.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Property driven reachability.] + + Synopsis [Equivalence classes of register outputs.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 20, 2010.] + + Revision [$Id: pdrClass.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "pdrInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs duplication with the variable map.] + + Description [Var map contains -1 if const0 and otherwise.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Pdr_ManRehashWithMap( Aig_Man_t * pAig, Vec_Int_t * vMap ) +{ + Aig_Man_t * pFrames; + Aig_Obj_t * pObj; + int i, iReg; + assert( Vec_IntSize(vMap) == Aig_ManRegNum(pAig) ); + // start the fraig package + pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) ); + pFrames->pName = Abc_UtilStrsav( pAig->pName ); + pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec ); + // create CI mapping + Aig_ManCleanData( pAig ); + Aig_ManConst1(pAig)->pData = Aig_ManConst1(pFrames); + Aig_ManForEachPi( pAig, pObj, i ) + pObj->pData = Aig_ObjCreatePi(pFrames); + Saig_ManForEachLo( pAig, pObj, i ) + { + iReg = Vec_IntEntry(vMap, i); + if ( iReg == -1 ) + pObj->pData = Aig_ManConst0(pFrames); + else + pObj->pData = Saig_ManLo(pAig, iReg)->pData; + } + // add internal nodes of this frame + Aig_ManForEachNode( pAig, pObj, i ) + pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + // add output nodes + Aig_ManForEachPo( pAig, pObj, i ) + pObj->pData = Aig_ObjCreatePo( pFrames, Aig_ObjChild0Copy(pObj) ); + // finish off + Aig_ManCleanup( pFrames ); + Aig_ManSetRegNum( pFrames, Aig_ManRegNum(pAig) ); + return pFrames; +} + +/**Function************************************************************* + + Synopsis [Creates mapping of registers.] + + Description [Var map contains -1 if const0 and otherwise.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Pdr_ManCreateMap( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + Vec_Int_t * vMap; + int * pLit2Id, Lit, i; + pLit2Id = ABC_ALLOC( int, Aig_ManObjNumMax(p) * 2 ); + for ( i = 0; i < Aig_ManObjNumMax(p) * 2; i++ ) + pLit2Id[i] = -1; + vMap = Vec_IntAlloc( Aig_ManRegNum(p) ); + Saig_ManForEachLi( p, pObj, i ) + { + if ( Aig_ObjChild0(pObj) == Aig_ManConst0(p) ) + { + Vec_IntPush( vMap, -1 ); + continue; + } + Lit = 2 * Aig_ObjFaninId0(pObj) + Aig_ObjFaninC0(pObj); + if ( pLit2Id[Lit] < 0 ) // the first time + pLit2Id[Lit] = i; + Vec_IntPush( vMap, pLit2Id[Lit] ); + } + ABC_FREE( pLit2Id ); + return vMap; +} + +/**Function************************************************************* + + Synopsis [Counts reduced registers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pdr_ManCountMap( Vec_Int_t * vMap ) +{ + int i, Entry, Counter = 0; + Vec_IntForEachEntry( vMap, Entry, i ) + if ( Entry != i ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts reduced registers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pdr_ManPrintMap( Vec_Int_t * vMap ) +{ + Vec_Int_t * vMarks; + int f, i, iClass, Entry, Counter = 0; + printf( " Consts: " ); + Vec_IntForEachEntry( vMap, Entry, i ) + if ( Entry == -1 ) + printf( "%d ", i ); + printf( "\n" ); + vMarks = Vec_IntAlloc( 100 ); + Vec_IntForEachEntry( vMap, iClass, f ) + { + if ( iClass == -1 ) + continue; + if ( iClass == f ) + continue; + // check previous classes + if ( Vec_IntFind( vMarks, iClass ) >= 0 ) + continue; + Vec_IntPush( vMarks, iClass ); + // print class + printf( " Class %d : ", iClass ); + Vec_IntForEachEntry( vMap, Entry, i ) + if ( Entry == iClass ) + printf( "%d ", i ); + printf( "\n" ); + } + Vec_IntFree( vMarks ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pdr_ManEquivClasses( Aig_Man_t * pAig ) +{ + Vec_Int_t * vMap; + Aig_Man_t * pTemp; + int f, nFrames = 100; + assert( Saig_ManRegNum(pAig) > 0 ); + // start the map + vMap = Vec_IntAlloc( 0 ); + Vec_IntFill( vMap, Aig_ManRegNum(pAig), -1 ); + // iterate and print changes + for ( f = 0; f < nFrames; f++ ) + { + // implement variable map + pTemp = Pdr_ManRehashWithMap( pAig, vMap ); + // report the result + printf( "F =%4d : Total = %6d. Nodes = %6d. RedRegs = %6d. Prop = %s\n", + f+1, Aig_ManNodeNum(pAig), Aig_ManNodeNum(pTemp), Pdr_ManCountMap(vMap), + Aig_ObjChild0(Aig_ManPo(pTemp,0)) == Aig_ManConst0(pTemp) ? "proof" : "unknown" ); + // recreate the map + Pdr_ManPrintMap( vMap ); + Vec_IntFree( vMap ); + vMap = Pdr_ManCreateMap( pTemp ); + Aig_ManStop( pTemp ); + if ( Pdr_ManCountMap(vMap) == 0 ) + break; + } + Vec_IntFree( vMap ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/pdr/pdrCnf.c b/src/proof/pdr/pdrCnf.c new file mode 100644 index 00000000..fddd292b --- /dev/null +++ b/src/proof/pdr/pdrCnf.c @@ -0,0 +1,357 @@ +/**CFile**************************************************************** + + FileName [pdrCnf.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Property driven reachability.] + + Synopsis [CNF computation on demand.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 20, 2010.] + + Revision [$Id: pdrCnf.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "pdrInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/* + The CNF (p->pCnf2) is expressed in terms of object IDs. + Each node in the CNF is marked if it has clauses (p->pCnf2->pObj2Count[Id] > 0). + Each node in the CNF has the first clause (p->pCnf2->pObj2Clause) + and the number of clauses (p->pCnf2->pObj2Count). + Each node used in a CNF of any timeframe has its SAT var recorded. + Each frame has a reserve mapping of SAT variables into ObjIds. +*/ + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns SAT variable of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Pdr_ObjSatVar1( Pdr_Man_t * p, int k, Aig_Obj_t * pObj ) +{ + return p->pCnf1->pVarNums[ Aig_ObjId(pObj) ]; +} + +/**Function************************************************************* + + Synopsis [Returns SAT variable of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Pdr_ObjSatVar2FindOrAdd( Pdr_Man_t * p, int k, Aig_Obj_t * pObj ) +{ + assert( p->pCnf2->pObj2Count[Aig_ObjId(pObj)] >= 0 ); + if ( p->pvId2Vars[Aig_ObjId(pObj)] == NULL ) + p->pvId2Vars[Aig_ObjId(pObj)] = Vec_IntStart( 16 ); + if ( Vec_IntGetEntry( p->pvId2Vars[Aig_ObjId(pObj)], k ) == 0 ) + { + sat_solver * pSat = Pdr_ManSolver(p, k); + Vec_Int_t * vVar2Ids = (Vec_Int_t *)Vec_PtrEntry(p->vVar2Ids, k); + int iVarNew = Vec_IntSize( vVar2Ids ); + assert( iVarNew > 0 ); + Vec_IntPush( vVar2Ids, Aig_ObjId(pObj) ); + Vec_IntWriteEntry( p->pvId2Vars[Aig_ObjId(pObj)], k, iVarNew ); + sat_solver_setnvars( pSat, iVarNew + 1 ); + if ( k == 0 && Saig_ObjIsLo(p->pAig, pObj) ) // initialize the register output + { + int Lit = toLitCond( iVarNew, 1 ); + int RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 ); + assert( RetValue == 1 ); + sat_solver_compress( pSat ); + } + } + return Vec_IntEntry( p->pvId2Vars[Aig_ObjId(pObj)], k ); +} + +/**Function************************************************************* + + Synopsis [Recursively adds CNF for the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pdr_ObjSatVar2( Pdr_Man_t * p, int k, Aig_Obj_t * pObj ) +{ + sat_solver * pSat; + Vec_Int_t * vLits; + Vec_Int_t * vVar2Ids = (Vec_Int_t *)Vec_PtrEntry(p->vVar2Ids, k); + int nVarCount = Vec_IntSize(vVar2Ids); + int iVarThis = Pdr_ObjSatVar2FindOrAdd( p, k, pObj ); + int * pLit, i, iVar, nClauses, iFirstClause, RetValue; + if ( nVarCount == Vec_IntSize(vVar2Ids) ) + return iVarThis; + assert( nVarCount + 1 == Vec_IntSize(vVar2Ids) ); + if ( Aig_ObjIsPi(pObj) ) + return iVarThis; + nClauses = p->pCnf2->pObj2Count[Aig_ObjId(pObj)]; + iFirstClause = p->pCnf2->pObj2Clause[Aig_ObjId(pObj)]; + assert( nClauses > 0 ); + pSat = Pdr_ManSolver(p, k); + vLits = Vec_IntAlloc( 16 ); + for ( i = iFirstClause; i < iFirstClause + nClauses; i++ ) + { + Vec_IntClear( vLits ); + for ( pLit = p->pCnf2->pClauses[i]; pLit < p->pCnf2->pClauses[i+1]; pLit++ ) + { + iVar = Pdr_ObjSatVar2( p, k, Aig_ManObj(p->pAig, lit_var(*pLit)) ); + Vec_IntPush( vLits, toLitCond( iVar, lit_sign(*pLit) ) ); + } + RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits)+Vec_IntSize(vLits) ); + assert( RetValue ); + } + Vec_IntFree( vLits ); + return iVarThis; +} + +/**Function************************************************************* + + Synopsis [Returns SAT variable of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pdr_ObjSatVar( Pdr_Man_t * p, int k, Aig_Obj_t * pObj ) +{ + if ( p->pPars->fMonoCnf ) + return Pdr_ObjSatVar1( p, k, pObj ); + else + return Pdr_ObjSatVar2( p, k, pObj ); +} + + +/**Function************************************************************* + + Synopsis [Returns register number for the given SAT variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Pdr_ObjRegNum1( Pdr_Man_t * p, int k, int iSatVar ) +{ + int RegId; + assert( iSatVar >= 0 ); + // consider the case of auxiliary variable + if ( iSatVar >= p->pCnf1->nVars ) + return -1; + // consider the case of register output + RegId = Vec_IntEntry( p->vVar2Reg, iSatVar ); + assert( RegId >= 0 && RegId < Aig_ManRegNum(p->pAig) ); + return RegId; +} + +/**Function************************************************************* + + Synopsis [Returns register number for the given SAT variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Pdr_ObjRegNum2( Pdr_Man_t * p, int k, int iSatVar ) +{ + Aig_Obj_t * pObj; + int ObjId; + Vec_Int_t * vVar2Ids = (Vec_Int_t *)Vec_PtrEntry(p->vVar2Ids, k); + assert( iSatVar > 0 && iSatVar < Vec_IntSize(vVar2Ids) ); + ObjId = Vec_IntEntry( vVar2Ids, iSatVar ); + if ( ObjId == -1 ) // activation variable + return -1; + pObj = Aig_ManObj( p->pAig, ObjId ); + if ( Saig_ObjIsLi( p->pAig, pObj ) ) + return Aig_ObjPioNum(pObj)-Saig_ManPoNum(p->pAig); + assert( 0 ); // should be called for register inputs only + return -1; +} + +/**Function************************************************************* + + Synopsis [Returns register number for the given SAT variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pdr_ObjRegNum( Pdr_Man_t * p, int k, int iSatVar ) +{ + if ( p->pPars->fMonoCnf ) + return Pdr_ObjRegNum1( p, k, iSatVar ); + else + return Pdr_ObjRegNum2( p, k, iSatVar ); +} + + +/**Function************************************************************* + + Synopsis [Returns the index of unused SAT variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pdr_ManFreeVar( Pdr_Man_t * p, int k ) +{ + if ( p->pPars->fMonoCnf ) + return sat_solver_nvars( Pdr_ManSolver(p, k) ); + else + { + Vec_Int_t * vVar2Ids = (Vec_Int_t *)Vec_PtrEntry( p->vVar2Ids, k ); + Vec_IntPush( vVar2Ids, -1 ); + return Vec_IntSize( vVar2Ids ) - 1; + } +} + +/**Function************************************************************* + + Synopsis [Creates SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline sat_solver * Pdr_ManNewSolver1( sat_solver * pSat, Pdr_Man_t * p, int k, int fInit ) +{ + Aig_Obj_t * pObj; + int i; + assert( pSat ); + if ( p->pCnf1 == NULL ) + { + int nRegs = p->pAig->nRegs; + p->pAig->nRegs = Aig_ManPoNum(p->pAig); + p->pCnf1 = Cnf_Derive( p->pAig, Aig_ManPoNum(p->pAig) ); + p->pAig->nRegs = nRegs; + assert( p->vVar2Reg == NULL ); + p->vVar2Reg = Vec_IntStartFull( p->pCnf1->nVars ); + Saig_ManForEachLi( p->pAig, pObj, i ) + Vec_IntWriteEntry( p->vVar2Reg, Pdr_ObjSatVar(p, k, pObj), i ); + } + pSat = (sat_solver *)Cnf_DataWriteIntoSolverInt( pSat, p->pCnf1, 1, fInit ); + sat_solver_set_runtime_limit( pSat, p->timeToStop ); + return pSat; +} + +/**Function************************************************************* + + Synopsis [Creates SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline sat_solver * Pdr_ManNewSolver2( sat_solver * pSat, Pdr_Man_t * p, int k, int fInit ) +{ + Vec_Int_t * vVar2Ids; + int i, Entry; + assert( pSat ); + if ( p->pCnf2 == NULL ) + { + p->pCnf2 = Cnf_DeriveOther( p->pAig ); + p->pvId2Vars = ABC_CALLOC( Vec_Int_t *, Aig_ManObjNumMax(p->pAig) ); + p->vVar2Ids = Vec_PtrAlloc( 256 ); + } + // update the variable mapping + vVar2Ids = (Vec_Int_t *)Vec_PtrGetEntry( p->vVar2Ids, k ); + if ( vVar2Ids == NULL ) + { + vVar2Ids = Vec_IntAlloc( 500 ); + Vec_PtrWriteEntry( p->vVar2Ids, k, vVar2Ids ); + } + Vec_IntForEachEntry( vVar2Ids, Entry, i ) + { + if ( Entry == -1 ) + continue; + assert( Vec_IntEntry( p->pvId2Vars[Entry], k ) > 0 ); + Vec_IntWriteEntry( p->pvId2Vars[Entry], k, 0 ); + } + Vec_IntClear( vVar2Ids ); + Vec_IntPush( vVar2Ids, -1 ); + // start the SAT solver +// pSat = sat_solver_new(); + sat_solver_setnvars( pSat, 500 ); + sat_solver_set_runtime_limit( pSat, p->timeToStop ); + return pSat; +} + +/**Function************************************************************* + + Synopsis [Creates SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +sat_solver * Pdr_ManNewSolver( sat_solver * pSat, Pdr_Man_t * p, int k, int fInit ) +{ + assert( pSat != NULL ); + if ( p->pPars->fMonoCnf ) + return Pdr_ManNewSolver1( pSat, p, k, fInit ); + else + return Pdr_ManNewSolver2( pSat, p, k, fInit ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/pdr/pdrCore.c b/src/proof/pdr/pdrCore.c new file mode 100644 index 00000000..025ada06 --- /dev/null +++ b/src/proof/pdr/pdrCore.c @@ -0,0 +1,722 @@ +/**CFile**************************************************************** + + FileName [pdrCore.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Property driven reachability.] + + Synopsis [Core procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 20, 2010.] + + Revision [$Id: pdrCore.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "pdrInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns 1 if the state could be blocked.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pdr_ManSetDefaultParams( Pdr_Par_t * pPars ) +{ + memset( pPars, 0, sizeof(Pdr_Par_t) ); + pPars->iOutput = -1; // zero-based output number + pPars->nRecycle = 300; // limit on vars for recycling + pPars->nFrameMax = 5000; // limit on number of timeframes + pPars->nTimeOut = 0; // timeout in seconds + pPars->nConfLimit = 100000; // limit on SAT solver conflicts + pPars->fTwoRounds = 0; // use two rounds for generalization + pPars->fMonoCnf = 0; // monolythic CNF + pPars->fDumpInv = 0; // dump inductive invariant + pPars->fShortest = 0; // forces bug traces to be shortest + pPars->fVerbose = 0; // verbose output + pPars->fVeryVerbose = 0; // very verbose output + pPars->iFrame = -1; // explored up to this frame +} + +/**Function************************************************************* + + Synopsis [Reduces clause using analyzeFinal.] + + Description [Assumes that the SAT solver just terminated an UNSAT call.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Pdr_Set_t * Pdr_ManReduceClause( Pdr_Man_t * p, int k, Pdr_Set_t * pCube ) +{ + Pdr_Set_t * pCubeMin; + Vec_Int_t * vLits; + int i, Entry, nCoreLits, * pCoreLits; + // get relevant SAT literals + nCoreLits = sat_solver_final(Pdr_ManSolver(p, k), &pCoreLits); + // translate them into register literals and remove auxiliary + vLits = Pdr_ManLitsToCube( p, k, pCoreLits, nCoreLits ); + // skip if there is no improvement + if ( Vec_IntSize(vLits) == pCube->nLits ) + return NULL; + assert( Vec_IntSize(vLits) < pCube->nLits ); + // if the cube overlaps with init, add any literal + Vec_IntForEachEntry( vLits, Entry, i ) + if ( lit_sign(Entry) == 0 ) // positive literal + break; + if ( i == Vec_IntSize(vLits) ) // only negative literals + { + // add the first positive literal + for ( i = 0; i < pCube->nLits; i++ ) + if ( lit_sign(pCube->Lits[i]) == 0 ) // positive literal + { + Vec_IntPush( vLits, pCube->Lits[i] ); + break; + } + assert( i < pCube->nLits ); + } + // generate a starting cube + pCubeMin = Pdr_SetCreateSubset( pCube, Vec_IntArray(vLits), Vec_IntSize(vLits) ); + assert( !Pdr_SetIsInit(pCubeMin, -1) ); +/* + // make sure the cube works + { + int RetValue; + RetValue = Pdr_ManCheckCube( p, k, pCubeMin, NULL, 0 ); + assert( RetValue ); + } +*/ + return pCubeMin; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the state could be blocked.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pdr_ManPushClauses( Pdr_Man_t * p ) +{ + Pdr_Set_t * pTemp, * pCubeK, * pCubeK1; + Vec_Ptr_t * vArrayK, * vArrayK1; + int i, j, k, m, RetValue = 0, RetValue2, kMax = Vec_PtrSize(p->vSolvers)-1; + int Counter = 0; + int clk = clock(); + Vec_VecForEachLevelStartStop( p->vClauses, vArrayK, k, 1, kMax ) + { + Vec_PtrSort( vArrayK, (int (*)(void))Pdr_SetCompare ); + vArrayK1 = Vec_VecEntry( p->vClauses, k+1 ); + Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCubeK, j ) + { + Counter++; + + // remove cubes in the same frame that are contained by pCubeK + Vec_PtrForEachEntryStart( Pdr_Set_t *, vArrayK, pTemp, m, j+1 ) + { + if ( !Pdr_SetContains( pTemp, pCubeK ) ) // pCubeK contains pTemp + continue; + Pdr_SetDeref( pTemp ); + Vec_PtrWriteEntry( vArrayK, m, Vec_PtrEntryLast(vArrayK) ); + Vec_PtrPop(vArrayK); + m--; + } + + // check if the clause can be moved to the next frame + RetValue2 = Pdr_ManCheckCube( p, k, pCubeK, NULL, 0 ); + if ( RetValue2 == -1 ) + return -1; + if ( !RetValue2 ) + continue; + + { + Pdr_Set_t * pCubeMin; + pCubeMin = Pdr_ManReduceClause( p, k, pCubeK ); + if ( pCubeMin != NULL ) + { +// printf( "%d ", pCubeK->nLits - pCubeMin->nLits ); + Pdr_SetDeref( pCubeK ); + pCubeK = pCubeMin; + } + } + + // if it can be moved, add it to the next frame + Pdr_ManSolverAddClause( p, k+1, pCubeK ); + // check if the clause subsumes others + Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK1, pCubeK1, i ) + { + if ( !Pdr_SetContains( pCubeK1, pCubeK ) ) // pCubeK contains pCubeK1 + continue; + Pdr_SetDeref( pCubeK1 ); + Vec_PtrWriteEntry( vArrayK1, i, Vec_PtrEntryLast(vArrayK1) ); + Vec_PtrPop(vArrayK1); + i--; + } + // add the last clause + Vec_PtrPush( vArrayK1, pCubeK ); + Vec_PtrWriteEntry( vArrayK, j, Vec_PtrEntryLast(vArrayK) ); + Vec_PtrPop(vArrayK); + j--; + } + if ( Vec_PtrSize(vArrayK) == 0 ) + RetValue = 1; + } + + // clean up the last one + vArrayK = Vec_VecEntry( p->vClauses, kMax ); + Vec_PtrSort( vArrayK, (int (*)(void))Pdr_SetCompare ); + Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCubeK, j ) + { + // remove cubes in the same frame that are contained by pCubeK + Vec_PtrForEachEntryStart( Pdr_Set_t *, vArrayK, pTemp, m, j+1 ) + { + if ( !Pdr_SetContains( pTemp, pCubeK ) ) // pCubeK contains pTemp + continue; +/* + printf( "===\n" ); + Pdr_SetPrint( stdout, pCubeK, Aig_ManRegNum(p->pAig), NULL ); + printf( "\n" ); + Pdr_SetPrint( stdout, pTemp, Aig_ManRegNum(p->pAig), NULL ); + printf( "\n" ); +*/ + Pdr_SetDeref( pTemp ); + Vec_PtrWriteEntry( vArrayK, m, Vec_PtrEntryLast(vArrayK) ); + Vec_PtrPop(vArrayK); + m--; + } + } + p->tPush += clock() - clk; + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the clause is contained in higher clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pdr_ManCheckContainment( Pdr_Man_t * p, int k, Pdr_Set_t * pSet ) +{ + Pdr_Set_t * pThis; + Vec_Ptr_t * vArrayK; + int i, j, kMax = Vec_PtrSize(p->vSolvers)-1; + Vec_VecForEachLevelStartStop( p->vClauses, vArrayK, i, k, kMax+1 ) + Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pThis, j ) + if ( Pdr_SetContains( pSet, pThis ) ) + return 1; + return 0; +} + + +/**Function************************************************************* + + Synopsis [Sorts literals by priority.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Pdr_ManSortByPriority( Pdr_Man_t * p, Pdr_Set_t * pCube ) +{ + int * pPrios = Vec_IntArray(p->vPrio); + int * pArray = p->pOrder; + int temp, i, j, best_i, nSize = pCube->nLits; + // initialize variable order + for ( i = 0; i < nSize; i++ ) + pArray[i] = i; + for ( i = 0; i < nSize-1; i++ ) + { + best_i = i; + for ( j = i+1; j < nSize; j++ ) +// if ( pArray[j] < pArray[best_i] ) + if ( pPrios[pCube->Lits[pArray[j]]>>1] < pPrios[pCube->Lits[pArray[best_i]]>>1] ) + best_i = j; + temp = pArray[i]; + pArray[i] = pArray[best_i]; + pArray[best_i] = temp; + } +/* + for ( i = 0; i < pCube->nLits; i++ ) + printf( "%2d : %5d %5d %5d\n", i, pArray[i], pCube->Lits[pArray[i]]>>1, pPrios[pCube->Lits[pArray[i]]>>1] ); + printf( "\n" ); +*/ + return pArray; +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if the state could be blocked.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pdr_ManGeneralize( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, Pdr_Set_t ** ppPred, Pdr_Set_t ** ppCubeMin ) +{ + Pdr_Set_t * pCubeMin, * pCubeTmp = NULL; + int i, j, n, Lit, RetValue, clk = clock(); + int * pOrder; + // if there is no induction, return + *ppCubeMin = NULL; + RetValue = Pdr_ManCheckCube( p, k, pCube, ppPred, p->pPars->nConfLimit ); + if ( RetValue == -1 ) + return -1; + if ( RetValue == 0 ) + { + p->tGeneral += clock() - clk; + return 0; + } + + // reduce clause using assumptions +// pCubeMin = Pdr_SetDup( pCube ); + pCubeMin = Pdr_ManReduceClause( p, k, pCube ); + if ( pCubeMin == NULL ) + pCubeMin = Pdr_SetDup( pCube ); + + // perform generalization + if ( !p->pPars->fSkipGeneral ) + { + // sort literals by their occurences + pOrder = Pdr_ManSortByPriority( p, pCubeMin ); + // try removing literals + for ( j = 0; j < pCubeMin->nLits; j++ ) + { + // use ordering + // i = j; + i = pOrder[j]; + + // check init state + assert( pCubeMin->Lits[i] != -1 ); + if ( Pdr_SetIsInit(pCubeMin, i) ) + continue; + // try removing this literal + Lit = pCubeMin->Lits[i]; pCubeMin->Lits[i] = -1; + RetValue = Pdr_ManCheckCube( p, k, pCubeMin, NULL, p->pPars->nConfLimit ); + if ( RetValue == -1 ) + { + Pdr_SetDeref( pCubeMin ); + return -1; + } + pCubeMin->Lits[i] = Lit; + if ( RetValue == 0 ) + continue; + + // remove j-th entry + for ( n = j; n < pCubeMin->nLits-1; n++ ) + pOrder[n] = pOrder[n+1]; + j--; + + // success - update the cube + pCubeMin = Pdr_SetCreateFrom( pCubeTmp = pCubeMin, i ); + Pdr_SetDeref( pCubeTmp ); + assert( pCubeMin->nLits > 0 ); + i--; + + // get the ordering by decreasing priorit + pOrder = Pdr_ManSortByPriority( p, pCubeMin ); + } + + if ( p->pPars->fTwoRounds ) + for ( j = 0; j < pCubeMin->nLits; j++ ) + { + // use ordering + // i = j; + i = pOrder[j]; + + // check init state + assert( pCubeMin->Lits[i] != -1 ); + if ( Pdr_SetIsInit(pCubeMin, i) ) + continue; + // try removing this literal + Lit = pCubeMin->Lits[i]; pCubeMin->Lits[i] = -1; + RetValue = Pdr_ManCheckCube( p, k, pCubeMin, NULL, p->pPars->nConfLimit ); + if ( RetValue == -1 ) + { + Pdr_SetDeref( pCubeMin ); + return -1; + } + pCubeMin->Lits[i] = Lit; + if ( RetValue == 0 ) + continue; + + // remove j-th entry + for ( n = j; n < pCubeMin->nLits-1; n++ ) + pOrder[n] = pOrder[n+1]; + j--; + + // success - update the cube + pCubeMin = Pdr_SetCreateFrom( pCubeTmp = pCubeMin, i ); + Pdr_SetDeref( pCubeTmp ); + assert( pCubeMin->nLits > 0 ); + i--; + + // get the ordering by decreasing priorit + pOrder = Pdr_ManSortByPriority( p, pCubeMin ); + } + } + + assert( ppCubeMin != NULL ); + *ppCubeMin = pCubeMin; + p->tGeneral += clock() - clk; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the state could be blocked.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pdr_ManBlockCube( Pdr_Man_t * p, Pdr_Set_t * pCube ) +{ + Pdr_Obl_t * pThis; + Pdr_Set_t * pPred, * pCubeMin; + int i, k, RetValue, Prio = ABC_INFINITY, Counter = 0; + int kMax = Vec_PtrSize(p->vSolvers)-1, clk; + p->nBlocks++; + // create first proof obligation + assert( p->pQueue == NULL ); + pThis = Pdr_OblStart( kMax, Prio--, pCube, NULL ); // consume ref + Pdr_QueuePush( p, pThis ); + // try to solve it recursively + while ( !Pdr_QueueIsEmpty(p) ) + { + Counter++; + pThis = Pdr_QueueHead( p ); + if ( pThis->iFrame == 0 ) + return 0; // SAT + pThis = Pdr_QueuePop( p ); + assert( pThis->iFrame > 0 ); + assert( !Pdr_SetIsInit(pThis->pState, -1) ); + + clk = clock(); + if ( Pdr_ManCheckContainment( p, pThis->iFrame, pThis->pState ) ) + { + p->tContain += clock() - clk; + Pdr_OblDeref( pThis ); + continue; + } + p->tContain += clock() - clk; + + // check if the cube is already contained + RetValue = Pdr_ManCheckCubeCs( p, pThis->iFrame, pThis->pState ); + if ( RetValue == -1 ) // cube is blocked by clauses in this frame + { + Pdr_OblDeref( pThis ); + return -1; + } + if ( RetValue ) // cube is blocked by clauses in this frame + { + Pdr_OblDeref( pThis ); + continue; + } + + // check if the cube holds with relative induction + pCubeMin = NULL; + RetValue = Pdr_ManGeneralize( p, pThis->iFrame-1, pThis->pState, &pPred, &pCubeMin ); + if ( RetValue == -1 ) + { + Pdr_OblDeref( pThis ); + return -1; + } + if ( RetValue ) // cube is blocked inductively in this frame + { + assert( pCubeMin != NULL ); + + // k is the last frame where pCubeMin holds + k = pThis->iFrame; + + // check other frames + assert( pPred == NULL ); + for ( k = pThis->iFrame; k < kMax; k++ ) + if ( !Pdr_ManCheckCube( p, k, pCubeMin, NULL, 0 ) ) + break; + + // add new clause + if ( p->pPars->fVeryVerbose ) + { + printf( "Adding cube " ); + Pdr_SetPrint( stdout, pCubeMin, Aig_ManRegNum(p->pAig), NULL ); + printf( " to frame %d.\n", k ); + } + // set priority flops + for ( i = 0; i < pCubeMin->nLits; i++ ) + { + assert( pCubeMin->Lits[i] >= 0 ); + assert( (pCubeMin->Lits[i] / 2) < Aig_ManRegNum(p->pAig) ); + Vec_IntAddToEntry( p->vPrio, pCubeMin->Lits[i] / 2, 1 ); + } + + Vec_VecPush( p->vClauses, k, pCubeMin ); // consume ref + p->nCubes++; + // add clause + for ( i = 1; i <= k; i++ ) + Pdr_ManSolverAddClause( p, i, pCubeMin ); + // schedule proof obligation + if ( k < kMax && !p->pPars->fShortest ) + { + pThis->iFrame = k+1; + pThis->prio = Prio--; + Pdr_QueuePush( p, pThis ); + } + else + { + Pdr_OblDeref( pThis ); + } + } + else + { + assert( pCubeMin == NULL ); + assert( pPred != NULL ); + pThis->prio = Prio--; + Pdr_QueuePush( p, pThis ); + + pThis = Pdr_OblStart( pThis->iFrame-1, Prio--, pPred, Pdr_OblRef(pThis) ); + Pdr_QueuePush( p, pThis ); + } + + // check the timeout + if ( p->timeToStop && time(NULL) > p->timeToStop ) + return -1; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pdr_ManSolveInt( Pdr_Man_t * p ) +{ + int fPrintClauses = 0; + Pdr_Set_t * pCube; + int k, RetValue = -1; + int clkTotal = clock(); + int clkStart = clock(); + p->timeToStop = p->pPars->nTimeOut ? time(NULL) + p->pPars->nTimeOut : 0; + assert( Vec_PtrSize(p->vSolvers) == 0 ); + // create the first timeframe + Pdr_ManCreateSolver( p, (k = 0) ); + while ( 1 ) + { + p->nFrames = k; + assert( k == Vec_PtrSize(p->vSolvers)-1 ); + RetValue = Pdr_ManCheckCube( p, k, NULL, &pCube, p->pPars->nConfLimit ); + if ( RetValue == -1 ) + { + if ( p->pPars->fVerbose ) + Pdr_ManPrintProgress( p, 1, clock() - clkStart ); + printf( "Reached conflict limit (%d).\n", p->pPars->nConfLimit ); + p->pPars->iFrame = k; + return -1; + } + if ( RetValue == 0 ) + { + RetValue = Pdr_ManBlockCube( p, pCube ); + if ( RetValue == -1 ) + { + if ( p->pPars->fVerbose ) + Pdr_ManPrintProgress( p, 1, clock() - clkStart ); + printf( "Reached conflict limit (%d).\n", p->pPars->nConfLimit ); + p->pPars->iFrame = k; + return -1; + } + if ( RetValue == 0 ) + { + if ( fPrintClauses ) + { + printf( "*** Clauses after frame %d:\n", k ); + Pdr_ManPrintClauses( p, 0 ); + } + if ( p->pPars->fVerbose ) + Pdr_ManPrintProgress( p, 1, clock() - clkStart ); + p->pPars->iFrame = k; + return 0; // SAT + } + } + else + { + if ( p->pPars->fVerbose ) + Pdr_ManPrintProgress( p, 1, clock() - clkStart ); + // open a new timeframe + assert( pCube == NULL ); + Pdr_ManSetPropertyOutput( p, k ); + Pdr_ManCreateSolver( p, ++k ); + if ( fPrintClauses ) + { + printf( "*** Clauses after frame %d:\n", k ); + Pdr_ManPrintClauses( p, 0 ); + } + // push clauses into this timeframe + RetValue = Pdr_ManPushClauses( p ); + if ( RetValue == -1 ) + { + if ( p->pPars->fVerbose ) + Pdr_ManPrintProgress( p, 1, clock() - clkStart ); + printf( "Reached conflict limit (%d).\n", p->pPars->nConfLimit ); + p->pPars->iFrame = k; + return -1; + } + if ( RetValue ) + { + if ( p->pPars->fVerbose ) + Pdr_ManPrintProgress( p, 1, clock() - clkStart ); + Pdr_ManReportInvariant( p ); + Pdr_ManVerifyInvariant( p ); + p->pPars->iFrame = k; + return 1; // UNSAT + } + if ( p->pPars->fVerbose ) + Pdr_ManPrintProgress( p, 0, clock() - clkStart ); + clkStart = clock(); + } + + // check the timeout + if ( p->timeToStop && time(NULL) > p->timeToStop ) + { + if ( fPrintClauses ) + { + printf( "*** Clauses after frame %d:\n", k ); + Pdr_ManPrintClauses( p, 0 ); + } + if ( p->pPars->fVerbose ) + Pdr_ManPrintProgress( p, 1, clock() - clkStart ); + printf( "Reached timeout (%d seconds).\n", p->pPars->nTimeOut ); + p->pPars->iFrame = k; + return -1; + } + if ( p->pPars->nFrameMax && k >= p->pPars->nFrameMax ) + { + if ( p->pPars->fVerbose ) + Pdr_ManPrintProgress( p, 1, clock() - clkStart ); + printf( "Reached limit on the number of timeframes (%d).\n", p->pPars->nFrameMax ); + p->pPars->iFrame = k; + return -1; + } + } + return RetValue; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pdr_ManSolve_( Aig_Man_t * pAig, Pdr_Par_t * pPars, Vec_Int_t ** pvPrioInit, Abc_Cex_t ** ppCex ) +{ + Pdr_Man_t * p; + int RetValue; + int clk = clock(); + p = Pdr_ManStart( pAig, pPars, pvPrioInit? *pvPrioInit : NULL ); + RetValue = Pdr_ManSolveInt( p ); + *ppCex = RetValue ? NULL : Pdr_ManDeriveCex( p ); + if ( p->pPars->fDumpInv ) + Pdr_ManDumpClauses( p, (char *)"inv.pla", RetValue==1 ); + +// if ( *ppCex && pPars->fVerbose ) +// printf( "Found counter-example in frame %d after exploring %d frames.\n", +// (*ppCex)->iFrame, p->nFrames ); + p->tTotal += clock() - clk; + if ( pvPrioInit ) + { + *pvPrioInit = p->vPrio; + p->vPrio = NULL; + } + Pdr_ManStop( p ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pdr_ManSolve( Aig_Man_t * pAig, Pdr_Par_t * pPars, Abc_Cex_t ** ppCex ) +{ +/* + Vec_Int_t * vPrioInit = NULL; + int RetValue, nTimeOut; + if ( pPars->nTimeOut > 0 ) + return Pdr_ManSolve_( pAig, pPars, NULL, ppCex ); + nTimeOut = pPars->nTimeOut; + pPars->nTimeOut = 10; + RetValue = Pdr_ManSolve_( pAig, pPars, &vPrioInit, ppCex ); + pPars->nTimeOut = nTimeOut; + if ( RetValue == -1 ) + RetValue = Pdr_ManSolve_( pAig, pPars, &vPrioInit, ppCex ); + Vec_IntFree( vPrioInit ); + return RetValue; +*/ + return Pdr_ManSolve_( pAig, pPars, NULL, ppCex ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/pdr/pdrInt.h b/src/proof/pdr/pdrInt.h new file mode 100644 index 00000000..baf4ca02 --- /dev/null +++ b/src/proof/pdr/pdrInt.h @@ -0,0 +1,198 @@ +/**CFile**************************************************************** + + FileName [pdrInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Property driven reachability.] + + Synopsis [Internal declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 20, 2010.] + + Revision [$Id: pdrInt.h,v 1.00 2010/11/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__sat__pdr__pdrInt_h +#define ABC__sat__pdr__pdrInt_h + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "src/aig/saig/saig.h" +#include "src/sat/cnf/cnf.h" +#include "src/sat/bsat/satSolver.h" +#include "pdr.h" + +ABC_NAMESPACE_HEADER_START + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Pdr_Set_t_ Pdr_Set_t; +struct Pdr_Set_t_ +{ + word Sign; // signature + int nRefs; // ref counter + int nTotal; // total literals + int nLits; // num flop literals + int Lits[0]; +}; + +typedef struct Pdr_Obl_t_ Pdr_Obl_t; +struct Pdr_Obl_t_ +{ + int iFrame; // time frame + int prio; // priority + int nRefs; // reference counter + Pdr_Set_t * pState; // state cube + Pdr_Obl_t * pNext; // next one + Pdr_Obl_t * pLink; // queue link +}; + +typedef struct Pdr_Man_t_ Pdr_Man_t; +struct Pdr_Man_t_ +{ + // input problem + Pdr_Par_t * pPars; // parameters + Aig_Man_t * pAig; // user's AIG + // static CNF representation + Cnf_Dat_t * pCnf1; // CNF for this AIG + Vec_Int_t * vVar2Reg; // mapping of SAT var into registers + // dynamic CNF representation + Cnf_Dat_t * pCnf2; // CNF for this AIG + Vec_Int_t** pvId2Vars; // for each used ObjId, maps frame into SAT var + Vec_Ptr_t * vVar2Ids; // for each used frame, maps SAT var into ObjId + // data representation + Vec_Ptr_t * vSolvers; // SAT solvers + Vec_Vec_t * vClauses; // clauses by timeframe + Pdr_Obl_t * pQueue; // proof obligations + int * pOrder; // ordering of the lits + Vec_Int_t * vActVars; // the counter of activation variables + // internal use + Vec_Int_t * vPrio; // priority flops + Vec_Int_t * vLits; // array of literals + Vec_Int_t * vCiObjs; // cone leaves + Vec_Int_t * vCoObjs; // cone roots + Vec_Int_t * vCiVals; // cone leaf values + Vec_Int_t * vCoVals; // cone root values + Vec_Int_t * vNodes; // cone nodes + Vec_Int_t * vUndo; // cone undos + Vec_Int_t * vVisits; // intermediate + Vec_Int_t * vCi2Rem; // CIs to be removed + Vec_Int_t * vRes; // final result + Vec_Int_t * vSuppLits; // support literals + Pdr_Set_t * pCubeJust; // justification + // statistics + int nBlocks; // the number of times blockState was called + int nObligs; // the number of proof obligations derived + int nCubes; // the number of cubes derived + int nCalls; // the number of SAT calls + int nCallsS; // the number of SAT calls (sat) + int nCallsU; // the number of SAT calls (unsat) + int nStarts; // the number of SAT solver restarts + int nFrames; // frames explored + int nCasesSS; + int nCasesSU; + int nCasesUS; + int nCasesUU; + // runtime + int timeStart; + int timeToStop; + // time stats + int tSat; + int tSatSat; + int tSatUnsat; + int tGeneral; + int tPush; + int tTsim; + int tContain; + int tCnf; + int tTotal; +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline sat_solver * Pdr_ManSolver( Pdr_Man_t * p, int k ) { return (sat_solver *)Vec_PtrEntry(p->vSolvers, k); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== pdrCex.c ==========================================================*/ +extern Abc_Cex_t * Pdr_ManDeriveCex( Pdr_Man_t * p ); +/*=== pdrCnf.c ==========================================================*/ +extern int Pdr_ObjSatVar( Pdr_Man_t * p, int k, Aig_Obj_t * pObj ); +extern int Pdr_ObjRegNum( Pdr_Man_t * p, int k, int iSatVar ); +extern int Pdr_ManFreeVar( Pdr_Man_t * p, int k ); +extern sat_solver * Pdr_ManNewSolver( sat_solver * pSat, Pdr_Man_t * p, int k, int fInit ); +/*=== pdrCore.c ==========================================================*/ +extern int Pdr_ManCheckContainment( Pdr_Man_t * p, int k, Pdr_Set_t * pSet ); +/*=== pdrInv.c ==========================================================*/ +extern void Pdr_ManPrintProgress( Pdr_Man_t * p, int fClose, int Time ); +extern void Pdr_ManPrintClauses( Pdr_Man_t * p, int kStart ); +extern void Pdr_ManDumpClauses( Pdr_Man_t * p, char * pFileName, int fProved ); +extern void Pdr_ManReportInvariant( Pdr_Man_t * p ); +extern void Pdr_ManVerifyInvariant( Pdr_Man_t * p ); +/*=== pdrMan.c ==========================================================*/ +extern Pdr_Man_t * Pdr_ManStart( Aig_Man_t * pAig, Pdr_Par_t * pPars, Vec_Int_t * vPrioInit ); +extern void Pdr_ManStop( Pdr_Man_t * p ); +extern Abc_Cex_t * Pdr_ManDeriveCex( Pdr_Man_t * p ); +/*=== pdrSat.c ==========================================================*/ +extern sat_solver * Pdr_ManCreateSolver( Pdr_Man_t * p, int k ); +extern sat_solver * Pdr_ManFetchSolver( Pdr_Man_t * p, int k ); +extern void Pdr_ManSetPropertyOutput( Pdr_Man_t * p, int k ); +extern Vec_Int_t * Pdr_ManCubeToLits( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, int fCompl, int fNext ); +extern Vec_Int_t * Pdr_ManLitsToCube( Pdr_Man_t * p, int k, int * pArray, int nArray ); +extern void Pdr_ManSolverAddClause( Pdr_Man_t * p, int k, Pdr_Set_t * pCube ); +extern void Pdr_ManCollectValues( Pdr_Man_t * p, int k, Vec_Int_t * vObjIds, Vec_Int_t * vValues ); +extern int Pdr_ManCheckCubeCs( Pdr_Man_t * p, int k, Pdr_Set_t * pCube ); +extern int Pdr_ManCheckCube( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, Pdr_Set_t ** ppPred, int nConfLimit ); +/*=== pdrTsim.c ==========================================================*/ +extern Pdr_Set_t * Pdr_ManTernarySim( Pdr_Man_t * p, int k, Pdr_Set_t * pCube ); +/*=== pdrUtil.c ==========================================================*/ +extern Pdr_Set_t * Pdr_SetAlloc( int nSize ); +extern Pdr_Set_t * Pdr_SetCreate( Vec_Int_t * vLits, Vec_Int_t * vPiLits ); +extern Pdr_Set_t * Pdr_SetCreateFrom( Pdr_Set_t * pSet, int iRemove ); +extern Pdr_Set_t * Pdr_SetCreateSubset( Pdr_Set_t * pSet, int * pLits, int nLits ); +extern Pdr_Set_t * Pdr_SetDup( Pdr_Set_t * pSet ); +extern Pdr_Set_t * Pdr_SetRef( Pdr_Set_t * p ); +extern void Pdr_SetDeref( Pdr_Set_t * p ); +extern int Pdr_SetContains( Pdr_Set_t * pOld, Pdr_Set_t * pNew ); +extern int Pdr_SetContainsSimple( Pdr_Set_t * pOld, Pdr_Set_t * pNew ); +extern int Pdr_SetIsInit( Pdr_Set_t * p, int iRemove ); +extern void Pdr_SetPrint( FILE * pFile, Pdr_Set_t * p, int nRegs, Vec_Int_t * vFlopCounts ); +extern int Pdr_SetCompare( Pdr_Set_t ** pp1, Pdr_Set_t ** pp2 ); +extern Pdr_Obl_t * Pdr_OblStart( int k, int prio, Pdr_Set_t * pState, Pdr_Obl_t * pNext ); +extern Pdr_Obl_t * Pdr_OblRef( Pdr_Obl_t * p ); +extern void Pdr_OblDeref( Pdr_Obl_t * p ); +extern int Pdr_QueueIsEmpty( Pdr_Man_t * p ); +extern Pdr_Obl_t * Pdr_QueueHead( Pdr_Man_t * p ); +extern Pdr_Obl_t * Pdr_QueuePop( Pdr_Man_t * p ); +extern void Pdr_QueuePush( Pdr_Man_t * p, Pdr_Obl_t * pObl ); +extern void Pdr_QueuePrint( Pdr_Man_t * p ); +extern void Pdr_QueueStop( Pdr_Man_t * p ); +extern int Pdr_ManCubeJust( Pdr_Man_t * p, int k, Pdr_Set_t * pCube ); + +ABC_NAMESPACE_HEADER_END + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/proof/pdr/pdrInv.c b/src/proof/pdr/pdrInv.c new file mode 100644 index 00000000..30d1145d --- /dev/null +++ b/src/proof/pdr/pdrInv.c @@ -0,0 +1,374 @@ +/**CFile**************************************************************** + + FileName [pdrInv.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Property driven reachability.] + + Synopsis [Invariant computation, printing, verification.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 20, 2010.] + + Revision [$Id: pdrInv.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "pdrInt.h" +#include "src/base/abc/abc.h" // for Abc_NtkCollectCioNames() +#include "src/base/main/main.h" // for Abc_FrameReadGlobalFrame() + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pdr_ManPrintProgress( Pdr_Man_t * p, int fClose, int Time ) +{ + static int PastSize; + Vec_Ptr_t * vVec; + int i, ThisSize, Length, LengthStart; + if ( Vec_PtrSize(p->vSolvers) < 2 ) + return; + // count the total length of the printout + Length = 0; + Vec_VecForEachLevel( p->vClauses, vVec, i ) + Length += 1 + Abc_Base10Log(Vec_PtrSize(vVec)+1); + // determine the starting point + LengthStart = Abc_MaxInt( 0, Length - 70 ); + printf( "%3d :", Vec_PtrSize(p->vSolvers)-1 ); + ThisSize = 6; + if ( LengthStart > 0 ) + { + printf( " ..." ); + ThisSize += 4; + } + Length = 0; + Vec_VecForEachLevel( p->vClauses, vVec, i ) + { + if ( Length < LengthStart ) + { + Length += 1 + Abc_Base10Log(Vec_PtrSize(vVec)+1); + continue; + } + printf( " %d", Vec_PtrSize(vVec) ); + Length += 1 + Abc_Base10Log(Vec_PtrSize(vVec)+1); + ThisSize += 1 + Abc_Base10Log(Vec_PtrSize(vVec)+1); + } + if ( fClose ) + { + for ( i = 0; i < PastSize - ThisSize; i++ ) + printf( " " ); + printf( "\n" ); + } + else + { + printf( "\r" ); + PastSize = ThisSize; + } +// printf(" %.2f sec", (float)(Time)/(float)(CLOCKS_PER_SEC)); +} + +/**Function************************************************************* + + Synopsis [Counts how many times each flop appears in the set of cubes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Pdr_ManCountFlops( Pdr_Man_t * p, Vec_Ptr_t * vCubes ) +{ + Vec_Int_t * vFlopCount; + Pdr_Set_t * pCube; + int i, n; + vFlopCount = Vec_IntStart( Aig_ManRegNum(p->pAig) ); + Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i ) + for ( n = 0; n < pCube->nLits; n++ ) + { + assert( pCube->Lits[n] >= 0 && pCube->Lits[n] < 2*Aig_ManRegNum(p->pAig) ); + Vec_IntAddToEntry( vFlopCount, pCube->Lits[n] >> 1, 1 ); + } + return vFlopCount; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pdr_ManFindInvariantStart( Pdr_Man_t * p ) +{ + Vec_Ptr_t * vArrayK; + int k, kMax = Vec_PtrSize(p->vSolvers)-1; + Vec_VecForEachLevelStartStop( p->vClauses, vArrayK, k, 1, kMax+1 ) + if ( Vec_PtrSize(vArrayK) == 0 ) + return k; +// return -1; + // if there is no starting point (as in case of SAT or undecided), return the last frame +// printf( "The last timeframe contains %d clauses.\n", Vec_PtrSize(Vec_VecEntry(p->vClauses, kMax)) ); + return kMax; +} + +/**Function************************************************************* + + Synopsis [Counts the number of variables used in the clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Pdr_ManCollectCubes( Pdr_Man_t * p, int kStart ) +{ + Vec_Ptr_t * vResult; + Vec_Ptr_t * vArrayK; + Pdr_Set_t * pSet; + int i, j; + vResult = Vec_PtrAlloc( 100 ); + Vec_VecForEachLevelStart( p->vClauses, vArrayK, i, kStart ) + Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pSet, j ) + Vec_PtrPush( vResult, pSet ); + return vResult; +} + +/**Function************************************************************* + + Synopsis [Counts the number of variables used in the clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pdr_ManCountVariables( Pdr_Man_t * p, int kStart ) +{ + Vec_Int_t * vFlopCounts; + Vec_Ptr_t * vCubes; + int i, Entry, Counter = 0; + vCubes = Pdr_ManCollectCubes( p, kStart ); + vFlopCounts = Pdr_ManCountFlops( p, vCubes ); + Vec_IntForEachEntry( vFlopCounts, Entry, i ) + Counter += (Entry > 0); + Vec_IntFreeP( &vFlopCounts ); + Vec_PtrFree( vCubes ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pdr_ManPrintClauses( Pdr_Man_t * p, int kStart ) +{ + Vec_Ptr_t * vArrayK; + Pdr_Set_t * pCube; + int i, k, Counter = 0; + Vec_VecForEachLevelStart( p->vClauses, vArrayK, k, kStart ) + { + Vec_PtrSort( vArrayK, (int (*)(void))Pdr_SetCompare ); + Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCube, i ) + { + printf( "C=%4d. F=%4d ", Counter++, k ); + Pdr_SetPrint( stdout, pCube, Aig_ManRegNum(p->pAig), NULL ); + printf( "\n" ); + } + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pdr_ManDumpClauses( Pdr_Man_t * p, char * pFileName, int fProved ) +{ + int fUseSupp = 1; + FILE * pFile; + Vec_Int_t * vFlopCounts; + Vec_Ptr_t * vCubes; + Pdr_Set_t * pCube; + char ** pNamesCi; + int i, kStart; + // create file + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for writing invariant.\n", pFileName ); + return; + } + // collect cubes + kStart = Pdr_ManFindInvariantStart( p ); + vCubes = Pdr_ManCollectCubes( p, kStart ); + Vec_PtrSort( vCubes, (int (*)(void))Pdr_SetCompare ); + // collect variable appearances + vFlopCounts = fUseSupp ? Pdr_ManCountFlops( p, vCubes ) : NULL; + // output the header + if ( fProved ) + fprintf( pFile, "# Inductive invariant for \"%s\"\n", p->pAig->pName ); + else + fprintf( pFile, "# Clauses of the last timeframe for \"%s\"\n", p->pAig->pName ); + fprintf( pFile, "# generated by PDR in ABC on %s\n", Aig_TimeStamp() ); + fprintf( pFile, ".i %d\n", fUseSupp ? Pdr_ManCountVariables(p, kStart) : Aig_ManRegNum(p->pAig) ); + fprintf( pFile, ".o 1\n" ); + fprintf( pFile, ".p %d\n", Vec_PtrSize(vCubes) ); + // output flop names + pNamesCi = Abc_NtkCollectCioNames( Abc_FrameReadNtk( Abc_FrameReadGlobalFrame() ), 0 ); + if ( pNamesCi ) + { + fprintf( pFile, ".ilb" ); + for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ ) + if ( !fUseSupp || Vec_IntEntry( vFlopCounts, i ) ) + fprintf( pFile, " %s", pNamesCi[Saig_ManPiNum(p->pAig) + i] ); + fprintf( pFile, "\n" ); + ABC_FREE( pNamesCi ); + fprintf( pFile, ".ob inv\n" ); + } + // output cubes + Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i ) + { + Pdr_SetPrint( pFile, pCube, Aig_ManRegNum(p->pAig), vFlopCounts ); + fprintf( pFile, " 1\n" ); + } + fprintf( pFile, ".e\n\n" ); + fclose( pFile ); + Vec_IntFreeP( &vFlopCounts ); + Vec_PtrFree( vCubes ); + if ( fProved ) + printf( "Inductive invariant was written into file \"%s\".\n", pFileName ); + else + printf( "Clauses of the last timeframe were written into file \"%s\".\n", pFileName ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pdr_ManReportInvariant( Pdr_Man_t * p ) +{ + Vec_Ptr_t * vCubes; + int kStart = Pdr_ManFindInvariantStart( p ); + vCubes = Pdr_ManCollectCubes( p, kStart ); + printf( "Invariant F[%d] : %d clauses with %d flops (out of %d)\n", + kStart, Vec_PtrSize(vCubes), Pdr_ManCountVariables(p, kStart), Aig_ManRegNum(p->pAig) ); + Vec_PtrFree( vCubes ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pdr_ManVerifyInvariant( Pdr_Man_t * p ) +{ + sat_solver * pSat; + Vec_Int_t * vLits; + Vec_Ptr_t * vCubes; + Pdr_Set_t * pCube; + int i, kStart, kThis, RetValue, Counter = 0, clk = clock(); + // collect cubes used in the inductive invariant + kStart = Pdr_ManFindInvariantStart( p ); + vCubes = Pdr_ManCollectCubes( p, kStart ); + // create solver with the cubes + kThis = Vec_PtrSize(p->vSolvers); + pSat = Pdr_ManCreateSolver( p, kThis ); + // add the property output + Pdr_ManSetPropertyOutput( p, kThis ); + // add the clauses + Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i ) + { + vLits = Pdr_ManCubeToLits( p, kThis, pCube, 1, 0 ); + RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ); + assert( RetValue ); + sat_solver_compress( pSat ); + } + // check each clause + Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i ) + { + vLits = Pdr_ManCubeToLits( p, kThis, pCube, 0, 1 ); + RetValue = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), 0, 0, 0, 0 ); + if ( RetValue != l_False ) + { + printf( "Verification of clause %d failed.\n", i ); + Counter++; + } + } + if ( Counter ) + printf( "Verification of %d clauses has failed.\n", Counter ); + else + { + printf( "Verification of invariant with %d clauses was successful. ", Vec_PtrSize(vCubes) ); + Abc_PrintTime( 1, "Time", clock() - clk ); + } +// sat_solver_delete( pSat ); + Vec_PtrFree( vCubes ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/pdr/pdrMan.c b/src/proof/pdr/pdrMan.c new file mode 100644 index 00000000..33c94d40 --- /dev/null +++ b/src/proof/pdr/pdrMan.c @@ -0,0 +1,194 @@ +/**CFile**************************************************************** + + FileName [pdrMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Property driven reachability.] + + Synopsis [Manager procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 20, 2010.] + + Revision [$Id: pdrMan.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "pdrInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Pdr_Man_t * Pdr_ManStart( Aig_Man_t * pAig, Pdr_Par_t * pPars, Vec_Int_t * vPrioInit ) +{ + Pdr_Man_t * p; + p = ABC_CALLOC( Pdr_Man_t, 1 ); + p->pPars = pPars; + p->pAig = pAig; + p->vSolvers = Vec_PtrAlloc( 0 ); + p->vClauses = Vec_VecAlloc( 0 ); + p->pQueue = NULL; + p->pOrder = ABC_ALLOC( int, Aig_ManRegNum(pAig) ); + p->vActVars = Vec_IntAlloc( 256 ); + // internal use + p->vPrio = vPrioInit ? vPrioInit : Vec_IntStart( Aig_ManRegNum(pAig) ); // priority flops + p->vLits = Vec_IntAlloc( 100 ); // array of literals + p->vCiObjs = Vec_IntAlloc( 100 ); // cone leaves + p->vCoObjs = Vec_IntAlloc( 100 ); // cone roots + p->vCiVals = Vec_IntAlloc( 100 ); // cone leaf values + p->vCoVals = Vec_IntAlloc( 100 ); // cone root values + p->vNodes = Vec_IntAlloc( 100 ); // cone nodes + p->vUndo = Vec_IntAlloc( 100 ); // cone undos + p->vVisits = Vec_IntAlloc( 100 ); // intermediate + p->vCi2Rem = Vec_IntAlloc( 100 ); // CIs to be removed + p->vRes = Vec_IntAlloc( 100 ); // final result + p->vSuppLits= Vec_IntAlloc( 100 ); // support literals + p->pCubeJust= Pdr_SetAlloc( Saig_ManRegNum(pAig) ); + // additional AIG data-members + if ( pAig->pFanData == NULL ) + Aig_ManFanoutStart( pAig ); + if ( pAig->pTerSimData == NULL ) + pAig->pTerSimData = ABC_CALLOC( unsigned, 1 + (Aig_ManObjNumMax(pAig) / 16) ); + p->timeStart = clock(); + return p; +} + +/**Function************************************************************* + + Synopsis [Frees manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pdr_ManStop( Pdr_Man_t * p ) +{ + Pdr_Set_t * pCla; + sat_solver * pSat; + int i, k; + Aig_ManCleanMarkAB( p->pAig ); + if ( p->pPars->fVerbose ) + { + printf( "Block =%5d Oblig =%6d Clause =%6d Call =%6d (sat=%.1f%%) Start =%4d\n", + p->nBlocks, p->nObligs, p->nCubes, p->nCalls, 100.0 * p->nCallsS / p->nCalls, p->nStarts ); + ABC_PRTP( "SAT solving", p->tSat, p->tTotal ); + ABC_PRTP( " unsat ", p->tSatUnsat, p->tTotal ); + ABC_PRTP( " sat ", p->tSatSat, p->tTotal ); + ABC_PRTP( "Generalize ", p->tGeneral, p->tTotal ); + ABC_PRTP( "Push clause", p->tPush, p->tTotal ); + ABC_PRTP( "Ternary sim", p->tTsim, p->tTotal ); + ABC_PRTP( "Containment", p->tContain, p->tTotal ); + ABC_PRTP( "CNF compute", p->tCnf, p->tTotal ); + ABC_PRTP( "TOTAL ", p->tTotal, p->tTotal ); + } +// printf( "SS =%6d. SU =%6d. US =%6d. UU =%6d.\n", p->nCasesSS, p->nCasesSU, p->nCasesUS, p->nCasesUU ); + Vec_PtrForEachEntry( sat_solver *, p->vSolvers, pSat, i ) + sat_solver_delete( pSat ); + Vec_PtrFree( p->vSolvers ); + Vec_VecForEachEntry( Pdr_Set_t *, p->vClauses, pCla, i, k ) + Pdr_SetDeref( pCla ); + Vec_VecFree( p->vClauses ); + Pdr_QueueStop( p ); + ABC_FREE( p->pOrder ); + Vec_IntFree( p->vActVars ); + // static CNF + Cnf_DataFree( p->pCnf1 ); + Vec_IntFreeP( &p->vVar2Reg ); + // dynamic CNF + Cnf_DataFree( p->pCnf2 ); + if ( p->pvId2Vars ) + for ( i = 0; i < Aig_ManObjNumMax(p->pAig); i++ ) + Vec_IntFreeP( &p->pvId2Vars[i] ); + ABC_FREE( p->pvId2Vars ); + Vec_VecFreeP( (Vec_Vec_t **)&p->vVar2Ids ); + // internal use + Vec_IntFreeP( &p->vPrio ); // priority flops + Vec_IntFree( p->vLits ); // array of literals + Vec_IntFree( p->vCiObjs ); // cone leaves + Vec_IntFree( p->vCoObjs ); // cone roots + Vec_IntFree( p->vCiVals ); // cone leaf values + Vec_IntFree( p->vCoVals ); // cone root values + Vec_IntFree( p->vNodes ); // cone nodes + Vec_IntFree( p->vUndo ); // cone undos + Vec_IntFree( p->vVisits ); // intermediate + Vec_IntFree( p->vCi2Rem ); // CIs to be removed + Vec_IntFree( p->vRes ); // final result + Vec_IntFree( p->vSuppLits ); // support literals + ABC_FREE( p->pCubeJust ); + // additional AIG data-members + if ( p->pAig->pFanData != NULL ) + Aig_ManFanoutStop( p->pAig ); + if ( p->pAig->pTerSimData != NULL ) + ABC_FREE( p->pAig->pTerSimData ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Derives counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Pdr_ManDeriveCex( Pdr_Man_t * p ) +{ + Abc_Cex_t * pCex; + Pdr_Obl_t * pObl; + int i, f, Lit, nFrames = 0; + // count the number of frames + for ( pObl = p->pQueue; pObl; pObl = pObl->pNext ) + nFrames++; + // create the counter-example + pCex = Abc_CexAlloc( Aig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), nFrames ); + pCex->iPo = (p->pPars->iOutput==-1)? 0 : p->pPars->iOutput; + pCex->iFrame = nFrames-1; + for ( pObl = p->pQueue, f = 0; pObl; pObl = pObl->pNext, f++ ) + for ( i = pObl->pState->nLits; i < pObl->pState->nTotal; i++ ) + { + Lit = pObl->pState->Lits[i]; + if ( lit_sign(Lit) ) + continue; + assert( lit_var(Lit) < pCex->nPis ); + Abc_InfoSetBit( pCex->pData, pCex->nRegs + f * pCex->nPis + lit_var(Lit) ); + } + assert( f == nFrames ); + return pCex; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/pdr/pdrSat.c b/src/proof/pdr/pdrSat.c new file mode 100644 index 00000000..c191654a --- /dev/null +++ b/src/proof/pdr/pdrSat.c @@ -0,0 +1,373 @@ +/**CFile**************************************************************** + + FileName [pdrSat.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Property driven reachability.] + + Synopsis [SAT solver procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 20, 2010.] + + Revision [$Id: pdrSat.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "pdrInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates new SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +sat_solver * Pdr_ManCreateSolver( Pdr_Man_t * p, int k ) +{ + sat_solver * pSat; + assert( Vec_PtrSize(p->vSolvers) == k ); + assert( Vec_VecSize(p->vClauses) == k ); + assert( Vec_IntSize(p->vActVars) == k ); + // create new solver + pSat = sat_solver_new(); + pSat = Pdr_ManNewSolver( pSat, p, k, (int)(k == 0) ); + Vec_PtrPush( p->vSolvers, pSat ); + Vec_VecExpand( p->vClauses, k ); + Vec_IntPush( p->vActVars, 0 ); + // add property cone + Pdr_ObjSatVar( p, k, Aig_ManPo(p->pAig, (p->pPars->iOutput==-1)?0:p->pPars->iOutput ) ); + return pSat; +} + +/**Function************************************************************* + + Synopsis [Returns old or restarted solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +sat_solver * Pdr_ManFetchSolver( Pdr_Man_t * p, int k ) +{ + sat_solver * pSat; + Vec_Ptr_t * vArrayK; + Pdr_Set_t * pCube; + int i, j; + pSat = Pdr_ManSolver(p, k); + if ( Vec_IntEntry(p->vActVars, k) < p->pPars->nRecycle ) + return pSat; + assert( k < Vec_PtrSize(p->vSolvers) - 1 ); + p->nStarts++; +// sat_solver_delete( pSat ); +// pSat = sat_solver_new(); + sat_solver_rollback( pSat ); + // create new SAT solver + pSat = Pdr_ManNewSolver( pSat, p, k, (int)(k == 0) ); + // write new SAT solver + Vec_PtrWriteEntry( p->vSolvers, k, pSat ); + Vec_IntWriteEntry( p->vActVars, k, 0 ); + // set the property output + Pdr_ManSetPropertyOutput( p, k ); + // add the clauses + Vec_VecForEachLevelStart( p->vClauses, vArrayK, i, k ) + Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCube, j ) + Pdr_ManSolverAddClause( p, k, pCube ); + return pSat; +} + +/**Function************************************************************* + + Synopsis [Converts SAT variables into register IDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Pdr_ManLitsToCube( Pdr_Man_t * p, int k, int * pArray, int nArray ) +{ + int i, RegId; + Vec_IntClear( p->vLits ); + for ( i = 0; i < nArray; i++ ) + { + RegId = Pdr_ObjRegNum( p, k, lit_var(pArray[i]) ); + if ( RegId == -1 ) + continue; + assert( RegId >= 0 && RegId < Aig_ManRegNum(p->pAig) ); + Vec_IntPush( p->vLits, toLitCond(RegId, !lit_sign(pArray[i])) ); + } + assert( Vec_IntSize(p->vLits) >= 0 && Vec_IntSize(p->vLits) <= nArray ); + return p->vLits; +} + +/**Function************************************************************* + + Synopsis [Converts the cube in terms of RO numbers into array of CNF literals.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Pdr_ManCubeToLits( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, int fCompl, int fNext ) +{ + Aig_Obj_t * pObj; + int i, iVar, iVarMax = 0; + int clk = clock(); + Vec_IntClear( p->vLits ); + for ( i = 0; i < pCube->nLits; i++ ) + { + if ( pCube->Lits[i] == -1 ) + continue; + if ( fNext ) + pObj = Saig_ManLi( p->pAig, lit_var(pCube->Lits[i]) ); + else + pObj = Saig_ManLo( p->pAig, lit_var(pCube->Lits[i]) ); + iVar = Pdr_ObjSatVar( p, k, pObj ); assert( iVar >= 0 ); + iVarMax = Abc_MaxInt( iVarMax, iVar ); + Vec_IntPush( p->vLits, toLitCond( iVar, fCompl ^ lit_sign(pCube->Lits[i]) ) ); + } +// sat_solver_setnvars( Pdr_ManSolver(p, k), iVarMax + 1 ); + p->tCnf += clock() - clk; + return p->vLits; +} + +/**Function************************************************************* + + Synopsis [Sets the property output to 0 (sat) forever.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pdr_ManSetPropertyOutput( Pdr_Man_t * p, int k ) +{ + sat_solver * pSat; + int Lit, RetValue; + pSat = Pdr_ManSolver(p, k); + Lit = toLitCond( Pdr_ObjSatVar(p, k, Aig_ManPo(p->pAig, (p->pPars->iOutput==-1)?0:p->pPars->iOutput)), 1 ); // neg literal + RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 ); + assert( RetValue == 1 ); + sat_solver_compress( pSat ); +} + +/**Function************************************************************* + + Synopsis [Adds one clause in terms of ROs to the k-th SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pdr_ManSolverAddClause( Pdr_Man_t * p, int k, Pdr_Set_t * pCube ) +{ + sat_solver * pSat; + Vec_Int_t * vLits; + int RetValue; + pSat = Pdr_ManSolver(p, k); + vLits = Pdr_ManCubeToLits( p, k, pCube, 1, 0 ); + RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ); + assert( RetValue == 1 ); + sat_solver_compress( pSat ); +} + +/**Function************************************************************* + + Synopsis [Collects values of the RO/RI variables in k-th SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pdr_ManCollectValues( Pdr_Man_t * p, int k, Vec_Int_t * vObjIds, Vec_Int_t * vValues ) +{ + sat_solver * pSat; + Aig_Obj_t * pObj; + int iVar, i; + Vec_IntClear( vValues ); + pSat = Pdr_ManSolver(p, k); + Aig_ManForEachObjVec( vObjIds, p->pAig, pObj, i ) + { + iVar = Pdr_ObjSatVar( p, k, pObj ); assert( iVar >= 0 ); + Vec_IntPush( vValues, sat_solver_var_value(pSat, iVar) ); + } +} + +/**Function************************************************************* + + Synopsis [Checks if the cube holds (UNSAT) in the given timeframe.] + + Description [Return 1/0 if cube or property are proved to hold/fail + in k-th timeframe. Returns the predecessor bad state in ppPred.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pdr_ManCheckCubeCs( Pdr_Man_t * p, int k, Pdr_Set_t * pCube ) +{ + sat_solver * pSat; + Vec_Int_t * vLits; + int RetValue; + pSat = Pdr_ManFetchSolver( p, k ); + vLits = Pdr_ManCubeToLits( p, k, pCube, 0, 0 ); + RetValue = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), 0, 0, 0, 0 ); + if ( RetValue == l_Undef ) + return -1; + return (RetValue == l_False); +} + +/**Function************************************************************* + + Synopsis [Checks if the cube holds (UNSAT) in the given timeframe.] + + Description [Return 1/0 if cube or property are proved to hold/fail + in k-th timeframe. Returns the predecessor bad state in ppPred.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pdr_ManCheckCube( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, Pdr_Set_t ** ppPred, int nConfLimit ) +{ + int fUseLit = 1; + int fLitUsed = 0; + sat_solver * pSat; + Vec_Int_t * vLits; + int Lit, RetValue, clk; + p->nCalls++; + pSat = Pdr_ManFetchSolver( p, k ); + if ( pCube == NULL ) // solve the property + { + clk = clock(); + Lit = toLit( Pdr_ObjSatVar(p, k, Aig_ManPo(p->pAig, (p->pPars->iOutput==-1)?0:p->pPars->iOutput)) ); // pos literal (property fails) + RetValue = sat_solver_solve( pSat, &Lit, &Lit + 1, nConfLimit, 0, 0, 0 ); + if ( RetValue == l_Undef ) + return -1; + } + else // check relative containment in terms of next states + { + if ( fUseLit ) + { + fLitUsed = 1; + Vec_IntAddToEntry( p->vActVars, k, 1 ); + // add the cube in terms of current state variables + vLits = Pdr_ManCubeToLits( p, k, pCube, 1, 0 ); + // add activation literal + Lit = toLit( Pdr_ManFreeVar(p, k) ); + // add activation literal + Vec_IntPush( vLits, Lit ); + RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ); + assert( RetValue == 1 ); + sat_solver_compress( pSat ); + // create assumptions + vLits = Pdr_ManCubeToLits( p, k, pCube, 0, 1 ); + // add activation literal + Vec_IntPush( vLits, lit_neg(Lit) ); + } + else + vLits = Pdr_ManCubeToLits( p, k, pCube, 0, 1 ); + + // solve + clk = clock(); + RetValue = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), nConfLimit, 0, 0, 0 ); + if ( RetValue == l_Undef ) + return -1; +/* + if ( RetValue == l_True ) + { + int RetValue2 = Pdr_ManCubeJust( p, k, pCube ); + if ( RetValue2 ) + p->nCasesSS++; + else + p->nCasesSU++; + } + else + { + int RetValue2 = Pdr_ManCubeJust( p, k, pCube ); + if ( RetValue2 ) + p->nCasesUS++; + else + p->nCasesUU++; + } +*/ + } + clk = clock() - clk; + p->tSat += clk; + assert( RetValue != l_Undef ); + if ( RetValue == l_False ) + { + p->tSatUnsat += clk; + p->nCallsU++; + if ( ppPred ) + *ppPred = NULL; + RetValue = 1; + } + else // if ( RetValue == l_True ) + { + p->tSatSat += clk; + p->nCallsS++; + if ( ppPred ) + *ppPred = Pdr_ManTernarySim( p, k, pCube ); + RetValue = 0; + } + +/* // for some reason, it does not work... + if ( fLitUsed ) + { + int RetValue; + Lit = lit_neg(Lit); + RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 ); + assert( RetValue == 1 ); + sat_solver_compress( pSat ); + } +*/ + return RetValue; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/pdr/pdrTsim.c b/src/proof/pdr/pdrTsim.c new file mode 100644 index 00000000..6fec1605 --- /dev/null +++ b/src/proof/pdr/pdrTsim.c @@ -0,0 +1,450 @@ +/**CFile**************************************************************** + + FileName [pdrTsim.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Property driven reachability.] + + Synopsis [Ternary simulation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 20, 2010.] + + Revision [$Id: pdrTsim.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "pdrInt.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define PDR_ZER 1 +#define PDR_ONE 2 +#define PDR_UND 3 + +static inline int Pdr_ManSimInfoNot( int Value ) +{ + if ( Value == PDR_ZER ) + return PDR_ONE; + if ( Value == PDR_ONE ) + return PDR_ZER; + return PDR_UND; +} + +static inline int Pdr_ManSimInfoAnd( int Value0, int Value1 ) +{ + if ( Value0 == PDR_ZER || Value1 == PDR_ZER ) + return PDR_ZER; + if ( Value0 == PDR_ONE && Value1 == PDR_ONE ) + return PDR_ONE; + return PDR_UND; +} + +static inline int Pdr_ManSimInfoGet( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + return 3 & (p->pTerSimData[Aig_ObjId(pObj) >> 4] >> ((Aig_ObjId(pObj) & 15) << 1)); +} + +static inline void Pdr_ManSimInfoSet( Aig_Man_t * p, Aig_Obj_t * pObj, int Value ) +{ + assert( Value >= PDR_ZER && Value <= PDR_UND ); + Value ^= Pdr_ManSimInfoGet( p, pObj ); + p->pTerSimData[Aig_ObjId(pObj) >> 4] ^= (Value << ((Aig_ObjId(pObj) & 15) << 1)); +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Marks the TFI cone and collects CIs and nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pdr_ManCollectCone_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vCiObjs, Vec_Int_t * vNodes ) +{ + assert( !Aig_IsComplement(pObj) ); + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + return; + Aig_ObjSetTravIdCurrent(pAig, pObj); + if ( Aig_ObjIsPi(pObj) ) + { + Vec_IntPush( vCiObjs, Aig_ObjId(pObj) ); + return; + } + Pdr_ManCollectCone_rec( pAig, Aig_ObjFanin0(pObj), vCiObjs, vNodes ); + if ( Aig_ObjIsPo(pObj) ) + return; + Pdr_ManCollectCone_rec( pAig, Aig_ObjFanin1(pObj), vCiObjs, vNodes ); + Vec_IntPush( vNodes, Aig_ObjId(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Marks the TFI cone and collects CIs and nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pdr_ManCollectCone( Aig_Man_t * pAig, Vec_Int_t * vCoObjs, Vec_Int_t * vCiObjs, Vec_Int_t * vNodes ) +{ + Aig_Obj_t * pObj; + int i; + Vec_IntClear( vCiObjs ); + Vec_IntClear( vNodes ); + Aig_ManIncrementTravId( pAig ); + Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) ); + Aig_ManForEachObjVec( vCoObjs, pAig, pObj, i ) + Pdr_ManCollectCone_rec( pAig, pObj, vCiObjs, vNodes ); +} + +/**Function************************************************************* + + Synopsis [Performs ternary simulation for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pdr_ManExtendOneEval( Aig_Man_t * pAig, Aig_Obj_t * pObj ) +{ + int Value0, Value1, Value; + Value0 = Pdr_ManSimInfoGet( pAig, Aig_ObjFanin0(pObj) ); + if ( Aig_ObjFaninC0(pObj) ) + Value0 = Pdr_ManSimInfoNot( Value0 ); + if ( Aig_ObjIsPo(pObj) ) + { + Pdr_ManSimInfoSet( pAig, pObj, Value0 ); + return Value0; + } + assert( Aig_ObjIsNode(pObj) ); + Value1 = Pdr_ManSimInfoGet( pAig, Aig_ObjFanin1(pObj) ); + if ( Aig_ObjFaninC1(pObj) ) + Value1 = Pdr_ManSimInfoNot( Value1 ); + Value = Pdr_ManSimInfoAnd( Value0, Value1 ); + Pdr_ManSimInfoSet( pAig, pObj, Value ); + return Value; +} + +/**Function************************************************************* + + Synopsis [Performs ternary simulation for one design.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pdr_ManSimDataInit( Aig_Man_t * pAig, + Vec_Int_t * vCiObjs, Vec_Int_t * vCiVals, Vec_Int_t * vNodes, + Vec_Int_t * vCoObjs, Vec_Int_t * vCoVals, Vec_Int_t * vCi2Rem ) +{ + Aig_Obj_t * pObj; + int i; + // set the CI values + Pdr_ManSimInfoSet( pAig, Aig_ManConst1(pAig), PDR_ONE ); + Aig_ManForEachObjVec( vCiObjs, pAig, pObj, i ) + Pdr_ManSimInfoSet( pAig, pObj, (Vec_IntEntry(vCiVals, i)?PDR_ONE:PDR_ZER) ); + // set the FOs to remove + if ( vCi2Rem != NULL ) + Aig_ManForEachObjVec( vCi2Rem, pAig, pObj, i ) + Pdr_ManSimInfoSet( pAig, pObj, PDR_UND ); + // perform ternary simulation + Aig_ManForEachObjVec( vNodes, pAig, pObj, i ) + Pdr_ManExtendOneEval( pAig, pObj ); + // transfer results to the output + Aig_ManForEachObjVec( vCoObjs, pAig, pObj, i ) + Pdr_ManExtendOneEval( pAig, pObj ); + // check the results + Aig_ManForEachObjVec( vCoObjs, pAig, pObj, i ) + if ( Pdr_ManSimInfoGet( pAig, pObj ) != (Vec_IntEntry(vCoVals, i)?PDR_ONE:PDR_ZER) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Tries to assign ternary value to one of the CIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pdr_ManExtendOne( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vUndo, Vec_Int_t * vVis ) +{ + Aig_Obj_t * pFanout; + int i, k, iFanout, Value, Value2; + assert( Saig_ObjIsLo(pAig, pObj) ); + assert( Aig_ObjIsTravIdCurrent(pAig, pObj) ); + // save original value + Value = Pdr_ManSimInfoGet( pAig, pObj ); + assert( Value == PDR_ZER || Value == PDR_ONE ); + Vec_IntPush( vUndo, Aig_ObjId(pObj) ); + Vec_IntPush( vUndo, Value ); + // update original value + Pdr_ManSimInfoSet( pAig, pObj, PDR_UND ); + // traverse + Vec_IntClear( vVis ); + Vec_IntPush( vVis, Aig_ObjId(pObj) ); + Aig_ManForEachObjVec( vVis, pAig, pObj, i ) + { + Aig_ObjForEachFanout( pAig, pObj, pFanout, iFanout, k ) + { + if ( !Aig_ObjIsTravIdCurrent(pAig, pFanout) ) + continue; + assert( Aig_ObjId(pObj) < Aig_ObjId(pFanout) ); + Value = Pdr_ManSimInfoGet( pAig, pFanout ); + if ( Value == PDR_UND ) + continue; + Value2 = Pdr_ManExtendOneEval( pAig, pFanout ); + if ( Value2 == Value ) + continue; + assert( Value2 == PDR_UND ); + Vec_IntPush( vUndo, Aig_ObjId(pFanout) ); + Vec_IntPush( vUndo, Value ); + if ( Aig_ObjIsPo(pFanout) ) + return 0; + assert( Aig_ObjIsNode(pFanout) ); + Vec_IntPushOrder( vVis, Aig_ObjId(pFanout) ); + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Undoes the partial results of ternary simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pdr_ManExtendUndo( Aig_Man_t * pAig, Vec_Int_t * vUndo ) +{ + Aig_Obj_t * pObj; + int i, Value; + Aig_ManForEachObjVec( vUndo, pAig, pObj, i ) + { + Value = Vec_IntEntry(vUndo, ++i); + assert( Pdr_ManSimInfoGet(pAig, pObj) == PDR_UND ); + Pdr_ManSimInfoSet( pAig, pObj, Value ); + } +} + +/**Function************************************************************* + + Synopsis [Derives the resulting cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pdr_ManDeriveResult( Aig_Man_t * pAig, Vec_Int_t * vCiObjs, Vec_Int_t * vCiVals, Vec_Int_t * vCi2Rem, Vec_Int_t * vRes, Vec_Int_t * vPiLits ) +{ + Aig_Obj_t * pObj; + int i, Lit; + // mark removed flop outputs + Aig_ManIncrementTravId( pAig ); + Aig_ManForEachObjVec( vCi2Rem, pAig, pObj, i ) + { + assert( Saig_ObjIsLo( pAig, pObj ) ); + Aig_ObjSetTravIdCurrent(pAig, pObj); + } + // collect flop outputs that are not marked + Vec_IntClear( vRes ); + Vec_IntClear( vPiLits ); + Aig_ManForEachObjVec( vCiObjs, pAig, pObj, i ) + { + if ( Saig_ObjIsPi(pAig, pObj) ) + { + Lit = toLitCond( Aig_ObjPioNum(pObj), (Vec_IntEntry(vCiVals, i) == 0) ); + Vec_IntPush( vPiLits, Lit ); + continue; + } + assert( Saig_ObjIsLo(pAig, pObj) ); + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + continue; + Lit = toLitCond( Aig_ObjPioNum(pObj) - Saig_ManPiNum(pAig), (Vec_IntEntry(vCiVals, i) == 0) ); + Vec_IntPush( vRes, Lit ); + } + if ( Vec_IntSize(vRes) == 0 ) + Vec_IntPush(vRes, 0); +} + +/**Function************************************************************* + + Synopsis [Derives the resulting cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pdr_ManPrintCex( Aig_Man_t * pAig, Vec_Int_t * vCiObjs, Vec_Int_t * vCiVals, Vec_Int_t * vCi2Rem ) +{ + Aig_Obj_t * pObj; + int i; + char * pBuff = ABC_ALLOC( char, Aig_ManPiNum(pAig)+1 ); + for ( i = 0; i < Aig_ManPiNum(pAig); i++ ) + pBuff[i] = '-'; + pBuff[i] = 0; + Aig_ManForEachObjVec( vCiObjs, pAig, pObj, i ) + pBuff[Aig_ObjPioNum(pObj)] = (Vec_IntEntry(vCiVals, i)? '1':'0'); + if ( vCi2Rem ) + Aig_ManForEachObjVec( vCi2Rem, pAig, pObj, i ) + pBuff[Aig_ObjPioNum(pObj)] = 'x'; + printf( "%s\n", pBuff ); + ABC_FREE( pBuff ); +} + +/**Function************************************************************* + + Synopsis [Shrinks values using ternary simulation.] + + Description [The cube contains the set of flop index literals which, + when converted into a clause and applied to the combinational outputs, + led to a satisfiable SAT run in frame k (values stored in the SAT solver). + If the cube is NULL, it is assumed that the first property output was + asserted and failed. + The resulting array is a set of flop index literals that asserts the COs. + Priority contains 0 for i-th entry if the i-th FF is desirable to remove.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Pdr_Set_t * Pdr_ManTernarySim( Pdr_Man_t * p, int k, Pdr_Set_t * pCube ) +{ + Vec_Int_t * vPrio = p->vPrio; // priority flops (flop indices) + Vec_Int_t * vPiLits = p->vLits; // array of literals (0/1 PI values) + Vec_Int_t * vCiObjs = p->vCiObjs; // cone leaves (CI obj IDs) + Vec_Int_t * vCoObjs = p->vCoObjs; // cone roots (CO obj IDs) + Vec_Int_t * vCiVals = p->vCiVals; // cone leaf values (0/1 CI values) + Vec_Int_t * vCoVals = p->vCoVals; // cone root values (0/1 CO values) + Vec_Int_t * vNodes = p->vNodes; // cone nodes (node obj IDs) + Vec_Int_t * vUndo = p->vUndo; // cone undos (node obj IDs) + Vec_Int_t * vVisits = p->vVisits; // intermediate (obj IDs) + Vec_Int_t * vCi2Rem = p->vCi2Rem; // CIs to be removed (CI obj IDs) + Vec_Int_t * vRes = p->vRes; // final result (flop literals) + Aig_Obj_t * pObj; + int i, Entry, RetValue; + int clk = clock(); + + // collect CO objects + Vec_IntClear( vCoObjs ); + if ( pCube == NULL ) // the target is the property output + Vec_IntPush( vCoObjs, Aig_ObjId(Aig_ManPo(p->pAig, (p->pPars->iOutput==-1)?0:p->pPars->iOutput)) ); + else // the target is the cube + { + for ( i = 0; i < pCube->nLits; i++ ) + { + if ( pCube->Lits[i] == -1 ) + continue; + pObj = Saig_ManLi(p->pAig, (pCube->Lits[i] >> 1)); + Vec_IntPush( vCoObjs, Aig_ObjId(pObj) ); + } + } +if ( p->pPars->fVeryVerbose ) +{ +printf( "Trying to justify cube " ); +if ( pCube ) + Pdr_SetPrint( stdout, pCube, Aig_ManRegNum(p->pAig), NULL ); +else + printf( "" ); +printf( " in frame %d.\n", k ); +} + + // collect CI objects + Pdr_ManCollectCone( p->pAig, vCoObjs, vCiObjs, vNodes ); + // collect values + Pdr_ManCollectValues( p, k, vCiObjs, vCiVals ); + Pdr_ManCollectValues( p, k, vCoObjs, vCoVals ); + // simulate for the first time +if ( p->pPars->fVeryVerbose ) +Pdr_ManPrintCex( p->pAig, vCiObjs, vCiVals, NULL ); + RetValue = Pdr_ManSimDataInit( p->pAig, vCiObjs, vCiVals, vNodes, vCoObjs, vCoVals, NULL ); + assert( RetValue ); + + // try removing high-priority flops + Vec_IntClear( vCi2Rem ); + Aig_ManForEachObjVec( vCiObjs, p->pAig, pObj, i ) + { + if ( !Saig_ObjIsLo( p->pAig, pObj ) ) + continue; + Entry = Aig_ObjPioNum(pObj) - Saig_ManPiNum(p->pAig); + if ( vPrio != NULL && Vec_IntEntry( vPrio, Entry ) != 0 ) + continue; + Vec_IntClear( vUndo ); + if ( Pdr_ManExtendOne( p->pAig, pObj, vUndo, vVisits ) ) + Vec_IntPush( vCi2Rem, Aig_ObjId(pObj) ); + else + Pdr_ManExtendUndo( p->pAig, vUndo ); + } + // try removing low-priority flops + Aig_ManForEachObjVec( vCiObjs, p->pAig, pObj, i ) + { + if ( !Saig_ObjIsLo( p->pAig, pObj ) ) + continue; + Entry = Aig_ObjPioNum(pObj) - Saig_ManPiNum(p->pAig); + if ( vPrio == NULL || Vec_IntEntry( vPrio, Entry ) == 0 ) + continue; + Vec_IntClear( vUndo ); + if ( Pdr_ManExtendOne( p->pAig, pObj, vUndo, vVisits ) ) + Vec_IntPush( vCi2Rem, Aig_ObjId(pObj) ); + else + Pdr_ManExtendUndo( p->pAig, vUndo ); + } +if ( p->pPars->fVeryVerbose ) +Pdr_ManPrintCex( p->pAig, vCiObjs, vCiVals, vCi2Rem ); + RetValue = Pdr_ManSimDataInit( p->pAig, vCiObjs, vCiVals, vNodes, vCoObjs, vCoVals, vCi2Rem ); + assert( RetValue ); + + // derive the set of resulting registers + Pdr_ManDeriveResult( p->pAig, vCiObjs, vCiVals, vCi2Rem, vRes, vPiLits ); + assert( Vec_IntSize(vRes) > 0 ); + p->tTsim += clock() - clk; + return Pdr_SetCreate( vRes, vPiLits ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/pdr/pdrUtil.c b/src/proof/pdr/pdrUtil.c new file mode 100644 index 00000000..17383425 --- /dev/null +++ b/src/proof/pdr/pdrUtil.c @@ -0,0 +1,719 @@ +/**CFile**************************************************************** + + FileName [pdrUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Property driven reachability.] + + Synopsis [Various utilities.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 20, 2010.] + + Revision [$Id: pdrUtil.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "pdrInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Pdr_Set_t * Pdr_SetAlloc( int nSize ) +{ + Pdr_Set_t * p; + assert( nSize >= 0 && nSize < (1<<30) ); + p = (Pdr_Set_t *)ABC_CALLOC( char, sizeof(Pdr_Set_t) + nSize * sizeof(int) ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Pdr_Set_t * Pdr_SetCreate( Vec_Int_t * vLits, Vec_Int_t * vPiLits ) +{ + Pdr_Set_t * p; + int i; + assert( Vec_IntSize(vLits) + Vec_IntSize(vPiLits) < (1<<30) ); + p = (Pdr_Set_t *)ABC_ALLOC( char, sizeof(Pdr_Set_t) + (Vec_IntSize(vLits) + Vec_IntSize(vPiLits)) * sizeof(int) ); + p->nLits = Vec_IntSize(vLits); + p->nTotal = Vec_IntSize(vLits) + Vec_IntSize(vPiLits); + p->nRefs = 1; + p->Sign = 0; + for ( i = 0; i < p->nLits; i++ ) + { + p->Lits[i] = Vec_IntEntry(vLits, i); + p->Sign |= ((word)1 << (p->Lits[i] % 63)); + } + Vec_IntSelectSort( p->Lits, p->nLits ); +/* + for ( i = 0; i < p->nLits; i++ ) + printf( "%d ", p->Lits[i] ); + printf( "\n" ); +*/ + // remember PI literals + for ( i = p->nLits; i < p->nTotal; i++ ) + p->Lits[i] = Vec_IntEntry(vPiLits, i-p->nLits); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Pdr_Set_t * Pdr_SetCreateFrom( Pdr_Set_t * pSet, int iRemove ) +{ + Pdr_Set_t * p; + int i, k = 0; + assert( iRemove >= 0 && iRemove < pSet->nLits ); + p = (Pdr_Set_t *)ABC_ALLOC( char, sizeof(Pdr_Set_t) + (pSet->nTotal - 1) * sizeof(int) ); + p->nLits = pSet->nLits - 1; + p->nTotal = pSet->nTotal - 1; + p->nRefs = 1; + p->Sign = 0; + for ( i = 0; i < pSet->nTotal; i++ ) + { + if ( i == iRemove ) + continue; + p->Lits[k++] = pSet->Lits[i]; + if ( i >= pSet->nLits ) + continue; + p->Sign |= ((word)1 << (pSet->Lits[i] % 63)); + } + assert( k == p->nTotal ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Pdr_Set_t * Pdr_SetCreateSubset( Pdr_Set_t * pSet, int * pLits, int nLits ) +{ + Pdr_Set_t * p; + int i, k = 0; + assert( nLits >= 0 && nLits <= pSet->nLits ); + p = (Pdr_Set_t *)ABC_ALLOC( char, sizeof(Pdr_Set_t) + (nLits + pSet->nTotal - pSet->nLits) * sizeof(int) ); + p->nLits = nLits; + p->nTotal = nLits + pSet->nTotal - pSet->nLits; + p->nRefs = 1; + p->Sign = 0; + for ( i = 0; i < nLits; i++ ) + { + assert( pLits[i] >= 0 ); + p->Lits[k++] = pLits[i]; + p->Sign |= ((word)1 << (pLits[i] % 63)); + } + Vec_IntSelectSort( p->Lits, p->nLits ); + for ( i = pSet->nLits; i < pSet->nTotal; i++ ) + p->Lits[k++] = pSet->Lits[i]; + assert( k == p->nTotal ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Pdr_Set_t * Pdr_SetDup( Pdr_Set_t * pSet ) +{ + Pdr_Set_t * p; + int i; + p = (Pdr_Set_t *)ABC_ALLOC( char, sizeof(Pdr_Set_t) + pSet->nTotal * sizeof(int) ); + p->nLits = pSet->nLits; + p->nTotal = pSet->nTotal; + p->nRefs = 1; + p->Sign = pSet->Sign; + for ( i = 0; i < pSet->nTotal; i++ ) + p->Lits[i] = pSet->Lits[i]; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Pdr_Set_t * Pdr_SetRef( Pdr_Set_t * p ) +{ + p->nRefs++; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pdr_SetDeref( Pdr_Set_t * p ) +{ + if ( --p->nRefs == 0 ) + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pdr_SetPrint( FILE * pFile, Pdr_Set_t * p, int nRegs, Vec_Int_t * vFlopCounts ) +{ + char * pBuff; + int i, k, Entry; + pBuff = ABC_ALLOC( char, nRegs + 1 ); + for ( i = 0; i < nRegs; i++ ) + pBuff[i] = '-'; + pBuff[i] = 0; + for ( i = 0; i < p->nLits; i++ ) + { + if ( p->Lits[i] == -1 ) + continue; + pBuff[lit_var(p->Lits[i])] = (lit_sign(p->Lits[i])? '0':'1'); + } + if ( vFlopCounts ) + { + // skip some literals + k = 0; + Vec_IntForEachEntry( vFlopCounts, Entry, i ) + if ( Entry ) + pBuff[k++] = pBuff[i]; + pBuff[k] = 0; + } + fprintf( pFile, "%s", pBuff ); + ABC_FREE( pBuff ); +} + +/**Function************************************************************* + + Synopsis [Return 1 if pOld set-theoretically contains pNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pdr_SetContains( Pdr_Set_t * pOld, Pdr_Set_t * pNew ) +{ + int * pOldInt, * pNewInt; + assert( pOld->nLits > 0 ); + assert( pNew->nLits > 0 ); + if ( pOld->nLits < pNew->nLits ) + return 0; + if ( (pOld->Sign & pNew->Sign) != pNew->Sign ) + return 0; + pOldInt = pOld->Lits + pOld->nLits - 1; + pNewInt = pNew->Lits + pNew->nLits - 1; + while ( pNew->Lits <= pNewInt ) + { + if ( pOld->Lits > pOldInt ) + return 0; + assert( *pNewInt != -1 ); + assert( *pOldInt != -1 ); + if ( *pNewInt == *pOldInt ) + pNewInt--, pOldInt--; + else if ( *pNewInt < *pOldInt ) + pOldInt--; + else + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Return 1 if pOld set-theoretically contains pNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pdr_SetContainsSimple( Pdr_Set_t * pOld, Pdr_Set_t * pNew ) +{ + int * pOldInt, * pNewInt; + assert( pOld->nLits > 0 ); + assert( pNew->nLits > 0 ); + pOldInt = pOld->Lits + pOld->nLits - 1; + pNewInt = pNew->Lits + pNew->nLits - 1; + while ( pNew->Lits <= pNewInt ) + { + assert( *pOldInt != -1 ); + if ( *pNewInt == -1 ) + { + pNewInt--; + continue; + } + if ( pOld->Lits > pOldInt ) + return 0; + assert( *pNewInt != -1 ); + assert( *pOldInt != -1 ); + if ( *pNewInt == *pOldInt ) + pNewInt--, pOldInt--; + else if ( *pNewInt < *pOldInt ) + pOldInt--; + else + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Return 1 if the state cube contains init state (000...0).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pdr_SetIsInit( Pdr_Set_t * pCube, int iRemove ) +{ + int i; + for ( i = 0; i < pCube->nLits; i++ ) + { + assert( pCube->Lits[i] != -1 ); + if ( i == iRemove ) + continue; + if ( lit_sign( pCube->Lits[i] ) == 0 ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pdr_SetCompare( Pdr_Set_t ** pp1, Pdr_Set_t ** pp2 ) +{ + Pdr_Set_t * p1 = *pp1; + Pdr_Set_t * p2 = *pp2; + int i; + for ( i = 0; i < p1->nLits && i < p2->nLits; i++ ) + { + if ( p1->Lits[i] > p2->Lits[i] ) + return -1; + if ( p1->Lits[i] < p2->Lits[i] ) + return 1; + } + if ( i == p1->nLits && i < p2->nLits ) + return -1; + if ( i < p1->nLits && i == p2->nLits ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Pdr_Obl_t * Pdr_OblStart( int k, int prio, Pdr_Set_t * pState, Pdr_Obl_t * pNext ) +{ + Pdr_Obl_t * p; + p = ABC_ALLOC( Pdr_Obl_t, 1 ); + p->iFrame = k; + p->prio = prio; + p->nRefs = 1; + p->pState = pState; + p->pNext = pNext; + p->pLink = NULL; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Pdr_Obl_t * Pdr_OblRef( Pdr_Obl_t * p ) +{ + p->nRefs++; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pdr_OblDeref( Pdr_Obl_t * p ) +{ + if ( --p->nRefs == 0 ) + { + if ( p->pNext ) + Pdr_OblDeref( p->pNext ); + Pdr_SetDeref( p->pState ); + ABC_FREE( p ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pdr_QueueIsEmpty( Pdr_Man_t * p ) +{ + return p->pQueue == NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Pdr_Obl_t * Pdr_QueueHead( Pdr_Man_t * p ) +{ + return p->pQueue; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Pdr_Obl_t * Pdr_QueuePop( Pdr_Man_t * p ) +{ + Pdr_Obl_t * pRes = p->pQueue; + if ( p->pQueue == NULL ) + return NULL; + p->pQueue = p->pQueue->pLink; + Pdr_OblDeref( pRes ); + return pRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pdr_QueuePush( Pdr_Man_t * p, Pdr_Obl_t * pObl ) +{ + Pdr_Obl_t * pTemp, ** ppPrev; + p->nObligs++; + Pdr_OblRef( pObl ); + if ( p->pQueue == NULL ) + { + p->pQueue = pObl; + return; + } + for ( ppPrev = &p->pQueue, pTemp = p->pQueue; pTemp; ppPrev = &pTemp->pLink, pTemp = pTemp->pLink ) + if ( pTemp->iFrame > pObl->iFrame || (pTemp->iFrame == pObl->iFrame && pTemp->prio > pObl->prio) ) + break; + *ppPrev = pObl; + pObl->pLink = pTemp; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pdr_QueuePrint( Pdr_Man_t * p ) +{ + Pdr_Obl_t * pObl; + for ( pObl = p->pQueue; pObl; pObl = pObl->pLink ) + printf( "Frame = %2d. Prio = %8d.\n", pObl->iFrame, pObl->prio ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pdr_QueueStop( Pdr_Man_t * p ) +{ + Pdr_Obl_t * pObl; + while ( !Pdr_QueueIsEmpty(p) ) + { + pObl = Pdr_QueuePop(p); + Pdr_OblDeref( pObl ); + } + p->pQueue = NULL; +} + + +#define PDR_VAL0 1 +#define PDR_VAL1 2 +#define PDR_VALX 3 + +/**Function************************************************************* + + Synopsis [Returns value (0 or 1) or X if unassigned.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Pdr_ObjSatValue( Aig_Man_t * pAig, Aig_Obj_t * pNode, int fCompl ) +{ + if ( Aig_ObjIsTravIdCurrent(pAig, pNode) ) + return (pNode->fMarkA ^ fCompl) ? PDR_VAL1 : PDR_VAL0; + return PDR_VALX; +} + +/**Function************************************************************* + + Synopsis [Recursively searched for a satisfying assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pdr_NtkFindSatAssign_rec( Aig_Man_t * pAig, Aig_Obj_t * pNode, int Value, Pdr_Set_t * pCube, int Heur ) +{ + int Value0, Value1; + if ( Aig_ObjIsConst1(pNode) ) + return 1; + if ( Aig_ObjIsTravIdCurrent(pAig, pNode) ) + return ((int)pNode->fMarkA == Value); + Aig_ObjSetTravIdCurrent(pAig, pNode); + pNode->fMarkA = Value; + if ( Aig_ObjIsPi(pNode) ) + { +// if ( vSuppLits ) +// Vec_IntPush( vSuppLits, Abc_Var2Lit( Aig_ObjPioNum(pNode), !Value ) ); + if ( Saig_ObjIsLo(pAig, pNode) ) + { +// pCube->Lits[pCube->nLits++] = Abc_Var2Lit( Aig_ObjPioNum(pNode) - Saig_ManPiNum(pAig), !Value ); + pCube->Lits[pCube->nLits++] = Abc_Var2Lit( Aig_ObjPioNum(pNode) - Saig_ManPiNum(pAig), Value ); + pCube->Sign |= ((word)1 << (pCube->Lits[pCube->nLits-1] % 63)); + } + return 1; + } + assert( Aig_ObjIsNode(pNode) ); + // propagation + if ( Value ) + { + if ( !Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin0(pNode), !Aig_ObjFaninC0(pNode), pCube, Heur) ) + return 0; + return Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin1(pNode), !Aig_ObjFaninC1(pNode), pCube, Heur); + } + // justification + Value0 = Pdr_ObjSatValue( pAig, Aig_ObjFanin0(pNode), Aig_ObjFaninC0(pNode) ); + if ( Value0 == PDR_VAL0 ) + return 1; + Value1 = Pdr_ObjSatValue( pAig, Aig_ObjFanin1(pNode), Aig_ObjFaninC1(pNode) ); + if ( Value1 == PDR_VAL0 ) + return 1; + if ( Value0 == PDR_VAL1 && Value1 == PDR_VAL1 ) + return 0; + if ( Value0 == PDR_VAL1 ) + return Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin1(pNode), Aig_ObjFaninC1(pNode), pCube, Heur); + if ( Value1 == PDR_VAL1 ) + return Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin0(pNode), Aig_ObjFaninC0(pNode), pCube, Heur); + assert( Value0 == PDR_VALX && Value1 == PDR_VALX ); + // decision making +// if ( rand() % 10 == Heur ) + if ( Aig_ObjId(pNode) % 4 == Heur ) + return Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin1(pNode), Aig_ObjFaninC1(pNode), pCube, Heur); + else + return Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin0(pNode), Aig_ObjFaninC0(pNode), pCube, Heur); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if SAT assignment is found; 0 otherwise.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pdr_ManCubeJust( Pdr_Man_t * p, int k, Pdr_Set_t * pCube ) +{ + Aig_Obj_t * pNode; + int i, v, fCompl; +// return 0; + for ( i = 0; i < 4; i++ ) + { + // derive new assignment + p->pCubeJust->nLits = 0; + p->pCubeJust->Sign = 0; + Aig_ManIncrementTravId( p->pAig ); + for ( v = 0; v < pCube->nLits; v++ ) + { + if ( pCube->Lits[v] == -1 ) + continue; + pNode = Saig_ManLi( p->pAig, lit_var(pCube->Lits[v]) ); + fCompl = lit_sign(pCube->Lits[v]) ^ Aig_ObjFaninC0(pNode); + if ( !Pdr_NtkFindSatAssign_rec( p->pAig, Aig_ObjFanin0(pNode), !fCompl, p->pCubeJust, i ) ) + break; + } + if ( v < pCube->nLits ) + continue; + // figure this out!!! + if ( p->pCubeJust->nLits == 0 ) + continue; + // successfully derived new assignment + Vec_IntSelectSort( p->pCubeJust->Lits, p->pCubeJust->nLits ); + // check assignment against this cube + if ( Pdr_SetContainsSimple( p->pCubeJust, pCube ) ) + continue; +//printf( "\n" ); +//Pdr_SetPrint( stdout, pCube, Saig_ManRegNum(p->pAig), NULL ); printf( "\n" ); +//Pdr_SetPrint( stdout, p->pCubeJust, Saig_ManRegNum(p->pAig), NULL ); printf( "\n" ); + // check assignment against the clauses + if ( Pdr_ManCheckContainment( p, k, p->pCubeJust ) ) + continue; + // find good assignment + return 1; + } + return 0; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/ssw/module.make b/src/proof/ssw/module.make new file mode 100644 index 00000000..58345a1b --- /dev/null +++ b/src/proof/ssw/module.make @@ -0,0 +1,20 @@ +SRC += src/proof/ssw/sswAig.c \ + src/proof/ssw/sswBmc.c \ + src/proof/ssw/sswClass.c \ + src/proof/ssw/sswCnf.c \ + src/proof/ssw/sswConstr.c \ + src/proof/ssw/sswCore.c \ + src/proof/ssw/sswDyn.c \ + src/proof/ssw/sswFilter.c \ + src/proof/ssw/sswIslands.c \ + src/proof/ssw/sswLcorr.c \ + src/proof/ssw/sswMan.c \ + src/proof/ssw/sswPart.c \ + src/proof/ssw/sswPairs.c \ + src/proof/ssw/sswRarity.c \ + src/proof/ssw/sswSat.c \ + src/proof/ssw/sswSemi.c \ + src/proof/ssw/sswSim.c \ + src/proof/ssw/sswSimSat.c \ + src/proof/ssw/sswSweep.c \ + src/proof/ssw/sswUnique.c diff --git a/src/proof/ssw/ssw.h b/src/proof/ssw/ssw.h new file mode 100644 index 00000000..4680f6fb --- /dev/null +++ b/src/proof/ssw/ssw.h @@ -0,0 +1,142 @@ +/**CFile**************************************************************** + + FileName [ssw.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Inductive prover with constraints.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 1, 2008.] + + Revision [$Id: ssw.h,v 1.00 2008/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__ssw__ssw_h +#define ABC__aig__ssw__ssw_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_HEADER_START + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +// choicing parameters +typedef struct Ssw_Pars_t_ Ssw_Pars_t; +struct Ssw_Pars_t_ +{ + int nPartSize; // size of the partition + int nOverSize; // size of the overlap between partitions + int nFramesK; // the induction depth + int nFramesAddSim; // the number of additional frames to simulate + int fConstrs; // treat the last nConstrs POs as seq constraints + int fMergeFull; // enables full merge when constraints are used + int nMaxLevs; // the max number of levels of nodes to consider + int nBTLimit; // conflict limit at a node + int nBTLimitGlobal;// conflict limit for multiple runs + int nMinDomSize; // min clock domain considered for optimization + int nItersStop; // stop after the given number of iterations + int fDumpSRInit; // dumps speculative reduction + int nResimDelta; // the number of nodes to resimulate + int nStepsMax; // (scorr only) the max number of induction steps + int TimeLimit; // time out in seconds + int fPolarFlip; // uses polarity adjustment + int fLatchCorr; // perform register correspondence + int fConstCorr; // perform constant correspondence + int fOutputCorr; // perform 'PO correspondence' + int fSemiFormal; // enable semiformal filtering +// int fUniqueness; // enable uniqueness constraints + int fDynamic; // enable dynamic addition of constraints + int fLocalSim; // enable local simulation simulation + int fPartSigCorr; // uses partial signal correspondence + int nIsleDist; // extends islands by the given distance + int fScorrGia; // new signal correspondence implementation + int fUseCSat; // new SAT solver using when fScorrGia is selected + int fVerbose; // verbose stats + int fFlopVerbose; // verbose printout of redundant flops + int fEquivDump; // enables dumping equivalences + // optimized latch correspondence + int fLatchCorrOpt; // perform register correspondence (optimized) + int nSatVarMax; // max number of SAT vars before recycling SAT solver (optimized latch corr only) + int nRecycleCalls; // calls to perform before recycling SAT solver (optimized latch corr only) + // optimized signal correspondence + int nSatVarMax2; // max number of SAT vars before recycling SAT solver (optimized latch corr only) + int nRecycleCalls2;// calls to perform before recycling SAT solver (optimized latch corr only) + // internal parameters + int nIters; // the number of iterations performed + int nConflicts; // the total number of conflicts performed + // callback + void * pData; + void * pFunc; +}; + +typedef struct Ssw_Sml_t_ Ssw_Sml_t; // sequential simulation manager + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== sswBmc.c ==========================================================*/ +extern int Ssw_BmcDynamic( Aig_Man_t * pAig, int nFramesMax, int nConfLimit, int fVerbose, int * piFrame ); +/*=== sswConstr.c ==========================================================*/ +extern int Ssw_ManSetConstrPhases( Aig_Man_t * p, int nFrames, Vec_Int_t ** pvInits ); +/*=== sswCore.c ==========================================================*/ +extern void Ssw_ManSetDefaultParams( Ssw_Pars_t * p ); +extern void Ssw_ManSetDefaultParamsLcorr( Ssw_Pars_t * p ); +extern Aig_Man_t * Ssw_SignalCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars ); +extern Aig_Man_t * Ssw_LatchCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars ); +/*=== sswIslands.c ==========================================================*/ +extern int Ssw_SecWithSimilarityPairs( Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairs, Ssw_Pars_t * pPars ); +extern int Ssw_SecWithSimilarity( Aig_Man_t * p0, Aig_Man_t * p1, Ssw_Pars_t * pPars ); +/*=== sswMiter.c ===================================================*/ +/*=== sswPart.c ==========================================================*/ +extern Aig_Man_t * Ssw_SignalCorrespondencePart( Aig_Man_t * pAig, Ssw_Pars_t * pPars ); +/*=== sswPairs.c ===================================================*/ +extern int Ssw_MiterStatus( Aig_Man_t * p, int fVerbose ); +extern int Ssw_SecWithPairs( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec_Int_t * vIds1, Vec_Int_t * vIds2, Ssw_Pars_t * pPars ); +extern int Ssw_SecGeneral( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Ssw_Pars_t * pPars ); +extern int Ssw_SecGeneralMiter( Aig_Man_t * pMiter, Ssw_Pars_t * pPars ); +/*=== sswRarity.c ===================================================*/ +extern int Ssw_RarSignalFilter( Aig_Man_t * pAig, int nFrames, int nWords, int nBinSize, int nRounds, int nRandSeed, int TimeOut, int fMiter, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose ); +extern int Ssw_RarSimulate( Aig_Man_t * pAig, int nFrames, int nWords, int nBinSize, int nRounds, int nRandSeed, int TimeOut, int fVerbose ); +/*=== sswSim.c ===================================================*/ +extern Ssw_Sml_t * Ssw_SmlSimulateComb( Aig_Man_t * pAig, int nWords ); +extern Ssw_Sml_t * Ssw_SmlSimulateSeq( Aig_Man_t * pAig, int nPref, int nFrames, int nWords ); +extern void Ssw_SmlUnnormalize( Ssw_Sml_t * p ); +extern void Ssw_SmlStop( Ssw_Sml_t * p ); +extern int Ssw_SmlNumFrames( Ssw_Sml_t * p ); +extern int Ssw_SmlNumWordsTotal( Ssw_Sml_t * p ); +extern unsigned * Ssw_SmlSimInfo( Ssw_Sml_t * p, Aig_Obj_t * pObj ); +extern int Ssw_SmlObjsAreEqualWord( Ssw_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ); +extern void Ssw_SmlInitializeSpecial( Ssw_Sml_t * p, Vec_Int_t * vInit ); +extern int Ssw_SmlCheckNonConstOutputs( Ssw_Sml_t * p ); +extern Vec_Ptr_t * Ssw_SmlSimDataPointers( Ssw_Sml_t * p ); + + +ABC_NAMESPACE_HEADER_END + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/proof/ssw/sswAig.c b/src/proof/ssw/sswAig.c new file mode 100644 index 00000000..8ab99f83 --- /dev/null +++ b/src/proof/ssw/sswAig.c @@ -0,0 +1,259 @@ +/**CFile**************************************************************** + + FileName [sswAig.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Inductive prover with constraints.] + + Synopsis [AIG manipulation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 1, 2008.] + + Revision [$Id: sswAig.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sswInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the SAT manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ssw_Frm_t * Ssw_FrmStart( Aig_Man_t * pAig ) +{ + Ssw_Frm_t * p; + p = ABC_ALLOC( Ssw_Frm_t, 1 ); + memset( p, 0, sizeof(Ssw_Frm_t) ); + p->pAig = pAig; + p->nObjs = Aig_ManObjNumMax( pAig ); + p->nFrames = 0; + p->pFrames = NULL; + p->vAig2Frm = Vec_PtrAlloc( 0 ); + Vec_PtrFill( p->vAig2Frm, 2 * p->nObjs, NULL ); + return p; +} + +/**Function************************************************************* + + Synopsis [Starts the SAT manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_FrmStop( Ssw_Frm_t * p ) +{ + if ( p->pFrames ) + Aig_ManStop( p->pFrames ); + Vec_PtrFree( p->vAig2Frm ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Performs speculative reduction for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Ssw_FramesConstrainNode( Ssw_Man_t * p, Aig_Man_t * pFrames, Aig_Man_t * pAig, Aig_Obj_t * pObj, int iFrame, int fTwoPos ) +{ + Aig_Obj_t * pObjNew, * pObjNew2, * pObjRepr, * pObjReprNew, * pMiter; + // skip nodes without representative + pObjRepr = Aig_ObjRepr(pAig, pObj); + if ( pObjRepr == NULL ) + return; + p->nConstrTotal++; + assert( pObjRepr->Id < pObj->Id ); + // get the new node + pObjNew = Ssw_ObjFrame( p, pObj, iFrame ); + // get the new node of the representative + pObjReprNew = Ssw_ObjFrame( p, pObjRepr, iFrame ); + // if this is the same node, no need to add constraints + if ( pObj->fPhase == pObjRepr->fPhase ) + { + assert( pObjNew != Aig_Not(pObjReprNew) ); + if ( pObjNew == pObjReprNew ) + return; + } + else + { + assert( pObjNew != pObjReprNew ); + if ( pObjNew == Aig_Not(pObjReprNew) ) + return; + } + p->nConstrReduced++; + // these are different nodes - perform speculative reduction + pObjNew2 = Aig_NotCond( pObjReprNew, pObj->fPhase ^ pObjRepr->fPhase ); + // set the new node + Ssw_ObjSetFrame( p, pObj, iFrame, pObjNew2 ); + // add the constraint + if ( fTwoPos ) + { + Aig_ObjCreatePo( pFrames, pObjNew2 ); + Aig_ObjCreatePo( pFrames, pObjNew ); + } + else + { + pMiter = Aig_Exor( pFrames, pObjNew, pObjNew2 ); + Aig_ObjCreatePo( pFrames, Aig_NotCond(pMiter, Aig_ObjPhaseReal(pMiter)) ); + } +} + +/**Function************************************************************* + + Synopsis [Prepares the inductive case with speculative reduction.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Ssw_FramesWithClasses( Ssw_Man_t * p ) +{ + Aig_Man_t * pFrames; + Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew; + int i, f, iLits; + assert( p->pFrames == NULL ); + assert( Aig_ManRegNum(p->pAig) > 0 ); + assert( Aig_ManRegNum(p->pAig) < Aig_ManPiNum(p->pAig) ); + p->nConstrTotal = p->nConstrReduced = 0; + + // start the fraig package + pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->nFrames ); + // create latches for the first frame + Saig_ManForEachLo( p->pAig, pObj, i ) + Ssw_ObjSetFrame( p, pObj, 0, Aig_ObjCreatePi(pFrames) ); + // add timeframes + iLits = 0; + for ( f = 0; f < p->pPars->nFramesK; f++ ) + { + // map constants and PIs + Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(pFrames) ); + Saig_ManForEachPi( p->pAig, pObj, i ) + { + pObjNew = Aig_ObjCreatePi(pFrames); + pObjNew->fPhase = (p->vInits != NULL) && Vec_IntEntry(p->vInits, iLits++); + Ssw_ObjSetFrame( p, pObj, f, pObjNew ); + } + // set the constraints on the latch outputs + Saig_ManForEachLo( p->pAig, pObj, i ) + Ssw_FramesConstrainNode( p, pFrames, p->pAig, pObj, f, 1 ); + // add internal nodes of this frame + Aig_ManForEachNode( p->pAig, pObj, i ) + { + pObjNew = Aig_And( pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); + Ssw_ObjSetFrame( p, pObj, f, pObjNew ); + Ssw_FramesConstrainNode( p, pFrames, p->pAig, pObj, f, 1 ); + } + // transfer to the primary outputs + Aig_ManForEachPo( p->pAig, pObj, i ) + Ssw_ObjSetFrame( p, pObj, f, Ssw_ObjChild0Fra(p, pObj,f) ); + // transfer latch input to the latch outputs + Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) + Ssw_ObjSetFrame( p, pObjLo, f+1, Ssw_ObjFrame(p, pObjLi,f) ); + } + assert( p->vInits == NULL || Vec_IntSize(p->vInits) == iLits + Saig_ManPiNum(p->pAig) ); + // add the POs for the latch outputs of the last frame + Saig_ManForEachLo( p->pAig, pObj, i ) + Aig_ObjCreatePo( pFrames, Ssw_ObjFrame( p, pObj, p->pPars->nFramesK ) ); + + // remove dangling nodes + Aig_ManCleanup( pFrames ); + // make sure the satisfying assignment is node assigned + assert( pFrames->pData == NULL ); +//Aig_ManShow( pFrames, 0, NULL ); + return pFrames; +} + +/**Function************************************************************* + + Synopsis [Prepares the inductive case with speculative reduction.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Ssw_SpeculativeReduction( Ssw_Man_t * p ) +{ + Aig_Man_t * pFrames; + Aig_Obj_t * pObj, * pObjNew; + int i; + assert( p->pFrames == NULL ); + assert( Aig_ManRegNum(p->pAig) > 0 ); + assert( Aig_ManRegNum(p->pAig) < Aig_ManPiNum(p->pAig) ); + p->nConstrTotal = p->nConstrReduced = 0; + + // start the fraig package + pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->nFrames ); + pFrames->pName = Abc_UtilStrsav( p->pAig->pName ); + // map constants and PIs + Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), 0, Aig_ManConst1(pFrames) ); + Saig_ManForEachPi( p->pAig, pObj, i ) + Ssw_ObjSetFrame( p, pObj, 0, Aig_ObjCreatePi(pFrames) ); + // create latches for the first frame + Saig_ManForEachLo( p->pAig, pObj, i ) + Ssw_ObjSetFrame( p, pObj, 0, Aig_ObjCreatePi(pFrames) ); + // set the constraints on the latch outputs + Saig_ManForEachLo( p->pAig, pObj, i ) + Ssw_FramesConstrainNode( p, pFrames, p->pAig, pObj, 0, 0 ); + // add internal nodes of this frame + Aig_ManForEachNode( p->pAig, pObj, i ) + { + pObjNew = Aig_And( pFrames, Ssw_ObjChild0Fra(p, pObj, 0), Ssw_ObjChild1Fra(p, pObj, 0) ); + Ssw_ObjSetFrame( p, pObj, 0, pObjNew ); + Ssw_FramesConstrainNode( p, pFrames, p->pAig, pObj, 0, 0 ); + } + // add the POs for the latch outputs of the last frame + Saig_ManForEachLi( p->pAig, pObj, i ) + Aig_ObjCreatePo( pFrames, Ssw_ObjChild0Fra(p, pObj,0) ); + // remove dangling nodes + Aig_ManCleanup( pFrames ); + Aig_ManSetRegNum( pFrames, Aig_ManRegNum(p->pAig) ); +// printf( "SpecRed: Total constraints = %d. Reduced constraints = %d.\n", +// p->nConstrTotal, p->nConstrReduced ); + return pFrames; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/ssw/sswBmc.c b/src/proof/ssw/sswBmc.c new file mode 100644 index 00000000..8cb14f4a --- /dev/null +++ b/src/proof/ssw/sswBmc.c @@ -0,0 +1,224 @@ +/**CFile**************************************************************** + + FileName [sswBmc.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Inductive prover with constraints.] + + Synopsis [Bounded model checker using dynamic unrolling.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 1, 2008.] + + Revision [$Id: sswBmc.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sswInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Incrementally unroll the timeframes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Ssw_BmcUnroll_rec( Ssw_Frm_t * pFrm, Aig_Obj_t * pObj, int f ) +{ + Aig_Obj_t * pRes, * pRes0, * pRes1; + if ( (pRes = Ssw_ObjFrame_(pFrm, pObj, f)) ) + return pRes; + if ( Aig_ObjIsConst1(pObj) ) + pRes = Aig_ManConst1( pFrm->pFrames ); + else if ( Saig_ObjIsPi(pFrm->pAig, pObj) ) + pRes = Aig_ObjCreatePi( pFrm->pFrames ); + else if ( Aig_ObjIsPo(pObj) ) + { + Ssw_BmcUnroll_rec( pFrm, Aig_ObjFanin0(pObj), f ); + pRes = Ssw_ObjChild0Fra_( pFrm, pObj, f ); + } + else if ( Saig_ObjIsLo(pFrm->pAig, pObj) ) + { + if ( f == 0 ) + pRes = Aig_ManConst0( pFrm->pFrames ); + else + pRes = Ssw_BmcUnroll_rec( pFrm, Saig_ObjLoToLi(pFrm->pAig, pObj), f-1 ); + } + else + { + assert( Aig_ObjIsNode(pObj) ); + Ssw_BmcUnroll_rec( pFrm, Aig_ObjFanin0(pObj), f ); + Ssw_BmcUnroll_rec( pFrm, Aig_ObjFanin1(pObj), f ); + pRes0 = Ssw_ObjChild0Fra_( pFrm, pObj, f ); + pRes1 = Ssw_ObjChild1Fra_( pFrm, pObj, f ); + pRes = Aig_And( pFrm->pFrames, pRes0, pRes1 ); + } + Ssw_ObjSetFrame_( pFrm, pObj, f, pRes ); + return pRes; +} + +/**Function************************************************************* + + Synopsis [Derives counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Ssw_BmcGetCounterExample( Ssw_Frm_t * pFrm, Ssw_Sat_t * pSat, int iPo, int iFrame ) +{ + Abc_Cex_t * pCex; + Aig_Obj_t * pObj, * pObjFrames; + int f, i, nShift; + assert( Saig_ManRegNum(pFrm->pAig) > 0 ); + // allocate the counter example + pCex = Abc_CexAlloc( Saig_ManRegNum(pFrm->pAig), Saig_ManPiNum(pFrm->pAig), iFrame + 1 ); + pCex->iPo = iPo; + pCex->iFrame = iFrame; + // create data-bits + nShift = Saig_ManRegNum(pFrm->pAig); + for ( f = 0; f <= iFrame; f++, nShift += Saig_ManPiNum(pFrm->pAig) ) + Saig_ManForEachPi( pFrm->pAig, pObj, i ) + { + pObjFrames = Ssw_ObjFrame_(pFrm, pObj, f); + if ( pObjFrames == NULL ) + continue; + if ( Ssw_CnfGetNodeValue( pSat, pObjFrames ) ) + Abc_InfoSetBit( pCex->pData, nShift + i ); + } + return pCex; +} + + +/**Function************************************************************* + + Synopsis [Performs BMC for the given AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_BmcDynamic( Aig_Man_t * pAig, int nFramesMax, int nConfLimit, int fVerbose, int * piFrame ) +{ + Ssw_Frm_t * pFrm; + Ssw_Sat_t * pSat; + Aig_Obj_t * pObj, * pObjFrame; + int status, clkPart, Lit, i, f, RetValue; + + // start managers + assert( Saig_ManRegNum(pAig) > 0 ); + Aig_ManSetPioNumbers( pAig ); + pSat = Ssw_SatStart( 0 ); + pFrm = Ssw_FrmStart( pAig ); + pFrm->pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * 3 ); + // report statistics + if ( fVerbose ) + { + printf( "AIG: PI/PO/Reg = %d/%d/%d. Node = %6d. Lev = %5d.\n", + Saig_ManPiNum(pAig), Saig_ManPoNum(pAig), Saig_ManRegNum(pAig), + Aig_ManNodeNum(pAig), Aig_ManLevelNum(pAig) ); + fflush( stdout ); + } + // perform dynamic unrolling + RetValue = -1; + for ( f = 0; f < nFramesMax; f++ ) + { + clkPart = clock(); + Saig_ManForEachPo( pAig, pObj, i ) + { + // unroll the circuit for this output + Ssw_BmcUnroll_rec( pFrm, pObj, f ); + pObjFrame = Ssw_ObjFrame_( pFrm, pObj, f ); + Ssw_CnfNodeAddToSolver( pSat, Aig_Regular(pObjFrame) ); + status = sat_solver_simplify(pSat->pSat); + assert( status ); + // solve + Lit = toLitCond( Ssw_ObjSatNum(pSat,pObjFrame), Aig_IsComplement(pObjFrame) ); + if ( fVerbose ) + { + printf( "Solving output %2d of frame %3d ... \r", + i % Saig_ManPoNum(pAig), i / Saig_ManPoNum(pAig) ); + } + status = sat_solver_solve( pSat->pSat, &Lit, &Lit + 1, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + if ( status == l_False ) + { +/* + Lit = lit_neg( Lit ); + RetValue = sat_solver_addclause( pSat->pSat, &Lit, &Lit + 1 ); + assert( RetValue ); + if ( pSat->pSat->qtail != pSat->pSat->qhead ) + { + RetValue = sat_solver_simplify(pSat->pSat); + assert( RetValue ); + } +*/ + RetValue = 1; + continue; + } + else if ( status == l_True ) + { + pAig->pSeqModel = Ssw_BmcGetCounterExample( pFrm, pSat, i, f ); + if ( piFrame ) + *piFrame = f; + RetValue = 0; + break; + } + else + { + if ( piFrame ) + *piFrame = f; + RetValue = -1; + break; + } + } + if ( fVerbose ) + { + printf( "Solved %2d outputs of frame %3d. ", Saig_ManPoNum(pAig), f ); + printf( "Conf =%8.0f. Var =%8d. AIG=%9d. ", + (double)pSat->pSat->stats.conflicts, + pSat->nSatVars, Aig_ManNodeNum(pFrm->pFrames) ); + ABC_PRT( "T", clock() - clkPart ); + clkPart = clock(); + fflush( stdout ); + } + if ( RetValue != 1 ) + break; + } + + Ssw_SatStop( pSat ); + Ssw_FrmStop( pFrm ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/ssw/sswClass.c b/src/proof/ssw/sswClass.c new file mode 100644 index 00000000..dd075f44 --- /dev/null +++ b/src/proof/ssw/sswClass.c @@ -0,0 +1,1170 @@ +/**CFile**************************************************************** + + FileName [sswClass.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Inductive prover with constraints.] + + Synopsis [Representation of candidate equivalence classes.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 1, 2008.] + + Revision [$Id: sswClass.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sswInt.h" + +ABC_NAMESPACE_IMPL_START + + +/* + 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 topo order of their representatives. +*/ + +// internal representation of candidate equivalence classes +struct Ssw_Cla_t_ +{ + // class information + Aig_Man_t * pAig; // original AIG manager + Aig_Obj_t *** pId2Class; // non-const classes by ID of repr node + int * pClassSizes; // sizes of each equivalence class + int fConstCorr; + // statistics + int nClasses; // the total number of non-const classes + int nCands1; // the total number of const candidates + int nLits; // the number of literals in all classes + // memory + Aig_Obj_t ** pMemClasses; // memory allocated for equivalence classes + Aig_Obj_t ** pMemClassesFree; // memory allocated for equivalence classes to be used + // temporary data + Vec_Ptr_t * vClassOld; // old equivalence class after splitting + Vec_Ptr_t * vClassNew; // new equivalence class(es) after splitting + Vec_Ptr_t * vRefined; // the nodes refined since the last iteration + // procedures used for class refinement + void * pManData; + unsigned (*pFuncNodeHash) (void *,Aig_Obj_t *); // returns hash key of the node + int (*pFuncNodeIsConst) (void *,Aig_Obj_t *); // returns 1 if the node is a constant + int (*pFuncNodesAreEqual) (void *,Aig_Obj_t *, Aig_Obj_t *); // returns 1 if nodes are equal up to a complement +}; + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline Aig_Obj_t * Ssw_ObjNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj ) { return ppNexts[pObj->Id]; } +static inline void Ssw_ObjSetNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { ppNexts[pObj->Id] = pNext; } + +// iterator through the equivalence classes +#define Ssw_ManForEachClass( p, ppClass, i ) \ + for ( i = 0; i < Aig_ManObjNumMax(p->pAig); i++ ) \ + if ( ((ppClass) = p->pId2Class[i]) == NULL ) {} else +// iterator through the nodes in one class +#define Ssw_ClassForEachNode( p, pRepr, pNode, i ) \ + for ( i = 0; i < p->pClassSizes[pRepr->Id]; i++ ) \ + if ( ((pNode) = p->pId2Class[pRepr->Id][i]) == NULL ) {} else + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates one equivalence class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Ssw_ObjAddClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, Aig_Obj_t ** pClass, int nSize ) +{ + assert( p->pId2Class[pRepr->Id] == NULL ); + assert( pClass[0] == pRepr ); + p->pId2Class[pRepr->Id] = pClass; + assert( p->pClassSizes[pRepr->Id] == 0 ); + assert( nSize > 1 ); + p->pClassSizes[pRepr->Id] = nSize; + p->nClasses++; + p->nLits += nSize - 1; +} + +/**Function************************************************************* + + Synopsis [Removes one equivalence class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Aig_Obj_t ** Ssw_ObjRemoveClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr ) +{ + Aig_Obj_t ** pClass = p->pId2Class[pRepr->Id]; + int nSize; + assert( pClass != NULL ); + p->pId2Class[pRepr->Id] = NULL; + nSize = p->pClassSizes[pRepr->Id]; + assert( nSize > 1 ); + p->nClasses--; + p->nLits -= nSize - 1; + p->pClassSizes[pRepr->Id] = 0; + return pClass; +} + +/**Function************************************************************* + + Synopsis [Starts representation of equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ssw_Cla_t * Ssw_ClassesStart( Aig_Man_t * pAig ) +{ + Ssw_Cla_t * p; + p = ABC_ALLOC( Ssw_Cla_t, 1 ); + memset( p, 0, sizeof(Ssw_Cla_t) ); + p->pAig = pAig; + p->pId2Class = ABC_CALLOC( Aig_Obj_t **, Aig_ManObjNumMax(pAig) ); + p->pClassSizes = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); + p->vClassOld = Vec_PtrAlloc( 100 ); + p->vClassNew = Vec_PtrAlloc( 100 ); + p->vRefined = Vec_PtrAlloc( 1000 ); + if ( pAig->pReprs == NULL ) + Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) ); + return p; +} + +/**Function************************************************************* + + Synopsis [Starts representation of equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ClassesSetData( Ssw_Cla_t * p, void * pManData, + unsigned (*pFuncNodeHash)(void *,Aig_Obj_t *), // returns hash key of the node + int (*pFuncNodeIsConst)(void *,Aig_Obj_t *), // returns 1 if the node is a constant + int (*pFuncNodesAreEqual)(void *,Aig_Obj_t *, Aig_Obj_t *) ) // returns 1 if nodes are equal up to a complement +{ + p->pManData = pManData; + p->pFuncNodeHash = pFuncNodeHash; + p->pFuncNodeIsConst = pFuncNodeIsConst; + p->pFuncNodesAreEqual = pFuncNodesAreEqual; +} + +/**Function************************************************************* + + Synopsis [Stop representation of equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ClassesStop( Ssw_Cla_t * p ) +{ + if ( p->vClassNew ) Vec_PtrFree( p->vClassNew ); + if ( p->vClassOld ) Vec_PtrFree( p->vClassOld ); + Vec_PtrFree( p->vRefined ); + ABC_FREE( p->pId2Class ); + ABC_FREE( p->pClassSizes ); + ABC_FREE( p->pMemClasses ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Stop representation of equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Ssw_ClassesReadAig( Ssw_Cla_t * p ) +{ + return p->pAig; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Ssw_ClassesGetRefined( Ssw_Cla_t * p ) +{ + return p->vRefined; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ClassesClearRefined( Ssw_Cla_t * p ) +{ + Vec_PtrClear( p->vRefined ); +} + +/**Function************************************************************* + + Synopsis [Stop representation of equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ClassesCand1Num( Ssw_Cla_t * p ) +{ + return p->nCands1; +} + +/**Function************************************************************* + + Synopsis [Stop representation of equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ClassesClassNum( Ssw_Cla_t * p ) +{ + return p->nClasses; +} + +/**Function************************************************************* + + Synopsis [Stop representation of equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ClassesLitNum( Ssw_Cla_t * p ) +{ + return p->nLits; +} + +/**Function************************************************************* + + Synopsis [Stop representation of equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t ** Ssw_ClassesReadClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, int * pnSize ) +{ + if ( p->pId2Class[pRepr->Id] == NULL ) + return NULL; + assert( p->pId2Class[pRepr->Id] != NULL ); + assert( p->pClassSizes[pRepr->Id] > 1 ); + *pnSize = p->pClassSizes[pRepr->Id]; + return p->pId2Class[pRepr->Id]; +} + +/**Function************************************************************* + + Synopsis [Stop representation of equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ClassesCollectClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, Vec_Ptr_t * vClass ) +{ + int i; + Vec_PtrClear( vClass ); + if ( p->pId2Class[pRepr->Id] == NULL ) + return; + assert( p->pClassSizes[pRepr->Id] > 1 ); + for ( i = 1; i < p->pClassSizes[pRepr->Id]; i++ ) + Vec_PtrPush( vClass, p->pId2Class[pRepr->Id][i] ); +} + +/**Function************************************************************* + + Synopsis [Checks candidate equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ClassesCheck( Ssw_Cla_t * p ) +{ + Aig_Obj_t * pObj, * pPrev, ** ppClass; + int i, k, nLits, nClasses, nCands1; + nClasses = nLits = 0; + Ssw_ManForEachClass( p, ppClass, k ) + { + pPrev = NULL; + assert( p->pClassSizes[ppClass[0]->Id] >= 2 ); + Ssw_ClassForEachNode( p, ppClass[0], pObj, i ) + { + if ( i == 0 ) + assert( Aig_ObjRepr(p->pAig, pObj) == NULL ); + else + { + assert( Aig_ObjRepr(p->pAig, pObj) == ppClass[0] ); + assert( pPrev->Id < pObj->Id ); + nLits++; + } + pPrev = pObj; + } + nClasses++; + } + nCands1 = 0; + Aig_ManForEachObj( p->pAig, pObj, i ) + nCands1 += Ssw_ObjIsConst1Cand( p->pAig, pObj ); + assert( p->nLits == nLits ); + assert( p->nCands1 == nCands1 ); + assert( p->nClasses == nClasses ); +} + +/**Function************************************************************* + + Synopsis [Prints simulation classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ClassesPrintOne( Ssw_Cla_t * p, Aig_Obj_t * pRepr ) +{ + Aig_Obj_t * pObj; + int i; + printf( "{ " ); + Ssw_ClassForEachNode( p, pRepr, pObj, i ) + printf( "%d(%d,%d,%d) ", pObj->Id, pObj->Level, + Aig_SupportSize(p->pAig,pObj), Aig_NodeMffcSupp(p->pAig,pObj,0,NULL) ); + printf( "}\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints simulation classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ClassesPrint( Ssw_Cla_t * p, int fVeryVerbose ) +{ + Aig_Obj_t ** ppClass; + Aig_Obj_t * pObj; + int i; + printf( "Equiv classes: Const1 = %5d. Class = %5d. Lit = %5d.\n", + p->nCands1, p->nClasses, p->nCands1+p->nLits ); + if ( !fVeryVerbose ) + return; + printf( "Constants { " ); + Aig_ManForEachObj( p->pAig, pObj, i ) + if ( Ssw_ObjIsConst1Cand( p->pAig, pObj ) ) + printf( "%d(%d,%d,%d) ", pObj->Id, pObj->Level, + Aig_SupportSize(p->pAig,pObj), Aig_NodeMffcSupp(p->pAig,pObj,0,NULL) ); + printf( "}\n" ); + Ssw_ManForEachClass( p, ppClass, i ) + { + printf( "%3d (%3d) : ", i, p->pClassSizes[i] ); + Ssw_ClassesPrintOne( p, ppClass[0] ); + } + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints simulation classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ClassesRemoveNode( Ssw_Cla_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pRepr, * pTemp; + assert( p->pClassSizes[pObj->Id] == 0 ); + assert( p->pId2Class[pObj->Id] == NULL ); + pRepr = Aig_ObjRepr( p->pAig, pObj ); + assert( pRepr != NULL ); +// Vec_PtrPush( p->vRefined, pObj ); + if ( Ssw_ObjIsConst1Cand( p->pAig, pObj ) ) + { + assert( p->pClassSizes[pRepr->Id] == 0 ); + assert( p->pId2Class[pRepr->Id] == NULL ); + Aig_ObjSetRepr( p->pAig, pObj, NULL ); + p->nCands1--; + return; + } +// Vec_PtrPush( p->vRefined, pRepr ); + Aig_ObjSetRepr( p->pAig, pObj, NULL ); + assert( p->pId2Class[pRepr->Id][0] == pRepr ); + assert( p->pClassSizes[pRepr->Id] >= 2 ); + if ( p->pClassSizes[pRepr->Id] == 2 ) + { + p->pId2Class[pRepr->Id] = NULL; + p->nClasses--; + p->pClassSizes[pRepr->Id] = 0; + p->nLits--; + } + else + { + int i, k = 0; + // remove the entry from the class + Ssw_ClassForEachNode( p, pRepr, pTemp, i ) + if ( pTemp != pObj ) + p->pId2Class[pRepr->Id][k++] = pTemp; + assert( k + 1 == p->pClassSizes[pRepr->Id] ); + // reduce the class + p->pClassSizes[pRepr->Id]--; + p->nLits--; + } +} + +/**Function************************************************************* + + Synopsis [Takes the set of const1 cands and rehashes them using sim info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ClassesPrepareRehash( Ssw_Cla_t * p, Vec_Ptr_t * vCands, int fConstCorr ) +{ + Aig_Man_t * pAig = p->pAig; + Aig_Obj_t ** ppTable, ** ppNexts, ** ppClassNew; + Aig_Obj_t * pObj, * pTemp, * pRepr; + int i, k, nTableSize, nNodes, iEntry, nEntries, nEntries2; + + // allocate the hash table hashing simulation info into nodes + nTableSize = Abc_PrimeCudd( Vec_PtrSize(vCands)/2 ); + ppTable = ABC_CALLOC( Aig_Obj_t *, nTableSize ); + ppNexts = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) ); + + // sort through the candidates + nEntries = 0; + p->nCands1 = 0; + Vec_PtrForEachEntry( Aig_Obj_t *, vCands, pObj, i ) + { + assert( p->pClassSizes[pObj->Id] == 0 ); + Aig_ObjSetRepr( p->pAig, pObj, NULL ); + // check if the node belongs to the class of constant 1 + if ( p->pFuncNodeIsConst( p->pManData, pObj ) ) + { + Ssw_ObjSetConst1Cand( p->pAig, pObj ); + p->nCands1++; + continue; + } + if ( fConstCorr ) + continue; + // hash the node by its simulation info + iEntry = p->pFuncNodeHash( p->pManData, pObj ) % nTableSize; + // add the node to the class + if ( ppTable[iEntry] == NULL ) + { + ppTable[iEntry] = pObj; + } + else + { + // set the representative of this node + pRepr = ppTable[iEntry]; + Aig_ObjSetRepr( p->pAig, pObj, pRepr ); + // add node to the table + if ( Ssw_ObjNext( ppNexts, pRepr ) == NULL ) + { // this will be the second entry + p->pClassSizes[pRepr->Id]++; + nEntries++; + } + // add the entry to the list + Ssw_ObjSetNext( ppNexts, pObj, Ssw_ObjNext( ppNexts, pRepr ) ); + Ssw_ObjSetNext( ppNexts, pRepr, pObj ); + p->pClassSizes[pRepr->Id]++; + nEntries++; + } + } + + // copy the entries into storage in the topological order + nEntries2 = 0; + Vec_PtrForEachEntry( Aig_Obj_t *, vCands, pObj, i ) + { + nNodes = p->pClassSizes[pObj->Id]; + // skip the nodes that are not representatives of non-trivial classes + if ( nNodes == 0 ) + continue; + assert( nNodes > 1 ); + // add the nodes to the class in the topological order + ppClassNew = p->pMemClassesFree + nEntries2; + ppClassNew[0] = pObj; + for ( pTemp = Ssw_ObjNext(ppNexts, pObj), k = 1; pTemp; + pTemp = Ssw_ObjNext(ppNexts, pTemp), k++ ) + { + ppClassNew[nNodes-k] = pTemp; + } + // add the class of nodes + p->pClassSizes[pObj->Id] = 0; + Ssw_ObjAddClass( p, pObj, ppClassNew, nNodes ); + // increment the number of entries + nEntries2 += nNodes; + } + p->pMemClassesFree += nEntries2; + assert( nEntries == nEntries2 ); + ABC_FREE( ppTable ); + ABC_FREE( ppNexts ); + // now it is time to refine the classes + return Ssw_ClassesRefine( p, 1 ); +} + +/**Function************************************************************* + + Synopsis [Creates initial simulation classes.] + + Description [Assumes that simulation info is assigned.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ssw_Cla_t * Ssw_ClassesPrepare( Aig_Man_t * pAig, int nFramesK, int fLatchCorr, int fConstCorr, int fOutputCorr, int nMaxLevs, int fVerbose ) +{ +// int nFrames = 4; +// int nWords = 1; +// int nIters = 16; + +// int nFrames = 32; +// int nWords = 4; +// int nIters = 0; + + int nFrames = Abc_MaxInt( nFramesK, 4 ); + int nWords = 2; + int nIters = 16; + Ssw_Cla_t * p; + Ssw_Sml_t * pSml; + Vec_Ptr_t * vCands; + Aig_Obj_t * pObj; + int i, k, RetValue, clk; + + // start the classes + p = Ssw_ClassesStart( pAig ); + p->fConstCorr = fConstCorr; + + // perform sequential simulation +clk = clock(); + pSml = Ssw_SmlSimulateSeq( pAig, 0, nFrames, nWords ); +if ( fVerbose ) +{ + printf( "Allocated %.2f Mb to store simulation information.\n", + 1.0*(sizeof(unsigned) * Aig_ManObjNumMax(pAig) * nFrames * nWords)/(1<<20) ); + printf( "Initial simulation of %d frames with %d words. ", nFrames, nWords ); + ABC_PRT( "Time", clock() - clk ); +} + + // set comparison procedures +clk = clock(); + Ssw_ClassesSetData( p, pSml, (unsigned(*)(void *,Aig_Obj_t *))Ssw_SmlObjHashWord, (int(*)(void *,Aig_Obj_t *))Ssw_SmlObjIsConstWord, (int(*)(void *,Aig_Obj_t *,Aig_Obj_t *))Ssw_SmlObjsAreEqualWord ); + + // collect nodes to be considered as candidates + vCands = Vec_PtrAlloc( 1000 ); + Aig_ManForEachObj( p->pAig, pObj, i ) + { + if ( fLatchCorr ) + { + if ( !Saig_ObjIsLo(p->pAig, 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; + } + Vec_PtrPush( vCands, pObj ); + } + + // this change will consider all PO drivers + if ( fOutputCorr ) + { + Vec_PtrClear( vCands ); + Aig_ManForEachObj( p->pAig, pObj, i ) + pObj->fMarkB = 0; + Saig_ManForEachPo( p->pAig, pObj, i ) + if ( Aig_ObjIsCand(Aig_ObjFanin0(pObj)) ) + Aig_ObjFanin0(pObj)->fMarkB = 1; + Aig_ManForEachObj( p->pAig, pObj, i ) + if ( pObj->fMarkB ) + Vec_PtrPush( vCands, pObj ); + Aig_ManForEachObj( p->pAig, pObj, i ) + pObj->fMarkB = 0; + } + + // allocate room for classes + p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, Vec_PtrSize(vCands) ); + p->pMemClassesFree = p->pMemClasses; + + // now it is time to refine the classes + Ssw_ClassesPrepareRehash( p, vCands, fConstCorr ); +if ( fVerbose ) +{ + printf( "Collecting candidate equivalence classes. " ); +ABC_PRT( "Time", clock() - clk ); +} + +clk = clock(); + // perform iterative refinement using simulation + for ( i = 1; i < nIters; i++ ) + { + // collect const1 candidates + Vec_PtrClear( vCands ); + Aig_ManForEachObj( p->pAig, pObj, k ) + if ( Ssw_ObjIsConst1Cand( p->pAig, pObj ) ) + Vec_PtrPush( vCands, pObj ); + assert( Vec_PtrSize(vCands) == p->nCands1 ); + // perform new round of simulation + Ssw_SmlResimulateSeq( pSml ); + // check equivalence classes + RetValue = Ssw_ClassesPrepareRehash( p, vCands, fConstCorr ); + if ( RetValue == 0 ) + break; + } + Ssw_SmlStop( pSml ); + Vec_PtrFree( vCands ); +if ( fVerbose ) +{ + printf( "Simulation of %d frames with %d words (%2d rounds). ", + nFrames, nWords, i-1 ); + ABC_PRT( "Time", clock() - clk ); +} + Ssw_ClassesCheck( p ); +// Ssw_ClassesPrint( p, 0 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Creates initial simulation classes.] + + Description [Assumes that simulation info is assigned.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ssw_Cla_t * Ssw_ClassesPrepareSimple( Aig_Man_t * pAig, int fLatchCorr, int nMaxLevs ) +{ + Ssw_Cla_t * p; + Aig_Obj_t * pObj; + int i; + // start the classes + p = Ssw_ClassesStart( pAig ); + // go through the nodes + p->nCands1 = 0; + Aig_ManForEachObj( pAig, pObj, i ) + { + if ( fLatchCorr ) + { + if ( !Saig_ObjIsLo(pAig, pObj) ) + continue; + } + else + { + if ( !Aig_ObjIsNode(pObj) && !Saig_ObjIsLo(pAig, pObj) ) + continue; + // skip the node with more that the given number of levels + if ( nMaxLevs && (int)pObj->Level > nMaxLevs ) + continue; + } + Ssw_ObjSetConst1Cand( pAig, pObj ); + p->nCands1++; + } + // allocate room for classes + p->pMemClassesFree = p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, p->nCands1 ); +// Ssw_ClassesPrint( p, 0 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Creates initial simulation classes.] + + Description [Assumes that simulation info is assigned.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ssw_Cla_t * Ssw_ClassesPrepareFromReprs( Aig_Man_t * pAig ) +{ + Ssw_Cla_t * p; + Aig_Obj_t * pObj, * pRepr; + int * pClassSizes, nEntries, i; + // start the classes + p = Ssw_ClassesStart( pAig ); + // allocate memory for classes + p->pMemClasses = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) ); + // count classes + p->nCands1 = 0; + Aig_ManForEachObj( pAig, pObj, i ) + { + if ( Ssw_ObjIsConst1Cand(pAig, pObj) ) + { + p->nCands1++; + continue; + } + if ( (pRepr = Aig_ObjRepr(pAig, pObj)) ) + { + if ( p->pClassSizes[pRepr->Id]++ == 0 ) + p->pClassSizes[pRepr->Id]++; + } + } + // add nodes + nEntries = 0; + p->nClasses = 0; + pClassSizes = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); + Aig_ManForEachObj( pAig, pObj, i ) + { + if ( p->pClassSizes[i] ) + { + p->pId2Class[i] = p->pMemClasses + nEntries; + nEntries += p->pClassSizes[i]; + p->pId2Class[i][pClassSizes[i]++] = pObj; + p->nClasses++; + continue; + } + if ( Ssw_ObjIsConst1Cand(pAig, pObj) ) + continue; + if ( (pRepr = Aig_ObjRepr(pAig, pObj)) ) + p->pId2Class[pRepr->Id][pClassSizes[pRepr->Id]++] = pObj; + } + p->pMemClassesFree = p->pMemClasses + nEntries; + p->nLits = nEntries - p->nClasses; + assert( memcmp(pClassSizes, p->pClassSizes, sizeof(int)*Aig_ManObjNumMax(pAig)) == 0 ); + ABC_FREE( pClassSizes ); +// printf( "After converting:\n" ); +// Ssw_ClassesPrint( p, 0 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Creates initial simulation classes.] + + Description [Assumes that simulation info is assigned.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ssw_Cla_t * Ssw_ClassesPrepareTargets( Aig_Man_t * pAig ) +{ + Ssw_Cla_t * p; + Aig_Obj_t * pObj; + int i; + // start the classes + p = Ssw_ClassesStart( pAig ); + // go through the nodes + p->nCands1 = 0; + Saig_ManForEachPo( pAig, pObj, i ) + { + Ssw_ObjSetConst1Cand( pAig, Aig_ObjFanin0(pObj) ); + p->nCands1++; + } + // allocate room for classes + p->pMemClassesFree = p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, p->nCands1 ); +// Ssw_ClassesPrint( p, 0 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Creates classes from the temporary representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ssw_Cla_t * Ssw_ClassesPreparePairs( Aig_Man_t * pAig, Vec_Int_t ** pvClasses ) +{ + Ssw_Cla_t * p; + Aig_Obj_t ** ppClassNew; + Aig_Obj_t * pObj, * pRepr, * pPrev; + int i, k, nTotalObjs, nEntries, Entry; + // start the classes + p = Ssw_ClassesStart( pAig ); + // count the number of entries in the classes + nTotalObjs = 0; + for ( i = 0; i < Aig_ManObjNumMax(pAig); i++ ) + nTotalObjs += pvClasses[i] ? Vec_IntSize(pvClasses[i]) : 0; + // allocate memory for classes + p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, nTotalObjs ); + // create constant-1 class + if ( pvClasses[0] ) + Vec_IntForEachEntry( pvClasses[0], Entry, i ) + { + assert( (i == 0) == (Entry == 0) ); + if ( i == 0 ) + continue; + pObj = Aig_ManObj( pAig, Entry ); + Ssw_ObjSetConst1Cand( pAig, pObj ); + p->nCands1++; + } + // create classes + nEntries = 0; + for ( i = 1; i < Aig_ManObjNumMax(pAig); i++ ) + { + if ( pvClasses[i] == NULL ) + continue; + // get room for storing the class + ppClassNew = p->pMemClasses + nEntries; + nEntries += Vec_IntSize( pvClasses[i] ); + // store the nodes of the class + pPrev = pRepr = Aig_ManObj( pAig, Vec_IntEntry(pvClasses[i],0) ); + ppClassNew[0] = pRepr; + Vec_IntForEachEntryStart( pvClasses[i], Entry, k, 1 ) + { + pObj = Aig_ManObj( pAig, Entry ); + assert( pPrev->Id < pObj->Id ); + pPrev = pObj; + ppClassNew[k] = pObj; + Aig_ObjSetRepr( pAig, pObj, pRepr ); + } + // create new class + Ssw_ObjAddClass( p, pRepr, ppClassNew, Vec_IntSize(pvClasses[i]) ); + } + // prepare room for new classes + p->pMemClassesFree = p->pMemClasses + nEntries; + Ssw_ClassesCheck( p ); +// Ssw_ClassesPrint( p, 0 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Creates classes from the temporary representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ssw_Cla_t * Ssw_ClassesPreparePairsSimple( Aig_Man_t * pMiter, Vec_Int_t * vPairs ) +{ + Ssw_Cla_t * p; + Aig_Obj_t ** ppClassNew; + Aig_Obj_t * pObj, * pRepr; + int i; + // start the classes + p = Ssw_ClassesStart( pMiter ); + // allocate memory for classes + p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, Vec_IntSize(vPairs) ); + // create classes + for ( i = 0; i < Vec_IntSize(vPairs); i += 2 ) + { + pRepr = Aig_ManObj( pMiter, Vec_IntEntry(vPairs, i) ); + pObj = Aig_ManObj( pMiter, Vec_IntEntry(vPairs, i+1) ); + assert( Aig_ObjId(pRepr) < Aig_ObjId(pObj) ); + Aig_ObjSetRepr( pMiter, pObj, pRepr ); + // get room for storing the class + ppClassNew = p->pMemClasses + i; + ppClassNew[0] = pRepr; + ppClassNew[1] = pObj; + // create new class + Ssw_ObjAddClass( p, pRepr, ppClassNew, 2 ); + } + // prepare room for new classes + p->pMemClassesFree = NULL; + Ssw_ClassesCheck( p ); +// Ssw_ClassesPrint( p, 0 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Iteratively refines the classes after simulation.] + + Description [Returns the number of refinements performed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ClassesRefineOneClass( Ssw_Cla_t * p, Aig_Obj_t * pReprOld, int fRecursive ) +{ + Aig_Obj_t ** pClassOld, ** pClassNew; + Aig_Obj_t * pObj, * pReprNew; + int i; + + // split the class + Vec_PtrClear( p->vClassOld ); + Vec_PtrClear( p->vClassNew ); + Ssw_ClassForEachNode( p, pReprOld, pObj, i ) + if ( p->pFuncNodesAreEqual(p->pManData, pReprOld, pObj) ) + Vec_PtrPush( p->vClassOld, pObj ); + else + Vec_PtrPush( p->vClassNew, pObj ); + // check if splitting happened + if ( Vec_PtrSize(p->vClassNew) == 0 ) + return 0; + // remember that this class is refined +// Ssw_ClassForEachNode( p, pReprOld, pObj, i ) +// Vec_PtrPush( p->vRefined, pObj ); + + // get the new representative + pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 ); + assert( Vec_PtrSize(p->vClassOld) > 0 ); + assert( Vec_PtrSize(p->vClassNew) > 0 ); + + // create old class + pClassOld = Ssw_ObjRemoveClass( p, pReprOld ); + Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassOld, pObj, i ) + { + pClassOld[i] = pObj; + Aig_ObjSetRepr( p->pAig, pObj, i? pReprOld : NULL ); + } + // create new class + pClassNew = pClassOld + i; + Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i ) + { + pClassNew[i] = pObj; + Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL ); + } + + // put classes back + if ( Vec_PtrSize(p->vClassOld) > 1 ) + Ssw_ObjAddClass( p, pReprOld, pClassOld, Vec_PtrSize(p->vClassOld) ); + if ( Vec_PtrSize(p->vClassNew) > 1 ) + Ssw_ObjAddClass( p, pReprNew, pClassNew, Vec_PtrSize(p->vClassNew) ); + + // check if the class should be recursively refined + if ( fRecursive && Vec_PtrSize(p->vClassNew) > 1 ) + return 1 + Ssw_ClassesRefineOneClass( p, pReprNew, 1 ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Refines the classes after simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ClassesRefine( Ssw_Cla_t * p, int fRecursive ) +{ + Aig_Obj_t ** ppClass; + int i, nRefis = 0; + Ssw_ManForEachClass( p, ppClass, i ) + nRefis += Ssw_ClassesRefineOneClass( p, ppClass[0], fRecursive ); + return nRefis; +} + +/**Function************************************************************* + + Synopsis [Refines the classes after simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ClassesRefineGroup( Ssw_Cla_t * p, Vec_Ptr_t * vReprs, int fRecursive ) +{ + Aig_Obj_t * pObj; + int i, nRefis = 0; + Vec_PtrForEachEntry( Aig_Obj_t *, vReprs, pObj, i ) + nRefis += Ssw_ClassesRefineOneClass( p, pObj, fRecursive ); + return nRefis; +} + +/**Function************************************************************* + + Synopsis [Refine the group of constant 1 nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ClassesRefineConst1Group( Ssw_Cla_t * p, Vec_Ptr_t * vRoots, int fRecursive ) +{ + Aig_Obj_t * pObj, * pReprNew, ** ppClassNew; + int i; + if ( Vec_PtrSize(vRoots) == 0 ) + return 0; + // collect the nodes to be refined + Vec_PtrClear( p->vClassNew ); + Vec_PtrForEachEntry( Aig_Obj_t *, vRoots, pObj, i ) + if ( !p->pFuncNodeIsConst( p->pManData, pObj ) ) + Vec_PtrPush( p->vClassNew, pObj ); + // check if there is a new class + if ( Vec_PtrSize(p->vClassNew) == 0 ) + return 0; + p->nCands1 -= Vec_PtrSize(p->vClassNew); + pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 ); + Aig_ObjSetRepr( p->pAig, pReprNew, NULL ); + if ( Vec_PtrSize(p->vClassNew) == 1 ) + return 1; + // create a new class composed of these nodes + ppClassNew = p->pMemClassesFree; + p->pMemClassesFree += Vec_PtrSize(p->vClassNew); + Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i ) + { + ppClassNew[i] = pObj; + Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL ); + } + Ssw_ObjAddClass( p, pReprNew, ppClassNew, Vec_PtrSize(p->vClassNew) ); + // refine them recursively + if ( fRecursive ) + return 1 + Ssw_ClassesRefineOneClass( p, pReprNew, 1 ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Refine the group of constant 1 nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ClassesRefineConst1( Ssw_Cla_t * p, int fRecursive ) +{ + Aig_Obj_t * pObj, * pReprNew, ** ppClassNew; + int i; + // collect the nodes to be refined + Vec_PtrClear( p->vClassNew ); + for ( i = 0; i < Vec_PtrSize(p->pAig->vObjs); i++ ) + if ( p->pAig->pReprs[i] == Aig_ManConst1(p->pAig) ) + { + pObj = Aig_ManObj( p->pAig, i ); + if ( !p->pFuncNodeIsConst( p->pManData, pObj ) ) + { + Vec_PtrPush( p->vClassNew, pObj ); +// Vec_PtrPush( p->vRefined, pObj ); + } + } + // check if there is a new class + if ( Vec_PtrSize(p->vClassNew) == 0 ) + return 0; + if ( p->fConstCorr ) + { + Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i ) + Aig_ObjSetRepr( p->pAig, pObj, NULL ); + return 1; + } + p->nCands1 -= Vec_PtrSize(p->vClassNew); + pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 ); + Aig_ObjSetRepr( p->pAig, pReprNew, NULL ); + if ( Vec_PtrSize(p->vClassNew) == 1 ) + return 1; + // create a new class composed of these nodes + ppClassNew = p->pMemClassesFree; + p->pMemClassesFree += Vec_PtrSize(p->vClassNew); + Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i ) + { + ppClassNew[i] = pObj; + Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL ); + } + Ssw_ObjAddClass( p, pReprNew, ppClassNew, Vec_PtrSize(p->vClassNew) ); + // refine them recursively + if ( fRecursive ) + return 1 + Ssw_ClassesRefineOneClass( p, pReprNew, 1 ); + return 1; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/ssw/sswCnf.c b/src/proof/ssw/sswCnf.c new file mode 100644 index 00000000..1970c62f --- /dev/null +++ b/src/proof/ssw/sswCnf.c @@ -0,0 +1,428 @@ +/**CFile**************************************************************** + + FileName [sswCnf.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Inductive prover with constraints.] + + Synopsis [Computation of CNF.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 1, 2008.] + + Revision [$Id: sswCnf.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sswInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the SAT manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ssw_Sat_t * Ssw_SatStart( int fPolarFlip ) +{ + Ssw_Sat_t * p; + int Lit; + p = ABC_ALLOC( Ssw_Sat_t, 1 ); + memset( p, 0, sizeof(Ssw_Sat_t) ); + p->pAig = NULL; + p->fPolarFlip = fPolarFlip; + p->vSatVars = Vec_IntStart( 10000 ); + p->vFanins = Vec_PtrAlloc( 100 ); + p->vUsedPis = Vec_PtrAlloc( 100 ); + p->pSat = sat_solver_new(); + sat_solver_setnvars( p->pSat, 1000 ); + // var 0 is not used + // var 1 is reserved for const1 node - add the clause + p->nSatVars = 1; + Lit = toLit( p->nSatVars ); + if ( fPolarFlip ) + Lit = lit_neg( Lit ); + sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ); +// Ssw_ObjSetSatNum( p, Aig_ManConst1(p->pAig), p->nSatVars++ ); + Vec_IntWriteEntry( p->vSatVars, 0, p->nSatVars++ ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stop the SAT manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SatStop( Ssw_Sat_t * p ) +{ +// printf( "Recycling SAT solver with %d vars and %d restarts.\n", +// p->pSat->size, p->pSat->stats.starts ); + if ( p->pSat ) + sat_solver_delete( p->pSat ); + Vec_IntFree( p->vSatVars ); + Vec_PtrFree( p->vFanins ); + Vec_PtrFree( p->vUsedPis ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Addes clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_AddClausesMux( Ssw_Sat_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 = Ssw_ObjSatNum(p,pNode); + VarI = Ssw_ObjSatNum(p,pNodeI); + VarT = Ssw_ObjSatNum(p,Aig_Regular(pNodeT)); + VarE = Ssw_ObjSatNum(p,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); + if ( p->fPolarFlip ) + { + if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Aig_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + 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); + if ( p->fPolarFlip ) + { + if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Aig_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + 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); + if ( p->fPolarFlip ) + { + if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + 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); + if ( p->fPolarFlip ) + { + if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + 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); + if ( p->fPolarFlip ) + { + if ( Aig_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + 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); + if ( p->fPolarFlip ) + { + if ( Aig_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); +} + +/**Function************************************************************* + + Synopsis [Addes clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_AddClausesSuper( Ssw_Sat_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 = ABC_ALLOC( int, nLits ); + // suppose AND-gate is A & B = C + // add !A => !C or A + !C + Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i ) + { + pLits[0] = toLitCond(Ssw_ObjSatNum(p,Aig_Regular(pFanin)), Aig_IsComplement(pFanin)); + pLits[1] = toLitCond(Ssw_ObjSatNum(p,pNode), 1); + if ( p->fPolarFlip ) + { + if ( Aig_Regular(pFanin)->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( pNode->fPhase ) pLits[1] = lit_neg( pLits[1] ); + } + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); + assert( RetValue ); + } + // add A & B => C or !A + !B + C + Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i ) + { + pLits[i] = toLitCond(Ssw_ObjSatNum(p,Aig_Regular(pFanin)), !Aig_IsComplement(pFanin)); + if ( p->fPolarFlip ) + { + if ( Aig_Regular(pFanin)->fPhase ) pLits[i] = lit_neg( pLits[i] ); + } + } + pLits[nLits-1] = toLitCond(Ssw_ObjSatNum(p,pNode), 0); + if ( p->fPolarFlip ) + { + if ( pNode->fPhase ) pLits[nLits-1] = lit_neg( pLits[nLits-1] ); + } + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits ); + assert( RetValue ); + ABC_FREE( pLits ); +} + +/**Function************************************************************* + + Synopsis [Collects the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_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; + } +// pObj->fMarkA = 1; + // go through the branches + Ssw_CollectSuper_rec( Aig_ObjChild0(pObj), vSuper, 0, fUseMuxes ); + Ssw_CollectSuper_rec( Aig_ObjChild1(pObj), vSuper, 0, fUseMuxes ); +} + +/**Function************************************************************* + + Synopsis [Collects the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_CollectSuper( Aig_Obj_t * pObj, int fUseMuxes, Vec_Ptr_t * vSuper ) +{ + assert( !Aig_IsComplement(pObj) ); + assert( !Aig_ObjIsPi(pObj) ); + Vec_PtrClear( vSuper ); + Ssw_CollectSuper_rec( pObj, vSuper, 1, fUseMuxes ); +} + +/**Function************************************************************* + + Synopsis [Updates the solver clause database.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ObjAddToFrontier( Ssw_Sat_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vFrontier ) +{ + assert( !Aig_IsComplement(pObj) ); + if ( Ssw_ObjSatNum(p,pObj) ) + return; + assert( Ssw_ObjSatNum(p,pObj) == 0 ); + if ( Aig_ObjIsConst1(pObj) ) + return; +// pObj->fMarkA = 1; + // save PIs (used by register correspondence) + if ( Aig_ObjIsPi(pObj) ) + Vec_PtrPush( p->vUsedPis, pObj ); + Ssw_ObjSetSatNum( p, pObj, p->nSatVars++ ); + sat_solver_setnvars( p->pSat, 100 * (1 + p->nSatVars / 100) ); + if ( Aig_ObjIsNode(pObj) ) + Vec_PtrPush( vFrontier, pObj ); +} + +/**Function************************************************************* + + Synopsis [Updates the solver clause database.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_CnfNodeAddToSolver( Ssw_Sat_t * p, Aig_Obj_t * pObj ) +{ + Vec_Ptr_t * vFrontier; + Aig_Obj_t * pNode, * pFanin; + int i, k, fUseMuxes = 1; + // quit if CNF is ready + if ( Ssw_ObjSatNum(p,pObj) ) + return; + // start the frontier + vFrontier = Vec_PtrAlloc( 100 ); + Ssw_ObjAddToFrontier( p, pObj, vFrontier ); + // explore nodes in the frontier + Vec_PtrForEachEntry( Aig_Obj_t *, vFrontier, pNode, i ) + { + // create the supergate + assert( Ssw_ObjSatNum(p,pNode) ); + if ( fUseMuxes && Aig_ObjIsMuxType(pNode) ) + { + Vec_PtrClear( p->vFanins ); + Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin0( Aig_ObjFanin0(pNode) ) ); + Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin0( Aig_ObjFanin1(pNode) ) ); + Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin1( Aig_ObjFanin0(pNode) ) ); + Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin1( Aig_ObjFanin1(pNode) ) ); + Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanins, pFanin, k ) + Ssw_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier ); + Ssw_AddClausesMux( p, pNode ); + } + else + { + Ssw_CollectSuper( pNode, fUseMuxes, p->vFanins ); + Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanins, pFanin, k ) + Ssw_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier ); + Ssw_AddClausesSuper( p, pNode, p->vFanins ); + } + assert( Vec_PtrSize(p->vFanins) > 1 ); + } + Vec_PtrFree( vFrontier ); +} + + +/**Function************************************************************* + + Synopsis [Copy pattern from the solver into the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_CnfGetNodeValue( Ssw_Sat_t * p, Aig_Obj_t * pObj ) +{ + int Value0, Value1, nVarNum; + assert( !Aig_IsComplement(pObj) ); + nVarNum = Ssw_ObjSatNum( p, pObj ); + if ( nVarNum > 0 ) + return sat_solver_var_value( p->pSat, nVarNum ); +// if ( pObj->fMarkA == 1 ) +// return 0; + if ( Aig_ObjIsPi(pObj) ) + return 0; + assert( Aig_ObjIsNode(pObj) ); + Value0 = Ssw_CnfGetNodeValue( p, Aig_ObjFanin0(pObj) ); + Value0 ^= Aig_ObjFaninC0(pObj); + Value1 = Ssw_CnfGetNodeValue( p, Aig_ObjFanin1(pObj) ); + Value1 ^= Aig_ObjFaninC1(pObj); + return Value0 & Value1; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/ssw/sswConstr.c b/src/proof/ssw/sswConstr.c new file mode 100644 index 00000000..239e35b9 --- /dev/null +++ b/src/proof/ssw/sswConstr.c @@ -0,0 +1,714 @@ +/**CFile**************************************************************** + + FileName [sswConstr.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Inductive prover with constraints.] + + Synopsis [One round of SAT sweeping.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 1, 2008.] + + Revision [$Id: sswConstr.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sswInt.h" +#include "src/sat/cnf/cnf.h" +#include "src/misc/bar/bar.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Constructs initialized timeframes with constraints as POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Ssw_FramesWithConstraints( Aig_Man_t * p, int nFrames ) +{ + Aig_Man_t * pFrames; + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + int i, f; + assert( Saig_ManConstrNum(p) > 0 ); + assert( Aig_ManRegNum(p) > 0 ); + assert( Aig_ManRegNum(p) < Aig_ManPiNum(p) ); + // start the fraig package + pFrames = Aig_ManStart( Aig_ManObjNumMax(p) * nFrames ); + // create latches for the first frame + Saig_ManForEachLo( p, pObj, i ) + Aig_ObjSetCopy( pObj, Aig_ManConst0(pFrames) ); + // add timeframes + for ( f = 0; f < nFrames; f++ ) + { + // map constants and PIs + Aig_ObjSetCopy( Aig_ManConst1(p), Aig_ManConst1(pFrames) ); + Saig_ManForEachPi( p, pObj, i ) + Aig_ObjSetCopy( pObj, Aig_ObjCreatePi(pFrames) ); + // add internal nodes of this frame + Aig_ManForEachNode( p, pObj, i ) + Aig_ObjSetCopy( pObj, Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ) ); + // transfer to the primary output + Aig_ManForEachPo( p, pObj, i ) + Aig_ObjSetCopy( pObj, Aig_ObjChild0Copy(pObj) ); + // create constraint outputs + Saig_ManForEachPo( p, pObj, i ) + { + if ( i < Saig_ManPoNum(p) - Saig_ManConstrNum(p) ) + continue; + Aig_ObjCreatePo( pFrames, Aig_Not( Aig_ObjCopy(pObj) ) ); + } + // transfer latch inputs to the latch outputs + Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) + Aig_ObjSetCopy( pObjLo, Aig_ObjCopy(pObjLi) ); + } + // remove dangling nodes + Aig_ManCleanup( pFrames ); + return pFrames; +} + +/**Function************************************************************* + + Synopsis [Finds one satisfiable assignment of the timeframes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ManSetConstrPhases( Aig_Man_t * p, int nFrames, Vec_Int_t ** pvInits ) +{ + Aig_Man_t * pFrames; + sat_solver * pSat; + Cnf_Dat_t * pCnf; + Aig_Obj_t * pObj; + int i, RetValue; + if ( pvInits ) + *pvInits = NULL; + assert( p->nConstrs > 0 ); + // derive the timeframes + pFrames = Ssw_FramesWithConstraints( p, nFrames ); + // create CNF + pCnf = Cnf_Derive( pFrames, 0 ); + // create SAT solver + pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + if ( pSat == NULL ) + { + Cnf_DataFree( pCnf ); + Aig_ManStop( pFrames ); + return 1; + } + // solve + RetValue = sat_solver_solve( pSat, NULL, NULL, + (ABC_INT64_T)1000000, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + if ( RetValue == l_True && pvInits ) + { + *pvInits = Vec_IntAlloc( 1000 ); + Aig_ManForEachPi( pFrames, pObj, i ) + Vec_IntPush( *pvInits, sat_solver_var_value(pSat, pCnf->pVarNums[Aig_ObjId(pObj)]) ); + +// Aig_ManForEachPi( pFrames, pObj, i ) +// printf( "%d", Vec_IntEntry(*pvInits, i) ); +// printf( "\n" ); + } + sat_solver_delete( pSat ); + Cnf_DataFree( pCnf ); + Aig_ManStop( pFrames ); + if ( RetValue == l_False ) + return 1; + if ( RetValue == l_True ) + return 0; + return -1; +} + +/**Function************************************************************* + + Synopsis [Performs fraiging for one node.] + + Description [Returns the fraiged node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ManSetConstrPhases_( Aig_Man_t * p, int nFrames, Vec_Int_t ** pvInits ) +{ + Vec_Int_t * vLits; + sat_solver * pSat; + Cnf_Dat_t * pCnf; + Aig_Obj_t * pObj; + int i, f, iVar, RetValue, nRegs; + if ( pvInits ) + *pvInits = NULL; + assert( p->nConstrs > 0 ); + // create CNF + nRegs = p->nRegs; p->nRegs = 0; + pCnf = Cnf_Derive( p, Aig_ManPoNum(p) ); + p->nRegs = nRegs; + // create SAT solver + pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, nFrames, 0 ); + assert( pSat->size == nFrames * pCnf->nVars ); + // collect constraint literals + vLits = Vec_IntAlloc( 100 ); + Saig_ManForEachLo( p, pObj, i ) + { + assert( pCnf->pVarNums[Aig_ObjId(pObj)] >= 0 ); + Vec_IntPush( vLits, toLitCond(pCnf->pVarNums[Aig_ObjId(pObj)], 1) ); + } + for ( f = 0; f < nFrames; f++ ) + { + Saig_ManForEachPo( p, pObj, i ) + { + if ( i < Saig_ManPoNum(p) - Saig_ManConstrNum(p) ) + continue; + assert( pCnf->pVarNums[Aig_ObjId(pObj)] >= 0 ); + iVar = pCnf->pVarNums[Aig_ObjId(pObj)] + pCnf->nVars*f; + Vec_IntPush( vLits, toLitCond(iVar, 1) ); + } + } + RetValue = sat_solver_solve( pSat, (int *)Vec_IntArray(vLits), + (int *)Vec_IntArray(vLits) + Vec_IntSize(vLits), + (ABC_INT64_T)1000000, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + if ( RetValue == l_True && pvInits ) + { + *pvInits = Vec_IntAlloc( 1000 ); + for ( f = 0; f < nFrames; f++ ) + { + Saig_ManForEachPi( p, pObj, i ) + { + iVar = pCnf->pVarNums[Aig_ObjId(pObj)] + pCnf->nVars*f; + Vec_IntPush( *pvInits, sat_solver_var_value(pSat, iVar) ); + } + } + } + sat_solver_delete( pSat ); + Vec_IntFree( vLits ); + Cnf_DataFree( pCnf ); + if ( RetValue == l_False ) + return 1; + if ( RetValue == l_True ) + return 0; + return -1; +} + +/**Function************************************************************* + + Synopsis [Performs fraiging for one node.] + + Description [Returns the fraiged node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManPrintPolarity( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachObj( p, pObj, i ) + printf( "%d", pObj->fPhase ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Performs fraiging for one node.] + + Description [Returns the fraiged node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManRefineByConstrSim( Ssw_Man_t * p ) +{ + Aig_Obj_t * pObj, * pObjLi; + int f, i, iLits, RetValue1, RetValue2; + int nFrames = Vec_IntSize(p->vInits) / Saig_ManPiNum(p->pAig); + assert( Vec_IntSize(p->vInits) % Saig_ManPiNum(p->pAig) == 0 ); + // assign register outputs + Saig_ManForEachLi( p->pAig, pObj, i ) + pObj->fMarkB = 0; + // simulate the timeframes + iLits = 0; + for ( f = 0; f < nFrames; f++ ) + { + // set the PI simulation information + Aig_ManConst1(p->pAig)->fMarkB = 1; + Saig_ManForEachPi( p->pAig, pObj, i ) + pObj->fMarkB = Vec_IntEntry( p->vInits, iLits++ ); + Saig_ManForEachLiLo( p->pAig, pObjLi, pObj, i ) + pObj->fMarkB = pObjLi->fMarkB; + // simulate internal nodes + Aig_ManForEachNode( p->pAig, pObj, i ) + pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ) + & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) ); + // assign the COs + Aig_ManForEachPo( p->pAig, pObj, i ) + pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ); + // check the outputs + Saig_ManForEachPo( p->pAig, pObj, i ) + { + if ( i < Saig_ManPoNum(p->pAig) - Saig_ManConstrNum(p->pAig) ) + { + if ( pObj->fMarkB ) + printf( "output %d failed in frame %d.\n", i, f ); + } + else + { + if ( pObj->fMarkB ) + printf( "constraint %d failed in frame %d.\n", i, f ); + } + } + // transfer + if ( f == 0 ) + { // copy markB into phase + Aig_ManForEachObj( p->pAig, pObj, i ) + pObj->fPhase = pObj->fMarkB; + } + else + { // refine classes + RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 0 ); + RetValue2 = Ssw_ClassesRefine( p->ppClasses, 0 ); + } + } + assert( iLits == Vec_IntSize(p->vInits) ); +} + + +/**Function************************************************************* + + Synopsis [Performs fraiging for one node.] + + Description [Returns the fraiged node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ManSweepNodeConstr( Ssw_Man_t * p, Aig_Obj_t * pObj, int f, int fBmc ) +{ + Aig_Obj_t * pObjRepr, * pObjFraig, * pObjFraig2, * pObjReprFraig; + int RetValue; + // get representative of this class + pObjRepr = Aig_ObjRepr( p->pAig, pObj ); + if ( pObjRepr == NULL ) + return 0; + // get the fraiged node + pObjFraig = Ssw_ObjFrame( p, pObj, f ); + // get the fraiged representative + pObjReprFraig = Ssw_ObjFrame( p, pObjRepr, f ); + // check if constant 0 pattern distinquishes these nodes + assert( pObjFraig != NULL && pObjReprFraig != NULL ); + assert( (pObj->fPhase == pObjRepr->fPhase) == (Aig_ObjPhaseReal(pObjFraig) == Aig_ObjPhaseReal(pObjReprFraig)) ); + // if the fraiged nodes are the same, return + if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) ) + return 0; + // call equivalence checking + if ( Aig_Regular(pObjFraig) != Aig_ManConst1(p->pFrames) ) + RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) ); + else + RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjFraig), Aig_Regular(pObjReprFraig) ); + if ( RetValue == 1 ) // proved equivalent + { + pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase ); + Ssw_ObjSetFrame( p, pObj, f, pObjFraig2 ); + return 0; + } + if ( RetValue == -1 ) // timed out + { + Ssw_ClassesRemoveNode( p->ppClasses, pObj ); + return 1; + } + // disproved equivalence + Ssw_SmlSavePatternAig( p, f ); + Ssw_ManResimulateBit( p, pObj, pObjRepr ); + assert( Aig_ObjRepr( p->pAig, pObj ) != pObjRepr ); + if ( Aig_ObjRepr( p->pAig, pObj ) == pObjRepr ) + { + printf( "Ssw_ManSweepNodeConstr(): Failed to refine representative.\n" ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Performs fraiging for the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Ssw_ManSweepBmcConstr_rec( Ssw_Man_t * p, Aig_Obj_t * pObj, int f ) +{ + Aig_Obj_t * pObjNew, * pObjLi; + pObjNew = Ssw_ObjFrame( p, pObj, f ); + if ( pObjNew ) + return pObjNew; + assert( !Saig_ObjIsPi(p->pAig, pObj) ); + if ( Saig_ObjIsLo(p->pAig, pObj) ) + { + assert( f > 0 ); + pObjLi = Saig_ObjLoToLi( p->pAig, pObj ); + pObjNew = Ssw_ManSweepBmcConstr_rec( p, Aig_ObjFanin0(pObjLi), f-1 ); + pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObjLi) ); + } + else + { + assert( Aig_ObjIsNode(pObj) ); + Ssw_ManSweepBmcConstr_rec( p, Aig_ObjFanin0(pObj), f ); + Ssw_ManSweepBmcConstr_rec( p, Aig_ObjFanin1(pObj), f ); + pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); + } + Ssw_ObjSetFrame( p, pObj, f, pObjNew ); + assert( pObjNew != NULL ); + return pObjNew; +} + +/**Function************************************************************* + + Synopsis [Performs fraiging for the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ManSweepBmcConstr_old( Ssw_Man_t * p ) +{ + Bar_Progress_t * pProgress = NULL; + Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo; + int i, f, iLits, clk; +clk = clock(); + + // start initialized timeframes + p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK ); + Saig_ManForEachLo( p->pAig, pObj, i ) + Ssw_ObjSetFrame( p, pObj, 0, Aig_ManConst0(p->pFrames) ); + + // build the constraint outputs + iLits = 0; + for ( f = 0; f < p->pPars->nFramesK; f++ ) + { + // map constants and PIs + Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) ); + Saig_ManForEachPi( p->pAig, pObj, i ) + { + pObjNew = Aig_ObjCreatePi(p->pFrames); + pObjNew->fPhase = Vec_IntEntry( p->vInits, iLits++ ); + Ssw_ObjSetFrame( p, pObj, f, pObjNew ); + } + // build the constraint cones + Saig_ManForEachPo( p->pAig, pObj, i ) + { + if ( i < Saig_ManPoNum(p->pAig) - Saig_ManConstrNum(p->pAig) ) + continue; + pObjNew = Ssw_ManSweepBmcConstr_rec( p, Aig_ObjFanin0(pObj), f ); + pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObj) ); + if ( Aig_Regular(pObjNew) == Aig_ManConst1(p->pFrames) ) + { + assert( Aig_IsComplement(pObjNew) ); + continue; + } + Ssw_NodesAreConstrained( p, pObjNew, Aig_ManConst0(p->pFrames) ); + } + } + assert( Vec_IntSize(p->vInits) == iLits + Saig_ManPiNum(p->pAig) ); + + // sweep internal nodes + p->fRefined = 0; + if ( p->pPars->fVerbose ) + pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK ); + for ( f = 0; f < p->pPars->nFramesK; f++ ) + { + // sweep internal nodes + Aig_ManForEachNode( p->pAig, pObj, i ) + { + if ( p->pPars->fVerbose ) + Bar_ProgressUpdate( pProgress, Aig_ManObjNumMax(p->pAig) * f + i, NULL ); + pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); + Ssw_ObjSetFrame( p, pObj, f, pObjNew ); + p->fRefined |= Ssw_ManSweepNodeConstr( p, pObj, f, 1 ); + } + // quit if this is the last timeframe + if ( f == p->pPars->nFramesK - 1 ) + break; + // transfer latch input to the latch outputs + Aig_ManForEachPo( p->pAig, pObj, i ) + Ssw_ObjSetFrame( p, pObj, f, Ssw_ObjChild0Fra(p, pObj, f) ); + // build logic cones for register outputs + Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) + { + pObjNew = Ssw_ObjFrame( p, pObjLi, f ); + Ssw_ObjSetFrame( p, pObjLo, f+1, pObjNew ); + Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pObjNew) );// + } + } + if ( p->pPars->fVerbose ) + Bar_ProgressStop( pProgress ); + + // cleanup +// Ssw_ClassesCheck( p->ppClasses ); +p->timeBmc += clock() - clk; + return p->fRefined; +} + +/**Function************************************************************* + + Synopsis [Performs fraiging for the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ManSweepBmcConstr( Ssw_Man_t * p ) +{ + Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo; + int i, f, iLits, clk; +clk = clock(); + + // start initialized timeframes + p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK ); + Saig_ManForEachLo( p->pAig, pObj, i ) + Ssw_ObjSetFrame( p, pObj, 0, Aig_ManConst0(p->pFrames) ); + + // build the constraint outputs + iLits = 0; + p->fRefined = 0; + for ( f = 0; f < p->pPars->nFramesK; f++ ) + { + // map constants and PIs + Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) ); + Saig_ManForEachPi( p->pAig, pObj, i ) + { + pObjNew = Aig_ObjCreatePi(p->pFrames); + pObjNew->fPhase = Vec_IntEntry( p->vInits, iLits++ ); + Ssw_ObjSetFrame( p, pObj, f, pObjNew ); + } + // build the constraint cones + Saig_ManForEachPo( p->pAig, pObj, i ) + { + if ( i < Saig_ManPoNum(p->pAig) - Saig_ManConstrNum(p->pAig) ) + continue; + pObjNew = Ssw_ManSweepBmcConstr_rec( p, Aig_ObjFanin0(pObj), f ); + pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObj) ); + if ( Aig_Regular(pObjNew) == Aig_ManConst1(p->pFrames) ) + { + assert( Aig_IsComplement(pObjNew) ); + continue; + } + Ssw_NodesAreConstrained( p, pObjNew, Aig_ManConst0(p->pFrames) ); + } + + // sweep internal nodes + Aig_ManForEachNode( p->pAig, pObj, i ) + { + pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); + Ssw_ObjSetFrame( p, pObj, f, pObjNew ); + p->fRefined |= Ssw_ManSweepNodeConstr( p, pObj, f, 1 ); + } + // quit if this is the last timeframe + if ( f == p->pPars->nFramesK - 1 ) + break; + // transfer latch input to the latch outputs + Aig_ManForEachPo( p->pAig, pObj, i ) + Ssw_ObjSetFrame( p, pObj, f, Ssw_ObjChild0Fra(p, pObj, f) ); + // build logic cones for register outputs + Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) + { + pObjNew = Ssw_ObjFrame( p, pObjLi, f ); + Ssw_ObjSetFrame( p, pObjLo, f+1, pObjNew ); + Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pObjNew) );// + } + } + assert( Vec_IntSize(p->vInits) == iLits + Saig_ManPiNum(p->pAig) ); + + // cleanup +// Ssw_ClassesCheck( p->ppClasses ); +p->timeBmc += clock() - clk; + return p->fRefined; +} + + + + +/**Function************************************************************* + + Synopsis [Performs fraiging for the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Ssw_FramesWithClasses_rec( Ssw_Man_t * p, Aig_Obj_t * pObj, int f ) +{ + Aig_Obj_t * pObjNew, * pObjLi; + pObjNew = Ssw_ObjFrame( p, pObj, f ); + if ( pObjNew ) + return pObjNew; + assert( !Saig_ObjIsPi(p->pAig, pObj) ); + if ( Saig_ObjIsLo(p->pAig, pObj) ) + { + assert( f > 0 ); + pObjLi = Saig_ObjLoToLi( p->pAig, pObj ); + pObjNew = Ssw_FramesWithClasses_rec( p, Aig_ObjFanin0(pObjLi), f-1 ); + pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObjLi) ); + } + else + { + assert( Aig_ObjIsNode(pObj) ); + Ssw_FramesWithClasses_rec( p, Aig_ObjFanin0(pObj), f ); + Ssw_FramesWithClasses_rec( p, Aig_ObjFanin1(pObj), f ); + pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); + } + Ssw_ObjSetFrame( p, pObj, f, pObjNew ); + assert( pObjNew != NULL ); + return pObjNew; +} + + +/**Function************************************************************* + + Synopsis [Performs fraiging for the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ManSweepConstr( Ssw_Man_t * p ) +{ + Bar_Progress_t * pProgress = NULL; + Aig_Obj_t * pObj, * pObj2, * pObjNew; + int nConstrPairs, clk, i, f, iLits; +//Ssw_ManPrintPolarity( p->pAig ); + + // perform speculative reduction +clk = clock(); + // create timeframes + p->pFrames = Ssw_FramesWithClasses( p ); + // add constants + nConstrPairs = Aig_ManPoNum(p->pFrames)-Aig_ManRegNum(p->pAig); + assert( (nConstrPairs & 1) == 0 ); + for ( i = 0; i < nConstrPairs; i += 2 ) + { + pObj = Aig_ManPo( p->pFrames, i ); + pObj2 = Aig_ManPo( p->pFrames, i+1 ); + Ssw_NodesAreConstrained( p, Aig_ObjChild0(pObj), Aig_ObjChild0(pObj2) ); + } + // build logic cones for register inputs + for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ ) + { + pObj = Aig_ManPo( p->pFrames, nConstrPairs + i ); + Ssw_CnfNodeAddToSolver( p->pMSat, Aig_ObjFanin0(pObj) );// + } + + // map constants and PIs of the last frame + f = p->pPars->nFramesK; +// iLits = 0; + iLits = f * Saig_ManPiNum(p->pAig); + Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) ); + Saig_ManForEachPi( p->pAig, pObj, i ) + { + pObjNew = Aig_ObjCreatePi(p->pFrames); + pObjNew->fPhase = (p->vInits != NULL) && Vec_IntEntry(p->vInits, iLits++); + Ssw_ObjSetFrame( p, pObj, f, pObjNew ); + } + assert( Vec_IntSize(p->vInits) == iLits ); +p->timeReduce += clock() - clk; + + // add constraints to all timeframes + for ( f = 0; f <= p->pPars->nFramesK; f++ ) + { + Saig_ManForEachPo( p->pAig, pObj, i ) + { + if ( i < Saig_ManPoNum(p->pAig) - Saig_ManConstrNum(p->pAig) ) + continue; + Ssw_FramesWithClasses_rec( p, Aig_ObjFanin0(pObj), f ); +// if ( Aig_Regular(Ssw_ObjChild0Fra(p,pObj,f)) == Aig_ManConst1(p->pFrames) ) + if ( Ssw_ObjChild0Fra(p,pObj,f) == Aig_ManConst0(p->pFrames) ) + continue; + assert( Ssw_ObjChild0Fra(p,pObj,f) != Aig_ManConst1(p->pFrames) ); + if ( Ssw_ObjChild0Fra(p,pObj,f) == Aig_ManConst1(p->pFrames) ) + { + printf( "Polarity violation.\n" ); + continue; + } + Ssw_NodesAreConstrained( p, Ssw_ObjChild0Fra(p,pObj,f), Aig_ManConst0(p->pFrames) ); + } + } + f = p->pPars->nFramesK; + // clean the solver + sat_solver_simplify( p->pMSat->pSat ); + + + // sweep internal nodes + p->fRefined = 0; + Ssw_ClassesClearRefined( p->ppClasses ); + if ( p->pPars->fVerbose ) + pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) ); + Aig_ManForEachObj( p->pAig, pObj, i ) + { + if ( p->pPars->fVerbose ) + Bar_ProgressUpdate( pProgress, i, NULL ); + if ( Saig_ObjIsLo(p->pAig, pObj) ) + p->fRefined |= Ssw_ManSweepNodeConstr( p, pObj, f, 0 ); + else if ( Aig_ObjIsNode(pObj) ) + { + pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); + Ssw_ObjSetFrame( p, pObj, f, pObjNew ); + p->fRefined |= Ssw_ManSweepNodeConstr( p, pObj, f, 0 ); + } + } + if ( p->pPars->fVerbose ) + Bar_ProgressStop( pProgress ); + // cleanup +// Ssw_ClassesCheck( p->ppClasses ); + return p->fRefined; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/ssw/sswCore.c b/src/proof/ssw/sswCore.c new file mode 100644 index 00000000..df48a5b8 --- /dev/null +++ b/src/proof/ssw/sswCore.c @@ -0,0 +1,522 @@ +/**CFile**************************************************************** + + FileName [sswCore.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Inductive prover with constraints.] + + Synopsis [The core procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 1, 2008.] + + Revision [$Id: sswCore.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sswInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [This procedure sets default parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManSetDefaultParams( Ssw_Pars_t * p ) +{ + memset( p, 0, sizeof(Ssw_Pars_t) ); + p->nPartSize = 0; // size of the partition + p->nOverSize = 0; // size of the overlap between partitions + p->nFramesK = 1; // the induction depth + p->nFramesAddSim = 2; // additional frames to simulate + p->fConstrs = 0; // treat the last nConstrs POs as seq constraints + p->fMergeFull = 0; // enables full merge when constraints are used + p->nBTLimit = 1000; // conflict limit at a node + p->nBTLimitGlobal = 5000000; // conflict limit for all runs + p->nMinDomSize = 100; // min clock domain considered for optimization + p->nItersStop = -1; // stop after the given number of iterations + p->nResimDelta = 1000; // the internal of nodes to resimulate + p->nStepsMax = -1; // (scorr only) the max number of induction steps + p->fPolarFlip = 0; // uses polarity adjustment + p->fLatchCorr = 0; // performs register correspondence + p->fConstCorr = 0; // performs constant correspondence + p->fOutputCorr = 0; // perform 'PO correspondence' + p->fSemiFormal = 0; // enable semiformal filtering + p->fDynamic = 0; // dynamic partitioning + p->fLocalSim = 0; // local simulation + p->fVerbose = 0; // verbose stats + p->fEquivDump = 0; // enables dumping equivalences + + // latch correspondence + p->fLatchCorrOpt = 0; // performs optimized register correspondence + p->nSatVarMax = 1000; // the max number of SAT variables + p->nRecycleCalls = 50; // calls to perform before recycling SAT solver + // signal correspondence + p->nSatVarMax2 = 5000; // the max number of SAT variables + p->nRecycleCalls2 = 250; // calls to perform before recycling SAT solver + // return values + p->nIters = 0; // the number of iterations performed +} + +/**Function************************************************************* + + Synopsis [This procedure sets default parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManSetDefaultParamsLcorr( Ssw_Pars_t * p ) +{ + Ssw_ManSetDefaultParams( p ); + p->fLatchCorrOpt = 1; + p->nBTLimit = 10000; +} + +/**Function************************************************************* + + Synopsis [Reports improvements for property cones.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ReportConeReductions( Ssw_Man_t * p, Aig_Man_t * pAigInit, Aig_Man_t * pAigStop ) +{ + Aig_Man_t * pAig1, * pAig2, * pAux; + pAig1 = Aig_ManDupOneOutput( pAigInit, 0, 1 ); + pAig1 = Aig_ManScl( pAux = pAig1, 1, 1, 0, -1, -1, 0, 0 ); + Aig_ManStop( pAux ); + pAig2 = Aig_ManDupOneOutput( pAigStop, 0, 1 ); + pAig2 = Aig_ManScl( pAux = pAig2, 1, 1, 0, -1, -1, 0, 0 ); + Aig_ManStop( pAux ); + + p->nNodesBegC = Aig_ManNodeNum(pAig1); + p->nNodesEndC = Aig_ManNodeNum(pAig2); + p->nRegsBegC = Aig_ManRegNum(pAig1); + p->nRegsEndC = Aig_ManRegNum(pAig2); + + Aig_ManStop( pAig1 ); + Aig_ManStop( pAig2 ); +} + +/**Function************************************************************* + + Synopsis [Reports one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ReportOneOutput( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + if ( pObj == Aig_ManConst1(p) ) + printf( "1" ); + else if ( pObj == Aig_ManConst0(p) ) + printf( "0" ); + else + printf( "X" ); +} + +/**Function************************************************************* + + Synopsis [Reports improvements for property cones.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ReportOutputs( Aig_Man_t * pAig ) +{ + Aig_Obj_t * pObj; + int i; + Saig_ManForEachPo( pAig, pObj, i ) + { + if ( i < Saig_ManPoNum(pAig)-Saig_ManConstrNum(pAig) ) + printf( "o" ); + else + printf( "c" ); + Ssw_ReportOneOutput( pAig, Aig_ObjChild0(pObj) ); + } + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Remove from-equivs that are in the cone of constraints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManUpdateEquivs( Ssw_Man_t * p, Aig_Man_t * pAig, int fVerbose ) +{ + Vec_Ptr_t * vCones; + Aig_Obj_t ** pArray; + Aig_Obj_t * pObj; + int i, nTotal = 0, nRemoved = 0; + // collect the nodes in the cone of constraints + pArray = (Aig_Obj_t **)Vec_PtrArray(pAig->vPos); + pArray += Saig_ManPoNum(pAig) - Saig_ManConstrNum(pAig); + vCones = Aig_ManDfsNodes( pAig, pArray, Saig_ManConstrNum(pAig) ); + // remove all the node that are equiv to something and are in the cones + Aig_ManForEachObj( pAig, pObj, i ) + { + if ( !Aig_ObjIsPi(pObj) && !Aig_ObjIsNode(pObj) ) + continue; + if ( pAig->pReprs[i] != NULL ) + nTotal++; + if ( !Aig_ObjIsTravIdCurrent(pAig, pObj) ) + continue; + if ( pAig->pReprs[i] ) + { + if ( p->pPars->fConstrs && !p->pPars->fMergeFull ) + { + pAig->pReprs[i] = NULL; + nRemoved++; + } + } + } + // collect statistics + p->nConesTotal = Aig_ManPiNum(pAig) + Aig_ManNodeNum(pAig); + p->nConesConstr = Vec_PtrSize(vCones); + p->nEquivsTotal = nTotal; + p->nEquivsConstr = nRemoved; + Vec_PtrFree( vCones ); +} + +/**Function************************************************************* + + Synopsis [Performs computation of signal correspondence with constraints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Ssw_SignalCorrespondenceRefine( Ssw_Man_t * p ) +{ + int nSatProof, nSatCallsSat, nRecycles, nSatFailsReal, nUniques; + Aig_Man_t * pAigNew; + int RetValue, nIter = -1; + int clk, clkTotal = clock(); + // get the starting stats + p->nLitsBeg = Ssw_ClassesLitNum( p->ppClasses ); + p->nNodesBeg = Aig_ManNodeNum(p->pAig); + p->nRegsBeg = Aig_ManRegNum(p->pAig); + // refine classes using BMC + if ( p->pPars->fVerbose ) + { + printf( "Before BMC: " ); + Ssw_ClassesPrint( p->ppClasses, 0 ); + } + if ( !p->pPars->fLatchCorr ) + { + p->pMSat = Ssw_SatStart( 0 ); + if ( p->pPars->fConstrs ) + Ssw_ManSweepBmcConstr( p ); + else + Ssw_ManSweepBmc( p ); + Ssw_SatStop( p->pMSat ); + p->pMSat = NULL; + Ssw_ManCleanup( p ); + } + if ( p->pPars->fVerbose ) + { + printf( "After BMC: " ); + Ssw_ClassesPrint( p->ppClasses, 0 ); + } + // apply semi-formal filtering +/* + if ( p->pPars->fSemiFormal ) + { + Aig_Man_t * pSRed; + Ssw_FilterUsingSemi( p, 0, 2000, p->pPars->fVerbose ); +// Ssw_FilterUsingSemi( p, 1, 100000, p->pPars->fVerbose ); + pSRed = Ssw_SpeculativeReduction( p ); + Aig_ManDumpBlif( pSRed, "srm.blif", NULL, NULL ); + Aig_ManStop( pSRed ); + } +*/ + if ( p->pPars->pFunc ) + { + ((int (*)(void *))p->pPars->pFunc)( p->pPars->pData ); + ((int (*)(void *))p->pPars->pFunc)( p->pPars->pData ); + } + if ( p->pPars->nStepsMax == 0 ) + { + printf( "Stopped signal correspondence after BMC.\n" ); + goto finalize; + } + // refine classes using induction + nSatProof = nSatCallsSat = nRecycles = nSatFailsReal = nUniques = 0; + for ( nIter = 0; ; nIter++ ) + { + if ( p->pPars->nStepsMax == nIter ) + { + printf( "Stopped signal correspondence after %d refiment iterations.\n", nIter ); + goto finalize; + } + if ( p->pPars->nItersStop >= 0 && p->pPars->nItersStop == nIter ) + { + Aig_Man_t * pSRed = Ssw_SpeculativeReduction( p ); + Aig_ManDumpBlif( pSRed, "srm.blif", NULL, NULL ); + Aig_ManStop( pSRed ); + printf( "Iterative refinement is stopped before iteration %d.\n", nIter ); + printf( "The network is reduced using candidate equivalences.\n" ); + printf( "Speculatively reduced miter is saved in file \"%s\".\n", "srm.blif" ); + printf( "If the miter is SAT, the reduced result is incorrect.\n" ); + break; + } + +clk = clock(); + p->pMSat = Ssw_SatStart( 0 ); + if ( p->pPars->fLatchCorrOpt ) + { + RetValue = Ssw_ManSweepLatch( p ); + if ( p->pPars->fVerbose ) + { + printf( "%3d : C =%7d. Cl =%7d. Pr =%6d. Cex =%5d. R =%4d. F =%4d. ", + nIter, Ssw_ClassesCand1Num(p->ppClasses), Ssw_ClassesClassNum(p->ppClasses), + p->nSatProof-nSatProof, p->nSatCallsSat-nSatCallsSat, + p->nRecycles-nRecycles, p->nSatFailsReal-nSatFailsReal ); + ABC_PRT( "T", clock() - clk ); + } + } + else + { + if ( p->pPars->fConstrs ) + RetValue = Ssw_ManSweepConstr( p ); + else if ( p->pPars->fDynamic ) + RetValue = Ssw_ManSweepDyn( p ); + else + RetValue = Ssw_ManSweep( p ); + + p->pPars->nConflicts += p->pMSat->pSat->stats.conflicts; + if ( p->pPars->fVerbose ) + { + printf( "%3d : C =%7d. Cl =%7d. LR =%6d. NR =%6d. ", + nIter, Ssw_ClassesCand1Num(p->ppClasses), Ssw_ClassesClassNum(p->ppClasses), + p->nConstrReduced, Aig_ManNodeNum(p->pFrames) ); + if ( p->pPars->fDynamic ) + { + printf( "Cex =%5d. ", p->nSatCallsSat-nSatCallsSat ); + printf( "R =%4d. ", p->nRecycles-nRecycles ); + } + printf( "F =%5d. %s ", p->nSatFailsReal-nSatFailsReal, + (Saig_ManPoNum(p->pAig)==1 && Ssw_ObjIsConst1Cand(p->pAig,Aig_ObjFanin0(Aig_ManPo(p->pAig,0))))? "+" : "-" ); + ABC_PRT( "T", clock() - clk ); + } +// if ( p->pPars->fDynamic && p->nSatCallsSat-nSatCallsSat < 100 ) +// p->pPars->nBTLimit = 10000; + } + nSatProof = p->nSatProof; + nSatCallsSat = p->nSatCallsSat; + nRecycles = p->nRecycles; + nSatFailsReal = p->nSatFailsReal; + nUniques = p->nUniques; + + p->nVarsMax = Abc_MaxInt( p->nVarsMax, p->pMSat->nSatVars ); + p->nCallsMax = Abc_MaxInt( p->nCallsMax, p->pMSat->nSolverCalls ); + Ssw_SatStop( p->pMSat ); + p->pMSat = NULL; + Ssw_ManCleanup( p ); + if ( !RetValue ) + break; + if ( p->pPars->pFunc ) + ((int (*)(void *))p->pPars->pFunc)( p->pPars->pData ); + } + +finalize: + p->pPars->nIters = nIter + 1; +p->timeTotal = clock() - clkTotal; + + Ssw_ManUpdateEquivs( p, p->pAig, p->pPars->fVerbose ); + pAigNew = Aig_ManDupRepr( p->pAig, 0 ); + Aig_ManSeqCleanup( pAigNew ); +//Ssw_ClassesPrint( p->ppClasses, 1 ); + // get the final stats + p->nLitsEnd = Ssw_ClassesLitNum( p->ppClasses ); + p->nNodesEnd = Aig_ManNodeNum(pAigNew); + p->nRegsEnd = Aig_ManRegNum(pAigNew); + // cleanup + Aig_ManSetPhase( p->pAig ); + Aig_ManCleanMarkB( p->pAig ); + return pAigNew; +} + +/**Function************************************************************* + + Synopsis [Performs computation of signal correspondence with constraints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Ssw_SignalCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars ) +{ + Ssw_Pars_t Pars; + Aig_Man_t * pAigNew; + Ssw_Man_t * p; + assert( Aig_ManRegNum(pAig) > 0 ); + // reset random numbers + Aig_ManRandom( 1 ); + // if parameters are not given, create them + if ( pPars == NULL ) + Ssw_ManSetDefaultParams( pPars = &Pars ); + // consider the case of empty AIG + if ( Aig_ManNodeNum(pAig) == 0 ) + { + pPars->nIters = 0; + // Ntl_ManFinalize() needs the following to satisfy an assertion + Aig_ManReprStart( pAig,Aig_ManObjNumMax(pAig) ); + return Aig_ManDupOrdered(pAig); + } + // check and update parameters + if ( pPars->fLatchCorrOpt ) + { + pPars->fLatchCorr = 1; + pPars->nFramesAddSim = 0; + if ( (pAig->vClockDoms && Vec_VecSize(pAig->vClockDoms) > 0) ) + return Ssw_SignalCorrespondencePart( pAig, pPars ); + } + else + { + assert( pPars->nFramesK > 0 ); + // perform partitioning + if ( (pPars->nPartSize > 0 && pPars->nPartSize < Aig_ManRegNum(pAig)) + || (pAig->vClockDoms && Vec_VecSize(pAig->vClockDoms) > 0) ) + return Ssw_SignalCorrespondencePart( pAig, pPars ); + } + + if ( pPars->fScorrGia ) + { + if ( pPars->fLatchCorrOpt ) + { + extern Aig_Man_t * Cec_LatchCorrespondence( Aig_Man_t * pAig, int nConfs, int fUseCSat ); + return Cec_LatchCorrespondence( pAig, pPars->nBTLimit, pPars->fUseCSat ); + } + else + { + extern Aig_Man_t * Cec_SignalCorrespondence( Aig_Man_t * pAig, int nConfs, int fUseCSat ); + return Cec_SignalCorrespondence( pAig, pPars->nBTLimit, pPars->fUseCSat ); + } + } + + // start the induction manager + p = Ssw_ManCreate( pAig, pPars ); + // compute candidate equivalence classes +// p->pPars->nConstrs = 1; + if ( p->pPars->fConstrs ) + { + // create trivial equivalence classes with all nodes being candidates for constant 1 + p->ppClasses = Ssw_ClassesPrepareSimple( pAig, pPars->fLatchCorr, pPars->nMaxLevs ); + Ssw_ClassesSetData( p->ppClasses, NULL, NULL, Ssw_SmlObjIsConstBit, Ssw_SmlObjsAreEqualBit ); + // derive phase bits to satisfy the constraints + if ( Ssw_ManSetConstrPhases( pAig, p->pPars->nFramesK + 1, &p->vInits ) != 0 ) + { + printf( "Ssw_SignalCorrespondence(): The init state does not satisfy the constraints!\n" ); + p->pPars->fVerbose = 0; + Ssw_ManStop( p ); + return NULL; + } + // perform simulation of the first timeframes + Ssw_ManRefineByConstrSim( p ); + } + else + { + // perform one round of seq simulation and generate candidate equivalence classes + p->ppClasses = Ssw_ClassesPrepare( pAig, pPars->nFramesK, pPars->fLatchCorr, pPars->fConstCorr, pPars->fOutputCorr, pPars->nMaxLevs, pPars->fVerbose ); +// p->ppClasses = Ssw_ClassesPrepareTargets( pAig ); + if ( pPars->fLatchCorrOpt ) + p->pSml = Ssw_SmlStart( pAig, 0, 2, 1 ); + else if ( pPars->fDynamic ) + p->pSml = Ssw_SmlStart( pAig, 0, p->nFrames + p->pPars->nFramesAddSim, 1 ); + else + p->pSml = Ssw_SmlStart( pAig, 0, 1 + p->pPars->nFramesAddSim, 1 ); + Ssw_ClassesSetData( p->ppClasses, p->pSml, (unsigned(*)(void *,Aig_Obj_t *))Ssw_SmlObjHashWord, (int(*)(void *,Aig_Obj_t *))Ssw_SmlObjIsConstWord, (int(*)(void *,Aig_Obj_t *,Aig_Obj_t *))Ssw_SmlObjsAreEqualWord ); + } + // allocate storage + if ( p->pPars->fLocalSim ) + p->pVisited = ABC_CALLOC( int, Ssw_SmlNumFrames( p->pSml ) * Aig_ManObjNumMax(p->pAig) ); + // perform refinement of classes + pAigNew = Ssw_SignalCorrespondenceRefine( p ); +// Ssw_ReportOutputs( pAigNew ); + if ( pPars->fConstrs && pPars->fVerbose ) + Ssw_ReportConeReductions( p, pAig, pAigNew ); + // cleanup + Ssw_ManStop( p ); + return pAigNew; +} + +/**Function************************************************************* + + Synopsis [Performs computation of latch correspondence.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Ssw_LatchCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars ) +{ + Aig_Man_t * pRes; + Ssw_Pars_t Pars; + if ( pPars == NULL ) + Ssw_ManSetDefaultParamsLcorr( pPars = &Pars ); + pRes = Ssw_SignalCorrespondence( pAig, pPars ); +// if ( pPars->fConstrs && pPars->fVerbose ) +// Ssw_ReportConeReductions( pAig, pRes ); + return pRes; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/ssw/sswDyn.c b/src/proof/ssw/sswDyn.c new file mode 100644 index 00000000..d9a16e22 --- /dev/null +++ b/src/proof/ssw/sswDyn.c @@ -0,0 +1,489 @@ +/**CFile**************************************************************** + + FileName [sswDyn.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Inductive prover with constraints.] + + Synopsis [Dynamic loading of constraints.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 1, 2008.] + + Revision [$Id: sswDyn.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sswInt.h" +#include "src/misc/bar/bar.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Label PIs nodes of the frames corresponding to PIs of AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManLabelPiNodes( Ssw_Man_t * p ) +{ + Aig_Obj_t * pObj, * pObjFrames; + int f, i; + Aig_ManConst1( p->pFrames )->fMarkA = 1; + Aig_ManConst1( p->pFrames )->fMarkB = 1; + for ( f = 0; f < p->nFrames; f++ ) + { + Saig_ManForEachPi( p->pAig, pObj, i ) + { + pObjFrames = Ssw_ObjFrame( p, pObj, f ); + assert( Aig_ObjIsPi(pObjFrames) ); + assert( pObjFrames->fMarkB == 0 ); + pObjFrames->fMarkA = 1; + pObjFrames->fMarkB = 1; + } + } +} + +/**Function************************************************************* + + Synopsis [Collects new POs in p->vNewPos.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManCollectPis_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vNewPis ) +{ + assert( !Aig_IsComplement(pObj) ); + if ( pObj->fMarkA ) + return; + pObj->fMarkA = 1; + if ( Aig_ObjIsPi(pObj) ) + { + Vec_PtrPush( vNewPis, pObj ); + return; + } + assert( Aig_ObjIsNode(pObj) ); + Ssw_ManCollectPis_rec( Aig_ObjFanin0(pObj), vNewPis ); + Ssw_ManCollectPis_rec( Aig_ObjFanin1(pObj), vNewPis ); +} + +/**Function************************************************************* + + Synopsis [Collects new POs in p->vNewPos.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManCollectPos_rec( Ssw_Man_t * p, Aig_Obj_t * pObj, Vec_Int_t * vNewPos ) +{ + Aig_Obj_t * pFanout; + int iFanout = -1, i; + assert( !Aig_IsComplement(pObj) ); + if ( pObj->fMarkB ) + return; + pObj->fMarkB = 1; + if ( pObj->Id > p->nSRMiterMaxId ) + return; + if ( Aig_ObjIsPo(pObj) ) + { + // skip if it is a register input PO + if ( Aig_ObjPioNum(pObj) >= Aig_ManPoNum(p->pFrames)-Aig_ManRegNum(p->pAig) ) + return; + // add the number of this constraint + Vec_IntPush( vNewPos, Aig_ObjPioNum(pObj)/2 ); + return; + } + // visit the fanouts + assert( p->pFrames->pFanData != NULL ); + Aig_ObjForEachFanout( p->pFrames, pObj, pFanout, iFanout, i ) + Ssw_ManCollectPos_rec( p, pFanout, vNewPos ); +} + +/**Function************************************************************* + + Synopsis [Loads logic cones and relevant constraints.] + + Description [Both pRepr and pObj are objects of the AIG. + The result is the current SAT solver loaded with the logic cones + for pRepr and pObj corresponding to them in the frames, + as well as all the relevant constraints.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManLoadSolver( Ssw_Man_t * p, Aig_Obj_t * pRepr, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pObjFrames, * pReprFrames; + Aig_Obj_t * pTemp, * pObj0, * pObj1; + int i, iConstr, RetValue; + + assert( pRepr != pObj ); + // get the corresponding frames nodes + pReprFrames = Aig_Regular( Ssw_ObjFrame( p, pRepr, p->pPars->nFramesK ) ); + pObjFrames = Aig_Regular( Ssw_ObjFrame( p, pObj, p->pPars->nFramesK ) ); + assert( pReprFrames != pObjFrames ); + /* + // compute the AIG support + Vec_PtrClear( p->vNewLos ); + Ssw_ManCollectPis_rec( pRepr, p->vNewLos ); + Ssw_ManCollectPis_rec( pObj, p->vNewLos ); + // add logic cones for register outputs + Vec_PtrForEachEntry( Aig_Obj_t *, p->vNewLos, pTemp, i ) + { + pObj0 = Aig_Regular( Ssw_ObjFrame( p, pTemp, p->pPars->nFramesK ) ); + Ssw_CnfNodeAddToSolver( p->pMSat, pObj0 ); + } +*/ + // add cones for the nodes + Ssw_CnfNodeAddToSolver( p->pMSat, pReprFrames ); + Ssw_CnfNodeAddToSolver( p->pMSat, pObjFrames ); + + // compute the frames support + Vec_PtrClear( p->vNewLos ); + Ssw_ManCollectPis_rec( pReprFrames, p->vNewLos ); + Ssw_ManCollectPis_rec( pObjFrames, p->vNewLos ); + // these nodes include both nodes corresponding to PIs and LOs + // (the nodes corresponding to PIs should be labeled with fMarkB!) + + // collect the related constraint POs + Vec_IntClear( p->vNewPos ); + Vec_PtrForEachEntry( Aig_Obj_t *, p->vNewLos, pTemp, i ) + Ssw_ManCollectPos_rec( p, pTemp, p->vNewPos ); + // check if the corresponding pairs are added + Vec_IntForEachEntry( p->vNewPos, iConstr, i ) + { + pObj0 = Aig_ManPo( p->pFrames, 2*iConstr ); + pObj1 = Aig_ManPo( p->pFrames, 2*iConstr+1 ); +// if ( pObj0->fMarkB && pObj1->fMarkB ) + if ( pObj0->fMarkB || pObj1->fMarkB ) + { + pObj0->fMarkB = 1; + pObj1->fMarkB = 1; + Ssw_NodesAreConstrained( p, Aig_ObjChild0(pObj0), Aig_ObjChild0(pObj1) ); + } + } + if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead ) + { + RetValue = sat_solver_simplify(p->pMSat->pSat); + assert( RetValue != 0 ); + } +} + +/**Function************************************************************* + + Synopsis [Tranfers simulation information from FRAIG to AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManSweepTransferDyn( Ssw_Man_t * p ) +{ + Aig_Obj_t * pObj, * pObjFraig; + unsigned * pInfo; + int i, f, nFrames; + + // transfer simulation information + Aig_ManForEachPi( p->pAig, pObj, i ) + { + pObjFraig = Ssw_ObjFrame( p, pObj, 0 ); + if ( pObjFraig == Aig_ManConst0(p->pFrames) ) + { + Ssw_SmlObjAssignConst( p->pSml, pObj, 0, 0 ); + continue; + } + assert( !Aig_IsComplement(pObjFraig) ); + assert( Aig_ObjIsPi(pObjFraig) ); + pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjPioNum(pObjFraig) ); + Ssw_SmlObjSetWord( p->pSml, pObj, pInfo[0], 0, 0 ); + } + // set random simulation info for the second frame + for ( f = 1; f < p->nFrames; f++ ) + { + Saig_ManForEachPi( p->pAig, pObj, i ) + { + pObjFraig = Ssw_ObjFrame( p, pObj, f ); + assert( !Aig_IsComplement(pObjFraig) ); + assert( Aig_ObjIsPi(pObjFraig) ); + pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjPioNum(pObjFraig) ); + Ssw_SmlObjSetWord( p->pSml, pObj, pInfo[0], 0, f ); + } + } + // create random info + nFrames = Ssw_SmlNumFrames( p->pSml ); + for ( ; f < nFrames; f++ ) + { + Saig_ManForEachPi( p->pAig, pObj, i ) + Ssw_SmlAssignRandomFrame( p->pSml, pObj, f ); + } +} + +/**Function************************************************************* + + Synopsis [Performs one round of simulation with counter-examples.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ManSweepResimulateDyn( Ssw_Man_t * p, int f ) +{ + int RetValue1, RetValue2, clk = clock(); + // transfer PI simulation information from storage +// Ssw_SmlAssignDist1Plus( p->pSml, p->pPatWords ); + Ssw_ManSweepTransferDyn( p ); + // simulate internal nodes +// Ssw_SmlSimulateOneFrame( p->pSml ); + Ssw_SmlSimulateOne( p->pSml ); + // check equivalence classes + RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 1 ); + RetValue2 = Ssw_ClassesRefine( p->ppClasses, 1 ); + // prepare simulation info for the next round + Vec_PtrCleanSimInfo( p->vSimInfo, 0, 1 ); + p->nPatterns = 0; + p->nSimRounds++; +p->timeSimSat += clock() - clk; + return RetValue1 > 0 || RetValue2 > 0; +} + +/**Function************************************************************* + + Synopsis [Performs one round of simulation with counter-examples.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ManSweepResimulateDynLocal( Ssw_Man_t * p, int f ) +{ + Aig_Obj_t * pObj, * pRepr, ** ppClass; + int i, k, nSize, RetValue1, RetValue2, clk = clock(); + p->nSimRounds++; + // transfer PI simulation information from storage +// Ssw_SmlAssignDist1Plus( p->pSml, p->pPatWords ); + Ssw_ManSweepTransferDyn( p ); + // determine const1 cands and classes to be simulated + Vec_PtrClear( p->vResimConsts ); + Vec_PtrClear( p->vResimClasses ); + Aig_ManIncrementTravId( p->pAig ); + for ( i = p->iNodeStart; i < p->iNodeLast + p->pPars->nResimDelta; i++ ) + { + if ( i >= Aig_ManObjNumMax( p->pAig ) ) + break; + pObj = Aig_ManObj( p->pAig, i ); + if ( pObj == NULL ) + continue; + if ( Ssw_ObjIsConst1Cand(p->pAig, pObj) ) + { + Vec_PtrPush( p->vResimConsts, pObj ); + continue; + } + pRepr = Aig_ObjRepr(p->pAig, pObj); + if ( pRepr == NULL ) + continue; + if ( Aig_ObjIsTravIdCurrent(p->pAig, pRepr) ) + continue; + Aig_ObjSetTravIdCurrent(p->pAig, pRepr); + Vec_PtrPush( p->vResimClasses, pRepr ); + } + // simulate internal nodes +// Ssw_SmlSimulateOneFrame( p->pSml ); +// Ssw_SmlSimulateOne( p->pSml ); + // resimulate dynamically +// Aig_ManIncrementTravId( p->pAig ); +// Aig_ObjIsTravIdCurrent( p->pAig, Aig_ManConst1(p->pAig) ); + p->nVisCounter++; + Vec_PtrForEachEntry( Aig_Obj_t *, p->vResimConsts, pObj, i ) + Ssw_SmlSimulateOneDyn_rec( p->pSml, pObj, p->nFrames-1, p->pVisited, p->nVisCounter ); + // resimulate the cone of influence of the cand classes + Vec_PtrForEachEntry( Aig_Obj_t *, p->vResimClasses, pRepr, i ) + { + ppClass = Ssw_ClassesReadClass( p->ppClasses, pRepr, &nSize ); + for ( k = 0; k < nSize; k++ ) + Ssw_SmlSimulateOneDyn_rec( p->pSml, ppClass[k], p->nFrames-1, p->pVisited, p->nVisCounter ); + } + + // check equivalence classes +// RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 1 ); +// RetValue2 = Ssw_ClassesRefine( p->ppClasses, 1 ); + // refine these nodes + RetValue1 = Ssw_ClassesRefineConst1Group( p->ppClasses, p->vResimConsts, 1 ); + RetValue2 = 0; + Vec_PtrForEachEntry( Aig_Obj_t *, p->vResimClasses, pRepr, i ) + RetValue2 += Ssw_ClassesRefineOneClass( p->ppClasses, pRepr, 1 ); + + // prepare simulation info for the next round + Vec_PtrCleanSimInfo( p->vSimInfo, 0, 1 ); + p->nPatterns = 0; + p->nSimRounds++; +p->timeSimSat += clock() - clk; + return RetValue1 > 0 || RetValue2 > 0; +} + +/**Function************************************************************* + + Synopsis [Performs fraiging for the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ManSweepDyn( Ssw_Man_t * p ) +{ + Bar_Progress_t * pProgress = NULL; + Aig_Obj_t * pObj, * pObjNew; + int clk, i, f; + + // perform speculative reduction +clk = clock(); + // create timeframes + p->pFrames = Ssw_FramesWithClasses( p ); + Aig_ManFanoutStart( p->pFrames ); + p->nSRMiterMaxId = Aig_ManObjNumMax( p->pFrames ); + + // map constants and PIs of the last frame + f = p->pPars->nFramesK; + Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) ); + Saig_ManForEachPi( p->pAig, pObj, i ) + Ssw_ObjSetFrame( p, pObj, f, Aig_ObjCreatePi(p->pFrames) ); + Aig_ManSetPioNumbers( p->pFrames ); + // label nodes corresponding to primary inputs + Ssw_ManLabelPiNodes( p ); +p->timeReduce += clock() - clk; + + // prepare simulation info + assert( p->vSimInfo == NULL ); + p->vSimInfo = Vec_PtrAllocSimInfo( Aig_ManPiNum(p->pFrames), 1 ); + Vec_PtrCleanSimInfo( p->vSimInfo, 0, 1 ); + + // sweep internal nodes + p->fRefined = 0; + Ssw_ClassesClearRefined( p->ppClasses ); + if ( p->pPars->fVerbose ) + pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) ); + p->iNodeStart = 0; + Aig_ManForEachObj( p->pAig, pObj, i ) + { + if ( p->iNodeStart == 0 ) + p->iNodeStart = i; + if ( p->pPars->fVerbose ) + Bar_ProgressUpdate( pProgress, i, NULL ); + if ( Saig_ObjIsLo(p->pAig, pObj) ) + p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 0, NULL ); + else if ( Aig_ObjIsNode(pObj) ) + { + pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); + Ssw_ObjSetFrame( p, pObj, f, pObjNew ); + p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 0, NULL ); + } + // check if it is time to recycle the solver + if ( p->pMSat->pSat == NULL || + (p->pPars->nSatVarMax2 && + p->pMSat->nSatVars > p->pPars->nSatVarMax2 && + p->nRecycleCalls > p->pPars->nRecycleCalls2) ) + { + // resimulate + if ( p->nPatterns > 0 ) + { + p->iNodeLast = i; + if ( p->pPars->fLocalSim ) + Ssw_ManSweepResimulateDynLocal( p, f ); + else + Ssw_ManSweepResimulateDyn( p, f ); + p->iNodeStart = i+1; + } +// printf( "Recycling SAT solver with %d vars and %d calls.\n", +// p->pMSat->nSatVars, p->nRecycleCalls ); +// Aig_ManCleanMarkAB( p->pAig ); + Aig_ManCleanMarkAB( p->pFrames ); + // label nodes corresponding to primary inputs + Ssw_ManLabelPiNodes( p ); + // replace the solver + if ( p->pMSat ) + { + p->nVarsMax = Abc_MaxInt( p->nVarsMax, p->pMSat->nSatVars ); + p->nCallsMax = Abc_MaxInt( p->nCallsMax, p->pMSat->nSolverCalls ); + Ssw_SatStop( p->pMSat ); + p->nRecycles++; + p->nRecyclesTotal++; + p->nRecycleCalls = 0; + } + p->pMSat = Ssw_SatStart( 0 ); + assert( p->nPatterns == 0 ); + } + // resimulate + if ( p->nPatterns == 32 ) + { + p->iNodeLast = i; + if ( p->pPars->fLocalSim ) + Ssw_ManSweepResimulateDynLocal( p, f ); + else + Ssw_ManSweepResimulateDyn( p, f ); + p->iNodeStart = i+1; + } + } + // resimulate + if ( p->nPatterns > 0 ) + { + p->iNodeLast = i; + if ( p->pPars->fLocalSim ) + Ssw_ManSweepResimulateDynLocal( p, f ); + else + Ssw_ManSweepResimulateDyn( p, f ); + } + // collect stats + if ( p->pPars->fVerbose ) + Bar_ProgressStop( pProgress ); + + // cleanup +// Ssw_ClassesCheck( p->ppClasses ); + return p->fRefined; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/ssw/sswFilter.c b/src/proof/ssw/sswFilter.c new file mode 100644 index 00000000..380ac7e5 --- /dev/null +++ b/src/proof/ssw/sswFilter.c @@ -0,0 +1,493 @@ +/**CFile**************************************************************** + + FileName [sswConstr.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Inductive prover with constraints.] + + Synopsis [One round of SAT sweeping.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 1, 2008.] + + Revision [$Id: sswConstr.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sswInt.h" +#include "src/aig/gia/giaAig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs fraiging for one node.] + + Description [Returns the fraiged node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManRefineByFilterSim( Ssw_Man_t * p, int nFrames ) +{ + Aig_Obj_t * pObj, * pObjLi; + int f, i, RetValue1, RetValue2; + assert( nFrames > 0 ); + // assign register outputs + Saig_ManForEachLi( p->pAig, pObj, i ) + pObj->fMarkB = Abc_InfoHasBit( p->pPatWords, Saig_ManPiNum(p->pAig) + i ); + // simulate the timeframes + for ( f = 0; f < nFrames; f++ ) + { + // set the PI simulation information + Aig_ManConst1(p->pAig)->fMarkB = 1; + Saig_ManForEachPi( p->pAig, pObj, i ) + pObj->fMarkB = 0; + Saig_ManForEachLiLo( p->pAig, pObjLi, pObj, i ) + pObj->fMarkB = pObjLi->fMarkB; + // simulate internal nodes + Aig_ManForEachNode( p->pAig, pObj, i ) + pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ) + & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) ); + // assign the COs + Aig_ManForEachPo( p->pAig, pObj, i ) + pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ); + // transfer + if ( f == 0 ) + { // copy markB into phase + Aig_ManForEachObj( p->pAig, pObj, i ) + pObj->fPhase = pObj->fMarkB; + } + else + { // refine classes + RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 0 ); + RetValue2 = Ssw_ClassesRefine( p->ppClasses, 0 ); + } + } +} + + +/**Function************************************************************* + + Synopsis [Performs fraiging for one node.] + + Description [Returns the fraiged node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManRollForward( Ssw_Man_t * p, int nFrames ) +{ + Aig_Obj_t * pObj, * pObjLi; + int f, i; + assert( nFrames > 0 ); + // assign register outputs + Saig_ManForEachLi( p->pAig, pObj, i ) + pObj->fMarkB = Abc_InfoHasBit( p->pPatWords, Saig_ManPiNum(p->pAig) + i ); + // simulate the timeframes + for ( f = 0; f < nFrames; f++ ) + { + // set the PI simulation information + Aig_ManConst1(p->pAig)->fMarkB = 1; + Saig_ManForEachPi( p->pAig, pObj, i ) + pObj->fMarkB = Aig_ManRandom(0) & 1; + Saig_ManForEachLiLo( p->pAig, pObjLi, pObj, i ) + pObj->fMarkB = pObjLi->fMarkB; + // simulate internal nodes + Aig_ManForEachNode( p->pAig, pObj, i ) + pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ) + & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) ); + // assign the COs + Aig_ManForEachPo( p->pAig, pObj, i ) + pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ); + } + // record the new pattern + Saig_ManForEachLi( p->pAig, pObj, i ) + if ( pObj->fMarkB ^ Abc_InfoHasBit(p->pPatWords, Saig_ManPiNum(p->pAig) + i) ) + Abc_InfoXorBit( p->pPatWords, Saig_ManPiNum(p->pAig) + i ); +} + +/**Function************************************************************* + + Synopsis [Performs fraiging for one node.] + + Description [Returns the fraiged node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManFindStartingState( Ssw_Man_t * p, Abc_Cex_t * pCex ) +{ + Aig_Obj_t * pObj, * pObjLi; + int f, i, iBit; + // assign register outputs + Saig_ManForEachLi( p->pAig, pObj, i ) + pObj->fMarkB = 0; + // simulate the timeframes + iBit = pCex->nRegs; + for ( f = 0; f <= pCex->iFrame; f++ ) + { + // set the PI simulation information + Aig_ManConst1(p->pAig)->fMarkB = 1; + Saig_ManForEachPi( p->pAig, pObj, i ) + pObj->fMarkB = Abc_InfoHasBit( pCex->pData, iBit++ ); + Saig_ManForEachLiLo( p->pAig, pObjLi, pObj, i ) + pObj->fMarkB = pObjLi->fMarkB; + // simulate internal nodes + Aig_ManForEachNode( p->pAig, pObj, i ) + pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ) + & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) ); + // assign the COs + Aig_ManForEachPo( p->pAig, pObj, i ) + pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ); + } + assert( iBit == pCex->nBits ); + // check that the output failed as expected -- cannot check because it is not an SRM! +// pObj = Aig_ManPo( p->pAig, pCex->iPo ); +// if ( pObj->fMarkB != 1 ) +// printf( "The counter-example does not refine the output.\n" ); + // record the new pattern + Saig_ManForEachLo( p->pAig, pObj, i ) + if ( pObj->fMarkB ^ Abc_InfoHasBit(p->pPatWords, Saig_ManPiNum(p->pAig) + i) ) + Abc_InfoXorBit( p->pPatWords, Saig_ManPiNum(p->pAig) + i ); +} + +/**Function************************************************************* + + Synopsis [Performs fraiging for one node.] + + Description [Returns the fraiged node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ManSweepNodeFilter( Ssw_Man_t * p, Aig_Obj_t * pObj, int f ) +{ + Aig_Obj_t * pObjRepr, * pObjFraig, * pObjFraig2, * pObjReprFraig; + int RetValue; + // get representative of this class + pObjRepr = Aig_ObjRepr( p->pAig, pObj ); + if ( pObjRepr == NULL ) + return 0; + // get the fraiged node + pObjFraig = Ssw_ObjFrame( p, pObj, f ); + // get the fraiged representative + pObjReprFraig = Ssw_ObjFrame( p, pObjRepr, f ); + // check if constant 0 pattern distinquishes these nodes + assert( pObjFraig != NULL && pObjReprFraig != NULL ); + assert( (pObj->fPhase == pObjRepr->fPhase) == (Aig_ObjPhaseReal(pObjFraig) == Aig_ObjPhaseReal(pObjReprFraig)) ); + // if the fraiged nodes are the same, return + if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) ) + return 0; + // call equivalence checking + if ( Aig_Regular(pObjFraig) != Aig_ManConst1(p->pFrames) ) + RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) ); + else + RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjFraig), Aig_Regular(pObjReprFraig) ); + if ( RetValue == 1 ) // proved equivalent + { + pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase ); + Ssw_ObjSetFrame( p, pObj, f, pObjFraig2 ); + return 0; + } + if ( RetValue == -1 ) // timed out + { +// Ssw_ClassesRemoveNode( p->ppClasses, pObj ); + return 1; + } + // disproved equivalence + Ssw_SmlSavePatternAig( p, f ); + Ssw_ManResimulateBit( p, pObj, pObjRepr ); + assert( Aig_ObjRepr( p->pAig, pObj ) != pObjRepr ); + if ( Aig_ObjRepr( p->pAig, pObj ) == pObjRepr ) + { + printf( "Ssw_ManSweepNodeFilter(): Failed to refine representative.\n" ); + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Performs fraiging for the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Ssw_ManSweepBmcFilter_rec( Ssw_Man_t * p, Aig_Obj_t * pObj, int f ) +{ + Aig_Obj_t * pObjNew, * pObjLi; + pObjNew = Ssw_ObjFrame( p, pObj, f ); + if ( pObjNew ) + return pObjNew; + assert( !Saig_ObjIsPi(p->pAig, pObj) ); + if ( Saig_ObjIsLo(p->pAig, pObj) ) + { + assert( f > 0 ); + pObjLi = Saig_ObjLoToLi( p->pAig, pObj ); + pObjNew = Ssw_ManSweepBmcFilter_rec( p, Aig_ObjFanin0(pObjLi), f-1 ); + pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObjLi) ); + } + else + { + assert( Aig_ObjIsNode(pObj) ); + Ssw_ManSweepBmcFilter_rec( p, Aig_ObjFanin0(pObj), f ); + Ssw_ManSweepBmcFilter_rec( p, Aig_ObjFanin1(pObj), f ); + pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); + } + Ssw_ObjSetFrame( p, pObj, f, pObjNew ); + assert( pObjNew != NULL ); + return pObjNew; +} + +/**Function************************************************************* + + Synopsis [Filter equivalence classes of nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ManSweepBmcFilter( Ssw_Man_t * p, int TimeLimit ) +{ + Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo; + int f, f1, i, clkTotal = clock(); + // start initialized timeframes + p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK ); + Saig_ManForEachLo( p->pAig, pObj, i ) + { + if ( Abc_InfoHasBit( p->pPatWords, Saig_ManPiNum(p->pAig) + i ) ) + { + Ssw_ObjSetFrame( p, pObj, 0, Aig_ManConst1(p->pFrames) ); +//printf( "1" ); + } + else + { + Ssw_ObjSetFrame( p, pObj, 0, Aig_ManConst0(p->pFrames) ); +//printf( "0" ); + } + } +//printf( "\n" ); + + // sweep internal nodes + for ( f = 0; f < p->pPars->nFramesK; f++ ) + { + // realloc mapping of timeframes + if ( f == p->nFrames-1 ) + { + Aig_Obj_t ** pNodeToFrames; + pNodeToFrames = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) * 2 * p->nFrames ); + for ( f1 = 0; f1 < p->nFrames; f1++ ) + { + Aig_ManForEachObj( p->pAig, pObj, i ) + pNodeToFrames[2*p->nFrames*pObj->Id + f1] = Ssw_ObjFrame( p, pObj, f1 ); + } + ABC_FREE( p->pNodeToFrames ); + p->pNodeToFrames = pNodeToFrames; + p->nFrames *= 2; + } + // map constants and PIs + Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) ); + Saig_ManForEachPi( p->pAig, pObj, i ) + { + pObjNew = Aig_ObjCreatePi(p->pFrames); + Ssw_ObjSetFrame( p, pObj, f, pObjNew ); + } + // sweep internal nodes + Aig_ManForEachNode( p->pAig, pObj, i ) + { + pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); + Ssw_ObjSetFrame( p, pObj, f, pObjNew ); + if ( Ssw_ManSweepNodeFilter( p, pObj, f ) ) + break; + } + // printout + if ( p->pPars->fVerbose ) + { + printf( "Frame %4d : ", f ); + Ssw_ClassesPrint( p->ppClasses, 0 ); + } + if ( i < Vec_PtrSize(p->pAig->vObjs) ) + { + if ( p->pPars->fVerbose ) + printf( "Exceeded the resource limits (%d conflicts). Quitting...\n", p->pPars->nBTLimit ); + break; + } + // quit if this is the last timeframe + if ( f == p->pPars->nFramesK - 1 ) + { + if ( p->pPars->fVerbose ) + printf( "Exceeded the time frame limit (%d time frames). Quitting...\n", p->pPars->nFramesK ); + break; + } + // check timeout + if ( TimeLimit && ((float)TimeLimit <= (float)(clock()-clkTotal)/(float)(CLOCKS_PER_SEC)) ) + break; + // transfer latch input to the latch outputs + Aig_ManForEachPo( p->pAig, pObj, i ) + Ssw_ObjSetFrame( p, pObj, f, Ssw_ObjChild0Fra(p, pObj, f) ); + // build logic cones for register outputs + Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) + { + pObjNew = Ssw_ObjFrame( p, pObjLi, f ); + Ssw_ObjSetFrame( p, pObjLo, f+1, pObjNew ); + Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pObjNew) );// + } + } + // verify +// Ssw_ClassesCheck( p->ppClasses ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Filter equivalence classes of nodes.] + + Description [Unrolls at most nFramesMax frames. Works with nConfMax + conflicts until the first undefined SAT call. Verbose prints the message.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SignalFilter( Aig_Man_t * pAig, int nFramesMax, int nConfMax, int nRounds, int TimeLimit, int TimeLimit2, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose ) +{ + Ssw_Pars_t Pars, * pPars = &Pars; + Ssw_Man_t * p; + int r, TimeLimitPart, clkTotal = clock(); + int nTimeToStop = TimeLimit ? TimeLimit + time(NULL) : 0; + assert( Aig_ManRegNum(pAig) > 0 ); + assert( Aig_ManConstrNum(pAig) == 0 ); + // consider the case of empty AIG + if ( Aig_ManNodeNum(pAig) == 0 ) + return; + // reset random numbers + Aig_ManRandom( 1 ); + // if parameters are not given, create them + Ssw_ManSetDefaultParams( pPars = &Pars ); + pPars->nFramesK = 3; //nFramesMax; + pPars->nBTLimit = nConfMax; + pPars->TimeLimit = TimeLimit; + pPars->fVerbose = fVerbose; + // start the induction manager + p = Ssw_ManCreate( pAig, pPars ); + pPars->nFramesK = nFramesMax; + // create trivial equivalence classes with all nodes being candidates for constant 1 + if ( pAig->pReprs == NULL ) + p->ppClasses = Ssw_ClassesPrepareSimple( pAig, fLatchOnly, 0 ); + else + p->ppClasses = Ssw_ClassesPrepareFromReprs( pAig ); + Ssw_ClassesSetData( p->ppClasses, NULL, NULL, Ssw_SmlObjIsConstBit, Ssw_SmlObjsAreEqualBit ); + assert( p->vInits == NULL ); + // compute starting state if needed + if ( pCex ) + Ssw_ManFindStartingState( p, pCex ); + // refine classes using BMC + for ( r = 0; r < nRounds; r++ ) + { + if ( p->pPars->fVerbose ) + printf( "Round %3d:\n", r ); + // start filtering equivalence classes + Ssw_ManRefineByFilterSim( p, p->pPars->nFramesK ); + if ( Ssw_ClassesCand1Num(p->ppClasses) == 0 && Ssw_ClassesClassNum(p->ppClasses) == 0 ) + { + printf( "All equivalences are refined away.\n" ); + break; + } + // printout + if ( p->pPars->fVerbose ) + { + printf( "Initial : " ); + Ssw_ClassesPrint( p->ppClasses, 0 ); + } + p->pMSat = Ssw_SatStart( 0 ); + TimeLimitPart = TimeLimit ? nTimeToStop - time(NULL) : 0; + if ( TimeLimit2 ) + { + if ( TimeLimitPart ) + TimeLimitPart = Abc_MinInt( TimeLimitPart, TimeLimit2 ); + else + TimeLimitPart = TimeLimit2; + } + Ssw_ManSweepBmcFilter( p, TimeLimitPart ); + Ssw_SatStop( p->pMSat ); + p->pMSat = NULL; + Ssw_ManCleanup( p ); + // simulate pattern forward + Ssw_ManRollForward( p, p->pPars->nFramesK ); + // check timeout + if ( TimeLimit && time(NULL) > nTimeToStop ) + { + printf( "Reached timeout (%d seconds).\n", TimeLimit ); + break; + } + } + // cleanup + Aig_ManSetPhase( p->pAig ); + Aig_ManCleanMarkB( p->pAig ); + // cleanup + pPars->fVerbose = 0; + Ssw_ManStop( p ); +} + +/**Function************************************************************* + + Synopsis [Filter equivalence classes of nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SignalFilterGia( Gia_Man_t * p, int nFramesMax, int nConfMax, int nRounds, int TimeLimit, int TimeLimit2, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose ) +{ + Aig_Man_t * pAig; + pAig = Gia_ManToAigSimple( p ); + if ( p->pReprs != NULL ) + { + Gia_ManReprToAigRepr2( pAig, p ); + ABC_FREE( p->pReprs ); + ABC_FREE( p->pNexts ); + } + Ssw_SignalFilter( pAig, nFramesMax, nConfMax, nRounds, TimeLimit, TimeLimit2, pCex, fLatchOnly, fVerbose ); + Gia_ManReprFromAigRepr( pAig, p ); + Aig_ManStop( pAig ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/ssw/sswInt.h b/src/proof/ssw/sswInt.h new file mode 100644 index 00000000..acd273fd --- /dev/null +++ b/src/proof/ssw/sswInt.h @@ -0,0 +1,302 @@ +/**CFile**************************************************************** + + FileName [sswInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Inductive prover with constraints.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 1, 2008.] + + Revision [$Id: sswInt.h,v 1.00 2008/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__ssw__sswInt_h +#define ABC__aig__ssw__sswInt_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "src/aig/saig/saig.h" +#include "src/sat/bsat/satSolver.h" +#include "ssw.h" +#include "src/aig/ioa/ioa.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Ssw_Man_t_ Ssw_Man_t; // signal correspondence manager +typedef struct Ssw_Frm_t_ Ssw_Frm_t; // unrolled frames manager +typedef struct Ssw_Sat_t_ Ssw_Sat_t; // SAT solver manager +typedef struct Ssw_Cla_t_ Ssw_Cla_t; // equivalence classe manager + +struct Ssw_Man_t_ +{ + // parameters + Ssw_Pars_t * pPars; // parameters + int nFrames; // for quick lookup + // AIGs used in the package + Aig_Man_t * pAig; // user-given AIG + Aig_Man_t * pFrames; // final AIG + Aig_Obj_t ** pNodeToFrames; // mapping of AIG nodes into FRAIG nodes + // equivalence classes + Ssw_Cla_t * ppClasses; // equivalence classes of nodes + int fRefined; // is set to 1 when refinement happens + // SAT solving + Ssw_Sat_t * pMSatBmc; // SAT manager for base case + Ssw_Sat_t * pMSat; // SAT manager for inductive case + // SAT solving (latch corr only) + Vec_Ptr_t * vSimInfo; // simulation information for the framed PIs + int nPatterns; // the number of patterns saved + int nSimRounds; // the number of simulation rounds performed + int nCallsCount; // the number of calls in this round + int nCallsDelta; // the number of calls to skip + int nCallsSat; // the number of SAT calls in this round + int nCallsUnsat; // the number of UNSAT calls in this round + int nRecycleCalls; // the number of calls since last recycling + int nRecycles; // the number of time SAT solver was recycled + int nRecyclesTotal; // the number of time SAT solver was recycled + int nVarsMax; // the maximum variables in the solver + int nCallsMax; // the maximum number of SAT calls + // uniqueness + Vec_Ptr_t * vCommon; // the set of common variables in the logic cones + int iOutputLit; // the output literal of the uniqueness constraint + Vec_Int_t * vDiffPairs; // is set to 1 if reg pair can be diff + int nUniques; // the number of uniqueness constraints used + int nUniquesAdded; // useful uniqueness constraints + int nUniquesUseful; // useful uniqueness constraints + // dynamic constraint addition + int nSRMiterMaxId; // max ID after which the last frame begins + Vec_Ptr_t * vNewLos; // new time frame LOs of to constrain + Vec_Int_t * vNewPos; // new time frame POs of to add constraints + int * pVisited; // flags to label visited nodes in each frame + int nVisCounter; // the traversal ID + // sequential simulation + Ssw_Sml_t * pSml; // the simulator + int iNodeStart; // the first node considered + int iNodeLast; // the last node considered + Vec_Ptr_t * vResimConsts; // resimulation constants + Vec_Ptr_t * vResimClasses; // resimulation classes + Vec_Int_t * vInits; // the init values of primary inputs under constraints + // counter example storage + int nPatWords; // the number of words in the counter example + unsigned * pPatWords; // the counter example + // constraints + int nConstrTotal; // the number of total constraints + int nConstrReduced; // the number of reduced constraints + int nStrangers; // the number of strange situations + // SAT calls statistics + int nSatCalls; // the number of SAT calls + int nSatProof; // the number of proofs + int nSatFailsReal; // the number of timeouts + int nSatCallsUnsat; // the number of unsat SAT calls + int nSatCallsSat; // the number of sat SAT calls + // node/register/lit statistics + int nLitsBeg; + int nLitsEnd; + int nNodesBeg; + int nNodesEnd; + int nRegsBeg; + int nRegsEnd; + // equiv statistis + int nConesTotal; + int nConesConstr; + int nEquivsTotal; + int nEquivsConstr; + int nNodesBegC; + int nNodesEndC; + int nRegsBegC; + int nRegsEndC; + // runtime stats + int timeBmc; // bounded model checking + int timeReduce; // speculative reduction + int timeMarkCones; // marking the cones not to be refined + int timeSimSat; // simulation of the counter-examples + int timeSat; // solving SAT + int timeSatSat; // sat + int timeSatUnsat; // unsat + int timeSatUndec; // undecided + int timeOther; // other runtime + int timeTotal; // total runtime +}; + +// internal SAT manager +struct Ssw_Sat_t_ +{ + Aig_Man_t * pAig; // the AIG manager + int fPolarFlip; // flips polarity + sat_solver * pSat; // recyclable SAT solver + int nSatVars; // the counter of SAT variables + Vec_Int_t * vSatVars; // mapping of each node into its SAT var + Vec_Ptr_t * vFanins; // fanins of the CNF node + Vec_Ptr_t * vUsedPis; // the PIs with SAT variables + int nSolverCalls; // the total number of SAT calls +}; + +// internal frames manager +struct Ssw_Frm_t_ +{ + Aig_Man_t * pAig; // user-given AIG + int nObjs; // offset in terms of AIG nodes + int nFrames; // the number of frames in current unrolling + Aig_Man_t * pFrames; // unrolled AIG + Vec_Ptr_t * vAig2Frm; // mapping of AIG nodes into frame nodes +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Ssw_ObjSatNum( Ssw_Sat_t * p, Aig_Obj_t * pObj ) { return Vec_IntGetEntry( p->vSatVars, pObj->Id ); } +static inline void Ssw_ObjSetSatNum( Ssw_Sat_t * p, Aig_Obj_t * pObj, int Num ) { Vec_IntSetEntry(p->vSatVars, pObj->Id, Num); } + +static inline int Ssw_ObjIsConst1Cand( Aig_Man_t * pAig, Aig_Obj_t * pObj ) +{ + return Aig_ObjRepr(pAig, pObj) == Aig_ManConst1(pAig); +} +static inline void Ssw_ObjSetConst1Cand( Aig_Man_t * pAig, Aig_Obj_t * pObj ) +{ + assert( !Ssw_ObjIsConst1Cand( pAig, pObj ) ); + Aig_ObjSetRepr( pAig, pObj, Aig_ManConst1(pAig) ); +} + +static inline Aig_Obj_t * Ssw_ObjFrame( Ssw_Man_t * p, Aig_Obj_t * pObj, int i ) { return p->pNodeToFrames[p->nFrames*pObj->Id + i]; } +static inline void Ssw_ObjSetFrame( Ssw_Man_t * p, Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { p->pNodeToFrames[p->nFrames*pObj->Id + i] = pNode; } + +static inline Aig_Obj_t * Ssw_ObjChild0Fra( Ssw_Man_t * p, Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Ssw_ObjFrame(p, Aig_ObjFanin0(pObj), i), Aig_ObjFaninC0(pObj)) : NULL; } +static inline Aig_Obj_t * Ssw_ObjChild1Fra( Ssw_Man_t * p, Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Ssw_ObjFrame(p, Aig_ObjFanin1(pObj), i), Aig_ObjFaninC1(pObj)) : NULL; } + +static inline Aig_Obj_t * Ssw_ObjFrame_( Ssw_Frm_t * p, Aig_Obj_t * pObj, int i ) { return (Aig_Obj_t *)Vec_PtrGetEntry( p->vAig2Frm, p->nObjs*i+pObj->Id ); } +static inline void Ssw_ObjSetFrame_( Ssw_Frm_t * p, Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { Vec_PtrSetEntry( p->vAig2Frm, p->nObjs*i+pObj->Id, pNode ); } + +static inline Aig_Obj_t * Ssw_ObjChild0Fra_( Ssw_Frm_t * p, Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Ssw_ObjFrame_(p, Aig_ObjFanin0(pObj), i), Aig_ObjFaninC0(pObj)) : NULL; } +static inline Aig_Obj_t * Ssw_ObjChild1Fra_( Ssw_Frm_t * p, Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Ssw_ObjFrame_(p, Aig_ObjFanin1(pObj), i), Aig_ObjFaninC1(pObj)) : NULL; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== sswAig.c ===================================================*/ +extern Ssw_Frm_t * Ssw_FrmStart( Aig_Man_t * pAig ); +extern void Ssw_FrmStop( Ssw_Frm_t * p ); +extern Aig_Man_t * Ssw_FramesWithClasses( Ssw_Man_t * p ); +extern Aig_Man_t * Ssw_SpeculativeReduction( Ssw_Man_t * p ); +/*=== sswBmc.c ===================================================*/ +/*=== sswClass.c =================================================*/ +extern Ssw_Cla_t * Ssw_ClassesStart( Aig_Man_t * pAig ); +extern void Ssw_ClassesSetData( Ssw_Cla_t * p, void * pManData, + unsigned (*pFuncNodeHash)(void *,Aig_Obj_t *), + int (*pFuncNodeIsConst)(void *,Aig_Obj_t *), + int (*pFuncNodesAreEqual)(void *,Aig_Obj_t *, Aig_Obj_t *) ); +extern void Ssw_ClassesStop( Ssw_Cla_t * p ); +extern Aig_Man_t * Ssw_ClassesReadAig( Ssw_Cla_t * p ); +extern Vec_Ptr_t * Ssw_ClassesGetRefined( Ssw_Cla_t * p ); +extern void Ssw_ClassesClearRefined( Ssw_Cla_t * p ); +extern int Ssw_ClassesCand1Num( Ssw_Cla_t * p ); +extern int Ssw_ClassesClassNum( Ssw_Cla_t * p ); +extern int Ssw_ClassesLitNum( Ssw_Cla_t * p ); +extern Aig_Obj_t ** Ssw_ClassesReadClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, int * pnSize ); +extern void Ssw_ClassesCollectClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, Vec_Ptr_t * vClass ); +extern void Ssw_ClassesCheck( Ssw_Cla_t * p ); +extern void Ssw_ClassesPrint( Ssw_Cla_t * p, int fVeryVerbose ); +extern void Ssw_ClassesRemoveNode( Ssw_Cla_t * p, Aig_Obj_t * pObj ); +extern Ssw_Cla_t * Ssw_ClassesPrepare( Aig_Man_t * pAig, int nFramesK, int fLatchCorr, int fConstCorr, int fOutputCorr, int nMaxLevs, int fVerbose ); +extern Ssw_Cla_t * Ssw_ClassesPrepareSimple( Aig_Man_t * pAig, int fLatchCorr, int nMaxLevs ); +extern Ssw_Cla_t * Ssw_ClassesPrepareFromReprs( Aig_Man_t * pAig ); +extern Ssw_Cla_t * Ssw_ClassesPrepareTargets( Aig_Man_t * pAig ); +extern Ssw_Cla_t * Ssw_ClassesPreparePairs( Aig_Man_t * pAig, Vec_Int_t ** pvClasses ); +extern Ssw_Cla_t * Ssw_ClassesPreparePairsSimple( Aig_Man_t * pMiter, Vec_Int_t * vPairs ); +extern int Ssw_ClassesRefine( Ssw_Cla_t * p, int fRecursive ); +extern int Ssw_ClassesRefineGroup( Ssw_Cla_t * p, Vec_Ptr_t * vReprs, int fRecursive ); +extern int Ssw_ClassesRefineOneClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, int fRecursive ); +extern int Ssw_ClassesRefineConst1Group( Ssw_Cla_t * p, Vec_Ptr_t * vRoots, int fRecursive ); +extern int Ssw_ClassesRefineConst1( Ssw_Cla_t * p, int fRecursive ); +extern int Ssw_ClassesPrepareRehash( Ssw_Cla_t * p, Vec_Ptr_t * vCands, int fConstCorr ); +/*=== sswCnf.c ===================================================*/ +extern Ssw_Sat_t * Ssw_SatStart( int fPolarFlip ); +extern void Ssw_SatStop( Ssw_Sat_t * p ); +extern void Ssw_CnfNodeAddToSolver( Ssw_Sat_t * p, Aig_Obj_t * pObj ); +extern int Ssw_CnfGetNodeValue( Ssw_Sat_t * p, Aig_Obj_t * pObjFraig ); +/*=== sswConstr.c ===================================================*/ +extern int Ssw_ManSweepBmcConstr( Ssw_Man_t * p ); +extern int Ssw_ManSweepConstr( Ssw_Man_t * p ); +extern void Ssw_ManRefineByConstrSim( Ssw_Man_t * p ); +/*=== sswCore.c ===================================================*/ +extern Aig_Man_t * Ssw_SignalCorrespondenceRefine( Ssw_Man_t * p ); +/*=== sswDyn.c ===================================================*/ +extern void Ssw_ManLoadSolver( Ssw_Man_t * p, Aig_Obj_t * pRepr, Aig_Obj_t * pObj ); +extern int Ssw_ManSweepDyn( Ssw_Man_t * p ); +/*=== sswLcorr.c ==========================================================*/ +extern int Ssw_ManSweepLatch( Ssw_Man_t * p ); +/*=== sswMan.c ===================================================*/ +extern Ssw_Man_t * Ssw_ManCreate( Aig_Man_t * pAig, Ssw_Pars_t * pPars ); +extern void Ssw_ManCleanup( Ssw_Man_t * p ); +extern void Ssw_ManStop( Ssw_Man_t * p ); +/*=== sswSat.c ===================================================*/ +extern int Ssw_NodesAreEquiv( Ssw_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ); +extern int Ssw_NodesAreConstrained( Ssw_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ); +extern int Ssw_NodeIsConstrained( Ssw_Man_t * p, Aig_Obj_t * pPoObj ); +/*=== sswSemi.c ===================================================*/ +extern int Ssw_FilterUsingSemi( Ssw_Man_t * pMan, int fCheckTargets, int nConfMax, int fVerbose ); +/*=== sswSim.c ===================================================*/ +extern unsigned Ssw_SmlObjHashWord( Ssw_Sml_t * p, Aig_Obj_t * pObj ); +extern int Ssw_SmlObjIsConstWord( Ssw_Sml_t * p, Aig_Obj_t * pObj ); +extern int Ssw_SmlObjsAreEqualWord( Ssw_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ); +extern int Ssw_SmlObjIsConstBit( void * p, Aig_Obj_t * pObj ); +extern int Ssw_SmlObjsAreEqualBit( void * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ); +extern void Ssw_SmlAssignRandomFrame( Ssw_Sml_t * p, Aig_Obj_t * pObj, int iFrame ); +extern Ssw_Sml_t * Ssw_SmlStart( Aig_Man_t * pAig, int nPref, int nFrames, int nWordsFrame ); +extern void Ssw_SmlClean( Ssw_Sml_t * p ); +extern void Ssw_SmlStop( Ssw_Sml_t * p ); +extern void Ssw_SmlObjAssignConst( Ssw_Sml_t * p, Aig_Obj_t * pObj, int fConst1, int iFrame ); +extern void Ssw_SmlObjSetWord( Ssw_Sml_t * p, Aig_Obj_t * pObj, unsigned Word, int iWord, int iFrame ); +extern void Ssw_SmlAssignDist1Plus( Ssw_Sml_t * p, unsigned * pPat ); +extern void Ssw_SmlSimulateOne( Ssw_Sml_t * p ); +extern void Ssw_SmlSimulateOneFrame( Ssw_Sml_t * p ); +extern void Ssw_SmlSimulateOneDyn_rec( Ssw_Sml_t * p, Aig_Obj_t * pObj, int f, int * pVisited, int nVisCounter ); +extern void Ssw_SmlResimulateSeq( Ssw_Sml_t * p ); +/*=== sswSimSat.c ===================================================*/ +extern void Ssw_ManResimulateBit( Ssw_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr ); +extern void Ssw_ManResimulateWord( Ssw_Man_t * p, Aig_Obj_t * pCand, Aig_Obj_t * pRepr, int f ); +/*=== sswSweep.c ===================================================*/ +extern int Ssw_ManGetSatVarValue( Ssw_Man_t * p, Aig_Obj_t * pObj, int f ); +extern void Ssw_SmlSavePatternAig( Ssw_Man_t * p, int f ); +extern int Ssw_ManSweepNode( Ssw_Man_t * p, Aig_Obj_t * pObj, int f, int fBmc, Vec_Int_t * vPairs ); +extern int Ssw_ManSweepBmc( Ssw_Man_t * p ); +extern int Ssw_ManSweep( Ssw_Man_t * p ); +/*=== sswUnique.c ===================================================*/ +extern void Ssw_UniqueRegisterPairInfo( Ssw_Man_t * p ); +extern int Ssw_ManUniqueOne( Ssw_Man_t * p, Aig_Obj_t * pRepr, Aig_Obj_t * pObj, int fVerbose ); +extern int Ssw_ManUniqueAddConstraint( Ssw_Man_t * p, Vec_Ptr_t * vCommon, int f1, int f2 ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/proof/ssw/sswIslands.c b/src/proof/ssw/sswIslands.c new file mode 100644 index 00000000..0802aca5 --- /dev/null +++ b/src/proof/ssw/sswIslands.c @@ -0,0 +1,598 @@ +/**CFile**************************************************************** + + FileName [sswIslands.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Inductive prover with constraints.] + + Synopsis [Detection of islands of difference.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 1, 2008.] + + Revision [$Id: sswIslands.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sswInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates pair of structurally equivalent nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_CreatePair( Vec_Int_t * vPairs, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) +{ + pObj0->pData = pObj1; + pObj1->pData = pObj0; + Vec_IntPush( vPairs, pObj0->Id ); + Vec_IntPush( vPairs, pObj1->Id ); +} + +/**Function************************************************************* + + Synopsis [Establishes relationship between nodes using pairing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_MatchingStart( Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairs ) +{ + Aig_Obj_t * pObj0, * pObj1; + int i; + // create matching + Aig_ManCleanData( p0 ); + Aig_ManCleanData( p1 ); + for ( i = 0; i < Vec_IntSize(vPairs); i += 2 ) + { + pObj0 = Aig_ManObj( p0, Vec_IntEntry(vPairs, i) ); + pObj1 = Aig_ManObj( p1, Vec_IntEntry(vPairs, i+1) ); + assert( pObj0->pData == NULL ); + assert( pObj1->pData == NULL ); + pObj0->pData = pObj1; + pObj1->pData = pObj0; + } + // make sure constants are matched + pObj0 = Aig_ManConst1( p0 ); + pObj1 = Aig_ManConst1( p1 ); + assert( pObj0->pData == pObj1 ); + assert( pObj1->pData == pObj0 ); + // make sure PIs are matched + Saig_ManForEachPi( p0, pObj0, i ) + { + pObj1 = Aig_ManPi( p1, i ); + assert( pObj0->pData == pObj1 ); + assert( pObj1->pData == pObj0 ); + } + // make sure the POs are not matched + Aig_ManForEachPo( p0, pObj0, i ) + { + pObj1 = Aig_ManPo( p1, i ); + assert( pObj0->pData == NULL ); + assert( pObj1->pData == NULL ); + } + + // check that LIs/LOs are matched in sync + Saig_ManForEachLo( p0, pObj0, i ) + { + if ( pObj0->pData == NULL ) + continue; + pObj1 = (Aig_Obj_t *)pObj0->pData; + if ( !Saig_ObjIsLo(p1, pObj1) ) + printf( "Mismatch between LO pairs.\n" ); + } + Saig_ManForEachLo( p1, pObj1, i ) + { + if ( pObj1->pData == NULL ) + continue; + pObj0 = (Aig_Obj_t *)pObj1->pData; + if ( !Saig_ObjIsLo(p0, pObj0) ) + printf( "Mismatch between LO pairs.\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Establishes relationship between nodes using pairing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_MatchingExtendOne( Aig_Man_t * p, Vec_Ptr_t * vNodes ) +{ + Aig_Obj_t * pNext, * pObj; + int i, k, iFan; + Vec_PtrClear( vNodes ); + Aig_ManIncrementTravId( p ); + Aig_ManForEachObj( p, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) ) + continue; + if ( pObj->pData != NULL ) + continue; + if ( Saig_ObjIsLo(p, pObj) ) + { + pNext = Saig_ObjLoToLi(p, pObj); + pNext = Aig_ObjFanin0(pNext); + if ( pNext->pData && !Aig_ObjIsTravIdCurrent(p, pNext) && !Aig_ObjIsConst1(pNext) ) + { + Aig_ObjSetTravIdCurrent(p, pNext); + Vec_PtrPush( vNodes, pNext ); + } + } + if ( Aig_ObjIsNode(pObj) ) + { + pNext = Aig_ObjFanin0(pObj); + if ( pNext->pData && !Aig_ObjIsTravIdCurrent(p, pNext) ) + { + Aig_ObjSetTravIdCurrent(p, pNext); + Vec_PtrPush( vNodes, pNext ); + } + pNext = Aig_ObjFanin1(pObj); + if ( pNext->pData && !Aig_ObjIsTravIdCurrent(p, pNext) ) + { + Aig_ObjSetTravIdCurrent(p, pNext); + Vec_PtrPush( vNodes, pNext ); + } + } + Aig_ObjForEachFanout( p, pObj, pNext, iFan, k ) + { + if ( Saig_ObjIsPo(p, pNext) ) + continue; + if ( Saig_ObjIsLi(p, pNext) ) + pNext = Saig_ObjLiToLo(p, pNext); + if ( pNext->pData && !Aig_ObjIsTravIdCurrent(p, pNext) ) + { + Aig_ObjSetTravIdCurrent(p, pNext); + Vec_PtrPush( vNodes, pNext ); + } + } + } +} + +/**Function************************************************************* + + Synopsis [Establishes relationship between nodes using pairing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_MatchingCountUnmached( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + Aig_ManForEachObj( p, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) ) + continue; + if ( pObj->pData != NULL ) + continue; + Counter++; + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Establishes relationship between nodes using pairing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_MatchingExtend( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose ) +{ + Vec_Ptr_t * vNodes0, * vNodes1; + Aig_Obj_t * pNext0, * pNext1; + int d, k; + Aig_ManFanoutStart(p0); + Aig_ManFanoutStart(p1); + vNodes0 = Vec_PtrAlloc( 1000 ); + vNodes1 = Vec_PtrAlloc( 1000 ); + if ( fVerbose ) + { + int nUnmached = Ssw_MatchingCountUnmached(p0); + printf( "Extending islands by %d steps:\n", nDist ); + printf( "%2d : Total = %6d. Unmatched = %6d. Ratio = %6.2f %%\n", + 0, Aig_ManPiNum(p0) + Aig_ManNodeNum(p0), + nUnmached, 100.0 * nUnmached/(Aig_ManPiNum(p0) + Aig_ManNodeNum(p0)) ); + } + for ( d = 0; d < nDist; d++ ) + { + Ssw_MatchingExtendOne( p0, vNodes0 ); + Ssw_MatchingExtendOne( p1, vNodes1 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes0, pNext0, k ) + { + pNext1 = (Aig_Obj_t *)pNext0->pData; + if ( pNext1 == NULL ) + continue; + assert( pNext1->pData == pNext0 ); + if ( Saig_ObjIsPi(p0, pNext1) ) + continue; + pNext0->pData = NULL; + pNext1->pData = NULL; + } + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes1, pNext0, k ) + { + pNext1 = (Aig_Obj_t *)pNext0->pData; + if ( pNext1 == NULL ) + continue; + assert( pNext1->pData == pNext0 ); + if ( Saig_ObjIsPi(p1, pNext1) ) + continue; + pNext0->pData = NULL; + pNext1->pData = NULL; + } + if ( fVerbose ) + { + int nUnmached = Ssw_MatchingCountUnmached(p0); + printf( "%2d : Total = %6d. Unmatched = %6d. Ratio = %6.2f %%\n", + d+1, Aig_ManPiNum(p0) + Aig_ManNodeNum(p0), + nUnmached, 100.0 * nUnmached/(Aig_ManPiNum(p0) + Aig_ManNodeNum(p0)) ); + } + } + Vec_PtrFree( vNodes0 ); + Vec_PtrFree( vNodes1 ); + Aig_ManFanoutStop(p0); + Aig_ManFanoutStop(p1); +} + +/**Function************************************************************* + + Synopsis [Used differences in p0 to complete p1.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_MatchingComplete( Aig_Man_t * p0, Aig_Man_t * p1 ) +{ + Vec_Ptr_t * vNewLis; + Aig_Obj_t * pObj0, * pObj0Li, * pObj1; + int i; + // create register outputs in p0 that are absent in p1 + vNewLis = Vec_PtrAlloc( 100 ); + Saig_ManForEachLiLo( p0, pObj0Li, pObj0, i ) + { + if ( pObj0->pData != NULL ) + continue; + pObj1 = Aig_ObjCreatePi( p1 ); + pObj0->pData = pObj1; + pObj1->pData = pObj0; + Vec_PtrPush( vNewLis, pObj0Li ); + } + // add missing nodes in the topological order + Aig_ManForEachNode( p0, pObj0, i ) + { + if ( pObj0->pData != NULL ) + continue; + pObj1 = Aig_And( p1, Aig_ObjChild0Copy(pObj0), Aig_ObjChild1Copy(pObj0) ); + pObj0->pData = pObj1; + pObj1->pData = pObj0; + } + // create register outputs in p0 that are absent in p1 + Vec_PtrForEachEntry( Aig_Obj_t *, vNewLis, pObj0Li, i ) + Aig_ObjCreatePo( p1, Aig_ObjChild0Copy(pObj0Li) ); + // increment the number of registers + Aig_ManSetRegNum( p1, Aig_ManRegNum(p1) + Vec_PtrSize(vNewLis) ); + Vec_PtrFree( vNewLis ); +} + + +/**Function************************************************************* + + Synopsis [Derives matching for all pairs.] + + Description [Modifies both AIGs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Ssw_MatchingPairs( Aig_Man_t * p0, Aig_Man_t * p1 ) +{ + Vec_Int_t * vPairsNew; + Aig_Obj_t * pObj0, * pObj1; + int i; + // check correctness + assert( Aig_ManPiNum(p0) == Aig_ManPiNum(p1) ); + assert( Aig_ManPoNum(p0) == Aig_ManPoNum(p1) ); + assert( Aig_ManRegNum(p0) == Aig_ManRegNum(p1) ); + assert( Aig_ManObjNum(p0) == Aig_ManObjNum(p1) ); + // create complete pairs + vPairsNew = Vec_IntAlloc( 2*Aig_ManObjNum(p0) ); + Aig_ManForEachObj( p0, pObj0, i ) + { + if ( Aig_ObjIsPo(pObj0) ) + continue; + pObj1 = (Aig_Obj_t *)pObj0->pData; + Vec_IntPush( vPairsNew, pObj0->Id ); + Vec_IntPush( vPairsNew, pObj1->Id ); + } + return vPairsNew; +} + + + + + +/**Function************************************************************* + + Synopsis [Transfers the result of matching to miter.] + + Description [The array of pairs should be complete.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Ssw_MatchingMiter( Aig_Man_t * pMiter, Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairsAll ) +{ + Vec_Int_t * vPairsMiter; + Aig_Obj_t * pObj0, * pObj1; + int i; + // create matching of nodes in the miter + vPairsMiter = Vec_IntAlloc( 2*Aig_ManObjNum(p0) ); + for ( i = 0; i < Vec_IntSize(vPairsAll); i += 2 ) + { + pObj0 = Aig_ManObj( p0, Vec_IntEntry(vPairsAll, i) ); + pObj1 = Aig_ManObj( p1, Vec_IntEntry(vPairsAll, i+1) ); + assert( pObj0->pData != NULL ); + assert( pObj1->pData != NULL ); + if ( pObj0->pData == pObj1->pData ) + continue; + if ( Aig_ObjIsNone((Aig_Obj_t *)pObj0->pData) || Aig_ObjIsNone((Aig_Obj_t *)pObj1->pData) ) + continue; + // get the miter nodes + pObj0 = (Aig_Obj_t *)pObj0->pData; + pObj1 = (Aig_Obj_t *)pObj1->pData; + assert( !Aig_IsComplement(pObj0) ); + assert( !Aig_IsComplement(pObj1) ); + assert( Aig_ObjType(pObj0) == Aig_ObjType(pObj1) ); + if ( Aig_ObjIsPo(pObj0) ) + continue; + assert( Aig_ObjIsNode(pObj0) || Saig_ObjIsLo(pMiter, pObj0) ); + assert( Aig_ObjIsNode(pObj1) || Saig_ObjIsLo(pMiter, pObj1) ); + assert( pObj0->Id < pObj1->Id ); + Vec_IntPush( vPairsMiter, pObj0->Id ); + Vec_IntPush( vPairsMiter, pObj1->Id ); + } + return vPairsMiter; +} + + + + + +/**Function************************************************************* + + Synopsis [Solves SEC using structural similarity.] + + Description [Modifies both p0 and p1 by adding extra logic.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Ssw_SecWithSimilaritySweep( Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairs, Ssw_Pars_t * pPars ) +{ + Ssw_Man_t * p; + Vec_Int_t * vPairsAll, * vPairsMiter; + Aig_Man_t * pMiter, * pAigNew; + // derive full matching + Ssw_MatchingStart( p0, p1, vPairs ); + if ( pPars->nIsleDist ) + Ssw_MatchingExtend( p0, p1, pPars->nIsleDist, pPars->fVerbose ); + Ssw_MatchingComplete( p0, p1 ); + Ssw_MatchingComplete( p1, p0 ); + vPairsAll = Ssw_MatchingPairs( p0, p1 ); + // create miter and transfer matching + pMiter = Saig_ManCreateMiter( p0, p1, 0 ); + vPairsMiter = Ssw_MatchingMiter( pMiter, p0, p1, vPairsAll ); + Vec_IntFree( vPairsAll ); + // start the induction manager + p = Ssw_ManCreate( pMiter, pPars ); + // create equivalence classes using these IDs + if ( p->pPars->fPartSigCorr ) + p->ppClasses = Ssw_ClassesPreparePairsSimple( pMiter, vPairsMiter ); + else + p->ppClasses = Ssw_ClassesPrepare( pMiter, pPars->nFramesK, pPars->fLatchCorr, pPars->fConstCorr, pPars->fOutputCorr, pPars->nMaxLevs, pPars->fVerbose ); + if ( p->pPars->fDumpSRInit ) + { + if ( p->pPars->fPartSigCorr ) + { + Aig_Man_t * pSRed = Ssw_SpeculativeReduction( p ); + Aig_ManDumpBlif( pSRed, "srm_part.blif", NULL, NULL ); + Aig_ManStop( pSRed ); + printf( "Speculatively reduced miter is saved in file \"%s\".\n", "srm_part.blif" ); + } + else + printf( "Dumping speculative miter is possible only for partial signal correspondence (switch \"-c\").\n" ); + } + p->pSml = Ssw_SmlStart( pMiter, 0, 1 + p->pPars->nFramesAddSim, 1 ); + Ssw_ClassesSetData( p->ppClasses, p->pSml, (unsigned(*)(void *,Aig_Obj_t *))Ssw_SmlObjHashWord, (int(*)(void *,Aig_Obj_t *))Ssw_SmlObjIsConstWord, (int(*)(void *,Aig_Obj_t *,Aig_Obj_t *))Ssw_SmlObjsAreEqualWord ); + // perform refinement of classes + pAigNew = Ssw_SignalCorrespondenceRefine( p ); + // cleanup + Ssw_ManStop( p ); + Aig_ManStop( pMiter ); + Vec_IntFree( vPairsMiter ); + return pAigNew; +} + +/**Function************************************************************* + + Synopsis [Solves SEC with structural similarity.] + + Description [The first two arguments are pointers to the AIG managers. + The third argument is the array of pairs of IDs of structurally equivalent + nodes from the first and second managers, respectively.] + + SideEffects [The managers will be updated by adding "islands of difference".] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SecWithSimilarityPairs( Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairs, Ssw_Pars_t * pPars ) +{ + Ssw_Pars_t Pars; + Aig_Man_t * pAigRes; + int RetValue, clk = clock(); + // derive parameters if not given + if ( pPars == NULL ) + Ssw_ManSetDefaultParams( pPars = &Pars ); + // reduce the AIG with pairs + pAigRes = Ssw_SecWithSimilaritySweep( p0, p1, vPairs, pPars ); + // report the result of verification + RetValue = Ssw_MiterStatus( pAigRes, 1 ); + if ( RetValue == 1 ) + printf( "Verification successful. " ); + else if ( RetValue == 0 ) + printf( "Verification failed with a counter-example. " ); + else + printf( "Verification UNDECIDED. The number of remaining regs = %d (total = %d). ", + Aig_ManRegNum(pAigRes), Aig_ManRegNum(p0)+Aig_ManRegNum(p1) ); + ABC_PRT( "Time", clock() - clk ); + Aig_ManStop( pAigRes ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Dummy procedure to detect structural similarity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Saig_StrSimPerformMatching_hack( Aig_Man_t * p0, Aig_Man_t * p1 ) +{ + Vec_Int_t * vPairs; + Aig_Obj_t * pObj; + int i; + // create array of pairs + vPairs = Vec_IntAlloc( 100 ); + Aig_ManForEachObj( p0, pObj, i ) + { + if ( !Aig_ObjIsConst1(pObj) && !Aig_ObjIsPi(pObj) && !Aig_ObjIsNode(pObj) ) + continue; + Vec_IntPush( vPairs, i ); + Vec_IntPush( vPairs, i ); + } + return vPairs; +} + +/**Function************************************************************* + + Synopsis [Solves SEC with structural similarity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SecWithSimilarity( Aig_Man_t * p0, Aig_Man_t * p1, Ssw_Pars_t * pPars ) +{ + Vec_Int_t * vPairs; + Aig_Man_t * pPart0, * pPart1; + int RetValue; + if ( pPars->fVerbose ) + printf( "Performing sequential verification using structural similarity.\n" ); + // consider the case when a miter is given + if ( p1 == NULL ) + { + if ( pPars->fVerbose ) + { + Aig_ManPrintStats( p0 ); + } + // demiter the miter + if ( !Saig_ManDemiterSimpleDiff( p0, &pPart0, &pPart1 ) ) + { + printf( "Demitering has failed.\n" ); + return -1; + } + } + else + { + pPart0 = Aig_ManDupSimple( p0 ); + pPart1 = Aig_ManDupSimple( p1 ); + } + if ( pPars->fVerbose ) + { +// Aig_ManPrintStats( pPart0 ); +// Aig_ManPrintStats( pPart1 ); + if ( p1 == NULL ) + { +// Aig_ManDumpBlif( pPart0, "part0.blif", NULL, NULL ); +// Aig_ManDumpBlif( pPart1, "part1.blif", NULL, NULL ); +// printf( "The result of demitering is written into files \"%s\" and \"%s\".\n", "part0.blif", "part1.blif" ); + } + } + assert( Aig_ManRegNum(pPart0) > 0 ); + assert( Aig_ManRegNum(pPart1) > 0 ); + assert( Saig_ManPiNum(pPart0) == Saig_ManPiNum(pPart1) ); + assert( Saig_ManPoNum(pPart0) == Saig_ManPoNum(pPart1) ); + // derive pairs +// vPairs = Saig_StrSimPerformMatching_hack( pPart0, pPart1 ); + vPairs = Saig_StrSimPerformMatching( pPart0, pPart1, 0, pPars->fVerbose, NULL ); + RetValue = Ssw_SecWithSimilarityPairs( pPart0, pPart1, vPairs, pPars ); + Aig_ManStop( pPart0 ); + Aig_ManStop( pPart1 ); + Vec_IntFree( vPairs ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/ssw/sswLcorr.c b/src/proof/ssw/sswLcorr.c new file mode 100644 index 00000000..ce9c2563 --- /dev/null +++ b/src/proof/ssw/sswLcorr.c @@ -0,0 +1,336 @@ +/**CFile**************************************************************** + + FileName [sswLcorr.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Inductive prover with constraints.] + + Synopsis [Latch correspondence.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 1, 2008.] + + Revision [$Id: sswLcorr.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sswInt.h" +//#include "bar.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Tranfers simulation information from FRAIG to AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManSweepTransfer( Ssw_Man_t * p ) +{ + Aig_Obj_t * pObj, * pObjFraig; + unsigned * pInfo; + int i; + // transfer simulation information + Aig_ManForEachPi( p->pAig, pObj, i ) + { + pObjFraig = Ssw_ObjFrame( p, pObj, 0 ); + if ( pObjFraig == Aig_ManConst0(p->pFrames) ) + { + Ssw_SmlObjAssignConst( p->pSml, pObj, 0, 0 ); + continue; + } + assert( !Aig_IsComplement(pObjFraig) ); + assert( Aig_ObjIsPi(pObjFraig) ); + pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjPioNum(pObjFraig) ); + Ssw_SmlObjSetWord( p->pSml, pObj, pInfo[0], 0, 0 ); + } +} + +/**Function************************************************************* + + Synopsis [Performs one round of simulation with counter-examples.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ManSweepResimulate( Ssw_Man_t * p ) +{ + int RetValue1, RetValue2, clk = clock(); + // transfer PI simulation information from storage + Ssw_ManSweepTransfer( p ); + // simulate internal nodes + Ssw_SmlSimulateOneFrame( p->pSml ); + // check equivalence classes + RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 1 ); + RetValue2 = Ssw_ClassesRefine( p->ppClasses, 1 ); + // prepare simulation info for the next round + Vec_PtrCleanSimInfo( p->vSimInfo, 0, 1 ); + p->nPatterns = 0; + p->nSimRounds++; +p->timeSimSat += clock() - clk; + return RetValue1 > 0 || RetValue2 > 0; +} + +/**Function************************************************************* + + Synopsis [Saves one counter-example into internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlAddPattern( Ssw_Man_t * p, Aig_Obj_t * pRepr, Aig_Obj_t * pCand ) +{ + Aig_Obj_t * pObj; + unsigned * pInfo; + int i, nVarNum, Value; + Vec_PtrForEachEntry( Aig_Obj_t *, p->pMSat->vUsedPis, pObj, i ) + { + nVarNum = Ssw_ObjSatNum( p->pMSat, pObj ); + assert( nVarNum > 0 ); + Value = sat_solver_var_value( p->pMSat->pSat, nVarNum ); + if ( Value == 0 ) + continue; + pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjPioNum(pObj) ); + Abc_InfoSetBit( pInfo, p->nPatterns ); + } +} + +/**Function************************************************************* + + Synopsis [Builds fraiged logic cone of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManBuildCone_rec( Ssw_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pObjNew; + assert( !Aig_IsComplement(pObj) ); + if ( Ssw_ObjFrame( p, pObj, 0 ) ) + return; + assert( Aig_ObjIsNode(pObj) ); + Ssw_ManBuildCone_rec( p, Aig_ObjFanin0(pObj) ); + Ssw_ManBuildCone_rec( p, Aig_ObjFanin1(pObj) ); + pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, 0), Ssw_ObjChild1Fra(p, pObj, 0) ); + Ssw_ObjSetFrame( p, pObj, 0, pObjNew ); +} + +/**Function************************************************************* + + Synopsis [Recycles the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManSweepLatchOne( Ssw_Man_t * p, Aig_Obj_t * pObjRepr, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pObjFraig, * pObjReprFraig, * pObjLi; + int RetValue, clk; + assert( Aig_ObjIsPi(pObj) ); + assert( Aig_ObjIsPi(pObjRepr) || Aig_ObjIsConst1(pObjRepr) ); + // check if it makes sense to skip some calls + if ( p->nCallsCount > 100 && p->nCallsUnsat < p->nCallsSat ) + { + if ( ++p->nCallsDelta < 0 ) + return; + } + p->nCallsDelta = 0; +clk = clock(); + // get the fraiged node + pObjLi = Saig_ObjLoToLi( p->pAig, pObj ); + Ssw_ManBuildCone_rec( p, Aig_ObjFanin0(pObjLi) ); + pObjFraig = Ssw_ObjChild0Fra( p, pObjLi, 0 ); + // get the fraiged representative + if ( Aig_ObjIsPi(pObjRepr) ) + { + pObjLi = Saig_ObjLoToLi( p->pAig, pObjRepr ); + Ssw_ManBuildCone_rec( p, Aig_ObjFanin0(pObjLi) ); + pObjReprFraig = Ssw_ObjChild0Fra( p, pObjLi, 0 ); + } + else + pObjReprFraig = Ssw_ObjFrame( p, pObjRepr, 0 ); +p->timeReduce += clock() - clk; + // if the fraiged nodes are the same, return + if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) ) + return; + p->nRecycleCalls++; + p->nCallsCount++; + + // check equivalence of the two nodes + if ( (pObj->fPhase == pObjRepr->fPhase) != (Aig_ObjPhaseReal(pObjFraig) == Aig_ObjPhaseReal(pObjReprFraig)) ) + { + p->nPatterns++; + p->nStrangers++; + p->fRefined = 1; + } + else + { + RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) ); + if ( RetValue == 1 ) // proved equivalence + { + p->nCallsUnsat++; + return; + } + if ( RetValue == -1 ) // timed out + { + Ssw_ClassesRemoveNode( p->ppClasses, pObj ); + p->nCallsUnsat++; + p->fRefined = 1; + return; + } + else // disproved equivalence + { + Ssw_SmlAddPattern( p, pObjRepr, pObj ); + p->nPatterns++; + p->nCallsSat++; + p->fRefined = 1; + } + } +} + +/**Function************************************************************* + + Synopsis [Performs one iteration of sweeping latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ManSweepLatch( Ssw_Man_t * p ) +{ +// Bar_Progress_t * pProgress = NULL; + Vec_Ptr_t * vClass; + Aig_Obj_t * pObj, * pRepr, * pTemp; + int i, k; + + // start the timeframe + p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) ); + // map constants and PIs + Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), 0, Aig_ManConst1(p->pFrames) ); + Saig_ManForEachPi( p->pAig, pObj, i ) + Ssw_ObjSetFrame( p, pObj, 0, Aig_ObjCreatePi(p->pFrames) ); + + // implement equivalence classes + Saig_ManForEachLo( p->pAig, pObj, i ) + { + pRepr = Aig_ObjRepr( p->pAig, pObj ); + if ( pRepr == NULL ) + { + pTemp = Aig_ObjCreatePi(p->pFrames); + pTemp->pData = pObj; + } + else + pTemp = Aig_NotCond( Ssw_ObjFrame(p, pRepr, 0), pRepr->fPhase ^ pObj->fPhase ); + Ssw_ObjSetFrame( p, pObj, 0, pTemp ); + } + Aig_ManSetPioNumbers( p->pFrames ); + + // prepare simulation info + assert( p->vSimInfo == NULL ); + p->vSimInfo = Vec_PtrAllocSimInfo( Aig_ManPiNum(p->pFrames), 1 ); + Vec_PtrCleanSimInfo( p->vSimInfo, 0, 1 ); + + // go through the registers +// if ( p->pPars->fVerbose ) +// pProgress = Bar_ProgressStart( stdout, Aig_ManRegNum(p->pAig) ); + vClass = Vec_PtrAlloc( 100 ); + p->fRefined = 0; + p->nCallsCount = p->nCallsSat = p->nCallsUnsat = 0; + Saig_ManForEachLo( p->pAig, pObj, i ) + { +// if ( p->pPars->fVerbose ) +// Bar_ProgressUpdate( pProgress, i, NULL ); + // consider the case of constant candidate + if ( Ssw_ObjIsConst1Cand( p->pAig, pObj ) ) + Ssw_ManSweepLatchOne( p, Aig_ManConst1(p->pAig), pObj ); + else + { + // consider the case of equivalence class + Ssw_ClassesCollectClass( p->ppClasses, pObj, vClass ); + if ( Vec_PtrSize(vClass) == 0 ) + continue; + // try to prove equivalences in this class + Vec_PtrForEachEntry( Aig_Obj_t *, vClass, pTemp, k ) + if ( Aig_ObjRepr(p->pAig, pTemp) == pObj ) + { + Ssw_ManSweepLatchOne( p, pObj, pTemp ); + if ( p->nPatterns == 32 ) + break; + } + } + // resimulate + if ( p->nPatterns == 32 ) + Ssw_ManSweepResimulate( p ); + // attempt recycling the SAT solver + if ( p->pPars->nSatVarMax && + p->pMSat->nSatVars > p->pPars->nSatVarMax && + p->nRecycleCalls > p->pPars->nRecycleCalls ) + { + p->nVarsMax = Abc_MaxInt( p->nVarsMax, p->pMSat->nSatVars ); + p->nCallsMax = Abc_MaxInt( p->nCallsMax, p->pMSat->nSolverCalls ); + Ssw_SatStop( p->pMSat ); + p->pMSat = Ssw_SatStart( 0 ); + p->nRecycles++; + p->nRecycleCalls = 0; + } + } +// ABC_PRT( "reduce", p->timeReduce ); +// Aig_TableProfile( p->pFrames ); +// printf( "And gates = %d\n", Aig_ManNodeNum(p->pFrames) ); + // resimulate + if ( p->nPatterns > 0 ) + Ssw_ManSweepResimulate( p ); + // cleanup + Vec_PtrFree( vClass ); +// if ( p->pPars->fVerbose ) +// Bar_ProgressStop( pProgress ); + + // cleanup +// Ssw_ClassesCheck( p->ppClasses ); + return p->fRefined; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/ssw/sswMan.c b/src/proof/ssw/sswMan.c new file mode 100644 index 00000000..c635569d --- /dev/null +++ b/src/proof/ssw/sswMan.c @@ -0,0 +1,218 @@ +/**CFile**************************************************************** + + FileName [sswMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Inductive prover with constraints.] + + Synopsis [Calls to the SAT solver.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 1, 2008.] + + Revision [$Id: sswMan.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sswInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ssw_Man_t * Ssw_ManCreate( Aig_Man_t * pAig, Ssw_Pars_t * pPars ) +{ + Ssw_Man_t * p; + // prepare the sequential AIG + assert( Saig_ManRegNum(pAig) > 0 ); + Aig_ManFanoutStart( pAig ); + Aig_ManSetPioNumbers( pAig ); + // create interpolation manager + p = ABC_ALLOC( Ssw_Man_t, 1 ); + memset( p, 0, sizeof(Ssw_Man_t) ); + p->pPars = pPars; + p->pAig = pAig; + p->nFrames = pPars->nFramesK + 1; + p->pNodeToFrames = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) * p->nFrames ); + p->vCommon = Vec_PtrAlloc( 100 ); + p->iOutputLit = -1; + // allocate storage for sim pattern + p->nPatWords = Abc_BitWordNum( Saig_ManPiNum(pAig) * p->nFrames + Saig_ManRegNum(pAig) ); + p->pPatWords = ABC_CALLOC( unsigned, p->nPatWords ); + // other + p->vNewLos = Vec_PtrAlloc( 100 ); + p->vNewPos = Vec_IntAlloc( 100 ); + p->vResimConsts = Vec_PtrAlloc( 100 ); + p->vResimClasses = Vec_PtrAlloc( 100 ); +// p->pPars->fVerbose = 1; + return p; +} + +/**Function************************************************************* + + Synopsis [Prints stats of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ManCountEquivs( Ssw_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, nEquivs = 0; + Aig_ManForEachObj( p->pAig, pObj, i ) + nEquivs += ( Aig_ObjRepr(p->pAig, pObj) != NULL ); + return nEquivs; +} + +/**Function************************************************************* + + Synopsis [Prints stats of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManPrintStats( Ssw_Man_t * p ) +{ + double nMemory = 1.0*Aig_ManObjNumMax(p->pAig)*p->nFrames*(2*sizeof(int)+2*sizeof(void*))/(1<<20); + + printf( "Parameters: F = %d. AddF = %d. C-lim = %d. Constr = %d. MaxLev = %d. Mem = %0.2f Mb.\n", + p->pPars->nFramesK, p->pPars->nFramesAddSim, p->pPars->nBTLimit, Saig_ManConstrNum(p->pAig), p->pPars->nMaxLevs, nMemory ); + printf( "AIG : PI = %d. PO = %d. Latch = %d. Node = %d. Ave SAT vars = %d.\n", + Saig_ManPiNum(p->pAig), Saig_ManPoNum(p->pAig), Saig_ManRegNum(p->pAig), Aig_ManNodeNum(p->pAig), + 0/(p->pPars->nIters+1) ); + printf( "SAT calls : Proof = %d. Cex = %d. Fail = %d. Lits proved = %d.\n", + p->nSatProof, p->nSatCallsSat, p->nSatFailsReal, Ssw_ManCountEquivs(p) ); + printf( "SAT solver: Vars max = %d. Calls max = %d. Recycles = %d. Sim rounds = %d.\n", + p->nVarsMax, p->nCallsMax, p->nRecyclesTotal, p->nSimRounds ); + 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) ); + + p->timeOther = p->timeTotal-p->timeBmc-p->timeReduce-p->timeMarkCones-p->timeSimSat-p->timeSat; + ABC_PRTP( "BMC ", p->timeBmc, p->timeTotal ); + ABC_PRTP( "Spec reduce", p->timeReduce, p->timeTotal ); + ABC_PRTP( "Mark cones ", p->timeMarkCones, p->timeTotal ); + ABC_PRTP( "Sim SAT ", p->timeSimSat, p->timeTotal ); + ABC_PRTP( "SAT solving", p->timeSat, p->timeTotal ); + ABC_PRTP( " unsat ", p->timeSatUnsat, p->timeTotal ); + ABC_PRTP( " sat ", p->timeSatSat, p->timeTotal ); + ABC_PRTP( " undecided", p->timeSatUndec, p->timeTotal ); + ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); + ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); + + // report the reductions + if ( p->pAig->nConstrs ) + { + printf( "Statistics reflecting the use of constraints:\n" ); + printf( "Total cones = %6d. Constraint cones = %6d. (%6.2f %%)\n", + p->nConesTotal, p->nConesConstr, 100.0*p->nConesConstr/p->nConesTotal ); + printf( "Total equivs = %6d. Removed equivs = %6d. (%6.2f %%)\n", + p->nEquivsTotal, p->nEquivsConstr, 100.0*p->nEquivsConstr/p->nEquivsTotal ); + printf( "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n", + p->nNodesBegC, p->nNodesEndC, 100.0*(p->nNodesBegC-p->nNodesEndC)/(p->nNodesBegC?p->nNodesBegC:1), + p->nRegsBegC, p->nRegsEndC, 100.0*(p->nRegsBegC-p->nRegsEndC)/(p->nRegsBegC?p->nRegsBegC:1) ); + } +} + +/**Function************************************************************* + + Synopsis [Frees the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManCleanup( Ssw_Man_t * p ) +{ +// Aig_ManCleanMarkAB( p->pAig ); + assert( p->pMSat == NULL ); + if ( p->pFrames ) + { + Aig_ManCleanMarkAB( p->pFrames ); + Aig_ManStop( p->pFrames ); + p->pFrames = NULL; + memset( p->pNodeToFrames, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(p->pAig) * p->nFrames ); + } + if ( p->vSimInfo ) + { + Vec_PtrFree( p->vSimInfo ); + p->vSimInfo = NULL; + } + p->nConstrTotal = 0; + p->nConstrReduced = 0; +} + +/**Function************************************************************* + + Synopsis [Frees the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManStop( Ssw_Man_t * p ) +{ + ABC_FREE( p->pVisited ); + if ( p->pPars->fVerbose )//&& p->pPars->nStepsMax == -1 ) + Ssw_ManPrintStats( p ); + if ( p->ppClasses ) + Ssw_ClassesStop( p->ppClasses ); + if ( p->pSml ) + Ssw_SmlStop( p->pSml ); + if ( p->vDiffPairs ) + Vec_IntFree( p->vDiffPairs ); + if ( p->vInits ) + Vec_IntFree( p->vInits ); + Vec_PtrFree( p->vResimConsts ); + Vec_PtrFree( p->vResimClasses ); + Vec_PtrFree( p->vNewLos ); + Vec_IntFree( p->vNewPos ); + Vec_PtrFree( p->vCommon ); + ABC_FREE( p->pNodeToFrames ); + ABC_FREE( p->pPatWords ); + ABC_FREE( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/ssw/sswPairs.c b/src/proof/ssw/sswPairs.c new file mode 100644 index 00000000..0aba942f --- /dev/null +++ b/src/proof/ssw/sswPairs.c @@ -0,0 +1,477 @@ +/**CFile**************************************************************** + + FileName [sswPairs.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Inductive prover with constraints.] + + Synopsis [Calls to the SAT solver.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 1, 2008.] + + Revision [$Id: sswPairs.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sswInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reports the status of the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_MiterStatus( Aig_Man_t * p, int fVerbose ) +{ + Aig_Obj_t * pObj, * pChild; + int i, CountConst0 = 0, CountNonConst0 = 0, CountUndecided = 0; +// if ( p->pData ) +// return 0; + Saig_ManForEachPo( 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 is a primary input + if ( p->nRegs == 0 && Aig_ObjIsPi(Aig_Regular(pChild)) ) + { + CountNonConst0++; + continue; + } + // check if the output can be not constant 0 + if ( Aig_Regular(pChild)->fPhase != (unsigned)Aig_IsComplement(pChild) ) + { + CountNonConst0++; + continue; + } + CountUndecided++; + } + + if ( fVerbose ) + { + printf( "Miter has %d outputs. ", Saig_ManPoNum(p) ); + 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 [Transfer equivalent pairs to the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Ssw_TransferSignalPairs( Aig_Man_t * pMiter, Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec_Int_t * vIds1, Vec_Int_t * vIds2 ) +{ + Vec_Int_t * vIds; + Aig_Obj_t * pObj1, * pObj2; + Aig_Obj_t * pObj1m, * pObj2m; + int i; + vIds = Vec_IntAlloc( 2 * Vec_IntSize(vIds1) ); + for ( i = 0; i < Vec_IntSize(vIds1); i++ ) + { + pObj1 = Aig_ManObj( pAig1, Vec_IntEntry(vIds1, i) ); + pObj2 = Aig_ManObj( pAig2, Vec_IntEntry(vIds2, i) ); + pObj1m = Aig_Regular((Aig_Obj_t *)pObj1->pData); + pObj2m = Aig_Regular((Aig_Obj_t *)pObj2->pData); + assert( pObj1m && pObj2m ); + if ( pObj1m == pObj2m ) + continue; + if ( pObj1m->Id < pObj2m->Id ) + { + Vec_IntPush( vIds, pObj1m->Id ); + Vec_IntPush( vIds, pObj2m->Id ); + } + else + { + Vec_IntPush( vIds, pObj2m->Id ); + Vec_IntPush( vIds, pObj1m->Id ); + } + } + return vIds; +} + +/**Function************************************************************* + + Synopsis [Transform pairs into class representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t ** Ssw_TransformPairsIntoTempClasses( Vec_Int_t * vPairs, int nObjNumMax ) +{ + Vec_Int_t ** pvClasses; // vector of classes + int * pReprs; // mapping nodes into their representatives + int Entry, idObj, idRepr, idReprObj, idReprRepr, i; + // allocate data-structures + pvClasses = ABC_CALLOC( Vec_Int_t *, nObjNumMax ); + pReprs = ABC_ALLOC( int, nObjNumMax ); + for ( i = 0; i < nObjNumMax; i++ ) + pReprs[i] = -1; + // consider pairs + for ( i = 0; i < Vec_IntSize(vPairs); i += 2 ) + { + // get both objects + idRepr = Vec_IntEntry( vPairs, i ); + idObj = Vec_IntEntry( vPairs, i+1 ); + assert( idObj > 0 ); + assert( (pReprs[idRepr] == -1) || (pvClasses[pReprs[idRepr]] != NULL) ); + assert( (pReprs[idObj] == -1) || (pvClasses[pReprs[idObj] ] != NULL) ); + // get representatives of both objects + idReprRepr = pReprs[idRepr]; + idReprObj = pReprs[idObj]; + // check different situations + if ( idReprRepr == -1 && idReprObj == -1 ) + { // they do not have classes + // create a class + pvClasses[idRepr] = Vec_IntAlloc( 4 ); + Vec_IntPush( pvClasses[idRepr], idRepr ); + Vec_IntPush( pvClasses[idRepr], idObj ); + pReprs[ idRepr ] = idRepr; + pReprs[ idObj ] = idRepr; + } + else if ( idReprRepr >= 0 && idReprObj == -1 ) + { // representative has a class + // add iObj to the same class + Vec_IntPushUniqueOrder( pvClasses[idReprRepr], idObj ); + pReprs[ idObj ] = idReprRepr; + } + else if ( idReprRepr == -1 && idReprObj >= 0 ) + { // object has a class + assert( idReprObj != idRepr ); + if ( idReprObj < idRepr ) + { // add idRepr to the same class + Vec_IntPushUniqueOrder( pvClasses[idReprObj], idRepr ); + pReprs[ idRepr ] = idReprObj; + } + else // if ( idReprObj > idRepr ) + { // make idRepr new representative + Vec_IntPushFirst( pvClasses[idReprObj], idRepr ); + pvClasses[idRepr] = pvClasses[idReprObj]; + pvClasses[idReprObj] = NULL; + // set correct representatives of each node + Vec_IntForEachEntry( pvClasses[idRepr], Entry, i ) + pReprs[ Entry ] = idRepr; + } + } + else // if ( idReprRepr >= 0 && idReprObj >= 0 ) + { // both have classes + if ( idReprRepr == idReprObj ) + { // the classes are the same + // nothing to do + } + else + { // the classes are different + // find the repr of the new class + if ( idReprRepr < idReprObj ) + { + Vec_IntForEachEntry( pvClasses[idReprObj], Entry, i ) + { + Vec_IntPushUniqueOrder( pvClasses[idReprRepr], Entry ); + pReprs[ Entry ] = idReprRepr; + } + Vec_IntFree( pvClasses[idReprObj] ); + pvClasses[idReprObj] = NULL; + } + else // if ( idReprRepr > idReprObj ) + { + Vec_IntForEachEntry( pvClasses[idReprRepr], Entry, i ) + { + Vec_IntPushUniqueOrder( pvClasses[idReprObj], Entry ); + pReprs[ Entry ] = idReprObj; + } + Vec_IntFree( pvClasses[idReprRepr] ); + pvClasses[idReprRepr] = NULL; + } + } + } + } + ABC_FREE( pReprs ); + return pvClasses; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_FreeTempClasses( Vec_Int_t ** pvClasses, int nObjNumMax ) +{ + int i; + for ( i = 0; i < nObjNumMax; i++ ) + if ( pvClasses[i] ) + Vec_IntFree( pvClasses[i] ); + ABC_FREE( pvClasses ); +} + +/**Function************************************************************* + + Synopsis [Performs signal correspondence for the miter of two AIGs with node pairs defined.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Ssw_SignalCorrespondenceWithPairs( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec_Int_t * vIds1, Vec_Int_t * vIds2, Ssw_Pars_t * pPars ) +{ + Ssw_Man_t * p; + Aig_Man_t * pAigNew, * pMiter; + Ssw_Pars_t Pars; + Vec_Int_t * vPairs; + Vec_Int_t ** pvClasses; + assert( Vec_IntSize(vIds1) == Vec_IntSize(vIds2) ); + // create sequential miter + pMiter = Saig_ManCreateMiter( pAig1, pAig2, 0 ); + Aig_ManCleanup( pMiter ); + // transfer information to the miter + vPairs = Ssw_TransferSignalPairs( pMiter, pAig1, pAig2, vIds1, vIds2 ); + // create representation of the classes + pvClasses = Ssw_TransformPairsIntoTempClasses( vPairs, Aig_ManObjNumMax(pMiter) ); + Vec_IntFree( vPairs ); + // if parameters are not given, create them + if ( pPars == NULL ) + Ssw_ManSetDefaultParams( pPars = &Pars ); + // start the induction manager + p = Ssw_ManCreate( pMiter, pPars ); + // create equivalence classes using these IDs + p->ppClasses = Ssw_ClassesPreparePairs( pMiter, pvClasses ); + p->pSml = Ssw_SmlStart( pMiter, 0, p->nFrames + p->pPars->nFramesAddSim, 1 ); + Ssw_ClassesSetData( p->ppClasses, p->pSml, (unsigned(*)(void *,Aig_Obj_t *))Ssw_SmlObjHashWord, (int(*)(void *,Aig_Obj_t *))Ssw_SmlObjIsConstWord, (int(*)(void *,Aig_Obj_t *,Aig_Obj_t *))Ssw_SmlObjsAreEqualWord ); + // perform refinement of classes + pAigNew = Ssw_SignalCorrespondenceRefine( p ); + // cleanup + Ssw_FreeTempClasses( pvClasses, Aig_ManObjNumMax(pMiter) ); + Ssw_ManStop( p ); + Aig_ManStop( pMiter ); + return pAigNew; +} + +/**Function************************************************************* + + Synopsis [Runs inductive SEC for the miter of two AIGs with node pairs defined.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Ssw_SignalCorrespondeceTestPairs( Aig_Man_t * pAig ) +{ + Aig_Man_t * pAigNew, * pAigRes; + Ssw_Pars_t Pars, * pPars = &Pars; + Vec_Int_t * vIds1, * vIds2; + Aig_Obj_t * pObj, * pRepr; + int RetValue, i, clk = clock(); + Ssw_ManSetDefaultParams( pPars ); + pPars->fVerbose = 1; + pAigNew = Ssw_SignalCorrespondence( pAig, pPars ); + // record pairs of equivalent nodes + vIds1 = Vec_IntAlloc( Aig_ManObjNumMax(pAig) ); + vIds2 = Vec_IntAlloc( Aig_ManObjNumMax(pAig) ); + Aig_ManForEachObj( pAig, pObj, i ) + { + pRepr = Aig_Regular((Aig_Obj_t *)pObj->pData); + if ( pRepr == NULL ) + continue; + if ( Aig_ManObj(pAigNew, pRepr->Id) == NULL ) + continue; +/* + if ( Aig_ObjIsNode(pObj) ) + printf( "n " ); + else if ( Saig_ObjIsPi(pAig, pObj) ) + printf( "pi " ); + else if ( Saig_ObjIsLo(pAig, pObj) ) + printf( "lo " ); +*/ + Vec_IntPush( vIds1, Aig_ObjId(pObj) ); + Vec_IntPush( vIds2, Aig_ObjId(pRepr) ); + } + printf( "Recorded %d pairs (before: %d after: %d).\n", Vec_IntSize(vIds1), Aig_ManObjNumMax(pAig), Aig_ManObjNumMax(pAigNew) ); + // try the new AIGs + pAigRes = Ssw_SignalCorrespondenceWithPairs( pAig, pAigNew, vIds1, vIds2, pPars ); + Vec_IntFree( vIds1 ); + Vec_IntFree( vIds2 ); + // report the results + RetValue = Ssw_MiterStatus( pAigRes, 1 ); + if ( RetValue == 1 ) + printf( "Verification successful. " ); + else if ( RetValue == 0 ) + printf( "Verification failed with the counter-example. " ); + else + printf( "Verification UNDECIDED. Remaining registers %d (total %d). ", + Aig_ManRegNum(pAigRes), Aig_ManRegNum(pAig) + Aig_ManRegNum(pAigNew) ); + ABC_PRT( "Time", clock() - clk ); + // cleanup + Aig_ManStop( pAigNew ); + return pAigRes; +} + +/**Function************************************************************* + + Synopsis [Runs inductive SEC for the miter of two AIGs with node pairs defined.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SecWithPairs( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec_Int_t * vIds1, Vec_Int_t * vIds2, Ssw_Pars_t * pPars ) +{ + Aig_Man_t * pAigRes; + int RetValue, clk = clock(); + assert( vIds1 != NULL && vIds2 != NULL ); + // try the new AIGs + printf( "Performing specialized verification with node pairs.\n" ); + pAigRes = Ssw_SignalCorrespondenceWithPairs( pAig1, pAig2, vIds1, vIds2, pPars ); + // report the results + RetValue = Ssw_MiterStatus( pAigRes, 1 ); + if ( RetValue == 1 ) + printf( "Verification successful. " ); + else if ( RetValue == 0 ) + printf( "Verification failed with a counter-example. " ); + else + printf( "Verification UNDECIDED. The number of remaining regs = %d (total = %d). ", + Aig_ManRegNum(pAigRes), Aig_ManRegNum(pAig1) + Aig_ManRegNum(pAig2) ); + ABC_PRT( "Time", clock() - clk ); + // cleanup + Aig_ManStop( pAigRes ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Runs inductive SEC for the miter of two AIGs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SecGeneral( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Ssw_Pars_t * pPars ) +{ + Aig_Man_t * pAigRes, * pMiter; + int RetValue, clk = clock(); + // try the new AIGs + printf( "Performing general verification without node pairs.\n" ); + pMiter = Saig_ManCreateMiter( pAig1, pAig2, 0 ); + Aig_ManCleanup( pMiter ); + pAigRes = Ssw_SignalCorrespondence( pMiter, pPars ); + Aig_ManStop( pMiter ); + // report the results + RetValue = Ssw_MiterStatus( pAigRes, 1 ); + if ( RetValue == 1 ) + printf( "Verification successful. " ); + else if ( RetValue == 0 ) + printf( "Verification failed with a counter-example. " ); + else + printf( "Verification UNDECIDED. The number of remaining regs = %d (total = %d). ", + Aig_ManRegNum(pAigRes), Aig_ManRegNum(pAig1) + Aig_ManRegNum(pAig2) ); + ABC_PRT( "Time", clock() - clk ); + // cleanup + Aig_ManStop( pAigRes ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Runs inductive SEC for the miter of two AIGs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SecGeneralMiter( Aig_Man_t * pMiter, Ssw_Pars_t * pPars ) +{ + Aig_Man_t * pAigRes; + int RetValue, clk = clock(); + // try the new AIGs +// printf( "Performing general verification without node pairs.\n" ); + pAigRes = Ssw_SignalCorrespondence( pMiter, pPars ); + // report the results + RetValue = Ssw_MiterStatus( pAigRes, 1 ); + if ( RetValue == 1 ) + printf( "Verification successful. " ); + else if ( RetValue == 0 ) + printf( "Verification failed with a counter-example. " ); + else + printf( "Verification UNDECIDED. The number of remaining regs = %d (total = %d). ", + Aig_ManRegNum(pAigRes), Aig_ManRegNum(pMiter) ); + ABC_PRT( "Time", clock() - clk ); + // cleanup + Aig_ManStop( pAigRes ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/ssw/sswPart.c b/src/proof/ssw/sswPart.c new file mode 100644 index 00000000..d2f07dc8 --- /dev/null +++ b/src/proof/ssw/sswPart.c @@ -0,0 +1,141 @@ +/**CFile**************************************************************** + + FileName [sswPart.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Inductive prover with constraints.] + + Synopsis [Partitioned signal correspondence.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 1, 2008.] + + Revision [$Id: sswPart.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sswInt.h" +#include "src/aig/ioa/ioa.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs partitioned sequential SAT sweeping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Ssw_SignalCorrespondencePart( Aig_Man_t * pAig, Ssw_Pars_t * pPars ) +{ + int fPrintParts = 0; + char Buffer[100]; + Aig_Man_t * pTemp, * pNew; + Vec_Ptr_t * vResult; + Vec_Int_t * vPart; + int * pMapBack; + int i, nCountPis, nCountRegs; + int nClasses, nPartSize, fVerbose; + int clk = clock(); + if ( pPars->fConstrs ) + { + printf( "Cannot use partitioned computation with constraints.\n" ); + return NULL; + } + // save parameters + nPartSize = pPars->nPartSize; pPars->nPartSize = 0; + fVerbose = pPars->fVerbose; pPars->fVerbose = 0; + // generate partitions + if ( pAig->vClockDoms ) + { + // divide large clock domains into separate partitions + vResult = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( Vec_Int_t *, (Vec_Ptr_t *)pAig->vClockDoms, vPart, i ) + { + if ( nPartSize && Vec_IntSize(vPart) > nPartSize ) + Aig_ManPartDivide( vResult, vPart, nPartSize, pPars->nOverSize ); + else + Vec_PtrPush( vResult, Vec_IntDup(vPart) ); + } + } + else + vResult = Aig_ManRegPartitionSimple( pAig, nPartSize, pPars->nOverSize ); +// vResult = Aig_ManPartitionSmartRegisters( pAig, nPartSize, 0 ); +// vResult = Aig_ManRegPartitionSmart( pAig, nPartSize ); + if ( fPrintParts ) + { + // print partitions + printf( "Simple partitioning. %d partitions are saved:\n", Vec_PtrSize(vResult) ); + Vec_PtrForEachEntry( Vec_Int_t *, vResult, vPart, i ) + { +// extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact ); + sprintf( Buffer, "part%03d.aig", i ); + pTemp = Aig_ManRegCreatePart( pAig, vPart, &nCountPis, &nCountRegs, NULL ); + Ioa_WriteAiger( pTemp, Buffer, 0, 0 ); + printf( "part%03d.aig : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d.\n", + i, Vec_IntSize(vPart), Aig_ManPiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Aig_ManNodeNum(pTemp) ); + Aig_ManStop( pTemp ); + } + } + + // perform SSW with partitions + Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) ); + Vec_PtrForEachEntry( Vec_Int_t *, vResult, vPart, i ) + { + pTemp = Aig_ManRegCreatePart( pAig, vPart, &nCountPis, &nCountRegs, &pMapBack ); + Aig_ManSetRegNum( pTemp, pTemp->nRegs ); + // create the projection of 1-hot registers + if ( pAig->vOnehots ) + pTemp->vOnehots = Aig_ManRegProjectOnehots( pAig, pTemp, pAig->vOnehots, fVerbose ); + // run SSW + if (nCountPis>0) { + pNew = Ssw_SignalCorrespondence( pTemp, pPars ); + nClasses = Aig_TransferMappedClasses( pAig, pTemp, pMapBack ); + if ( fVerbose ) + printf( "%3d : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d. It = %3d. Cl = %5d.\n", + i, Vec_IntSize(vPart), Aig_ManPiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Aig_ManNodeNum(pTemp), pPars->nIters, nClasses ); + Aig_ManStop( pNew ); + } + Aig_ManStop( pTemp ); + ABC_FREE( pMapBack ); + } + // remap the AIG + pNew = Aig_ManDupRepr( pAig, 0 ); + Aig_ManSeqCleanup( pNew ); +// Aig_ManPrintStats( pAig ); +// Aig_ManPrintStats( pNew ); + Vec_VecFree( (Vec_Vec_t *)vResult ); + pPars->nPartSize = nPartSize; + pPars->fVerbose = fVerbose; + if ( fVerbose ) + { + ABC_PRT( "Total time", clock() - clk ); + } + return pNew; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/ssw/sswRarity.c b/src/proof/ssw/sswRarity.c new file mode 100644 index 00000000..264bb2c8 --- /dev/null +++ b/src/proof/ssw/sswRarity.c @@ -0,0 +1,1158 @@ +/**CFile**************************************************************** + + FileName [sswRarity.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Inductive prover with constraints.] + + Synopsis [Rarity-driven refinement of equivalence classes.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 1, 2008.] + + Revision [$Id: sswRarity.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sswInt.h" +#include "src/aig/gia/giaAig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Ssw_RarMan_t_ Ssw_RarMan_t; +struct Ssw_RarMan_t_ +{ + // parameters + int nWords; // the number of words to simulate + int nFrames; // the number of frames to simulate + int nBinSize; // the number of flops in one group + int fVerbose; // the verbosiness flag + int nGroups; // the number of flop groups + int nWordsReg; // the number of words in the registers + // internal data + Aig_Man_t * pAig; // AIG with equivalence classes + Ssw_Cla_t * ppClasses; // equivalence classes + Vec_Int_t * vInits; // initial state + // simulation data + word * pObjData; // simulation info for each obj + word * pPatData; // pattern data for each reg + // candidates to update + Vec_Ptr_t * vUpdConst; // constant 1 candidates + Vec_Ptr_t * vUpdClass; // class representatives + // rarity data + int * pRarity; // occur counts for patterns in groups + double * pPatCosts; // pattern costs + // best patterns + Vec_Int_t * vPatBests; // best patterns + int iFailPo; // failed primary output + int iFailPat; // failed pattern +}; + + +static inline int Ssw_RarGetBinPat( Ssw_RarMan_t * p, int iBin, int iPat ) +{ + assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->nBinSize ); + assert( iPat >= 0 && iPat < (1 << p->nBinSize) ); + return p->pRarity[iBin * (1 << p->nBinSize) + iPat]; +} +static inline void Ssw_RarSetBinPat( Ssw_RarMan_t * p, int iBin, int iPat, int Value ) +{ + assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->nBinSize ); + assert( iPat >= 0 && iPat < (1 << p->nBinSize) ); + p->pRarity[iBin * (1 << p->nBinSize) + iPat] = Value; +} +static inline void Ssw_RarAddToBinPat( Ssw_RarMan_t * p, int iBin, int iPat ) +{ + assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->nBinSize ); + assert( iPat >= 0 && iPat < (1 << p->nBinSize) ); + p->pRarity[iBin * (1 << p->nBinSize) + iPat]++; +} + +static inline int Ssw_RarBitWordNum( int nBits ) { return (nBits>>6) + ((nBits&63) > 0); } + +static inline word * Ssw_RarObjSim( Ssw_RarMan_t * p, int Id ) { assert( Id < Aig_ManObjNumMax(p->pAig) ); return p->pObjData + p->nWords * Id; } +static inline word * Ssw_RarPatSim( Ssw_RarMan_t * p, int Id ) { assert( Id < 64 * p->nWords ); return p->pPatData + p->nWordsReg * Id; } + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Prepares random number generator.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_RarManPrepareRandom( int nRandSeed ) +{ + int i; + Aig_ManRandom( 1 ); + for ( i = 0; i < nRandSeed; i++ ) + Aig_ManRandom( 0 ); +} + +/**Function************************************************************* + + Synopsis [Initializes random primary inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_RarManAssingRandomPis( Ssw_RarMan_t * p ) +{ + word * pSim; + Aig_Obj_t * pObj; + int w, i; + Saig_ManForEachPi( p->pAig, pObj, i ) + { + pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); + for ( w = 0; w < p->nWords; w++ ) + pSim[w] = Aig_ManRandom64(0); +// pSim[0] <<= 1; +// pSim[0] = (pSim[0] << 2) | 2; + pSim[0] = (pSim[0] << 4) | ((i & 1) ? 0xA : 0xC); + } +} + +/**Function************************************************************* + + Synopsis [Derives the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Ssw_RarDeriveCex( Ssw_RarMan_t * p, int iFrame, int iPo, int iPatFinal, int fVerbose ) +{ + Abc_Cex_t * pCex; + Aig_Obj_t * pObj; + Vec_Int_t * vTrace; + word * pSim; + int i, r, f, iBit, iPatThis; + // compute the pattern sequence + iPatThis = iPatFinal; + vTrace = Vec_IntStartFull( iFrame / p->nFrames + 1 ); + Vec_IntWriteEntry( vTrace, iFrame / p->nFrames, iPatThis ); + for ( r = iFrame / p->nFrames - 1; r >= 0; r-- ) + { + iPatThis = Vec_IntEntry( p->vPatBests, r * p->nWords + iPatThis / 64 ); + Vec_IntWriteEntry( vTrace, r, iPatThis ); + } + // create counter-example + pCex = Abc_CexAlloc( Aig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), iFrame+1 ); + pCex->iFrame = iFrame; + pCex->iPo = iPo; + // insert the bits + iBit = Aig_ManRegNum(p->pAig); + for ( f = 0; f <= iFrame; f++ ) + { + Ssw_RarManAssingRandomPis( p ); + iPatThis = Vec_IntEntry( vTrace, f / p->nFrames ); + Saig_ManForEachPi( p->pAig, pObj, i ) + { + pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); + if ( Abc_InfoHasBit( (unsigned *)pSim, iPatThis ) ) + Abc_InfoSetBit( pCex->pData, iBit ); + iBit++; + } + } + Vec_IntFree( vTrace ); + assert( iBit == pCex->nBits ); + // verify the counter example + if ( !Saig_ManVerifyCex( p->pAig, pCex ) ) + { + printf( "Ssw_RarDeriveCex(): Counter-example is invalid.\n" ); +// Abc_CexFree( pCex ); +// pCex = NULL; + } + else + { +// printf( "Counter-example verification is successful.\n" ); + if ( fVerbose ) + printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump a witness). \n", pCex->iPo, pCex->iFrame ); + } + return pCex; +} + + +/**Function************************************************************* + + Synopsis [Transposing 32-bit matrix.] + + Description [Borrowed from "Hacker's Delight", by Henry Warren.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void transpose32( unsigned A[32] ) +{ + int j, k; + unsigned t, m = 0x0000FFFF; + for ( j = 16; j != 0; j = j >> 1, m = m ^ (m << j) ) + { + for ( k = 0; k < 32; k = (k + j + 1) & ~j ) + { + t = (A[k] ^ (A[k+j] >> j)) & m; + A[k] = A[k] ^ t; + A[k+j] = A[k+j] ^ (t << j); + } + } +} + +/**Function************************************************************* + + Synopsis [Transposing 64-bit matrix.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void transpose64( word A[64] ) +{ + int j, k; + word t, m = 0x00000000FFFFFFFF; + for ( j = 32; j != 0; j = j >> 1, m = m ^ (m << j) ) + { + for ( k = 0; k < 64; k = (k + j + 1) & ~j ) + { + t = (A[k] ^ (A[k+j] >> j)) & m; + A[k] = A[k] ^ t; + A[k+j] = A[k+j] ^ (t << j); + } + } +} + +/**Function************************************************************* + + Synopsis [Transposing 64-bit matrix.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void transpose64Simple( word A[64], word B[64] ) +{ + int i, k; + for ( i = 0; i < 64; i++ ) + B[i] = 0; + for ( i = 0; i < 64; i++ ) + for ( k = 0; k < 64; k++ ) + if ( (A[i] >> k) & 1 ) + B[k] |= ((word)1 << (63-i)); +} + +/**Function************************************************************* + + Synopsis [Testing the transposing code.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void TransposeTest() +{ + word M[64], N[64]; + int i, clk; + Aig_ManRandom64( 1 ); +// for ( i = 0; i < 64; i++ ) +// M[i] = Aig_ManRandom64( 0 ); + for ( i = 0; i < 64; i++ ) + M[i] = i? (word)0 : ~(word)0; +// for ( i = 0; i < 64; i++ ) +// Extra_PrintBinary( stdout, (unsigned *)&M[i], 64 ), printf( "\n" ); + + clk = clock(); + for ( i = 0; i < 100001; i++ ) + transpose64Simple( M, N ); + Abc_PrintTime( 1, "Time", clock() - clk ); + + clk = clock(); + for ( i = 0; i < 100001; i++ ) + transpose64( M ); + Abc_PrintTime( 1, "Time", clock() - clk ); + + for ( i = 0; i < 64; i++ ) + if ( M[i] != N[i] ) + printf( "Mismatch\n" ); +/* + printf( "\n" ); + for ( i = 0; i < 64; i++ ) + Extra_PrintBinary( stdout, (unsigned *)&M[i], 64 ), printf( "\n" ); + printf( "\n" ); + for ( i = 0; i < 64; i++ ) + Extra_PrintBinary( stdout, (unsigned *)&N[i], 64 ), printf( "\n" ); +*/ +} + +/**Function************************************************************* + + Synopsis [Transposing pObjData[ nRegs x nWords ] -> pPatData[ nWords x nRegs ].] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_RarTranspose( Ssw_RarMan_t * p ) +{ + Aig_Obj_t * pObj; + word M[64]; + int w, r, i; + for ( w = 0; w < p->nWords; w++ ) + for ( r = 0; r < p->nWordsReg; r++ ) + { + // save input + for ( i = 0; i < 64; i++ ) + { + if ( r*64 + 63-i < Aig_ManRegNum(p->pAig) ) + { + pObj = Saig_ManLi( p->pAig, r*64 + 63-i ); + M[i] = Ssw_RarObjSim( p, Aig_ObjId(pObj) )[w]; + } + else + M[i] = 0; + } + // transpose + transpose64( M ); + // save output + for ( i = 0; i < 64; i++ ) + Ssw_RarPatSim( p, w*64 + 63-i )[r] = M[i]; + } +/* + Saig_ManForEachLi( p->pAig, pObj, i ) + { + word * pBitData = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); + Extra_PrintBinary( stdout, (unsigned *)pBitData, 64*p->nWords ); printf( "\n" ); + } + printf( "\n" ); + for ( i = 0; i < p->nWords*64; i++ ) + { + word * pBitData = Ssw_RarPatSim( p, i ); + Extra_PrintBinary( stdout, (unsigned *)pBitData, Aig_ManRegNum(p->pAig) ); printf( "\n" ); + } + printf( "\n" ); +*/ +} + + + + +/**Function************************************************************* + + Synopsis [Sets random inputs and specialied flop outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_RarManInitialize( Ssw_RarMan_t * p, Vec_Int_t * vInit ) +{ + Aig_Obj_t * pObj, * pObjLi; + word * pSim, * pSimLi; + int w, i; + // constant + pObj = Aig_ManConst1( p->pAig ); + pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); + for ( w = 0; w < p->nWords; w++ ) + pSim[w] = ~(word)0; + // primary inputs + Ssw_RarManAssingRandomPis( p ); + // flop outputs + if ( vInit ) + { + assert( Vec_IntSize(vInit) == Saig_ManRegNum(p->pAig) * p->nWords ); + Saig_ManForEachLo( p->pAig, pObj, i ) + { + pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); + for ( w = 0; w < p->nWords; w++ ) + pSim[w] = Vec_IntEntry(vInit, w * Saig_ManRegNum(p->pAig) + i) ? ~(word)0 : (word)0; + } + } + else + { + Saig_ManForEachLiLo( p->pAig, pObjLi, pObj, i ) + { + pSimLi = Ssw_RarObjSim( p, Aig_ObjId(pObjLi) ); + pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); + for ( w = 0; w < p->nWords; w++ ) + pSim[w] = pSimLi[w]; + } + } +} + +/**Function************************************************************* + + Synopsis [Returns 1 if simulation info is composed of all zeros.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_RarManObjIsConst( void * pMan, Aig_Obj_t * pObj ) +{ + Ssw_RarMan_t * p = (Ssw_RarMan_t *)pMan; + word * pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); + word Flip = pObj->fPhase ? ~0 : 0; + int w; + for ( w = 0; w < p->nWords; w++ ) + if ( pSim[w] ^ Flip ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if simulation infos are equal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_RarManObjsAreEqual( void * pMan, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) +{ + Ssw_RarMan_t * p = (Ssw_RarMan_t *)pMan; + word * pSim0 = Ssw_RarObjSim( p, pObj0->Id ); + word * pSim1 = Ssw_RarObjSim( p, pObj1->Id ); + word Flip = (pObj0->fPhase != pObj1->fPhase) ? ~0 : 0; + int w; + for ( w = 0; w < p->nWords; w++ ) + if ( pSim0[w] ^ pSim1[w] ^ Flip ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes hash value of the node using its simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Ssw_RarManObjHashWord( void * pMan, Aig_Obj_t * pObj ) +{ + Ssw_RarMan_t * p = (Ssw_RarMan_t *)pMan; + static int s_SPrimes[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; + uHash = 0; + pSims = (unsigned *)Ssw_RarObjSim( p, pObj->Id ); + for ( i = 0; i < 2 * p->nWords; i++ ) + uHash ^= pSims[i] * s_SPrimes[i & 0x7F]; + return uHash; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if simulation info is composed of all zeros.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_RarManObjWhichOne( Ssw_RarMan_t * p, Aig_Obj_t * pObj ) +{ + word * pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); + word Flip = pObj->fPhase ? ~0 : 0; + int w, i; + for ( w = 0; w < p->nWords; w++ ) + if ( pSim[w] ^ Flip ) + { + for ( i = 0; i < 64; i++ ) + if ( ((pSim[w] ^ Flip) >> i) & 1 ) + break; + assert( i < 64 ); + return w * 64 + i; + } + return -1; +} + +/**Function************************************************************* + + Synopsis [Check if any of the POs becomes non-constant.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_RarManCheckNonConstOutputs( Ssw_RarMan_t * p ) +{ + Aig_Obj_t * pObj; + int i; + p->iFailPo = -1; + p->iFailPat = -1; + Saig_ManForEachPo( p->pAig, pObj, i ) + { + if ( p->pAig->nConstrs && i >= Saig_ManPoNum(p->pAig) - p->pAig->nConstrs ) + return 0; + if ( !Ssw_RarManObjIsConst(p, pObj) ) + { + p->iFailPo = i; + p->iFailPat = Ssw_RarManObjWhichOne( p, pObj ); + return 1; + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Performs one round of simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_RarManSimulate( Ssw_RarMan_t * p, Vec_Int_t * vInit, int fUpdate, int fFirst ) +{ + Aig_Obj_t * pObj, * pRepr; + word * pSim, * pSim0, * pSim1; + word Flip, Flip0, Flip1; + int w, i; + // initialize + Ssw_RarManInitialize( p, vInit ); + Vec_PtrClear( p->vUpdConst ); + Vec_PtrClear( p->vUpdClass ); + Aig_ManIncrementTravId( p->pAig ); + // check comb inputs + if ( fUpdate ) + Aig_ManForEachPi( p->pAig, pObj, i ) + { + pRepr = Aig_ObjRepr(p->pAig, pObj); + if ( pRepr == NULL || Aig_ObjIsTravIdCurrent( p->pAig, pRepr ) ) + continue; + if ( Ssw_RarManObjsAreEqual( p, pObj, pRepr ) ) + continue; + // save for update + if ( pRepr == Aig_ManConst1(p->pAig) ) + Vec_PtrPush( p->vUpdConst, pObj ); + else + { + Vec_PtrPush( p->vUpdClass, pRepr ); + Aig_ObjSetTravIdCurrent( p->pAig, pRepr ); + } + } + // simulate + Aig_ManForEachNode( p->pAig, pObj, i ) + { + pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); + pSim0 = Ssw_RarObjSim( p, Aig_ObjFaninId0(pObj) ); + pSim1 = Ssw_RarObjSim( p, Aig_ObjFaninId1(pObj) ); + Flip0 = Aig_ObjFaninC0(pObj) ? ~0 : 0; + Flip1 = Aig_ObjFaninC1(pObj) ? ~0 : 0; + for ( w = 0; w < p->nWords; w++ ) + pSim[w] = (Flip0 ^ pSim0[w]) & (Flip1 ^ pSim1[w]); + if ( !fUpdate ) + continue; + // check classes + pRepr = Aig_ObjRepr(p->pAig, pObj); + if ( pRepr == NULL || Aig_ObjIsTravIdCurrent( p->pAig, pRepr ) ) + continue; + if ( Ssw_RarManObjsAreEqual( p, pObj, pRepr ) ) + continue; + // save for update + if ( pRepr == Aig_ManConst1(p->pAig) ) + Vec_PtrPush( p->vUpdConst, pObj ); + else + { + Vec_PtrPush( p->vUpdClass, pRepr ); + Aig_ObjSetTravIdCurrent( p->pAig, pRepr ); + } + } + // transfer to POs + Aig_ManForEachPo( p->pAig, pObj, i ) + { + pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); + pSim0 = Ssw_RarObjSim( p, Aig_ObjFaninId0(pObj) ); + Flip = Aig_ObjFaninC0(pObj) ? ~0 : 0; + for ( w = 0; w < p->nWords; w++ ) + pSim[w] = Flip ^ pSim0[w]; + } + // refine classes + if ( fUpdate ) + { + if ( fFirst ) + { + Vec_Ptr_t * vCands = Vec_PtrAlloc( 1000 ); + Aig_ManForEachObj( p->pAig, pObj, i ) + if ( Ssw_ObjIsConst1Cand( p->pAig, pObj ) ) + Vec_PtrPush( vCands, pObj ); + assert( Vec_PtrSize(vCands) == Ssw_ClassesCand1Num(p->ppClasses) ); + Ssw_ClassesPrepareRehash( p->ppClasses, vCands, 0 ); + Vec_PtrFree( vCands ); + } + else + { + Ssw_ClassesRefineConst1Group( p->ppClasses, p->vUpdConst, 1 ); + Ssw_ClassesRefineGroup( p->ppClasses, p->vUpdClass, 1 ); + } + } +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Ssw_RarMan_t * Ssw_RarManStart( Aig_Man_t * pAig, int nWords, int nFrames, int nBinSize, int fVerbose ) +{ + Ssw_RarMan_t * p; +// if ( Aig_ManRegNum(pAig) < nBinSize || nBinSize <= 0 ) +// return NULL; + p = ABC_CALLOC( Ssw_RarMan_t, 1 ); + p->pAig = pAig; + p->nWords = nWords; + p->nFrames = nFrames; + p->nBinSize = nBinSize; + p->fVerbose = fVerbose; + p->nGroups = Aig_ManRegNum(pAig) / nBinSize; + p->pRarity = ABC_CALLOC( int, (1 << nBinSize) * p->nGroups ); + p->pPatCosts = ABC_CALLOC( double, p->nWords * 64 ); + p->nWordsReg = Ssw_RarBitWordNum( Aig_ManRegNum(pAig) ); + p->pObjData = ABC_ALLOC( word, Aig_ManObjNumMax(pAig) * p->nWords ); + p->pPatData = ABC_ALLOC( word, 64 * p->nWords * p->nWordsReg ); + p->vUpdConst = Vec_PtrAlloc( 100 ); + p->vUpdClass = Vec_PtrAlloc( 100 ); + p->vPatBests = Vec_IntAlloc( 100 ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Ssw_RarManStop( Ssw_RarMan_t * p ) +{ + if ( p->ppClasses ) Ssw_ClassesStop( p->ppClasses ); + Vec_IntFreeP( &p->vInits ); + Vec_IntFreeP( &p->vPatBests ); + Vec_PtrFreeP( &p->vUpdConst ); + Vec_PtrFreeP( &p->vUpdClass ); + ABC_FREE( p->pObjData ); + ABC_FREE( p->pPatData ); + ABC_FREE( p->pPatCosts ); + ABC_FREE( p->pRarity ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Select best patterns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Ssw_RarTransferPatterns( Ssw_RarMan_t * p, Vec_Int_t * vInits ) +{ +// Aig_Obj_t * pObj; + unsigned char * pData; + unsigned * pPattern; + int i, k, Value; + + // more data from regs to pats + Ssw_RarTranspose( p ); + + // update counters + for ( k = 0; k < p->nWords * 64; k++ ) + { + pData = (unsigned char *)Ssw_RarPatSim( p, k ); + for ( i = 0; i < p->nGroups; i++ ) + Ssw_RarAddToBinPat( p, i, pData[i] ); + } + + // for each pattern + for ( k = 0; k < p->nWords * 64; k++ ) + { + pData = (unsigned char *)Ssw_RarPatSim( p, k ); + // find the cost of its values + p->pPatCosts[k] = 0.0; + for ( i = 0; i < p->nGroups; i++ ) + { + Value = Ssw_RarGetBinPat( p, i, pData[i] ); + assert( Value > 0 ); + p->pPatCosts[k] += 1.0/(Value*Value); + } + // print the result +//printf( "%3d : %9.6f\n", k, p->pPatCosts[k] ); + } + + // choose as many as there are words + Vec_IntClear( vInits ); + for ( i = 0; i < p->nWords; i++ ) + { + // select the best + int iPatBest = -1; + double iCostBest = -ABC_INFINITY; + for ( k = 0; k < p->nWords * 64; k++ ) + if ( iCostBest < p->pPatCosts[k] ) + { + iCostBest = p->pPatCosts[k]; + iPatBest = k; + } + // remove from costs + assert( iPatBest >= 0 ); + p->pPatCosts[iPatBest] = -ABC_INFINITY; + // set the flops + pPattern = (unsigned *)Ssw_RarPatSim( p, iPatBest ); + for ( k = 0; k < Aig_ManRegNum(p->pAig); k++ ) + Vec_IntPush( vInits, Abc_InfoHasBit(pPattern, k) ); +//printf( "Best pattern %5d\n", iPatBest ); + Vec_IntPush( p->vPatBests, iPatBest ); + } + assert( Vec_IntSize(vInits) == Aig_ManRegNum(p->pAig) * p->nWords ); +} + + +/**Function************************************************************* + + Synopsis [Performs fraiging for one node.] + + Description [Returns the fraiged node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Vec_Int_t * Ssw_RarFindStartingState( Aig_Man_t * pAig, Abc_Cex_t * pCex ) +{ + Vec_Int_t * vInit; + Aig_Obj_t * pObj, * pObjLi; + int f, i, iBit; + // assign register outputs + Saig_ManForEachLi( pAig, pObj, i ) + pObj->fMarkB = Abc_InfoHasBit( pCex->pData, i ); + // simulate the timeframes + iBit = pCex->nRegs; + for ( f = 0; f <= pCex->iFrame; f++ ) + { + // set the PI simulation information + Aig_ManConst1(pAig)->fMarkB = 1; + Saig_ManForEachPi( pAig, pObj, i ) + pObj->fMarkB = Abc_InfoHasBit( pCex->pData, iBit++ ); + Saig_ManForEachLiLo( pAig, pObjLi, pObj, i ) + pObj->fMarkB = pObjLi->fMarkB; + // simulate internal nodes + Aig_ManForEachNode( pAig, pObj, i ) + pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ) + & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) ); + // assign the COs + Aig_ManForEachPo( pAig, pObj, i ) + pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ); + } + assert( iBit == pCex->nBits ); + // check that the output failed as expected -- cannot check because it is not an SRM! +// pObj = Aig_ManPo( pAig, pCex->iPo ); +// if ( pObj->fMarkB != 1 ) +// printf( "The counter-example does not refine the output.\n" ); + // record the new pattern + vInit = Vec_IntAlloc( Saig_ManRegNum(pAig) ); + Saig_ManForEachLo( pAig, pObj, i ) + { +//printf( "%d", pObj->fMarkB ); + Vec_IntPush( vInit, pObj->fMarkB ); + } +//printf( "\n" ); + Aig_ManCleanMarkB( pAig ); + return vInit; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_RarCheckTrivial( Aig_Man_t * pAig, int fVerbose ) +{ + Aig_Obj_t * pObj; + int i; + Saig_ManForEachPo( pAig, pObj, i ) + { + if ( pAig->nConstrs && i >= Saig_ManPoNum(pAig) - pAig->nConstrs ) + return 0; + if ( pObj->fPhase ) + { + ABC_FREE( pAig->pSeqModel ); + pAig->pSeqModel = Abc_CexAlloc( Aig_ManRegNum(pAig), Saig_ManPiNum(pAig), 1 ); + pAig->pSeqModel->iPo = i; + if ( fVerbose ) + printf( "Output %d is trivally SAT in frame 0. \n", i ); + return 1; + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Perform sequential simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_RarSimulate( Aig_Man_t * pAig, int nFrames, int nWords, int nBinSize, int nRounds, int nRandSeed, int TimeOut, int fVerbose ) +{ + int fTryBmc = 0; + int fMiter = 1; + Ssw_RarMan_t * p; + int r, f, clk, clkTotal = clock(); + int nTimeToStop = time(NULL) + TimeOut; + int RetValue = -1; + int iFrameFail = -1; + assert( Aig_ManRegNum(pAig) > 0 ); + assert( Aig_ManConstrNum(pAig) == 0 ); + // consider the case of empty AIG + if ( Aig_ManNodeNum(pAig) == 0 ) + return -1; + // check trivially SAT miters + if ( fMiter && Ssw_RarCheckTrivial( pAig, fVerbose ) ) + return 0; + if ( fVerbose ) + printf( "Rarity simulation with %d words, %d frames, %d rounds, %d seed, and %d sec timeout.\n", + nWords, nFrames, nRounds, nRandSeed, TimeOut ); + // reset random numbers + Ssw_RarManPrepareRandom( nRandSeed ); + + // create manager + p = Ssw_RarManStart( pAig, nWords, nFrames, nBinSize, fVerbose ); + p->vInits = Vec_IntStart( Aig_ManRegNum(pAig) * nWords ); + + // perform simulation rounds + for ( r = 0; r < nRounds; r++ ) + { + clk = clock(); + if ( fTryBmc ) + { + Aig_Man_t * pNewAig = Saig_ManDupWithPhase( pAig, p->vInits ); + Saig_BmcPerform( pNewAig, 0, 100, 2000, 3, 0, 0, 1 /*fVerbose*/, 0, &iFrameFail ); +// if ( pNewAig->pSeqModel != NULL ) +// printf( "BMC has found a counter-example in frame %d.\n", iFrameFail ); + Aig_ManStop( pNewAig ); + } + // simulate + for ( f = 0; f < nFrames; f++ ) + { + Ssw_RarManSimulate( p, f ? NULL : p->vInits, 0, 0 ); + if ( fMiter && Ssw_RarManCheckNonConstOutputs(p) ) + { + if ( fVerbose ) printf( "\n" ); +// printf( "Simulation asserted a PO in frame f: %d <= f < %d.\n", r * nFrames, (r+1) * nFrames ); + Ssw_RarManPrepareRandom( nRandSeed ); + ABC_FREE( pAig->pSeqModel ); + pAig->pSeqModel = Ssw_RarDeriveCex( p, r * p->nFrames + f, p->iFailPo, p->iFailPat, fVerbose ); + RetValue = 0; + goto finish; + } + // check timeout + if ( TimeOut && time(NULL) > nTimeToStop ) + { + if ( fVerbose ) printf( "\n" ); + printf( "Reached timeout (%d seconds).\n", TimeOut ); + goto finish; + } + } + // get initialization patterns + Ssw_RarTransferPatterns( p, p->vInits ); + // printout + if ( fVerbose ) + { +// printf( "Round %3d: ", r ); +// Abc_PrintTime( 1, "Time", clock() - clk ); + printf( "." ); + } + } +finish: + if ( r == nRounds && f == nFrames ) + { + if ( fVerbose ) printf( "\n" ); + printf( "Simulation did not assert POs in the first %d frames. ", nRounds * nFrames ); + Abc_PrintTime( 1, "Time", clock() - clkTotal ); + } + // cleanup + Ssw_RarManStop( p ); + return RetValue; +} + + +/**Function************************************************************* + + Synopsis [Perform sequential simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_RarSimulateGia( Gia_Man_t * p, int nFrames, int nWords, int nBinSize, int nRounds, int nRandSeed, int TimeOut, int fVerbose ) +{ + Aig_Man_t * pAig; + int RetValue; + pAig = Gia_ManToAigSimple( p ); + RetValue = Ssw_RarSimulate( pAig, nFrames, nWords, nBinSize, nRounds, nRandSeed, TimeOut, fVerbose ); + // save counter-example + Abc_CexFree( p->pCexSeq ); + p->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL; + Aig_ManStop( pAig ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Filter equivalence classes of nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_RarSignalFilter( Aig_Man_t * pAig, int nFrames, int nWords, int nBinSize, int nRounds, int nRandSeed, int TimeOut, int fMiter, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose ) +{ + Ssw_RarMan_t * p; + int r, f, i, k, clkTotal = clock(); + int nTimeToStop = time(NULL) + TimeOut; + int RetValue = -1; + assert( Aig_ManRegNum(pAig) > 0 ); + assert( Aig_ManConstrNum(pAig) == 0 ); + // consider the case of empty AIG + if ( Aig_ManNodeNum(pAig) == 0 ) + return -1; + // check trivially SAT miters + if ( fMiter && Ssw_RarCheckTrivial( pAig, 1 ) ) + return 0; + if ( fVerbose ) + printf( "Rarity equiv filtering with %d words, %d frames, %d rounds, %d seed, and %d sec timeout.\n", + nWords, nFrames, nRounds, nRandSeed, TimeOut ); + // reset random numbers + Ssw_RarManPrepareRandom( nRandSeed ); + + // create manager + p = Ssw_RarManStart( pAig, nWords, nFrames, nBinSize, fVerbose ); + // compute starting state if needed + assert( p->vInits == NULL ); + if ( pCex ) + { + p->vInits = Ssw_RarFindStartingState( pAig, pCex ); + printf( "Beginning simulation from the state derived using the counter-example.\n" ); + } + else + p->vInits = Vec_IntStart( Aig_ManRegNum(pAig) ); + // duplicate the array + for ( i = 1; i < nWords; i++ ) + for ( k = 0; k < Aig_ManRegNum(pAig); k++ ) + Vec_IntPush( p->vInits, Vec_IntEntry(p->vInits, k) ); + assert( Vec_IntSize(p->vInits) == Aig_ManRegNum(pAig) * nWords ); + + // create trivial equivalence classes with all nodes being candidates for constant 1 + if ( pAig->pReprs == NULL ) + p->ppClasses = Ssw_ClassesPrepareSimple( pAig, fLatchOnly, 0 ); + else + p->ppClasses = Ssw_ClassesPrepareFromReprs( pAig ); + Ssw_ClassesSetData( p->ppClasses, p, Ssw_RarManObjHashWord, Ssw_RarManObjIsConst, Ssw_RarManObjsAreEqual ); + // print the stats + if ( fVerbose ) + { + printf( "Initial : " ); + Ssw_ClassesPrint( p->ppClasses, 0 ); + } + // refine classes using BMC + for ( r = 0; r < nRounds; r++ ) + { + // start filtering equivalence classes + if ( Ssw_ClassesCand1Num(p->ppClasses) == 0 && Ssw_ClassesClassNum(p->ppClasses) == 0 ) + { + printf( "All equivalences are refined away.\n" ); + break; + } + // simulate + for ( f = 0; f < nFrames; f++ ) + { + Ssw_RarManSimulate( p, f ? NULL : p->vInits, 1, !r && !f ); + if ( fMiter && Ssw_RarManCheckNonConstOutputs(p) ) + { + if ( !fVerbose ) + printf( "\r" ); +// printf( "Simulation asserted a PO in frame f: %d <= f < %d.\n", r * nFrames, (r+1) * nFrames ); + Ssw_RarManPrepareRandom( nRandSeed ); + Abc_CexFree( pAig->pSeqModel ); + pAig->pSeqModel = Ssw_RarDeriveCex( p, r * p->nFrames + f, p->iFailPo, p->iFailPat, 1 ); + RetValue = 0; + goto finish; + } + // check timeout + if ( TimeOut && time(NULL) > nTimeToStop ) + { + if ( fVerbose ) printf( "\n" ); + printf( "Reached timeout (%d seconds).\n", TimeOut ); + goto finish; + } + } + // get initialization patterns + Ssw_RarTransferPatterns( p, p->vInits ); + // printout + if ( fVerbose ) + { + printf( "Round %3d: ", r ); + Ssw_ClassesPrint( p->ppClasses, 0 ); + } + else + { + printf( "." ); + } + } +finish: + // report + if ( r == nRounds && f == nFrames ) + { + if ( !fVerbose ) + printf( "\r" ); + printf( "Simulation did not assert POs in the first %d frames. ", nRounds * nFrames ); + Abc_PrintTime( 1, "Time", clock() - clkTotal ); + } + // cleanup + Ssw_RarManStop( p ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Filter equivalence classes of nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_RarSignalFilterGia( Gia_Man_t * p, int nFrames, int nWords, int nBinSize, int nRounds, int nRandSeed, int TimeOut, int fMiter, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose ) +{ + Aig_Man_t * pAig; + int RetValue; + pAig = Gia_ManToAigSimple( p ); + if ( p->pReprs != NULL ) + { + Gia_ManReprToAigRepr2( pAig, p ); + ABC_FREE( p->pReprs ); + ABC_FREE( p->pNexts ); + } + RetValue = Ssw_RarSignalFilter( pAig, nFrames, nWords, nBinSize, nRounds, nRandSeed, TimeOut, fMiter, pCex, fLatchOnly, fVerbose ); + Gia_ManReprFromAigRepr( pAig, p ); + // save counter-example + Abc_CexFree( p->pCexSeq ); + p->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL; + Aig_ManStop( pAig ); + return RetValue; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/ssw/sswRarity2.c b/src/proof/ssw/sswRarity2.c new file mode 100644 index 00000000..ac22b0d5 --- /dev/null +++ b/src/proof/ssw/sswRarity2.c @@ -0,0 +1,517 @@ +/**CFile**************************************************************** + + FileName [sswRarity.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Inductive prover with constraints.] + + Synopsis [Rarity-driven refinement of equivalence classes.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 1, 2008.] + + Revision [$Id: sswRarity.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sswInt.h" +#include "src/aig/gia/giaAig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Ssw_RarMan_t_ Ssw_RarMan_t; +struct Ssw_RarMan_t_ +{ + // parameters + int nWords; // the number of words to simulate + int nFrames; // the number of frames to simulate + int nBinSize; // the number of flops in one group + int fVerbose; // the verbosiness flag + int nGroups; // the number of flop groups + // internal data + Aig_Man_t * pAig; // AIG with equivalence classes + Ssw_Cla_t * ppClasses; // equivalence classes + Ssw_Sml_t * pSml; // simulation manager + Vec_Ptr_t * vSimInfo; // simulation info from pSml manager + Vec_Int_t * vInits; // initial state + // rarity data + int * pRarity; // occur counts for patterns in groups + int * pGroupValues; // occur counts in each group + double * pPatCosts; // pattern costs + +}; + +static inline int Ssw_RarGetBinPat( Ssw_RarMan_t * p, int iBin, int iPat ) +{ + assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->nBinSize ); + assert( iPat >= 0 && iPat < (1 << p->nBinSize) ); + return p->pRarity[iBin * (1 << p->nBinSize) + iPat]; +} +static inline void Ssw_RarSetBinPat( Ssw_RarMan_t * p, int iBin, int iPat, int Value ) +{ + assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->nBinSize ); + assert( iPat >= 0 && iPat < (1 << p->nBinSize) ); + p->pRarity[iBin * (1 << p->nBinSize) + iPat] = Value; +} +static inline void Ssw_RarAddToBinPat( Ssw_RarMan_t * p, int iBin, int iPat ) +{ + assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->nBinSize ); + assert( iPat >= 0 && iPat < (1 << p->nBinSize) ); + p->pRarity[iBin * (1 << p->nBinSize) + iPat]++; +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Ssw_RarMan_t * Ssw_RarManStart( Aig_Man_t * pAig, int nWords, int nFrames, int nBinSize, int fVerbose ) +{ + Ssw_RarMan_t * p; + if ( Aig_ManRegNum(pAig) < nBinSize || nBinSize <= 0 ) + return NULL; + p = ABC_CALLOC( Ssw_RarMan_t, 1 ); + p->pAig = pAig; + p->nWords = nWords; + p->nFrames = nFrames; + p->nBinSize = nBinSize; + p->fVerbose = fVerbose; + p->nGroups = Aig_ManRegNum(pAig) / nBinSize; + p->pRarity = ABC_CALLOC( int, (1 << nBinSize) * p->nGroups ); + p->pGroupValues = ABC_CALLOC( int, p->nGroups ); + p->pPatCosts = ABC_CALLOC( double, p->nWords * 32 ); + p->pSml = Ssw_SmlStart( pAig, 0, nFrames, nWords ); + p->vSimInfo = Ssw_SmlSimDataPointers( p->pSml ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Ssw_RarManStop( Ssw_RarMan_t * p ) +{ + if ( p->pSml ) Ssw_SmlStop( p->pSml ); + if ( p->ppClasses ) Ssw_ClassesStop( p->ppClasses ); + Vec_PtrFreeP( &p->vSimInfo ); + Vec_IntFreeP( &p->vInits ); + ABC_FREE( p->pGroupValues ); + ABC_FREE( p->pPatCosts ); + ABC_FREE( p->pRarity ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [Updates rarity counters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Ssw_RarUpdateCounters( Ssw_RarMan_t * p ) +{ + Aig_Obj_t * pObj; + unsigned * pData; + int i, k; +/* + Saig_ManForEachLi( p->pAig, pObj, i ) + { + pData = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjId(pObj) ) + p->nWords * (p->nFrames - 1); + Extra_PrintBinary( stdout, pData, 32 ); printf( "\n" ); + } +*/ + for ( k = 0; k < p->nWords * 32; k++ ) + { + for ( i = 0; i < p->nGroups; i++ ) + p->pGroupValues[i] = 0; + Saig_ManForEachLi( p->pAig, pObj, i ) + { + pData = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjId(pObj) ) + p->nWords * (p->nFrames - 1); + if ( Abc_InfoHasBit(pData, k) && i / p->nBinSize < p->nGroups ) + p->pGroupValues[i / p->nBinSize] |= (1 << (i % p->nBinSize)); + } + for ( i = 0; i < p->nGroups; i++ ) + Ssw_RarAddToBinPat( p, i, p->pGroupValues[i] ); + } +/* + for ( i = 0; i < p->nGroups; i++ ) + { + for ( k = 0; k < (1 << p->nBinSize); k++ ) + printf( "%d ", Ssw_RarGetBinPat(p, i, k) ); + printf( "\n" ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Select best patterns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Ssw_RarTransferPatterns( Ssw_RarMan_t * p, Vec_Int_t * vInits ) +{ + Aig_Obj_t * pObj; + unsigned * pData; + int i, k, Value; + + // for each pattern + for ( k = 0; k < p->nWords * 32; k++ ) + { + for ( i = 0; i < p->nGroups; i++ ) + p->pGroupValues[i] = 0; + // compute its group values + Saig_ManForEachLi( p->pAig, pObj, i ) + { + pData = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjId(pObj) ) + p->nWords * (p->nFrames - 1); + if ( Abc_InfoHasBit(pData, k) && i / p->nBinSize < p->nGroups ) + p->pGroupValues[i / p->nBinSize] |= (1 << (i % p->nBinSize)); + } + // find the cost of its values + p->pPatCosts[k] = 0.0; + for ( i = 0; i < p->nGroups; i++ ) + { + Value = Ssw_RarGetBinPat( p, i, p->pGroupValues[i] ); + assert( Value > 0 ); + p->pPatCosts[k] += 1.0/(Value*Value); + } + // print the result +// printf( "%3d : %9.6f\n", k, p->pPatCosts[k] ); + } + + // choose as many as there are words + Vec_IntClear( vInits ); + for ( i = 0; i < p->nWords; i++ ) + { + // select the best + int iPatBest = -1; + double iCostBest = -ABC_INFINITY; + for ( k = 0; k < p->nWords * 32; k++ ) + if ( iCostBest < p->pPatCosts[k] ) + { + iCostBest = p->pPatCosts[k]; + iPatBest = k; + } + // remove from costs + assert( iPatBest >= 0 ); + p->pPatCosts[iPatBest] = -ABC_INFINITY; + // set the flops + Saig_ManForEachLi( p->pAig, pObj, k ) + { + pData = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjId(pObj) ) + p->nWords * (p->nFrames - 1); + Vec_IntPush( vInits, Abc_InfoHasBit(pData, iPatBest) ); + } +//printf( "Best pattern %5d\n", iPatBest ); + } + assert( Vec_IntSize(vInits) == Aig_ManRegNum(p->pAig) * p->nWords ); +} + + +/**Function************************************************************* + + Synopsis [Performs fraiging for one node.] + + Description [Returns the fraiged node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Vec_Int_t * Ssw_RarFindStartingState( Aig_Man_t * pAig, Abc_Cex_t * pCex ) +{ + Vec_Int_t * vInit; + Aig_Obj_t * pObj, * pObjLi; + int f, i, iBit; + // assign register outputs + Saig_ManForEachLi( pAig, pObj, i ) + pObj->fMarkB = Abc_InfoHasBit( pCex->pData, i ); + // simulate the timeframes + iBit = pCex->nRegs; + for ( f = 0; f <= pCex->iFrame; f++ ) + { + // set the PI simulation information + Aig_ManConst1(pAig)->fMarkB = 1; + Saig_ManForEachPi( pAig, pObj, i ) + pObj->fMarkB = Abc_InfoHasBit( pCex->pData, iBit++ ); + Saig_ManForEachLiLo( pAig, pObjLi, pObj, i ) + pObj->fMarkB = pObjLi->fMarkB; + // simulate internal nodes + Aig_ManForEachNode( pAig, pObj, i ) + pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ) + & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) ); + // assign the COs + Aig_ManForEachPo( pAig, pObj, i ) + pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ); + } + assert( iBit == pCex->nBits ); + // check that the output failed as expected -- cannot check because it is not an SRM! +// pObj = Aig_ManPo( pAig, pCex->iPo ); +// if ( pObj->fMarkB != 1 ) +// printf( "The counter-example does not refine the output.\n" ); + // record the new pattern + vInit = Vec_IntAlloc( Saig_ManRegNum(pAig) ); + Saig_ManForEachLo( pAig, pObj, i ) + Vec_IntPush( vInit, pObj->fMarkB ); + return vInit; +} + + +/**Function************************************************************* + + Synopsis [Perform sequential simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_RarSimulate2( Aig_Man_t * pAig, int nFrames, int nWords, int nBinSize, int nRounds, int TimeOut, int fVerbose ) +{ + int fMiter = 1; + Ssw_RarMan_t * p; + int r, clk, clkTotal = clock(); + int nTimeToStop = time(NULL) + TimeOut; + int RetValue = -1; + assert( Aig_ManRegNum(pAig) > 0 ); + assert( Aig_ManConstrNum(pAig) == 0 ); + // consider the case of empty AIG + if ( Aig_ManNodeNum(pAig) == 0 ) + return -1; + if ( fVerbose ) + printf( "Simulating %d words through %d frames with %d binsize, %d rounds, and %d sec timeout.\n", + nWords, nFrames, nBinSize, nRounds, TimeOut ); + // reset random numbers + Aig_ManRandom( 1 ); + + // create manager + p = Ssw_RarManStart( pAig, nWords, nFrames, nBinSize, fVerbose ); + p->vInits = Vec_IntStart( Aig_ManRegNum(pAig) * nWords ); + Ssw_SmlInitializeSpecial( p->pSml, p->vInits ); + + // perform simulation rounds + for ( r = 0; r < nRounds; r++ ) + { + clk = clock(); + // simulate + Ssw_SmlSimulateOne( p->pSml ); + if ( fMiter && Ssw_SmlCheckNonConstOutputs(p->pSml) ) + { + if ( fVerbose ) printf( "\n" ); + printf( "Simulation asserted a PO in frame f: %d <= f < %d.\n", r * nFrames, (r+1) * nFrames ); + RetValue = 0; + break; + } + // get initialization patterns + Ssw_RarUpdateCounters( p ); + Ssw_RarTransferPatterns( p, p->vInits ); + Ssw_SmlInitializeSpecial( p->pSml, p->vInits ); + // printout + if ( fVerbose ) + { +// printf( "Round %3d: ", r ); +// Abc_PrintTime( 1, "Time", clock() - clk ); + printf( "." ); + } + // check timeout + if ( TimeOut && time(NULL) > nTimeToStop ) + { + if ( fVerbose ) printf( "\n" ); + printf( "Reached timeout (%d seconds).\n", TimeOut ); + break; + } + } + if ( r == nRounds ) + { + if ( fVerbose ) printf( "\n" ); + printf( "Simulation did not assert POs in the first %d frames. ", nRounds * nFrames ); + Abc_PrintTime( 1, "Time", clock() - clkTotal ); + } + // cleanup + Ssw_RarManStop( p ); + return RetValue; +} + + +/**Function************************************************************* + + Synopsis [Filter equivalence classes of nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_RarSignalFilter2( Aig_Man_t * pAig, int nFrames, int nWords, int nBinSize, int nRounds, int TimeOut, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose ) +{ + int fMiter = 0; + Ssw_RarMan_t * p; + int r, i, k, clkTotal = clock(); + int nTimeToStop = time(NULL) + TimeOut; + int RetValue = -1; + assert( Aig_ManRegNum(pAig) > 0 ); + assert( Aig_ManConstrNum(pAig) == 0 ); + // consider the case of empty AIG + if ( Aig_ManNodeNum(pAig) == 0 ) + return -1; + if ( fVerbose ) + printf( "Filtering equivs with %d words through %d frames with %d binsize, %d rounds, and %d sec timeout.\n", + nWords, nFrames, nBinSize, nRounds, TimeOut ); + // reset random numbers + Aig_ManRandom( 1 ); + + // create manager + p = Ssw_RarManStart( pAig, nWords, nFrames, nBinSize, fVerbose ); + // compute starting state if needed + assert( p->vInits == NULL ); + if ( pCex ) + p->vInits = Ssw_RarFindStartingState( pAig, pCex ); + else + p->vInits = Vec_IntStart( Aig_ManRegNum(pAig) ); + // duplicate the array + for ( i = 1; i < nWords; i++ ) + for ( k = 0; k < Aig_ManRegNum(pAig); k++ ) + Vec_IntPush( p->vInits, Vec_IntEntry(p->vInits, k) ); + assert( Vec_IntSize(p->vInits) == Aig_ManRegNum(pAig) * nWords ); + // initialize simulation manager + Ssw_SmlInitializeSpecial( p->pSml, p->vInits ); + + // create trivial equivalence classes with all nodes being candidates for constant 1 + if ( pAig->pReprs == NULL ) + p->ppClasses = Ssw_ClassesPrepareSimple( pAig, fLatchOnly, 0 ); + else + p->ppClasses = Ssw_ClassesPrepareFromReprs( pAig ); + Ssw_ClassesSetData( p->ppClasses, p->pSml, NULL, (int(*)(void *,Aig_Obj_t *))Ssw_SmlObjIsConstWord, (int(*)(void *,Aig_Obj_t *,Aig_Obj_t *))Ssw_SmlObjsAreEqualWord ); + // print the stats + if ( fVerbose ) + { + printf( "Initial : " ); + Ssw_ClassesPrint( p->ppClasses, 0 ); + } + // refine classes using BMC + for ( r = 0; r < nRounds; r++ ) + { + // start filtering equivalence classes + if ( Ssw_ClassesCand1Num(p->ppClasses) == 0 && Ssw_ClassesClassNum(p->ppClasses) == 0 ) + { + printf( "All equivalences are refined away.\n" ); + break; + } + // simulate + Ssw_SmlSimulateOne( p->pSml ); + if ( fMiter && Ssw_SmlCheckNonConstOutputs(p->pSml) ) + { + if ( fVerbose ) printf( "\n" ); + printf( "Simulation asserted a PO in frame f: %d <= f < %d.\n", r * nFrames, (r+1) * nFrames ); + RetValue = 0; + break; + } + // check equivalence classes + Ssw_ClassesRefineConst1( p->ppClasses, 1 ); + Ssw_ClassesRefine( p->ppClasses, 1 ); + // printout + if ( fVerbose ) + { + printf( "Round %3d: ", r ); + Ssw_ClassesPrint( p->ppClasses, 0 ); + } + // get initialization patterns + Ssw_RarUpdateCounters( p ); + Ssw_RarTransferPatterns( p, p->vInits ); + Ssw_SmlInitializeSpecial( p->pSml, p->vInits ); + // check timeout + if ( TimeOut && time(NULL) > nTimeToStop ) + { + if ( fVerbose ) printf( "\n" ); + printf( "Reached timeout (%d seconds).\n", TimeOut ); + break; + } + } + if ( r == nRounds ) + { + printf( "Simulation did not assert POs in the first %d frames. ", nRounds * nFrames ); + Abc_PrintTime( 1, "Time", clock() - clkTotal ); + } + // cleanup + Ssw_RarManStop( p ); + return -1; +} + +/**Function************************************************************* + + Synopsis [Filter equivalence classes of nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_RarSignalFilterGia2( Gia_Man_t * p, int nFrames, int nWords, int nBinSize, int nRounds, int TimeOut, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose ) +{ + Aig_Man_t * pAig; + int RetValue; + pAig = Gia_ManToAigSimple( p ); + if ( p->pReprs != NULL ) + { + Gia_ManReprToAigRepr2( pAig, p ); + ABC_FREE( p->pReprs ); + ABC_FREE( p->pNexts ); + } + RetValue = Ssw_RarSignalFilter2( pAig, nFrames, nWords, nBinSize, nRounds, TimeOut, pCex, fLatchOnly, fVerbose ); + Gia_ManReprFromAigRepr( pAig, p ); + Aig_ManStop( pAig ); + return RetValue; +} + + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/ssw/sswSat.c b/src/proof/ssw/sswSat.c new file mode 100644 index 00000000..7d371cac --- /dev/null +++ b/src/proof/ssw/sswSat.c @@ -0,0 +1,306 @@ +/**CFile**************************************************************** + + FileName [sswSat.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Inductive prover with constraints.] + + Synopsis [Calls to the SAT solver.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 1, 2008.] + + Revision [$Id: sswSat.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sswInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Runs equivalence test for the two nodes.] + + Description [Both nodes should be regular and different from each other.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_NodesAreEquiv( Ssw_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ) +{ + int nBTLimit = p->pPars->nBTLimit; + int pLits[3], nLits, RetValue, RetValue1, clk;//, status; + p->nSatCalls++; + p->pMSat->nSolverCalls++; + + // sanity checks + assert( !Aig_IsComplement(pOld) ); + assert( !Aig_IsComplement(pNew) ); + assert( pOld != pNew ); + assert( p->pMSat != NULL ); + + // if the nodes do not have SAT variables, allocate them + Ssw_CnfNodeAddToSolver( p->pMSat, pOld ); + Ssw_CnfNodeAddToSolver( p->pMSat, pNew ); + + // solve under assumptions + // A = 1; B = 0 OR A = 1; B = 1 + nLits = 2; + pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pOld), 0 ); + pLits[1] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), pOld->fPhase == pNew->fPhase ); + if ( p->iOutputLit > -1 ) + pLits[nLits++] = p->iOutputLit; + if ( p->pPars->fPolarFlip ) + { + if ( pOld->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( pNew->fPhase ) pLits[1] = lit_neg( pLits[1] ); + } +//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 ); + + if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead ) + { + RetValue = sat_solver_simplify(p->pMSat->pSat); + assert( RetValue != 0 ); + } + +clk = clock(); + RetValue1 = sat_solver_solve( p->pMSat->pSat, pLits, pLits + nLits, + (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); +p->timeSat += clock() - clk; + if ( RetValue1 == l_False ) + { +p->timeSatUnsat += clock() - clk; + if ( nLits == 2 ) + { + pLits[0] = lit_neg( pLits[0] ); + pLits[1] = lit_neg( pLits[1] ); + RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 2 ); + assert( RetValue ); +/* + if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead ) + { + RetValue = sat_solver_simplify(p->pMSat->pSat); + assert( RetValue != 0 ); + } +*/ + } + p->nSatCallsUnsat++; + } + else if ( RetValue1 == l_True ) + { +p->timeSatSat += clock() - clk; + p->nSatCallsSat++; + return 0; + } + else // if ( RetValue1 == l_Undef ) + { +p->timeSatUndec += clock() - clk; + p->nSatFailsReal++; + return -1; + } + + // if the old node was constant 0, we already know the answer + if ( pOld == Aig_ManConst1(p->pFrames) ) + { + p->nSatProof++; + return 1; + } + + // solve under assumptions + // A = 0; B = 1 OR A = 0; B = 0 + nLits = 2; + pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pOld), 1 ); + pLits[1] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), pOld->fPhase ^ pNew->fPhase ); + if ( p->iOutputLit > -1 ) + pLits[nLits++] = p->iOutputLit; + if ( p->pPars->fPolarFlip ) + { + if ( pOld->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( pNew->fPhase ) pLits[1] = lit_neg( pLits[1] ); + } + + if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead ) + { + RetValue = sat_solver_simplify(p->pMSat->pSat); + assert( RetValue != 0 ); + } + +clk = clock(); + RetValue1 = sat_solver_solve( p->pMSat->pSat, pLits, pLits + nLits, + (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); +p->timeSat += clock() - clk; + if ( RetValue1 == l_False ) + { +p->timeSatUnsat += clock() - clk; + if ( nLits == 2 ) + { + pLits[0] = lit_neg( pLits[0] ); + pLits[1] = lit_neg( pLits[1] ); + RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 2 ); + assert( RetValue ); +/* + if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead ) + { + RetValue = sat_solver_simplify(p->pMSat->pSat); + assert( RetValue != 0 ); + } +*/ + } + p->nSatCallsUnsat++; + } + else if ( RetValue1 == l_True ) + { +p->timeSatSat += clock() - clk; + p->nSatCallsSat++; + return 0; + } + else // if ( RetValue1 == l_Undef ) + { +p->timeSatUndec += clock() - clk; + p->nSatFailsReal++; + return -1; + } + // return SAT proof + p->nSatProof++; + return 1; +} + +/**Function************************************************************* + + Synopsis [Constrains two nodes to be equivalent in the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_NodesAreConstrained( Ssw_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ) +{ + int pLits[2], RetValue, fComplNew; + Aig_Obj_t * pTemp; + + // sanity checks + assert( Aig_Regular(pOld) != Aig_Regular(pNew) ); + assert( p->pPars->fConstrs || Aig_ObjPhaseReal(pOld) == Aig_ObjPhaseReal(pNew) ); + + // move constant to the old node + if ( Aig_Regular(pNew) == Aig_ManConst1(p->pFrames) ) + { + assert( Aig_Regular(pOld) != Aig_ManConst1(p->pFrames) ); + pTemp = pOld; + pOld = pNew; + pNew = pTemp; + } + + // move complement to the new node + if ( Aig_IsComplement(pOld) ) + { + pOld = Aig_Regular(pOld); + pNew = Aig_Not(pNew); + } + assert( p->pMSat != NULL ); + + // if the nodes do not have SAT variables, allocate them + Ssw_CnfNodeAddToSolver( p->pMSat, pOld ); + Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pNew) ); + + // transform the new node + fComplNew = Aig_IsComplement( pNew ); + pNew = Aig_Regular( pNew ); + + // consider the constant 1 case + if ( pOld == Aig_ManConst1(p->pFrames) ) + { + // add constraint A = 1 ----> A + pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), fComplNew ); + if ( p->pPars->fPolarFlip ) + { + if ( pNew->fPhase ) pLits[0] = lit_neg( pLits[0] ); + } + RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 1 ); + assert( RetValue ); + } + else + { + // add constraint A = B ----> (A v !B)(!A v B) + + // (A v !B) + pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pOld), 0 ); + pLits[1] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), !fComplNew ); + if ( p->pPars->fPolarFlip ) + { + if ( pOld->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( pNew->fPhase ) pLits[1] = lit_neg( pLits[1] ); + } + pLits[0] = lit_neg( pLits[0] ); + pLits[1] = lit_neg( pLits[1] ); + RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 2 ); + assert( RetValue ); + + // (!A v B) + pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pOld), 1 ); + pLits[1] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), fComplNew); + if ( p->pPars->fPolarFlip ) + { + if ( pOld->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( pNew->fPhase ) pLits[1] = lit_neg( pLits[1] ); + } + pLits[0] = lit_neg( pLits[0] ); + pLits[1] = lit_neg( pLits[1] ); + RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 2 ); + assert( RetValue ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Constrains one node in the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_NodeIsConstrained( Ssw_Man_t * p, Aig_Obj_t * pPoObj ) +{ + int RetValue, Lit; + Ssw_CnfNodeAddToSolver( p->pMSat, Aig_ObjFanin0(pPoObj) ); + // add constraint A = 1 ----> A + Lit = toLitCond( Ssw_ObjSatNum(p->pMSat,Aig_ObjFanin0(pPoObj)), !Aig_ObjFaninC0(pPoObj) ); + if ( p->pPars->fPolarFlip ) + { + if ( Aig_ObjFanin0(pPoObj)->fPhase ) Lit = lit_neg( Lit ); + } + RetValue = sat_solver_addclause( p->pMSat->pSat, &Lit, &Lit + 1 ); + assert( RetValue ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/ssw/sswSemi.c b/src/proof/ssw/sswSemi.c new file mode 100644 index 00000000..74305adf --- /dev/null +++ b/src/proof/ssw/sswSemi.c @@ -0,0 +1,322 @@ +/**CFile**************************************************************** + + FileName [sswSemi.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Inductive prover with constraints.] + + Synopsis [Semiformal for equivalence clases.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 1, 2008.] + + Revision [$Id: sswSemi.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sswInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Ssw_Sem_t_ Ssw_Sem_t; // BMC manager + +struct Ssw_Sem_t_ +{ + // parameters + int nConfMaxStart; // the starting conflict limit + int nConfMax; // the intermediate conflict limit + int nFramesSweep; // the number of frames to sweep + int fVerbose; // prints output statistics + // equivalences considered + Ssw_Man_t * pMan; // SAT sweeping manager + Vec_Ptr_t * vTargets; // the nodes that are watched + // storage for patterns + int nPatternsAlloc; // the max number of interesting states + int nPatterns; // the number of patterns + Vec_Ptr_t * vPatterns; // storage for the interesting states + Vec_Int_t * vHistory; // what state and how many steps +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ssw_Sem_t * Ssw_SemManStart( Ssw_Man_t * pMan, int nConfMax, int fVerbose ) +{ + Ssw_Sem_t * p; + Aig_Obj_t * pObj; + int i; + // create interpolation manager + p = ABC_ALLOC( Ssw_Sem_t, 1 ); + memset( p, 0, sizeof(Ssw_Sem_t) ); + p->nConfMaxStart = nConfMax; + p->nConfMax = nConfMax; + p->nFramesSweep = Abc_MaxInt( (1<<21)/Aig_ManNodeNum(pMan->pAig), pMan->nFrames ); + p->fVerbose = fVerbose; + // equivalences considered + p->pMan = pMan; + p->vTargets = Vec_PtrAlloc( Saig_ManPoNum(p->pMan->pAig) ); + Saig_ManForEachPo( p->pMan->pAig, pObj, i ) + Vec_PtrPush( p->vTargets, Aig_ObjFanin0(pObj) ); + // storage for patterns + p->nPatternsAlloc = 512; + p->nPatterns = 1; + p->vPatterns = Vec_PtrAllocSimInfo( Aig_ManRegNum(p->pMan->pAig), Abc_BitWordNum(p->nPatternsAlloc) ); + Vec_PtrCleanSimInfo( p->vPatterns, 0, Abc_BitWordNum(p->nPatternsAlloc) ); + p->vHistory = Vec_IntAlloc( 100 ); + Vec_IntPush( p->vHistory, 0 ); + // update arrays of the manager + assert( 0 ); +/* + ABC_FREE( p->pMan->pNodeToFrames ); + Vec_IntFree( p->pMan->vSatVars ); + p->pMan->pNodeToFrames = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pMan->pAig) * p->nFramesSweep ); + p->pMan->vSatVars = Vec_IntStart( Aig_ManObjNumMax(p->pMan->pAig) * (p->nFramesSweep+1) ); +*/ + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SemManStop( Ssw_Sem_t * p ) +{ + Vec_PtrFree( p->vTargets ); + Vec_PtrFree( p->vPatterns ); + Vec_IntFree( p->vHistory ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SemCheckTargets( Ssw_Sem_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Vec_PtrForEachEntry( Aig_Obj_t *, p->vTargets, pObj, i ) + if ( !Ssw_ObjIsConst1Cand(p->pMan->pAig, pObj) ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManFilterBmcSavePattern( Ssw_Sem_t * p ) +{ + unsigned * pInfo; + Aig_Obj_t * pObj; + int i; + if ( p->nPatterns >= p->nPatternsAlloc ) + return; + Saig_ManForEachLo( p->pMan->pAig, pObj, i ) + { + pInfo = (unsigned *)Vec_PtrEntry( p->vPatterns, i ); + if ( Abc_InfoHasBit( p->pMan->pPatWords, Saig_ManPiNum(p->pMan->pAig) + i ) ) + Abc_InfoSetBit( pInfo, p->nPatterns ); + } + p->nPatterns++; +} + +/**Function************************************************************* + + Synopsis [Performs fraiging for the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ManFilterBmc( Ssw_Sem_t * pBmc, int iPat, int fCheckTargets ) +{ + Ssw_Man_t * p = pBmc->pMan; + Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo; + unsigned * pInfo; + int i, f, clk, RetValue, fFirst = 0; +clk = clock(); + + // start initialized timeframes + p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * 3 ); + Saig_ManForEachLo( p->pAig, pObj, i ) + { + pInfo = (unsigned *)Vec_PtrEntry( pBmc->vPatterns, i ); + pObjNew = Aig_NotCond( Aig_ManConst1(p->pFrames), !Abc_InfoHasBit(pInfo, iPat) ); + Ssw_ObjSetFrame( p, pObj, 0, pObjNew ); + } + + // sweep internal nodes + RetValue = pBmc->nFramesSweep; + for ( f = 0; f < pBmc->nFramesSweep; f++ ) + { + // map constants and PIs + Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) ); + Saig_ManForEachPi( p->pAig, pObj, i ) + Ssw_ObjSetFrame( p, pObj, f, Aig_ObjCreatePi(p->pFrames) ); + // sweep internal nodes + Aig_ManForEachNode( p->pAig, pObj, i ) + { + pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); + Ssw_ObjSetFrame( p, pObj, f, pObjNew ); + if ( Ssw_ManSweepNode( p, pObj, f, 1, NULL ) ) + { + Ssw_ManFilterBmcSavePattern( pBmc ); + if ( fFirst == 0 ) + { + fFirst = 1; + pBmc->nConfMax *= 10; + } + } + if ( f > 0 && p->pMSat->pSat->stats.conflicts >= pBmc->nConfMax ) + { + RetValue = -1; + break; + } + } + // quit if this is the last timeframe + if ( p->pMSat->pSat->stats.conflicts >= pBmc->nConfMax ) + { + RetValue += f + 1; + break; + } + if ( fCheckTargets && Ssw_SemCheckTargets( pBmc ) ) + break; + // transfer latch input to the latch outputs + // build logic cones for register outputs + Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) + { + pObjNew = Ssw_ObjChild0Fra(p, pObjLi,f); + Ssw_ObjSetFrame( p, pObjLo, f+1, pObjNew ); + Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pObjNew) ); + } +//printf( "Frame %2d : Conflicts = %6d. \n", f, p->pSat->stats.conflicts ); + } + if ( fFirst ) + pBmc->nConfMax /= 10; + + // cleanup + Ssw_ClassesCheck( p->ppClasses ); +p->timeBmc += clock() - clk; + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if one of the targets has failed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_FilterUsingSemi( Ssw_Man_t * pMan, int fCheckTargets, int nConfMax, int fVerbose ) +{ + Ssw_Sem_t * p; + int RetValue, Frames, Iter, clk = clock(); + p = Ssw_SemManStart( pMan, nConfMax, fVerbose ); + if ( fCheckTargets && Ssw_SemCheckTargets( p ) ) + { + assert( 0 ); + Ssw_SemManStop( p ); + return 1; + } + if ( fVerbose ) + { + printf( "AIG : C = %6d. Cl = %6d. Nodes = %6d. ConfMax = %6d. FramesMax = %6d.\n", + Ssw_ClassesCand1Num(p->pMan->ppClasses), Ssw_ClassesClassNum(p->pMan->ppClasses), + Aig_ManNodeNum(p->pMan->pAig), p->nConfMax, p->nFramesSweep ); + } + RetValue = 0; + for ( Iter = 0; Iter < p->nPatterns; Iter++ ) + { +clk = clock(); + pMan->pMSat = Ssw_SatStart( 0 ); + Frames = Ssw_ManFilterBmc( p, Iter, fCheckTargets ); + if ( fVerbose ) + { + printf( "%3d : C = %6d. Cl = %6d. NR = %6d. F = %3d. C = %5d. P = %3d. %s ", + Iter, Ssw_ClassesCand1Num(p->pMan->ppClasses), Ssw_ClassesClassNum(p->pMan->ppClasses), + Aig_ManNodeNum(p->pMan->pFrames), Frames, (int)p->pMan->pMSat->pSat->stats.conflicts, p->nPatterns, + p->pMan->nSatFailsReal? "f" : " " ); + ABC_PRT( "T", clock() - clk ); + } + Ssw_ManCleanup( p->pMan ); + if ( fCheckTargets && Ssw_SemCheckTargets( p ) ) + { + printf( "Target is hit!!!\n" ); + RetValue = 1; + } + if ( p->nPatterns >= p->nPatternsAlloc ) + break; + } + Ssw_SemManStop( p ); + + pMan->nStrangers = 0; + pMan->nSatCalls = 0; + pMan->nSatProof = 0; + pMan->nSatFailsReal = 0; + pMan->nSatCallsUnsat = 0; + pMan->nSatCallsSat = 0; + pMan->timeSimSat = 0; + pMan->timeSat = 0; + pMan->timeSatSat = 0; + pMan->timeSatUnsat = 0; + pMan->timeSatUndec = 0; + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/ssw/sswSim.c b/src/proof/ssw/sswSim.c new file mode 100644 index 00000000..9ce89a71 --- /dev/null +++ b/src/proof/ssw/sswSim.c @@ -0,0 +1,1405 @@ +/**CFile**************************************************************** + + FileName [sswSim.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Inductive prover with constraints.] + + Synopsis [Sequential simulator used by the inductive prover.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 1, 2008.] + + Revision [$Id: sswSim.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sswInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// simulation manager +struct Ssw_Sml_t_ +{ + Aig_Man_t * pAig; // the original AIG manager + int nPref; // the number of timeframes in the prefix + int nFrames; // the number of timeframes + int nWordsFrame; // the number of words in each timeframe + 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 +}; + +static inline unsigned * Ssw_ObjSim( Ssw_Sml_t * p, int Id ) { return p->pData + p->nWordsTotal * Id; } +static inline unsigned Ssw_ObjRandomSim() { return Aig_ManRandom(0); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes hash value of the node using its simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Ssw_SmlObjHashWord( Ssw_Sml_t * p, Aig_Obj_t * pObj ) +{ + static int s_SPrimes[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->nWordsTotal <= 128 ); + uHash = 0; + pSims = Ssw_ObjSim(p, pObj->Id); + for ( i = p->nWordsPref; i < p->nWordsTotal; i++ ) + uHash ^= pSims[i] * s_SPrimes[i & 0x7F]; + return uHash; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if simulation info is composed of all zeros.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SmlObjIsConstWord( Ssw_Sml_t * p, Aig_Obj_t * pObj ) +{ + unsigned * pSims; + int i; + pSims = Ssw_ObjSim(p, pObj->Id); + for ( i = p->nWordsPref; i < p->nWordsTotal; i++ ) + if ( pSims[i] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if simulation infos are equal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SmlObjsAreEqualWord( Ssw_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) +{ + unsigned * pSims0, * pSims1; + int i; + pSims0 = Ssw_ObjSim(p, pObj0->Id); + pSims1 = Ssw_ObjSim(p, pObj1->Id); + for ( i = p->nWordsPref; i < p->nWordsTotal; i++ ) + if ( pSims0[i] != pSims1[i] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node appears to be constant 1 candidate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SmlObjIsConstBit( void * p, Aig_Obj_t * pObj ) +{ + return pObj->fPhase == pObj->fMarkB; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the nodes appear equal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SmlObjsAreEqualBit( void * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) +{ + return (pObj0->fPhase == pObj1->fPhase) == (pObj0->fMarkB == pObj1->fMarkB); +} + + +/**Function************************************************************* + + Synopsis [Counts the number of 1s in the XOR of simulation data.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SmlNodeNotEquWeight( Ssw_Sml_t * p, int Left, int Right ) +{ + unsigned * pSimL, * pSimR; + int k, Counter = 0; + pSimL = Ssw_ObjSim( p, Left ); + pSimR = Ssw_ObjSim( p, Right ); + for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) + Counter += Aig_WordCountOnes( pSimL[k] ^ pSimR[k] ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Checks implication.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SmlCheckXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo, Aig_Obj_t * pCand ) +{ + unsigned * pSimLi, * pSimLo, * pSimCand; + int k; + assert( pObjLo->fPhase == 0 ); + // pObjLi->fPhase may be 1, but the LI simulation data is not complemented! + pSimCand = Ssw_ObjSim( p, Aig_Regular(pCand)->Id ); + pSimLi = Ssw_ObjSim( p, pObjLi->Id ); + pSimLo = Ssw_ObjSim( p, pObjLo->Id ); + if ( Aig_Regular(pCand)->fPhase ^ Aig_IsComplement(pCand) ) + { + for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) + if ( ~pSimCand[k] & (pSimLi[k] ^ pSimLo[k]) ) + return 0; + } + else + { + for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) + if ( pSimCand[k] & (pSimLi[k] ^ pSimLo[k]) ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Counts the number of 1s in the implication.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SmlCountXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo, Aig_Obj_t * pCand ) +{ + unsigned * pSimLi, * pSimLo, * pSimCand; + int k, Counter = 0; + assert( pObjLo->fPhase == 0 ); + // pObjLi->fPhase may be 1, but the LI simulation data is not complemented! + pSimCand = Ssw_ObjSim( p, Aig_Regular(pCand)->Id ); + pSimLi = Ssw_ObjSim( p, pObjLi->Id ); + pSimLo = Ssw_ObjSim( p, pObjLo->Id ); + if ( Aig_Regular(pCand)->fPhase ^ Aig_IsComplement(pCand) ) + { + for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) + Counter += Aig_WordCountOnes(~pSimCand[k] & ~(pSimLi[k] ^ pSimLo[k])); + } + else + { + for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) + Counter += Aig_WordCountOnes(pSimCand[k] & ~(pSimLi[k] ^ pSimLo[k])); + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of 1s in the implication.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SmlCountEqual( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo ) +{ + unsigned * pSimLi, * pSimLo; + int k, Counter = 0; + assert( pObjLo->fPhase == 0 ); + // pObjLi->fPhase may be 1, but the LI simulation data is not complemented! + pSimLi = Ssw_ObjSim( p, pObjLi->Id ); + pSimLo = Ssw_ObjSim( p, pObjLo->Id ); + for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) + Counter += Aig_WordCountOnes( ~(pSimLi[k] ^ pSimLo[k]) ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if simulation info is composed of all zeros.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SmlNodeIsZero( Ssw_Sml_t * p, Aig_Obj_t * pObj ) +{ + unsigned * pSims; + int i; + pSims = Ssw_ObjSim(p, pObj->Id); + for ( i = p->nWordsPref; i < p->nWordsTotal; i++ ) + if ( pSims[i] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if simulation info is composed of all zeros.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SmlNodeIsZeroFrame( Ssw_Sml_t * p, Aig_Obj_t * pObj, int f ) +{ + unsigned * pSims = Ssw_ObjSim(p, pObj->Id); + return pSims[f] == 0; +} + +/**Function************************************************************* + + Synopsis [Counts the number of one's in the patten the object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SmlNodeCountOnesReal( Ssw_Sml_t * p, Aig_Obj_t * pObj ) +{ + unsigned * pSims; + int i, Counter = 0; + pSims = Ssw_ObjSim(p, Aig_Regular(pObj)->Id); + if ( Aig_Regular(pObj)->fPhase ^ Aig_IsComplement(pObj) ) + { + for ( i = 0; i < p->nWordsTotal; i++ ) + Counter += Aig_WordCountOnes( ~pSims[i] ); + } + else + { + for ( i = 0; i < p->nWordsTotal; i++ ) + Counter += Aig_WordCountOnes( pSims[i] ); + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of one's in the patten the object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SmlNodeCountOnesRealVec( Ssw_Sml_t * p, Vec_Ptr_t * vObjs ) +{ + Aig_Obj_t * pObj; + unsigned * pSims, uWord; + int i, k, Counter = 0; + if ( Vec_PtrSize(vObjs) == 0 ) + return 0; + for ( i = 0; i < p->nWordsTotal; i++ ) + { + uWord = 0; + Vec_PtrForEachEntry( Aig_Obj_t *, vObjs, pObj, k ) + { + pSims = Ssw_ObjSim(p, Aig_Regular(pObj)->Id); + if ( Aig_Regular(pObj)->fPhase ^ Aig_IsComplement(pObj) ) + uWord |= ~pSims[i]; + else + uWord |= pSims[i]; + } + Counter += Aig_WordCountOnes( uWord ); + } + return Counter; +} + + + +/**Function************************************************************* + + Synopsis [Generated const 0 pattern.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlSavePattern0( Ssw_Man_t * p, int fInit ) +{ + memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); +} + +/**Function************************************************************* + + Synopsis [[Generated const 1 pattern.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlSavePattern1( Ssw_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 = Saig_ManPiNum(p->pAig); + k = 0; + Saig_ManForEachLo( p->pAig, pObj, i ) + Abc_InfoXorBit( p->pPatWords, nTruePis * p->nFrames + k++ ); +} + + +/**Function************************************************************* + + Synopsis [Creates the counter-example from the successful pattern.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Ssw_SmlCheckOutputSavePattern( Ssw_Sml_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 = Ssw_ObjSim(p, pFanin->Id); + for ( i = 0; i < p->nWordsTotal; i++ ) + if ( pSims[i] ) + break; + assert( i < p->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 = ABC_ALLOC( int, Aig_ManPiNum(p->pAig)+1 ); + Aig_ManForEachPi( p->pAig, pObjPi, i ) + { + pModel[i] = Abc_InfoHasBit(Ssw_ObjSim(p, pObjPi->Id), BestPat); +// printf( "%d", pModel[i] ); + } + pModel[Aig_ManPiNum(p->pAig)] = pObjPo->Id; +// printf( "\n" ); + return pModel; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the one of the output is already non-constant 0.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Ssw_SmlCheckOutput( Ssw_Sml_t * p ) +{ + Aig_Obj_t * pObj; + int i; + // make sure the reference simulation pattern does not detect the bug + pObj = Aig_ManPo( p->pAig, 0 ); + assert( Aig_ObjFanin0(pObj)->fPhase == (unsigned)Aig_ObjFaninC0(pObj) ); + Aig_ManForEachPo( p->pAig, pObj, i ) + { + if ( !Ssw_SmlObjIsConstWord( p, Aig_ObjFanin0(pObj) ) ) + { + // create the counter-example from this pattern + return Ssw_SmlCheckOutputSavePattern( p, pObj ); + } + } + return NULL; +} + + + +/**Function************************************************************* + + Synopsis [Assigns random patterns to the PI node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlAssignRandom( Ssw_Sml_t * p, Aig_Obj_t * pObj ) +{ + unsigned * pSims; + int i, f; + assert( Aig_ObjIsPi(pObj) ); + pSims = Ssw_ObjSim( p, pObj->Id ); + for ( i = 0; i < p->nWordsTotal; i++ ) + pSims[i] = Ssw_ObjRandomSim(); + // set the first bit 0 in each frame + assert( p->nWordsFrame * p->nFrames == p->nWordsTotal ); + for ( f = 0; f < p->nFrames; f++ ) + pSims[p->nWordsFrame*f] <<= 1; +} + +/**Function************************************************************* + + Synopsis [Assigns random patterns to the PI node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlAssignRandomFrame( Ssw_Sml_t * p, Aig_Obj_t * pObj, int iFrame ) +{ + unsigned * pSims; + int i; + assert( iFrame < p->nFrames ); + assert( Aig_ObjIsPi(pObj) ); + pSims = Ssw_ObjSim( p, pObj->Id ) + p->nWordsFrame * iFrame; + for ( i = 0; i < p->nWordsFrame; i++ ) + pSims[i] = Ssw_ObjRandomSim(); +} + +/**Function************************************************************* + + Synopsis [Assigns constant patterns to the PI node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlObjAssignConst( Ssw_Sml_t * p, Aig_Obj_t * pObj, int fConst1, int iFrame ) +{ + unsigned * pSims; + int i; + assert( iFrame < p->nFrames ); + assert( Aig_ObjIsPi(pObj) ); + pSims = Ssw_ObjSim( p, pObj->Id ) + p->nWordsFrame * iFrame; + for ( i = 0; i < p->nWordsFrame; i++ ) + pSims[i] = fConst1? ~(unsigned)0 : 0; +} + +/**Function************************************************************* + + Synopsis [Assigns constant patterns to the PI node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlObjAssignConstWord( Ssw_Sml_t * p, Aig_Obj_t * pObj, int fConst1, int iFrame, int iWord ) +{ + unsigned * pSims; + assert( iFrame < p->nFrames ); + assert( iWord < p->nWordsFrame ); + assert( Aig_ObjIsPi(pObj) ); + pSims = Ssw_ObjSim( p, pObj->Id ) + p->nWordsFrame * iFrame; + pSims[iWord] = fConst1? ~(unsigned)0 : 0; +} + +/**Function************************************************************* + + Synopsis [Assigns constant patterns to the PI node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlObjSetWord( Ssw_Sml_t * p, Aig_Obj_t * pObj, unsigned Word, int iWord, int iFrame ) +{ + unsigned * pSims; + assert( iFrame < p->nFrames ); + assert( Aig_ObjIsPi(pObj) ); + pSims = Ssw_ObjSim( p, pObj->Id ) + p->nWordsFrame * iFrame; + pSims[iWord] = Word; +} + +/**Function************************************************************* + + Synopsis [Assings distance-1 simulation info for the PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlAssignDist1( Ssw_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 ) + Ssw_SmlObjAssignConst( p, pObj, Abc_InfoHasBit(pPat, i), 0 ); + // flip one bit + Limit = Abc_MinInt( Aig_ManPiNum(p->pAig), p->nWordsTotal * 32 - 1 ); + for ( i = 0; i < Limit; i++ ) + Abc_InfoXorBit( Ssw_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++ ) + Saig_ManForEachPi( p->pAig, pObj, i ) + Ssw_SmlObjAssignConst( p, pObj, Abc_InfoHasBit(pPat, nTruePis * f + i), f ); + // copy the latch info + k = 0; + Saig_ManForEachLo( p->pAig, pObj, i ) + Ssw_SmlObjAssignConst( p, pObj, Abc_InfoHasBit(pPat, nTruePis * p->nFrames + k++), 0 ); +// assert( p->pFrames == NULL || nTruePis * p->nFrames + k == Aig_ManPiNum(p->pFrames) ); + + // flip one bit of the last frame + if ( fUseDist1 ) //&& p->nFrames == 2 ) + { + Limit = Abc_MinInt( nTruePis, p->nWordsFrame * 32 - 1 ); + for ( i = 0; i < Limit; i++ ) + Abc_InfoXorBit( Ssw_ObjSim( p, Aig_ManPi(p->pAig, i)->Id ) + p->nWordsFrame*(p->nFrames-1), i+1 ); + } + } +} + +/**Function************************************************************* + + Synopsis [Assings distance-1 simulation info for the PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlAssignDist1Plus( Ssw_Sml_t * p, unsigned * pPat ) +{ + Aig_Obj_t * pObj; + int f, i, Limit; + assert( p->nFrames > 0 ); + + // copy the pattern into the primary inputs + Aig_ManForEachPi( p->pAig, pObj, i ) + Ssw_SmlObjAssignConst( p, pObj, Abc_InfoHasBit(pPat, i), 0 ); + + // set distance one PIs for the first frame + Limit = Abc_MinInt( Saig_ManPiNum(p->pAig), p->nWordsFrame * 32 - 1 ); + for ( i = 0; i < Limit; i++ ) + Abc_InfoXorBit( Ssw_ObjSim( p, Aig_ManPi(p->pAig, i)->Id ), i+1 ); + + // create random info for the remaining timeframes + for ( f = 1; f < p->nFrames; f++ ) + Saig_ManForEachPi( p->pAig, pObj, i ) + Ssw_SmlAssignRandomFrame( p, pObj, f ); +} + +/**Function************************************************************* + + Synopsis [Simulates one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlNodeSimulate( Ssw_Sml_t * p, Aig_Obj_t * pObj, int iFrame ) +{ + unsigned * pSims, * pSims0, * pSims1; + int fCompl, fCompl0, fCompl1, i; + assert( iFrame < p->nFrames ); + assert( !Aig_IsComplement(pObj) ); + assert( Aig_ObjIsNode(pObj) ); + assert( iFrame == 0 || p->nWordsFrame < p->nWordsTotal ); + // get hold of the simulation information + pSims = Ssw_ObjSim(p, pObj->Id) + p->nWordsFrame * iFrame; + pSims0 = Ssw_ObjSim(p, Aig_ObjFanin0(pObj)->Id) + p->nWordsFrame * iFrame; + pSims1 = Ssw_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 [] + +***********************************************************************/ +int Ssw_SmlNodesCompareInFrame( Ssw_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1, int iFrame0, int iFrame1 ) +{ + unsigned * pSims0, * pSims1; + int i; + assert( iFrame0 < p->nFrames ); + assert( iFrame1 < p->nFrames ); + assert( !Aig_IsComplement(pObj0) ); + assert( !Aig_IsComplement(pObj1) ); + assert( iFrame0 == 0 || p->nWordsFrame < p->nWordsTotal ); + assert( iFrame1 == 0 || p->nWordsFrame < p->nWordsTotal ); + // get hold of the simulation information + pSims0 = Ssw_ObjSim(p, pObj0->Id) + p->nWordsFrame * iFrame0; + pSims1 = Ssw_ObjSim(p, pObj1->Id) + p->nWordsFrame * iFrame1; + // compare + for ( i = 0; i < p->nWordsFrame; i++ ) + if ( pSims0[i] != pSims1[i] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Simulates one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlNodeCopyFanin( Ssw_Sml_t * p, Aig_Obj_t * pObj, int iFrame ) +{ + unsigned * pSims, * pSims0; + int fCompl, fCompl0, i; + assert( iFrame < p->nFrames ); + assert( !Aig_IsComplement(pObj) ); + assert( Aig_ObjIsPo(pObj) ); + assert( iFrame == 0 || p->nWordsFrame < p->nWordsTotal ); + // get hold of the simulation information + pSims = Ssw_ObjSim(p, pObj->Id) + p->nWordsFrame * iFrame; + pSims0 = Ssw_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 Ssw_SmlNodeTransferNext( Ssw_Sml_t * p, Aig_Obj_t * pOut, Aig_Obj_t * pIn, int iFrame ) +{ + unsigned * pSims0, * pSims1; + int i; + assert( iFrame < p->nFrames ); + 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 = Ssw_ObjSim(p, pOut->Id) + p->nWordsFrame * iFrame; + pSims1 = Ssw_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 [Simulates one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlNodeTransferFirst( Ssw_Sml_t * p, Aig_Obj_t * pOut, Aig_Obj_t * pIn ) +{ + unsigned * pSims0, * pSims1; + int i; + assert( !Aig_IsComplement(pOut) ); + assert( !Aig_IsComplement(pIn) ); + assert( Aig_ObjIsPo(pOut) ); + assert( Aig_ObjIsPi(pIn) ); + assert( p->nWordsFrame < p->nWordsTotal ); + // get hold of the simulation information + pSims0 = Ssw_ObjSim(p, pOut->Id) + p->nWordsFrame * (p->nFrames-1); + pSims1 = Ssw_ObjSim(p, pIn->Id); + // copy information as it is + for ( i = 0; i < p->nWordsFrame; i++ ) + pSims1[i] = pSims0[i]; +} + + +/**Function************************************************************* + + Synopsis [Assings random simulation info for the PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlInitialize( Ssw_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 + Saig_ManForEachPi( p->pAig, pObj, i ) + Ssw_SmlAssignRandom( p, pObj ); + // assign the initial state for the latches + Saig_ManForEachLo( p->pAig, pObj, i ) + Ssw_SmlObjAssignConst( p, pObj, 0, 0 ); + } + else + { + Aig_ManForEachPi( p->pAig, pObj, i ) + Ssw_SmlAssignRandom( p, pObj ); + } +} + +/**Function************************************************************* + + Synopsis [Assings random simulation info for the PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlInitializeSpecial( Ssw_Sml_t * p, Vec_Int_t * vInit ) +{ + Aig_Obj_t * pObj; + int Entry, i, nRegs; + nRegs = Aig_ManRegNum(p->pAig); + assert( nRegs > 0 ); + assert( nRegs <= Aig_ManPiNum(p->pAig) ); + assert( Vec_IntSize(vInit) == nRegs * p->nWordsFrame ); + // assign random info for primary inputs + Saig_ManForEachPi( p->pAig, pObj, i ) + Ssw_SmlAssignRandom( p, pObj ); + // assign the initial state for the latches + Vec_IntForEachEntry( vInit, Entry, i ) + Ssw_SmlObjAssignConstWord( p, Saig_ManLo(p->pAig, i % nRegs), Entry, 0, i / nRegs ); +} + +/**Function************************************************************* + + Synopsis [Assings random simulation info for the PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlReinitialize( Ssw_Sml_t * p ) +{ + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + int i; + assert( Aig_ManRegNum(p->pAig) > 0 ); + assert( Aig_ManRegNum(p->pAig) < Aig_ManPiNum(p->pAig) ); + // assign random info for primary inputs + Saig_ManForEachPi( p->pAig, pObj, i ) + Ssw_SmlAssignRandom( p, pObj ); + // copy simulation info into the inputs + Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) + Ssw_SmlNodeTransferFirst( p, pObjLi, pObjLo ); +} + +/**Function************************************************************* + + Synopsis [Check if any of the POs becomes non-constant.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SmlCheckNonConstOutputs( Ssw_Sml_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Saig_ManForEachPo( p->pAig, pObj, i ) + { + if ( p->pAig->nConstrs && i >= Saig_ManPoNum(p->pAig) - p->pAig->nConstrs ) + return 0; + if ( !Ssw_SmlNodeIsZero(p, pObj) ) + return 1; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Simulates AIG manager.] + + Description [Assumes that the PI simulation info is attached.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlSimulateOne( Ssw_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 ) + Ssw_SmlNodeSimulate( p, pObj, f ); + // copy simulation info into outputs + Saig_ManForEachPo( p->pAig, pObj, i ) + Ssw_SmlNodeCopyFanin( p, pObj, f ); + // copy simulation info into outputs + Saig_ManForEachLi( p->pAig, pObj, i ) + Ssw_SmlNodeCopyFanin( p, pObj, f ); + // quit if this is the last timeframe + if ( f == p->nFrames - 1 ) + break; + // copy simulation info into the inputs + Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) + Ssw_SmlNodeTransferNext( p, pObjLi, pObjLo, f ); + } +p->timeSim += clock() - clk; +p->nSimRounds++; +} + +/**Function************************************************************* + + Synopsis [Converts simulation information to be not normallized.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlUnnormalize( Ssw_Sml_t * p ) +{ + Aig_Obj_t * pObj; + unsigned * pSims; + int i, k; + // convert constant 1 + pSims = Ssw_ObjSim( p, 0 ); + for ( i = 0; i < p->nWordsFrame; i++ ) + pSims[i] = ~pSims[i]; + // convert internal nodes + Aig_ManForEachNode( p->pAig, pObj, k ) + { + if ( pObj->fPhase == 0 ) + continue; + pSims = Ssw_ObjSim( p, pObj->Id ); + for ( i = 0; i < p->nWordsFrame; i++ ) + pSims[i] = ~pSims[i]; + } + // PIs/POs are always stored in their natural state +} + +/**Function************************************************************* + + Synopsis [Simulates AIG manager.] + + Description [Assumes that the PI simulation info is attached.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlSimulateOneDyn_rec( Ssw_Sml_t * p, Aig_Obj_t * pObj, int f, int * pVisited, int nVisCounter ) +{ +// if ( Aig_ObjIsTravIdCurrent(p->pAig, pObj) ) +// return; +// Aig_ObjSetTravIdCurrent(p->pAig, pObj); + if ( pVisited[p->nFrames*pObj->Id+f] == nVisCounter ) + return; + pVisited[p->nFrames*pObj->Id+f] = nVisCounter; + if ( Saig_ObjIsPi( p->pAig, pObj ) || Aig_ObjIsConst1(pObj) ) + return; + if ( Saig_ObjIsLo( p->pAig, pObj ) ) + { + if ( f == 0 ) + return; + Ssw_SmlSimulateOneDyn_rec( p, Saig_ObjLoToLi(p->pAig, pObj), f-1, pVisited, nVisCounter ); + Ssw_SmlNodeTransferNext( p, Saig_ObjLoToLi(p->pAig, pObj), pObj, f-1 ); + return; + } + if ( Saig_ObjIsLi( p->pAig, pObj ) ) + { + Ssw_SmlSimulateOneDyn_rec( p, Aig_ObjFanin0(pObj), f, pVisited, nVisCounter ); + Ssw_SmlNodeCopyFanin( p, pObj, f ); + return; + } + assert( Aig_ObjIsNode(pObj) ); + Ssw_SmlSimulateOneDyn_rec( p, Aig_ObjFanin0(pObj), f, pVisited, nVisCounter ); + Ssw_SmlSimulateOneDyn_rec( p, Aig_ObjFanin1(pObj), f, pVisited, nVisCounter ); + Ssw_SmlNodeSimulate( p, pObj, f ); +} + +/**Function************************************************************* + + Synopsis [Simulates AIG manager.] + + Description [Assumes that the PI simulation info is attached.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlSimulateOneFrame( Ssw_Sml_t * p ) +{ + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + int i, clk; +clk = clock(); + // simulate the nodes + Aig_ManForEachNode( p->pAig, pObj, i ) + Ssw_SmlNodeSimulate( p, pObj, 0 ); + // copy simulation info into outputs + Saig_ManForEachLi( p->pAig, pObj, i ) + Ssw_SmlNodeCopyFanin( p, pObj, 0 ); + // copy simulation info into the inputs + Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) + Ssw_SmlNodeTransferNext( p, pObjLi, pObjLo, 0 ); +p->timeSim += clock() - clk; +p->nSimRounds++; +} + + +/**Function************************************************************* + + Synopsis [Allocates simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ssw_Sml_t * Ssw_SmlStart( Aig_Man_t * pAig, int nPref, int nFrames, int nWordsFrame ) +{ + Ssw_Sml_t * p; + p = (Ssw_Sml_t *)ABC_ALLOC( char, sizeof(Ssw_Sml_t) + sizeof(unsigned) * Aig_ManObjNumMax(pAig) * (nPref + nFrames) * nWordsFrame ); + memset( p, 0, sizeof(Ssw_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 [Allocates simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlClean( Ssw_Sml_t * p ) +{ + memset( p->pData, 0, sizeof(unsigned) * Aig_ManObjNumMax(p->pAig) * p->nWordsTotal ); +} + +/**Function************************************************************* + + Synopsis [Get simulation data.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Ssw_SmlSimDataPointers( Ssw_Sml_t * p ) +{ + Vec_Ptr_t * vSimInfo; + Aig_Obj_t * pObj; + int i; + vSimInfo = Vec_PtrStart( Aig_ManObjNumMax(p->pAig) ); + Aig_ManForEachObj( p->pAig, pObj, i ) + Vec_PtrWriteEntry( vSimInfo, i, Ssw_ObjSim(p, i) ); + return vSimInfo; +} + +/**Function************************************************************* + + Synopsis [Deallocates simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlStop( Ssw_Sml_t * p ) +{ + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [Performs simulation of the uninitialized circuit.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ssw_Sml_t * Ssw_SmlSimulateComb( Aig_Man_t * pAig, int nWords ) +{ + Ssw_Sml_t * p; + p = Ssw_SmlStart( pAig, 0, 1, nWords ); + Ssw_SmlInitialize( p, 0 ); + Ssw_SmlSimulateOne( p ); + return p; +} + +/**Function************************************************************* + + Synopsis [Performs simulation of the initialized circuit.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ssw_Sml_t * Ssw_SmlSimulateSeq( Aig_Man_t * pAig, int nPref, int nFrames, int nWords ) +{ + Ssw_Sml_t * p; + p = Ssw_SmlStart( pAig, nPref, nFrames, nWords ); + Ssw_SmlInitialize( p, 1 ); + Ssw_SmlSimulateOne( p ); + p->fNonConstOut = Ssw_SmlCheckNonConstOutputs( p ); + return p; +} + +/**Function************************************************************* + + Synopsis [Performs next round of sequential simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlResimulateSeq( Ssw_Sml_t * p ) +{ + Ssw_SmlReinitialize( p ); + Ssw_SmlSimulateOne( p ); + p->fNonConstOut = Ssw_SmlCheckNonConstOutputs( p ); +} + + +/**Function************************************************************* + + Synopsis [Returns the number of frames simulated in the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SmlNumFrames( Ssw_Sml_t * p ) +{ + return p->nFrames; +} + +/**Function************************************************************* + + Synopsis [Returns the total number of simulation words.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SmlNumWordsTotal( Ssw_Sml_t * p ) +{ + return p->nWordsTotal; +} + +/**Function************************************************************* + + Synopsis [Returns the pointer to the simulation info of the node.] + + Description [The simulation info is normalized unless procedure + Ssw_SmlUnnormalize() is called in advance.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Ssw_SmlSimInfo( Ssw_Sml_t * p, Aig_Obj_t * pObj ) +{ + assert( !Aig_IsComplement(pObj) ); + return Ssw_ObjSim( p, pObj->Id ); +} + +/**Function************************************************************* + + Synopsis [Creates sequential counter-example from the simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Ssw_SmlGetCounterExample( Ssw_Sml_t * p ) +{ + Abc_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; + Saig_ManForEachPo( p->pAig, pObj, iPo ) + { + if ( Ssw_SmlNodeIsZero(p, pObj) ) + continue; + pSims = Ssw_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 = Abc_CexAlloc( Aig_ManRegNum(p->pAig), Aig_ManPiNum(p->pAig) - Aig_ManRegNum(p->pAig), iFrame + 1 ); + pCex->iPo = iPo; + pCex->iFrame = iFrame; + + // copy the bit data + Saig_ManForEachLo( p->pAig, pObj, k ) + { + pSims = Ssw_ObjSim( p, pObj->Id ); + if ( Abc_InfoHasBit( pSims, iBit ) ) + Abc_InfoSetBit( pCex->pData, k ); + } + for ( i = 0; i <= iFrame; i++ ) + { + Saig_ManForEachPi( p->pAig, pObj, k ) + { + pSims = Ssw_ObjSim( p, pObj->Id ); + if ( Abc_InfoHasBit( pSims, 32 * p->nWordsFrame * i + iBit ) ) + Abc_InfoSetBit( pCex->pData, pCex->nRegs + pCex->nPis * i + k ); + } + } + // verify the counter example + if ( !Saig_ManVerifyCex( p->pAig, pCex ) ) + { + printf( "Ssw_SmlGetCounterExample(): Counter-example is invalid.\n" ); + Abc_CexFree( pCex ); + pCex = NULL; + } + return pCex; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/ssw/sswSimSat.c b/src/proof/ssw/sswSimSat.c new file mode 100644 index 00000000..4c094a2d --- /dev/null +++ b/src/proof/ssw/sswSimSat.c @@ -0,0 +1,123 @@ +/**CFile**************************************************************** + + FileName [sswSimSat.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Inductive prover with constraints.] + + Synopsis [Performs resimulation using counter-examples.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 1, 2008.] + + Revision [$Id: sswSimSat.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sswInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Handle the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManResimulateBit( Ssw_Man_t * p, Aig_Obj_t * pCand, Aig_Obj_t * pRepr ) +{ + Aig_Obj_t * pObj; + int i, RetValue1, RetValue2, clk = clock(); + // set the PI simulation information + Aig_ManConst1(p->pAig)->fMarkB = 1; + Aig_ManForEachPi( p->pAig, pObj, i ) + pObj->fMarkB = Abc_InfoHasBit( p->pPatWords, i ); + // simulate internal nodes + Aig_ManForEachNode( p->pAig, pObj, i ) + pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ) + & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) ); + // if repr is given, perform refinement + if ( pRepr ) + { + // check equivalence classes + RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 0 ); + RetValue2 = Ssw_ClassesRefine( p->ppClasses, 0 ); + // make sure refinement happened + if ( Aig_ObjIsConst1(pRepr) ) + { + assert( RetValue1 ); + if ( RetValue1 == 0 ) + printf( "\nSsw_ManResimulateBit() Error: RetValue1 does not hold.\n" ); + } + else + { + assert( RetValue2 ); + if ( RetValue2 == 0 ) + printf( "\nSsw_ManResimulateBit() Error: RetValue2 does not hold.\n" ); + } + } +p->timeSimSat += clock() - clk; +} + +/**Function************************************************************* + + Synopsis [Handle the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManResimulateWord( Ssw_Man_t * p, Aig_Obj_t * pCand, Aig_Obj_t * pRepr, int f ) +{ + int RetValue1, RetValue2, clk = clock(); + // set the PI simulation information + Ssw_SmlAssignDist1Plus( p->pSml, p->pPatWords ); + // simulate internal nodes + Ssw_SmlSimulateOne( p->pSml ); + // check equivalence classes + RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 1 ); + RetValue2 = Ssw_ClassesRefine( p->ppClasses, 1 ); + // make sure refinement happened + if ( Aig_ObjIsConst1(pRepr) ) + { + assert( RetValue1 ); + if ( RetValue1 == 0 ) + printf( "\nSsw_ManResimulateWord() Error: RetValue1 does not hold.\n" ); + } + else + { + assert( RetValue2 ); + if ( RetValue2 == 0 ) + printf( "\nSsw_ManResimulateWord() Error: RetValue2 does not hold.\n" ); + } +p->timeSimSat += clock() - clk; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/ssw/sswSweep.c b/src/proof/ssw/sswSweep.c new file mode 100644 index 00000000..e2a4f65d --- /dev/null +++ b/src/proof/ssw/sswSweep.c @@ -0,0 +1,435 @@ +/**CFile**************************************************************** + + FileName [sswSweep.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Inductive prover with constraints.] + + Synopsis [One round of SAT sweeping.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 1, 2008.] + + Revision [$Id: sswSweep.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sswInt.h" +#include "src/misc/bar/bar.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Retrives value of the PI in the original AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ManGetSatVarValue( Ssw_Man_t * p, Aig_Obj_t * pObj, int f ) +{ + int fUseNoBoundary = 0; + Aig_Obj_t * pObjFraig; + int Value; +// assert( Aig_ObjIsPi(pObj) ); + pObjFraig = Ssw_ObjFrame( p, pObj, f ); + if ( fUseNoBoundary ) + { + Value = Ssw_CnfGetNodeValue( p->pMSat, Aig_Regular(pObjFraig) ); + Value ^= Aig_IsComplement(pObjFraig); + } + else + { + int nVarNum = Ssw_ObjSatNum( p->pMSat, Aig_Regular(pObjFraig) ); + Value = (!nVarNum)? 0 : (Aig_IsComplement(pObjFraig) ^ sat_solver_var_value( p->pMSat->pSat, nVarNum )); + } + +// Value = (Aig_IsComplement(pObjFraig) ^ ((!nVarNum)? 0 : sat_solver_var_value( p->pSat, nVarNum ))); +// Value = (!nVarNum)? Aig_ManRandom(0) & 1 : (Aig_IsComplement(pObjFraig) ^ sat_solver_var_value( p->pSat, nVarNum )); + if ( p->pPars->fPolarFlip ) + { + if ( Aig_Regular(pObjFraig)->fPhase ) Value ^= 1; + } + return Value; +} + +/**Function************************************************************* + + Synopsis [Performs fraiging for the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_CheckConstraints( Ssw_Man_t * p ) +{ + Aig_Obj_t * pObj, * pObj2; + int nConstrPairs, i; + int Counter = 0; + nConstrPairs = Aig_ManPoNum(p->pFrames)-Aig_ManRegNum(p->pAig); + assert( (nConstrPairs & 1) == 0 ); + for ( i = 0; i < nConstrPairs; i += 2 ) + { + pObj = Aig_ManPo( p->pFrames, i ); + pObj2 = Aig_ManPo( p->pFrames, i+1 ); + if ( Ssw_NodesAreEquiv( p, Aig_ObjFanin0(pObj), Aig_ObjFanin0(pObj2) ) != 1 ) + { + Ssw_NodesAreConstrained( p, Aig_ObjChild0(pObj), Aig_ObjChild0(pObj2) ); + Counter++; + } + } + printf( "Total constraints = %d. Added constraints = %d.\n", nConstrPairs/2, Counter ); +} + +/**Function************************************************************* + + Synopsis [Copy pattern from the solver into the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlSavePatternAigPhase( Ssw_Man_t * p, int f ) +{ + Aig_Obj_t * pObj; + int i; + memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); + Aig_ManForEachPi( p->pAig, pObj, i ) + if ( Aig_ObjPhaseReal( Ssw_ObjFrame(p, pObj, f) ) ) + Abc_InfoSetBit( p->pPatWords, i ); +} + +/**Function************************************************************* + + Synopsis [Copy pattern from the solver into the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlSavePatternAig( Ssw_Man_t * p, int f ) +{ + Aig_Obj_t * pObj; + int i; + memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); + Aig_ManForEachPi( p->pAig, pObj, i ) + if ( Ssw_ManGetSatVarValue( p, pObj, f ) ) + Abc_InfoSetBit( p->pPatWords, i ); +} + +/**Function************************************************************* + + Synopsis [Saves one counter-example into internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlAddPatternDyn( Ssw_Man_t * p ) +{ + Aig_Obj_t * pObj; + unsigned * pInfo; + int i, nVarNum; + // iterate through the PIs of the frames + Vec_PtrForEachEntry( Aig_Obj_t *, p->pMSat->vUsedPis, pObj, i ) + { + assert( Aig_ObjIsPi(pObj) ); + nVarNum = Ssw_ObjSatNum( p->pMSat, pObj ); + assert( nVarNum > 0 ); + if ( sat_solver_var_value( p->pMSat->pSat, nVarNum ) ) + { + pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjPioNum(pObj) ); + Abc_InfoSetBit( pInfo, p->nPatterns ); + } + } +} + +/**Function************************************************************* + + Synopsis [Performs fraiging for one node.] + + Description [Returns the fraiged node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ManSweepNode( Ssw_Man_t * p, Aig_Obj_t * pObj, int f, int fBmc, Vec_Int_t * vPairs ) +{ + Aig_Obj_t * pObjRepr, * pObjFraig, * pObjFraig2, * pObjReprFraig; + int RetValue, clk; + // get representative of this class + pObjRepr = Aig_ObjRepr( p->pAig, pObj ); + if ( pObjRepr == NULL ) + return 0; + // get the fraiged node + pObjFraig = Ssw_ObjFrame( p, pObj, f ); + // get the fraiged representative + pObjReprFraig = Ssw_ObjFrame( p, pObjRepr, f ); + // check if constant 0 pattern distinquishes these nodes + assert( pObjFraig != NULL && pObjReprFraig != NULL ); + assert( (pObj->fPhase == pObjRepr->fPhase) == (Aig_ObjPhaseReal(pObjFraig) == Aig_ObjPhaseReal(pObjReprFraig)) ); + // if the fraiged nodes are the same, return + if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) ) + return 0; + // add constraints on demand + if ( !fBmc && p->pPars->fDynamic ) + { +clk = clock(); + Ssw_ManLoadSolver( p, pObjRepr, pObj ); + p->nRecycleCalls++; +p->timeMarkCones += clock() - clk; + } + // call equivalence checking + if ( Aig_Regular(pObjFraig) != Aig_ManConst1(p->pFrames) ) + RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) ); + else + RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjFraig), Aig_Regular(pObjReprFraig) ); + if ( RetValue == 1 ) // proved equivalent + { + pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase ); + Ssw_ObjSetFrame( p, pObj, f, pObjFraig2 ); + return 0; + } + if ( vPairs ) + { + Vec_IntPush( vPairs, pObjRepr->Id ); + Vec_IntPush( vPairs, pObj->Id ); + } + if ( RetValue == -1 ) // timed out + { + Ssw_ClassesRemoveNode( p->ppClasses, pObj ); + return 1; + } + // disproved the equivalence + if ( !fBmc && p->pPars->fDynamic ) + { + Ssw_SmlAddPatternDyn( p ); + p->nPatterns++; + return 1; + } + else + Ssw_SmlSavePatternAig( p, f ); + if ( !p->pPars->fConstrs ) + Ssw_ManResimulateWord( p, pObj, pObjRepr, f ); + else + Ssw_ManResimulateBit( p, pObj, pObjRepr ); + assert( Aig_ObjRepr( p->pAig, pObj ) != pObjRepr ); + if ( Aig_ObjRepr( p->pAig, pObj ) == pObjRepr ) + { + printf( "Ssw_ManSweepNode(): Failed to refine representative.\n" ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Performs fraiging for the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ManSweepBmc( Ssw_Man_t * p ) +{ + Bar_Progress_t * pProgress = NULL; + Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo; + int i, f, clk; +clk = clock(); + + // start initialized timeframes + p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK ); + Saig_ManForEachLo( p->pAig, pObj, i ) + Ssw_ObjSetFrame( p, pObj, 0, Aig_ManConst0(p->pFrames) ); + + // sweep internal nodes + p->fRefined = 0; + if ( p->pPars->fVerbose ) + pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK ); + for ( f = 0; f < p->pPars->nFramesK; f++ ) + { + // map constants and PIs + Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) ); + Saig_ManForEachPi( p->pAig, pObj, i ) + Ssw_ObjSetFrame( p, pObj, f, Aig_ObjCreatePi(p->pFrames) ); + // sweep internal nodes + Aig_ManForEachNode( p->pAig, pObj, i ) + { + if ( p->pPars->fVerbose ) + Bar_ProgressUpdate( pProgress, Aig_ManObjNumMax(p->pAig) * f + i, NULL ); + pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); + Ssw_ObjSetFrame( p, pObj, f, pObjNew ); + p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 1, NULL ); + } + // quit if this is the last timeframe + if ( f == p->pPars->nFramesK - 1 ) + break; + // transfer latch input to the latch outputs + Aig_ManForEachPo( p->pAig, pObj, i ) + Ssw_ObjSetFrame( p, pObj, f, Ssw_ObjChild0Fra(p, pObj, f) ); + // build logic cones for register outputs + Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) + { + pObjNew = Ssw_ObjFrame( p, pObjLi, f ); + Ssw_ObjSetFrame( p, pObjLo, f+1, pObjNew ); + Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pObjNew) );// + } + } + if ( p->pPars->fVerbose ) + Bar_ProgressStop( pProgress ); + + // cleanup +// Ssw_ClassesCheck( p->ppClasses ); +p->timeBmc += clock() - clk; + return p->fRefined; +} + + +/**Function************************************************************* + + Synopsis [Generates AIG with the following nodes put into seq miters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManDumpEquivMiter( Aig_Man_t * p, Vec_Int_t * vPairs, int Num ) +{ + FILE * pFile; + char pBuffer[16]; + Aig_Man_t * pNew; + sprintf( pBuffer, "equiv%03d.aig", Num ); + pFile = fopen( pBuffer, "w" ); + if ( pFile == NULL ) + { + printf( "Cannot open file %s for writing.\n", pBuffer ); + return; + } + fclose( pFile ); + pNew = Saig_ManCreateEquivMiter( p, vPairs ); + Ioa_WriteAiger( pNew, pBuffer, 0, 0 ); + Aig_ManStop( pNew ); + printf( "AIG with %4d disproved equivs is dumped into file \"%s\".\n", Vec_IntSize(vPairs)/2, pBuffer ); +} + + +/**Function************************************************************* + + Synopsis [Performs fraiging for the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ManSweep( Ssw_Man_t * p ) +{ + static int Counter; + Bar_Progress_t * pProgress = NULL; + Aig_Obj_t * pObj, * pObj2, * pObjNew; + int nConstrPairs, clk, i, f; + Vec_Int_t * vDisproved; + + // perform speculative reduction +clk = clock(); + // create timeframes + p->pFrames = Ssw_FramesWithClasses( p ); + // add constants + nConstrPairs = Aig_ManPoNum(p->pFrames)-Aig_ManRegNum(p->pAig); + assert( (nConstrPairs & 1) == 0 ); + for ( i = 0; i < nConstrPairs; i += 2 ) + { + pObj = Aig_ManPo( p->pFrames, i ); + pObj2 = Aig_ManPo( p->pFrames, i+1 ); + Ssw_NodesAreConstrained( p, Aig_ObjChild0(pObj), Aig_ObjChild0(pObj2) ); + } + // build logic cones for register inputs + for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ ) + { + pObj = Aig_ManPo( p->pFrames, nConstrPairs + i ); + Ssw_CnfNodeAddToSolver( p->pMSat, Aig_ObjFanin0(pObj) );// + } + sat_solver_simplify( p->pMSat->pSat ); + + // map constants and PIs of the last frame + f = p->pPars->nFramesK; + Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) ); + Saig_ManForEachPi( p->pAig, pObj, i ) + Ssw_ObjSetFrame( p, pObj, f, Aig_ObjCreatePi(p->pFrames) ); +p->timeReduce += clock() - clk; + + // sweep internal nodes + p->fRefined = 0; + Ssw_ClassesClearRefined( p->ppClasses ); + if ( p->pPars->fVerbose ) + pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) ); + vDisproved = p->pPars->fEquivDump? Vec_IntAlloc(1000) : NULL; + Aig_ManForEachObj( p->pAig, pObj, i ) + { + if ( p->pPars->fVerbose ) + Bar_ProgressUpdate( pProgress, i, NULL ); + if ( Saig_ObjIsLo(p->pAig, pObj) ) + p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 0, vDisproved ); + else if ( Aig_ObjIsNode(pObj) ) + { + pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); + Ssw_ObjSetFrame( p, pObj, f, pObjNew ); + p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 0, vDisproved ); + } + } + if ( p->pPars->fVerbose ) + Bar_ProgressStop( pProgress ); + + // cleanup +// Ssw_ClassesCheck( p->ppClasses ); + if ( p->pPars->fEquivDump ) + Ssw_ManDumpEquivMiter( p->pAig, vDisproved, Counter++ ); + Vec_IntFreeP( &vDisproved ); + return p->fRefined; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/ssw/sswUnique.c b/src/proof/ssw/sswUnique.c new file mode 100644 index 00000000..b5f6a853 --- /dev/null +++ b/src/proof/ssw/sswUnique.c @@ -0,0 +1,197 @@ +/**CFile**************************************************************** + + FileName [sswSat.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Inductive prover with constraints.] + + Synopsis [On-demand uniqueness constraints.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 1, 2008.] + + Revision [$Id: sswSat.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sswInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs computation of signal correspondence with constraints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_UniqueRegisterPairInfo( Ssw_Man_t * p ) +{ + Aig_Obj_t * pObjLo, * pObj0, * pObj1; + int i, RetValue, Counter; + if ( p->vDiffPairs == NULL ) + p->vDiffPairs = Vec_IntAlloc( Saig_ManRegNum(p->pAig) ); + Vec_IntClear( p->vDiffPairs ); + Saig_ManForEachLo( p->pAig, pObjLo, i ) + { + pObj0 = Ssw_ObjFrame( p, pObjLo, 0 ); + pObj1 = Ssw_ObjFrame( p, pObjLo, 1 ); + if ( pObj0 == pObj1 ) + Vec_IntPush( p->vDiffPairs, 0 ); + else if ( pObj0 == Aig_Not(pObj1) ) + Vec_IntPush( p->vDiffPairs, 1 ); +// else +// Vec_IntPush( p->vDiffPairs, 1 ); + else if ( Aig_ObjPhaseReal(pObj0) != Aig_ObjPhaseReal(pObj1) ) + Vec_IntPush( p->vDiffPairs, 1 ); + else + { + RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObj0), Aig_Regular(pObj1) ); + Vec_IntPush( p->vDiffPairs, RetValue!=1 ); + } + } + assert( Vec_IntSize(p->vDiffPairs) == Saig_ManRegNum(p->pAig) ); + // count the number of ones + Counter = 0; + Vec_IntForEachEntry( p->vDiffPairs, RetValue, i ) + Counter += RetValue; +// printf( "The number of different register pairs = %d.\n", Counter ); +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if uniqueness constraints can be added.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ManUniqueOne( Ssw_Man_t * p, Aig_Obj_t * pRepr, Aig_Obj_t * pObj, int fVerbose ) +{ + Aig_Obj_t * ppObjs[2], * pTemp; + int i, k, Value0, Value1, RetValue, fFeasible; + + assert( p->pPars->nFramesK > 1 ); + assert( p->vDiffPairs && Vec_IntSize(p->vDiffPairs) == Saig_ManRegNum(p->pAig) ); + + // compute the first support in terms of LOs + ppObjs[0] = pRepr; + ppObjs[1] = pObj; + Aig_SupportNodes( p->pAig, ppObjs, 2, p->vCommon ); + // keep only LOs + RetValue = Vec_PtrSize( p->vCommon ); + fFeasible = 0; + k = 0; + Vec_PtrForEachEntry( Aig_Obj_t *, p->vCommon, pTemp, i ) + { + assert( Aig_ObjIsPi(pTemp) ); + if ( !Saig_ObjIsLo(p->pAig, pTemp) ) + continue; + assert( Aig_ObjPioNum(pTemp) > 0 ); + Vec_PtrWriteEntry( p->vCommon, k++, pTemp ); + if ( Vec_IntEntry(p->vDiffPairs, Aig_ObjPioNum(pTemp) - Saig_ManPiNum(p->pAig)) ) + fFeasible = 1; + } + Vec_PtrShrink( p->vCommon, k ); + + if ( fVerbose ) + printf( "Node = %5d : Supp = %3d. Regs = %3d. Feasible = %s. ", + Aig_ObjId(pObj), RetValue, Vec_PtrSize(p->vCommon), + fFeasible? "yes": "no " ); + + // check the current values + RetValue = 1; + Vec_PtrForEachEntry( Aig_Obj_t *, p->vCommon, pTemp, i ) + { + Value0 = Ssw_ManGetSatVarValue( p, pTemp, 0 ); + Value1 = Ssw_ManGetSatVarValue( p, pTemp, 1 ); + if ( Value0 != Value1 ) + RetValue = 0; + if ( fVerbose ) + printf( "%d", Value0 ^ Value1 ); + } + if ( fVerbose ) + printf( "\n" ); + + return RetValue && fFeasible; +} + +/**Function************************************************************* + + Synopsis [Returns the output of the uniqueness constraint.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ManUniqueAddConstraint( Ssw_Man_t * p, Vec_Ptr_t * vCommon, int f1, int f2 ) +{ + Aig_Obj_t * pObj, * pObj1New, * pObj2New, * pMiter, * pTotal; + int i, pLits[2]; +// int RetValue; + assert( Vec_PtrSize(vCommon) > 0 ); + // generate the constraint + pTotal = Aig_ManConst0(p->pFrames); + Vec_PtrForEachEntry( Aig_Obj_t *, vCommon, pObj, i ) + { + assert( Saig_ObjIsLo(p->pAig, pObj) ); + pObj1New = Ssw_ObjFrame( p, pObj, f1 ); + pObj2New = Ssw_ObjFrame( p, pObj, f2 ); + pMiter = Aig_Exor( p->pFrames, pObj1New, pObj2New ); + pTotal = Aig_Or( p->pFrames, pTotal, pMiter ); + } + if ( Aig_ObjIsConst1(Aig_Regular(pTotal)) ) + { +// printf( "Skipped\n" ); + return 0; + } + // create CNF + Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pTotal) ); + // add output constraint + pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,Aig_Regular(pTotal)), Aig_IsComplement(pTotal) ); +/* + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 1 ); + assert( RetValue ); + // simplify the solver + if ( p->pSat->qtail != p->pSat->qhead ) + { + RetValue = sat_solver_simplify(p->pSat); + assert( RetValue != 0 ); + } +*/ + assert( p->iOutputLit == -1 ); + p->iOutputLit = pLits[0]; + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/sat/bsat/satChecker.c b/src/sat/bsat/satChecker.c index 041bc9ed..7aec4a4d 100644 --- a/src/sat/bsat/satChecker.c +++ b/src/sat/bsat/satChecker.c @@ -23,7 +23,7 @@ #include #include #include -#include "vec.h" +#include "misc/vec/vec.h" ABC_NAMESPACE_IMPL_START diff --git a/src/sat/bsat/satInterA.c b/src/sat/bsat/satInterA.c index a635516c..01a5ca31 100644 --- a/src/sat/bsat/satInterA.c +++ b/src/sat/bsat/satInterA.c @@ -24,7 +24,7 @@ #include #include #include "satStore.h" -#include "aig.h" +#include "src/aig/aig/aig.h" ABC_NAMESPACE_IMPL_START diff --git a/src/sat/bsat/satInterB.c b/src/sat/bsat/satInterB.c index 1ffb0dc5..5d348f62 100644 --- a/src/sat/bsat/satInterB.c +++ b/src/sat/bsat/satInterB.c @@ -24,7 +24,7 @@ #include #include #include "satStore.h" -#include "aig.h" +#include "src/aig/aig/aig.h" ABC_NAMESPACE_IMPL_START diff --git a/src/sat/bsat/satInterP.c b/src/sat/bsat/satInterP.c index ff0b0e94..b8ab473a 100644 --- a/src/sat/bsat/satInterP.c +++ b/src/sat/bsat/satInterP.c @@ -25,7 +25,7 @@ #include #include "satStore.h" -#include "vec.h" +#include "src/misc/vec/vec.h" ABC_NAMESPACE_IMPL_START diff --git a/src/sat/bsat/satMem.h b/src/sat/bsat/satMem.h index 8ea153a6..9dc9e692 100644 --- a/src/sat/bsat/satMem.h +++ b/src/sat/bsat/satMem.h @@ -18,14 +18,14 @@ ***********************************************************************/ -#ifndef __SAT_MEM_H__ -#define __SAT_MEM_H__ +#ifndef ABC__sat__bsat__satMem_h +#define ABC__sat__bsat__satMem_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// -#include "abc_global.h" +#include "src/misc/util/abc_global.h" ABC_NAMESPACE_HEADER_START diff --git a/src/sat/bsat/satProof.c b/src/sat/bsat/satProof.c index 79179952..111b3ece 100644 --- a/src/sat/bsat/satProof.c +++ b/src/sat/bsat/satProof.c @@ -19,8 +19,8 @@ ***********************************************************************/ #include "satSolver2.h" -#include "vec.h" -#include "aig.h" +#include "src/misc/vec/vec.h" +#include "src/aig/aig/aig.h" #include "satTruth.h" #include "vecRec.h" @@ -610,7 +610,7 @@ void * Sat_ProofInterpolant( sat_solver2 * s, void * pGloVars ) // start the AIG pAig = Aig_ManStart( 10000 ); - pAig->pName = Aig_UtilStrsav( "interpol" ); + pAig->pName = Abc_UtilStrsav( "interpol" ); for ( i = 0; i < Vec_IntSize(vGlobVars); i++ ) Aig_ObjCreatePi( pAig ); diff --git a/src/sat/bsat/satSolver.h b/src/sat/bsat/satSolver.h index 0ca934ed..30b3742b 100644 --- a/src/sat/bsat/satSolver.h +++ b/src/sat/bsat/satSolver.h @@ -19,8 +19,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA **************************************************************************************************/ // Modified to compile with MS Visual Studio 6.0 by Alan Mishchenko -#ifndef satSolver_h -#define satSolver_h +#ifndef ABC__sat__bsat__satSolver_h +#define ABC__sat__bsat__satSolver_h #include diff --git a/src/sat/bsat/satSolver2.h b/src/sat/bsat/satSolver2.h index baccf68d..29279b86 100644 --- a/src/sat/bsat/satSolver2.h +++ b/src/sat/bsat/satSolver2.h @@ -19,8 +19,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA **************************************************************************************************/ // Modified to compile with MS Visual Studio 6.0 by Alan Mishchenko -#ifndef satSolver2_h -#define satSolver2_h +#ifndef ABC__sat__bsat__satSolver2_h +#define ABC__sat__bsat__satSolver2_h #include diff --git a/src/sat/bsat/satSolver_old.h b/src/sat/bsat/satSolver_old.h index 4c577b1e..d2228f79 100644 --- a/src/sat/bsat/satSolver_old.h +++ b/src/sat/bsat/satSolver_old.h @@ -19,8 +19,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA **************************************************************************************************/ // Modified to compile with MS Visual Studio 6.0 by Alan Mishchenko -#ifndef satSolver_h -#define satSolver_h +#ifndef ABC__sat__bsat__satSolver_old_h +#define ABC__sat__bsat__satSolver_old_h #include diff --git a/src/sat/bsat/satStore.h b/src/sat/bsat/satStore.h index 0293aea7..206c6939 100644 --- a/src/sat/bsat/satStore.h +++ b/src/sat/bsat/satStore.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __SAT_STORE_H__ -#define __SAT_STORE_H__ +#ifndef ABC__sat__bsat__satStore_h +#define ABC__sat__bsat__satStore_h /* diff --git a/src/sat/bsat/satTruth.h b/src/sat/bsat/satTruth.h index e07518b0..2f17b6f0 100644 --- a/src/sat/bsat/satTruth.h +++ b/src/sat/bsat/satTruth.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __SAT_TRUTH_H__ -#define __SAT_TRUTH_H__ +#ifndef ABC__sat__bsat__satTruth_h +#define ABC__sat__bsat__satTruth_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// @@ -29,7 +29,7 @@ #include #include #include -#include "abc_global.h" +#include "src/misc/util/abc_global.h" ABC_NAMESPACE_HEADER_START diff --git a/src/sat/bsat/satVec.h b/src/sat/bsat/satVec.h index bf117521..01740580 100644 --- a/src/sat/bsat/satVec.h +++ b/src/sat/bsat/satVec.h @@ -19,10 +19,10 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA **************************************************************************************************/ // Modified to compile with MS Visual Studio 6.0 by Alan Mishchenko -#ifndef satVec_h -#define satVec_h +#ifndef ABC__sat__bsat__satVec_h +#define ABC__sat__bsat__satVec_h -#include "abc_global.h" +#include "src/misc/util/abc_global.h" ABC_NAMESPACE_HEADER_START diff --git a/src/sat/bsat/vecRec.h b/src/sat/bsat/vecRec.h index e92129be..82d7183d 100644 --- a/src/sat/bsat/vecRec.h +++ b/src/sat/bsat/vecRec.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __VEC_REC_H__ -#define __VEC_REC_H__ +#ifndef ABC__sat__bsat__vecRec_h +#define ABC__sat__bsat__vecRec_h //////////////////////////////////////////////////////////////////////// diff --git a/src/sat/cnf/cnf.h b/src/sat/cnf/cnf.h new file mode 100644 index 00000000..0b6fc8c2 --- /dev/null +++ b/src/sat/cnf/cnf.h @@ -0,0 +1,195 @@ +/**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 ABC__aig__cnf__cnf_h +#define ABC__aig__cnf__cnf_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + +#include "src/misc/vec/vec.h" +#include "src/aig/aig/aig.h" +#include "src/opt/dar/darInt.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// 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) + int * pObj2Clause; // the mapping of objects into clauses + int * pObj2Count; // the mapping of objects into clause number +}; + +// 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 (Cnf_Cut_t *)pObj->pData; } +static inline void Cnf_ObjSetBestCut( Aig_Obj_t * pObj, Cnf_Cut_t * pCut ) { pObj->pData = pCut; } + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +// iterator over the clauses +#define Cnf_CnfForClause( p, pBeg, pEnd, i ) \ + for ( i = 0; i < p->nClauses && (pBeg = p->pClauses[i]) && (pEnd = p->pClauses[i+1]); i++ ) + +// 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 Vec_Int_t * Cnf_DeriveMappingArray( Aig_Man_t * pAig ); +extern Cnf_Dat_t * Cnf_Derive( Aig_Man_t * pAig, int nOutputs ); +extern Cnf_Dat_t * Cnf_DeriveOther( Aig_Man_t * pAig ); +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 ); +/*=== cnfFast.c ========================================================*/ +extern void Cnf_CollectLeaves( Aig_Obj_t * pRoot, Vec_Ptr_t * vSuper, int fStopCompl ); +extern void Cnf_ComputeClauses( Aig_Man_t * p, Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, + Vec_Ptr_t * vNodes, Vec_Int_t * vMap, Vec_Int_t * vCover, Vec_Int_t * vClauses ); +extern void Cnf_DeriveFastMark( Aig_Man_t * p ); +extern Cnf_Dat_t * Cnf_DeriveFast( Aig_Man_t * p, int nOutputs ); +/*=== 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 Cnf_Dat_t * Cnf_DataAlloc( Aig_Man_t * pAig, int nVars, int nClauses, int nLiterals ); +extern Cnf_Dat_t * Cnf_DataDup( Cnf_Dat_t * p ); +extern void Cnf_DataFree( Cnf_Dat_t * p ); +extern void Cnf_DataLift( Cnf_Dat_t * p, int nVarsPlus ); +extern void Cnf_DataFlipLastLiteral( Cnf_Dat_t * p ); +extern void Cnf_DataPrint( Cnf_Dat_t * p, int fReadable ); +extern void Cnf_DataWriteIntoFile( Cnf_Dat_t * p, char * pFileName, int fReadable ); +extern void * Cnf_DataWriteIntoSolver( Cnf_Dat_t * p, int nFrames, int fInit ); +extern void * Cnf_DataWriteIntoSolverInt( void * pSat, Cnf_Dat_t * p, int nFrames, int fInit ); +extern int Cnf_DataWriteOrClause( void * pSat, Cnf_Dat_t * pCnf ); +extern int Cnf_DataWriteAndClauses( void * p, Cnf_Dat_t * pCnf ); +extern void Cnf_DataTranformPolarity( Cnf_Dat_t * pCnf, int fTransformPos ); +extern int Cnf_DataAddXorClause( void * pSat, int iVarA, int iVarB, int iVarC ); +/*=== 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 ); +extern Vec_Int_t * Cnf_DataCollectCiSatNums( Cnf_Dat_t * pCnf, Aig_Man_t * p ); +extern Vec_Int_t * Cnf_DataCollectCoSatNums( Cnf_Dat_t * pCnf, Aig_Man_t * p ); +/*=== cnfWrite.c ========================================================*/ +extern Vec_Int_t * Cnf_ManWriteCnfMapping( Cnf_Man_t * p, Vec_Ptr_t * vMapped ); +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_ManWriteCnfOther( Cnf_Man_t * p, Vec_Ptr_t * vMapped ); +extern Cnf_Dat_t * Cnf_DeriveSimple( Aig_Man_t * p, int nOutputs ); +extern Cnf_Dat_t * Cnf_DeriveSimpleForRetiming( Aig_Man_t * p ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/sat/cnf/cnfCore.c b/src/sat/cnf/cnfCore.c new file mode 100644 index 00000000..eb46e704 --- /dev/null +++ b/src/sat/cnf/cnfCore.c @@ -0,0 +1,296 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Cnf_Man_t * s_pManCnf = NULL; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Converts AIG into the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Cnf_DeriveMappingArray( Aig_Man_t * pAig ) +{ + Vec_Int_t * vResult; + Cnf_Man_t * p; + 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, 0 ); + vResult = Cnf_ManWriteCnfMapping( p, vMapped ); + Vec_PtrFree( vMapped ); + Aig_MmFixedStop( pMemCuts, 0 ); +p->timeSave = clock() - clk; + + // reset reference counters + Aig_ManResetRefs( pAig ); +//ABC_PRT( "Cuts ", p->timeCuts ); +//ABC_PRT( "Map ", p->timeMap ); +//ABC_PRT( "Saving ", p->timeSave ); + return vResult; +} + +/**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 ); +//ABC_PRT( "Cuts ", p->timeCuts ); +//ABC_PRT( "Map ", p->timeMap ); +//ABC_PRT( "Saving ", p->timeSave ); + return pCnf; +} + +/**Function************************************************************* + + Synopsis [Converts AIG into the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cnf_Dat_t * Cnf_DeriveOther( Aig_Man_t * pAig ) +{ + 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_ManWriteCnfOther( p, vMapped ); + Vec_PtrFree( vMapped ); + Aig_MmFixedStop( pMemCuts, 0 ); +p->timeSave = clock() - clk; + + // reset reference counters + Aig_ManResetRefs( pAig ); +//ABC_PRT( "Cuts ", p->timeCuts ); +//ABC_PRT( "Map ", p->timeMap ); +//ABC_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 ); +ABC_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 ); +*/ +ABC_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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/sat/cnf/cnfCut.c b/src/sat/cnf/cnfCut.c new file mode 100644 index 00000000..fef199c7 --- /dev/null +++ b/src/sat/cnf/cnfCut.c @@ -0,0 +1,376 @@ +/**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 "src/bool/kit/kit.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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) * Abc_TruthWordNum(nLeaves); + pCut = (Cnf_Cut_t *)Aig_MmFlexEntryFetch( p->pMemCuts, nSize ); + pCut->nFanins = nLeaves; + pCut->nWords = Abc_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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/sat/cnf/cnfData.c b/src/sat/cnf/cnfData.c new file mode 100644 index 00000000..3d3cdf37 --- /dev/null +++ b/src/sat/cnf/cnfData.c @@ -0,0 +1,4789 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static const char s_Data3[82] = "!#&()*+,-.0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ[]abcdefghijklmnopqrstuvwxyz|"; + +static const 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] = (char)(-1); + for ( i = 0; i < 81; i++ ) + Map[(int)s_Data3[i]] = (char)i; + + // count the number of strings + for ( Size = 0; s_Data4[Size] && Size < 100000; Size++ ); + assert( Size < 100000 ); + + // allocate memory + pMemory = ABC_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] = (char)(-1); + else + pMemory[i*75+k] = Map[(int)s_Data4[i][k]]; + + // set pointers and compute SOP sizes + pSopSizes = ABC_ALLOC( char, 65536 ); + pSops = ABC_ALLOC( char *, 65536 ); + pSopSizes[0] = 0; + pSops[0] = NULL; + pPrev = pMemory; + for ( k = 0, i = 1; i < 65536; k++ ) + if ( pMemory[k] == (char)(-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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/sat/cnf/cnfFast.c b/src/sat/cnf/cnfFast.c new file mode 100644 index 00000000..6ec2b6a6 --- /dev/null +++ b/src/sat/cnf/cnfFast.c @@ -0,0 +1,697 @@ +/**CFile**************************************************************** + + FileName [cnfFast.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: cnfFast.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cnf.h" +#include "src/bool/kit/kit.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Detects multi-input gate rooted at this node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_CollectLeaves_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper, int fStopCompl ) +{ + if ( pRoot != pObj && (pObj->fMarkA || (fStopCompl && Aig_IsComplement(pObj))) ) + { + Vec_PtrPushUnique( vSuper, fStopCompl ? pObj : Aig_Regular(pObj) ); + return; + } + assert( Aig_ObjIsNode(pObj) ); + if ( fStopCompl ) + { + Cnf_CollectLeaves_rec( pRoot, Aig_ObjChild0(pObj), vSuper, 1 ); + Cnf_CollectLeaves_rec( pRoot, Aig_ObjChild1(pObj), vSuper, 1 ); + } + else + { + Cnf_CollectLeaves_rec( pRoot, Aig_ObjFanin0(pObj), vSuper, 0 ); + Cnf_CollectLeaves_rec( pRoot, Aig_ObjFanin1(pObj), vSuper, 0 ); + } +} + +/**Function************************************************************* + + Synopsis [Detects multi-input gate rooted at this node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_CollectLeaves( Aig_Obj_t * pRoot, Vec_Ptr_t * vSuper, int fStopCompl ) +{ + assert( !Aig_IsComplement(pRoot) ); + Vec_PtrClear( vSuper ); + Cnf_CollectLeaves_rec( pRoot, pRoot, vSuper, fStopCompl ); +} + +/**Function************************************************************* + + Synopsis [Collects nodes inside the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_CollectVolume_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + if ( Aig_ObjIsTravIdCurrent( p, pObj ) ) + return; + Aig_ObjSetTravIdCurrent( p, pObj ); + assert( Aig_ObjIsNode(pObj) ); + Cnf_CollectVolume_rec( p, Aig_ObjFanin0(pObj), vNodes ); + Cnf_CollectVolume_rec( p, Aig_ObjFanin1(pObj), vNodes ); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Collects nodes inside the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_CollectVolume( Aig_Man_t * p, Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManIncrementTravId( p ); + Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + Vec_PtrClear( vNodes ); + Cnf_CollectVolume_rec( p, pRoot, vNodes ); +} + +/**Function************************************************************* + + Synopsis [Derive truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +word Cnf_CutDeriveTruth( Aig_Man_t * p, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes ) +{ + static word Truth6[6] = { + 0xAAAAAAAAAAAAAAAA, + 0xCCCCCCCCCCCCCCCC, + 0xF0F0F0F0F0F0F0F0, + 0xFF00FF00FF00FF00, + 0xFFFF0000FFFF0000, + 0xFFFFFFFF00000000 + }; + static word C[2] = { 0, ~0 }; + static word S[256]; + Aig_Obj_t * pObj; + int i; + assert( Vec_PtrSize(vLeaves) <= 6 && Vec_PtrSize(vNodes) > 0 ); + assert( Vec_PtrSize(vLeaves) + Vec_PtrSize(vNodes) <= 256 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i ) + { + pObj->iData = i; + S[pObj->iData] = Truth6[i]; + } + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + pObj->iData = Vec_PtrSize(vLeaves) + i; + S[pObj->iData] = (S[Aig_ObjFanin0(pObj)->iData] ^ C[Aig_ObjFaninC0(pObj)]) & + (S[Aig_ObjFanin1(pObj)->iData] ^ C[Aig_ObjFaninC1(pObj)]); + } + return S[pObj->iData]; +} + + +/**Function************************************************************* + + Synopsis [Collects nodes inside the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cnf_ObjGetLit( Vec_Int_t * vMap, Aig_Obj_t * pObj, int fCompl ) +{ + int iSatVar = vMap ? Vec_IntEntry(vMap, Aig_ObjId(pObj)) : Aig_ObjId(pObj); + assert( iSatVar > 0 ); + return iSatVar + iSatVar + fCompl; +} + +/**Function************************************************************* + + Synopsis [Collects nodes inside the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_ComputeClauses( Aig_Man_t * p, Aig_Obj_t * pRoot, + Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes, Vec_Int_t * vMap, Vec_Int_t * vCover, Vec_Int_t * vClauses ) +{ + Aig_Obj_t * pLeaf; + int c, k, Cube, OutLit, RetValue; + word Truth; + assert( pRoot->fMarkA ); + + Vec_IntClear( vClauses ); + + OutLit = Cnf_ObjGetLit( vMap, pRoot, 0 ); + // detect cone + Cnf_CollectLeaves( pRoot, vLeaves, 0 ); + Cnf_CollectVolume( p, pRoot, vLeaves, vNodes ); + assert( pRoot == Vec_PtrEntryLast(vNodes) ); + // check if this is an AND-gate + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pLeaf, k ) + { + if ( Aig_ObjFaninC0(pLeaf) && !Aig_ObjFanin0(pLeaf)->fMarkA ) + break; + if ( Aig_ObjFaninC1(pLeaf) && !Aig_ObjFanin1(pLeaf)->fMarkA ) + break; + } + if ( k == Vec_PtrSize(vNodes) ) + { + Cnf_CollectLeaves( pRoot, vLeaves, 1 ); + // write big clause + Vec_IntPush( vClauses, 0 ); + Vec_IntPush( vClauses, OutLit ); + Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pLeaf, k ) + Vec_IntPush( vClauses, Cnf_ObjGetLit(vMap, Aig_Regular(pLeaf), !Aig_IsComplement(pLeaf)) ); + // write small clauses + Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pLeaf, k ) + { + Vec_IntPush( vClauses, 0 ); + Vec_IntPush( vClauses, OutLit ^ 1 ); + Vec_IntPush( vClauses, Cnf_ObjGetLit(vMap, Aig_Regular(pLeaf), Aig_IsComplement(pLeaf)) ); + } + return; + } + if ( Vec_PtrSize(vLeaves) > 6 ) + printf( "FastCnfGeneration: Internal error!!!\n" ); + assert( Vec_PtrSize(vLeaves) <= 6 ); + + Truth = Cnf_CutDeriveTruth( p, vLeaves, vNodes ); + if ( Truth == 0 || Truth == ~0 ) + { + Vec_IntPush( vClauses, 0 ); + Vec_IntPush( vClauses, (Truth == 0) ? (OutLit ^ 1) : OutLit ); + return; + } + + RetValue = Kit_TruthIsop( (unsigned *)&Truth, Vec_PtrSize(vLeaves), vCover, 0 ); + assert( RetValue >= 0 ); + + Vec_IntForEachEntry( vCover, Cube, c ) + { + Vec_IntPush( vClauses, 0 ); + Vec_IntPush( vClauses, OutLit ); + for ( k = 0; k < Vec_PtrSize(vLeaves); k++, Cube >>= 2 ) + { + if ( (Cube & 3) == 0 ) + continue; + assert( (Cube & 3) != 3 ); + Vec_IntPush( vClauses, Cnf_ObjGetLit(vMap, (Aig_Obj_t *)Vec_PtrEntry(vLeaves,k), (Cube&3)!=1) ); + } + } + + Truth = ~Truth; + + RetValue = Kit_TruthIsop( (unsigned *)&Truth, Vec_PtrSize(vLeaves), vCover, 0 ); + assert( RetValue >= 0 ); + Vec_IntForEachEntry( vCover, Cube, c ) + { + Vec_IntPush( vClauses, 0 ); + Vec_IntPush( vClauses, OutLit ^ 1 ); + for ( k = 0; k < Vec_PtrSize(vLeaves); k++, Cube >>= 2 ) + { + if ( (Cube & 3) == 0 ) + continue; + assert( (Cube & 3) != 3 ); + Vec_IntPush( vClauses, Cnf_ObjGetLit(vMap, (Aig_Obj_t *)Vec_PtrEntry(vLeaves,k), (Cube&3)!=1) ); + } + } +} + + + +/**Function************************************************************* + + Synopsis [Marks AIG for CNF computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_DeriveFastMark( Aig_Man_t * p ) +{ + Vec_Int_t * vSupps; + Vec_Ptr_t * vLeaves, * vNodes; + Aig_Obj_t * pObj, * pTemp, * pObjC, * pObj0, * pObj1; + int i, k, nFans, Counter; + + vLeaves = Vec_PtrAlloc( 100 ); + vNodes = Vec_PtrAlloc( 100 ); + vSupps = Vec_IntStart( Aig_ManObjNumMax(p) ); + + // mark CIs + Aig_ManForEachPi( p, pObj, i ) + pObj->fMarkA = 1; + + // mark CO drivers + Aig_ManForEachPo( p, pObj, i ) + Aig_ObjFanin0(pObj)->fMarkA = 1; + + // mark MUX/XOR nodes + Aig_ManForEachNode( p, pObj, i ) + { + assert( !pObj->fMarkB ); + if ( !Aig_ObjIsMuxType(pObj) ) + continue; + pObj0 = Aig_ObjFanin0(pObj); + if ( pObj0->fMarkB || Aig_ObjRefs(pObj0) > 1 ) + continue; + pObj1 = Aig_ObjFanin1(pObj); + if ( pObj1->fMarkB || Aig_ObjRefs(pObj1) > 1 ) + continue; + // mark nodes + pObj->fMarkB = 1; + pObj0->fMarkB = 1; + pObj1->fMarkB = 1; + // mark inputs and outputs + pObj->fMarkA = 1; + Aig_ObjFanin0(pObj0)->fMarkA = 1; + Aig_ObjFanin1(pObj0)->fMarkA = 1; + Aig_ObjFanin0(pObj1)->fMarkA = 1; + Aig_ObjFanin1(pObj1)->fMarkA = 1; + } + + // mark nodes with multiple fanouts and pointed to by complemented edges + Aig_ManForEachNode( p, pObj, i ) + { + // mark nodes with many fanouts + if ( Aig_ObjRefs(pObj) > 1 ) + pObj->fMarkA = 1; + // mark nodes pointed to by a complemented edge + if ( Aig_ObjFaninC0(pObj) && !Aig_ObjFanin0(pObj)->fMarkB ) + Aig_ObjFanin0(pObj)->fMarkA = 1; + if ( Aig_ObjFaninC1(pObj) && !Aig_ObjFanin1(pObj)->fMarkB ) + Aig_ObjFanin1(pObj)->fMarkA = 1; + } + + // compute supergate size for internal marked nodes + Aig_ManForEachNode( p, pObj, i ) + { + if ( !pObj->fMarkA ) + continue; + if ( pObj->fMarkB ) + { + if ( !Aig_ObjIsMuxType(pObj) ) + continue; + pObjC = Aig_ObjRecognizeMux( pObj, &pObj1, &pObj0 ); + pObj0 = Aig_Regular(pObj0); + pObj1 = Aig_Regular(pObj1); + assert( pObj0->fMarkA ); + assert( pObj1->fMarkA ); +// if ( pObj0 == pObj1 ) +// continue; + nFans = 1 + (pObj0 == pObj1); + if ( !pObj0->fMarkB && !Aig_ObjIsPi(pObj0) && Aig_ObjRefs(pObj0) == nFans && Vec_IntEntry(vSupps, Aig_ObjId(pObj0)) < 3 ) + { + pObj0->fMarkA = 0; + continue; + } + if ( !pObj1->fMarkB && !Aig_ObjIsPi(pObj1) && Aig_ObjRefs(pObj1) == nFans && Vec_IntEntry(vSupps, Aig_ObjId(pObj1)) < 3 ) + { + pObj1->fMarkA = 0; + continue; + } + continue; + } + + Cnf_CollectLeaves( pObj, vLeaves, 1 ); + Vec_IntWriteEntry( vSupps, Aig_ObjId(pObj), Vec_PtrSize(vLeaves) ); + if ( Vec_PtrSize(vLeaves) >= 6 ) + continue; + Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pTemp, k ) + { + pTemp = Aig_Regular(pTemp); + assert( pTemp->fMarkA ); + if ( pTemp->fMarkB || Aig_ObjIsPi(pTemp) || Aig_ObjRefs(pTemp) > 1 ) + continue; + assert( Vec_IntEntry(vSupps, Aig_ObjId(pTemp)) > 0 ); + if ( Vec_PtrSize(vLeaves) - 1 + Vec_IntEntry(vSupps, Aig_ObjId(pTemp)) > 6 ) + continue; + pTemp->fMarkA = 0; + Vec_IntWriteEntry( vSupps, Aig_ObjId(pObj), 6 ); +//printf( "%d %d ", Vec_PtrSize(vLeaves), Vec_IntEntry(vSupps, Aig_ObjId(pTemp)) ); + break; + } + } + Aig_ManCleanMarkB( p ); + + // check CO drivers + Counter = 0; + Aig_ManForEachPo( p, pObj, i ) + Counter += !Aig_ObjFanin0(pObj)->fMarkA; + if ( Counter ) + printf( "PO-driver rule is violated %d times.\n", Counter ); + + // check that the AND-gates are fine + Counter = 0; + Aig_ManForEachNode( p, pObj, i ) + { + assert( pObj->fMarkB == 0 ); + if ( !pObj->fMarkA ) + continue; + Cnf_CollectLeaves( pObj, vLeaves, 0 ); + if ( Vec_PtrSize(vLeaves) <= 6 ) + continue; + Cnf_CollectVolume( p, pObj, vLeaves, vNodes ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pTemp, k ) + { + if ( Aig_ObjFaninC0(pTemp) && !Aig_ObjFanin0(pTemp)->fMarkA ) + Counter++; + if ( Aig_ObjFaninC1(pTemp) && !Aig_ObjFanin1(pTemp)->fMarkA ) + Counter++; + } + } + if ( Counter ) + printf( "AND-gate rule is violated %d times.\n", Counter ); + + Vec_PtrFree( vLeaves ); + Vec_PtrFree( vNodes ); + Vec_IntFree( vSupps ); +} + + +/**Function************************************************************* + + Synopsis [Counts the number of clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cnf_CutCountClauses( Aig_Man_t * p, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes, Vec_Int_t * vCover ) +{ + word Truth; + Aig_Obj_t * pObj; + int i, RetValue, nSize = 0; + if ( Vec_PtrSize(vLeaves) > 6 ) + { + // make sure this is an AND gate + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + if ( Aig_ObjFaninC0(pObj) && !Aig_ObjFanin0(pObj)->fMarkA ) + printf( "Unusual 1!\n" ); + if ( Aig_ObjFaninC1(pObj) && !Aig_ObjFanin1(pObj)->fMarkA ) + printf( "Unusual 2!\n" ); + continue; + + assert( !Aig_ObjFaninC0(pObj) || Aig_ObjFanin0(pObj)->fMarkA ); + assert( !Aig_ObjFaninC1(pObj) || Aig_ObjFanin1(pObj)->fMarkA ); + } + return Vec_PtrSize(vLeaves) + 1; + } + Truth = Cnf_CutDeriveTruth( p, vLeaves, vNodes ); + + RetValue = Kit_TruthIsop( (unsigned *)&Truth, Vec_PtrSize(vLeaves), vCover, 0 ); + assert( RetValue >= 0 ); + nSize += Vec_IntSize(vCover); + + Truth = ~Truth; + + RetValue = Kit_TruthIsop( (unsigned *)&Truth, Vec_PtrSize(vLeaves), vCover, 0 ); + assert( RetValue >= 0 ); + nSize += Vec_IntSize(vCover); + return nSize; +} + +/**Function************************************************************* + + Synopsis [Counts the size of the CNF, assuming marks are set.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cnf_CountCnfSize( Aig_Man_t * p ) +{ + Vec_Ptr_t * vLeaves, * vNodes; + Vec_Int_t * vCover; + Aig_Obj_t * pObj; + int nVars = 0, nClauses = 0; + int i, nSize; + + vLeaves = Vec_PtrAlloc( 100 ); + vNodes = Vec_PtrAlloc( 100 ); + vCover = Vec_IntAlloc( 1 << 16 ); + + Aig_ManForEachObj( p, pObj, i ) + nVars += pObj->fMarkA; + + Aig_ManForEachNode( p, pObj, i ) + { + if ( !pObj->fMarkA ) + continue; + Cnf_CollectLeaves( pObj, vLeaves, 0 ); + Cnf_CollectVolume( p, pObj, vLeaves, vNodes ); + assert( pObj == Vec_PtrEntryLast(vNodes) ); + + nSize = Cnf_CutCountClauses( p, vLeaves, vNodes, vCover ); +// printf( "%d(%d) ", Vec_PtrSize(vLeaves), nSize ); + + nClauses += nSize; + } +// printf( "\n" ); + printf( "Vars = %d Clauses = %d\n", nVars, nClauses ); + + Vec_PtrFree( vLeaves ); + Vec_PtrFree( vNodes ); + Vec_IntFree( vCover ); + return nClauses; +} + +/**Function************************************************************* + + Synopsis [Derives CNF from the marked AIG.] + + Description [Assumes that marking is such that when we traverse from each + marked node, the logic cone has 6 inputs or less, or it is a multi-input AND.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cnf_Dat_t * Cnf_DeriveFastClauses( Aig_Man_t * p, int nOutputs ) +{ + Cnf_Dat_t * pCnf; + Vec_Int_t * vLits, * vClas, * vMap, * vTemp; + Vec_Ptr_t * vLeaves, * vNodes; + Vec_Int_t * vCover; + Aig_Obj_t * pObj; + int i, k, nVars, Entry, OutLit, DriLit; + + vLits = Vec_IntAlloc( 1 << 16 ); + vClas = Vec_IntAlloc( 1 << 12 ); + vMap = Vec_IntStartFull( Aig_ManObjNumMax(p) ); + + // assign variables for the outputs + nVars = 1; + if ( nOutputs ) + { + if ( Aig_ManRegNum(p) == 0 ) + { + assert( nOutputs == Aig_ManPoNum(p) ); + Aig_ManForEachPo( p, pObj, i ) + Vec_IntWriteEntry( vMap, Aig_ObjId(pObj), nVars++ ); + } + else + { + assert( nOutputs == Aig_ManRegNum(p) ); + Aig_ManForEachLiSeq( p, pObj, i ) + Vec_IntWriteEntry( vMap, Aig_ObjId(pObj), nVars++ ); + } + } + // assign variables to the internal nodes + Aig_ManForEachNodeReverse( p, pObj, i ) + if ( pObj->fMarkA ) + Vec_IntWriteEntry( vMap, Aig_ObjId(pObj), nVars++ ); + // assign variables to the PIs and constant node + Aig_ManForEachPi( p, pObj, i ) + Vec_IntWriteEntry( vMap, Aig_ObjId(pObj), nVars++ ); + Vec_IntWriteEntry( vMap, Aig_ObjId(Aig_ManConst1(p)), nVars++ ); + + // create clauses + vLeaves = Vec_PtrAlloc( 100 ); + vNodes = Vec_PtrAlloc( 100 ); + vCover = Vec_IntAlloc( 1 << 16 ); + vTemp = Vec_IntAlloc( 100 ); + Aig_ManForEachNodeReverse( p, pObj, i ) + { + if ( !pObj->fMarkA ) + continue; + Cnf_ComputeClauses( p, pObj, vLeaves, vNodes, vMap, vCover, vTemp ); + Vec_IntForEachEntry( vTemp, Entry, k ) + { + if ( Entry == 0 ) + Vec_IntPush( vClas, Vec_IntSize(vLits) ); + else + Vec_IntPush( vLits, Entry ); + } + } + Vec_PtrFree( vLeaves ); + Vec_PtrFree( vNodes ); + Vec_IntFree( vCover ); + Vec_IntFree( vTemp ); + + // create clauses for the outputs + Aig_ManForEachPo( p, pObj, i ) + { + DriLit = Cnf_ObjGetLit( vMap, Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj) ); + if ( i < Aig_ManPoNum(p) - nOutputs ) + { + Vec_IntPush( vClas, Vec_IntSize(vLits) ); + Vec_IntPush( vLits, DriLit ); + } + else + { + OutLit = Cnf_ObjGetLit( vMap, pObj, 0 ); + // first clause + Vec_IntPush( vClas, Vec_IntSize(vLits) ); + Vec_IntPush( vLits, OutLit ); + Vec_IntPush( vLits, DriLit ^ 1 ); + // second clause + Vec_IntPush( vClas, Vec_IntSize(vLits) ); + Vec_IntPush( vLits, OutLit ^ 1 ); + Vec_IntPush( vLits, DriLit ); + } + } + + // write the constant literal + OutLit = Cnf_ObjGetLit( vMap, Aig_ManConst1(p), 0 ); + Vec_IntPush( vClas, Vec_IntSize(vLits) ); + Vec_IntPush( vLits, OutLit ); + + // create structure + pCnf = ABC_CALLOC( Cnf_Dat_t, 1 ); + pCnf->pMan = p; + pCnf->nVars = nVars; + pCnf->nLiterals = Vec_IntSize( vLits ); + pCnf->nClauses = Vec_IntSize( vClas ); + pCnf->pClauses = ABC_ALLOC( int *, pCnf->nClauses + 1 ); + pCnf->pClauses[0] = Vec_IntReleaseArray( vLits ); + Vec_IntForEachEntry( vClas, Entry, i ) + pCnf->pClauses[i] = pCnf->pClauses[0] + Entry; + pCnf->pClauses[pCnf->nClauses] = pCnf->pClauses[0] + pCnf->nLiterals; + pCnf->pVarNums = Vec_IntReleaseArray( vMap ); + + // cleanup + Vec_IntFree( vLits ); + Vec_IntFree( vClas ); + Vec_IntFree( vMap ); + return pCnf; +} + +/**Function************************************************************* + + Synopsis [Fast CNF computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cnf_Dat_t * Cnf_DeriveFast( Aig_Man_t * p, int nOutputs ) +{ + Cnf_Dat_t * pCnf = NULL; + int clk, clkTotal = clock(); +// printf( "\n" ); + Aig_ManCleanMarkAB( p ); + // create initial marking + clk = clock(); + Cnf_DeriveFastMark( p ); +// Abc_PrintTime( 1, "Marking", clock() - clk ); + // compute CNF size + clk = clock(); + pCnf = Cnf_DeriveFastClauses( p, nOutputs ); +// Abc_PrintTime( 1, "Clauses", clock() - clk ); + // derive the resulting CNF + Aig_ManCleanMarkA( p ); +// Abc_PrintTime( 1, "TOTAL ", clock() - clkTotal ); + +// printf( "Vars = %6d. Clauses = %7d. Literals = %8d. \n", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals ); + +// Cnf_DataFree( pCnf ); +// pCnf = NULL; + return pCnf; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/sat/cnf/cnfMan.c b/src/sat/cnf/cnfMan.c new file mode 100644 index 00000000..a670a69d --- /dev/null +++ b/src/sat/cnf/cnfMan.c @@ -0,0 +1,693 @@ +/**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 "src/sat/bsat/satSolver.h" +#include "src/sat/bsat/satSolver2.h" +#include "src/misc/zlib/zlib.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 = ABC_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] = ABC_ALLOC( unsigned, 4 * Abc_TruthWordNum(p->nMergeLimit) ); + for ( i = 1; i < 4; i++ ) + p->pTruths[i] = p->pTruths[i-1] + Abc_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 ); + ABC_FREE( p->pTruths[0] ); + Aig_MmFlexStop( p->pMemCuts, 0 ); + ABC_FREE( p->pSopSizes ); + ABC_FREE( p->pSops[1] ); + ABC_FREE( p->pSops ); + ABC_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 [Allocates the new CNF.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cnf_Dat_t * Cnf_DataAlloc( Aig_Man_t * pAig, int nVars, int nClauses, int nLiterals ) +{ + Cnf_Dat_t * pCnf; + int i; + pCnf = ABC_ALLOC( Cnf_Dat_t, 1 ); + memset( pCnf, 0, sizeof(Cnf_Dat_t) ); + pCnf->pMan = pAig; + pCnf->nVars = nVars; + pCnf->nClauses = nClauses; + pCnf->nLiterals = nLiterals; + pCnf->pClauses = ABC_ALLOC( int *, nClauses + 1 ); + pCnf->pClauses[0] = ABC_ALLOC( int, nLiterals ); + pCnf->pClauses[nClauses] = pCnf->pClauses[0] + nLiterals; + pCnf->pVarNums = ABC_ALLOC( int, Aig_ManObjNumMax(pAig) ); +// memset( pCnf->pVarNums, 0xff, sizeof(int) * Aig_ManObjNumMax(pAig) ); + for ( i = 0; i < Aig_ManObjNumMax(pAig); i++ ) + pCnf->pVarNums[i] = -1; + return pCnf; +} + +/**Function************************************************************* + + Synopsis [Allocates the new CNF.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cnf_Dat_t * Cnf_DataDup( Cnf_Dat_t * p ) +{ + Cnf_Dat_t * pCnf; + int i; + pCnf = Cnf_DataAlloc( p->pMan, p->nVars, p->nClauses, p->nLiterals ); + memcpy( pCnf->pClauses[0], p->pClauses[0], sizeof(int) * p->nLiterals ); + memcpy( pCnf->pVarNums, p->pVarNums, sizeof(int) * Aig_ManObjNumMax(p->pMan) ); + for ( i = 1; i < p->nClauses; i++ ) + pCnf->pClauses[i] = pCnf->pClauses[0] + (p->pClauses[i] - p->pClauses[0]); + return pCnf; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_DataFree( Cnf_Dat_t * p ) +{ + if ( p == NULL ) + return; + ABC_FREE( p->pObj2Clause ); + ABC_FREE( p->pObj2Count ); + ABC_FREE( p->pClauses[0] ); + ABC_FREE( p->pClauses ); + ABC_FREE( p->pVarNums ); + ABC_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] >= 0 ) + 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_DataFlipLastLiteral( Cnf_Dat_t * p ) +{ + p->pClauses[0][p->nLiterals-1] = lit_neg( p->pClauses[0][p->nLiterals-1] ); +} + +/**Function************************************************************* + + Synopsis [Writes CNF into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_DataPrint( Cnf_Dat_t * p, int fReadable ) +{ + FILE * pFile = stdout; + int * pLit, * pStop, i; + fprintf( pFile, "p cnf %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, "\n" ); + } + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Writes CNF into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_DataWriteIntoFileGz( Cnf_Dat_t * p, char * pFileName, int fReadable ) +{ + gzFile pFile; + int * pLit, * pStop, i; + pFile = gzopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cnf_WriteIntoFile(): Output file cannot be opened.\n" ); + return; + } + gzprintf( pFile, "c Result of efficient AIG-to-CNF conversion using package CNF\n" ); + gzprintf( pFile, "p cnf %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++ ) + gzprintf( pFile, "%d ", fReadable? Cnf_Lit2Var2(*pLit) : Cnf_Lit2Var(*pLit) ); + gzprintf( pFile, "0\n" ); + } + gzprintf( pFile, "\n" ); + gzclose( pFile ); +} + +/**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; + if ( !strncmp(pFileName+strlen(pFileName)-3,".gz",3) ) + { + Cnf_DataWriteIntoFileGz( p, pFileName, fReadable ); + return; + } + 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 cnf %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_DataWriteIntoSolverInt( void * pSolver, Cnf_Dat_t * p, int nFrames, int fInit ) +{ + sat_solver * pSat = (sat_solver *)pSolver; + int i, f, status; + assert( nFrames > 0 ); + assert( pSat ); +// 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; +} + +/**Function************************************************************* + + Synopsis [Writes CNF into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Cnf_DataWriteIntoSolver( Cnf_Dat_t * p, int nFrames, int fInit ) +{ + return Cnf_DataWriteIntoSolverInt( sat_solver_new(), p, nFrames, fInit ); +} + +/**Function************************************************************* + + Synopsis [Writes CNF into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Cnf_DataWriteIntoSolver2( Cnf_Dat_t * p, int nFrames, int fInit ) +{ + sat_solver2 * pSat; + int i, f, status; + assert( nFrames > 0 ); + pSat = sat_solver2_new(); + sat_solver2_setnvars( pSat, p->nVars * nFrames ); + for ( i = 0; i < p->nClauses; i++ ) + { + if ( !sat_solver2_addclause( pSat, p->pClauses[i], p->pClauses[i+1] ) ) + { + sat_solver2_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_solver2_addclause( pSat, Lits, Lits + 2 ) ) + { + sat_solver2_delete( pSat ); + return NULL; + } + Lits[0]++; + Lits[1]--; + if ( !sat_solver2_addclause( pSat, Lits, Lits + 2 ) ) + { + sat_solver2_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_solver2_addclause( pSat, p->pClauses[i], p->pClauses[i+1] ) ) + { + sat_solver2_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_solver2_addclause( pSat, Lits, Lits + 1 ) ) + { + sat_solver2_delete( pSat ); + return NULL; + } + } + } + status = sat_solver2_simplify(pSat); + if ( status == 0 ) + { + sat_solver2_delete( pSat ); + return NULL; + } + return pSat; +} + +/**Function************************************************************* + + Synopsis [Adds the OR-clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cnf_DataWriteOrClause( void * p, Cnf_Dat_t * pCnf ) +{ + sat_solver * pSat = (sat_solver *)p; + Aig_Obj_t * pObj; + int i, * pLits; + pLits = ABC_ALLOC( int, Aig_ManPoNum(pCnf->pMan) ); + Aig_ManForEachPo( pCnf->pMan, pObj, i ) + pLits[i] = toLitCond( pCnf->pVarNums[pObj->Id], 0 ); + if ( !sat_solver_addclause( pSat, pLits, pLits + Aig_ManPoNum(pCnf->pMan) ) ) + { + ABC_FREE( pLits ); + return 0; + } + ABC_FREE( pLits ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Adds the OR-clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cnf_DataWriteOrClause2( void * p, Cnf_Dat_t * pCnf ) +{ + sat_solver2 * pSat = (sat_solver2 *)p; + Aig_Obj_t * pObj; + int i, * pLits; + pLits = ABC_ALLOC( int, Aig_ManPoNum(pCnf->pMan) ); + Aig_ManForEachPo( pCnf->pMan, pObj, i ) + pLits[i] = toLitCond( pCnf->pVarNums[pObj->Id], 0 ); + if ( !sat_solver2_addclause( pSat, pLits, pLits + Aig_ManPoNum(pCnf->pMan) ) ) + { + ABC_FREE( pLits ); + return 0; + } + ABC_FREE( pLits ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Adds the OR-clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cnf_DataWriteAndClauses( void * p, Cnf_Dat_t * pCnf ) +{ + sat_solver * pSat = (sat_solver *)p; + Aig_Obj_t * pObj; + int i, Lit; + Aig_ManForEachPo( pCnf->pMan, pObj, i ) + { + Lit = toLitCond( pCnf->pVarNums[pObj->Id], 0 ); + if ( !sat_solver_addclause( pSat, &Lit, &Lit+1 ) ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Transforms polarity of the internal veriables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_DataTranformPolarity( Cnf_Dat_t * pCnf, int fTransformPos ) +{ + Aig_Obj_t * pObj; + int * pVarToPol; + int i, iVar; + // create map from the variable number to its polarity + pVarToPol = ABC_CALLOC( int, pCnf->nVars ); + Aig_ManForEachObj( pCnf->pMan, pObj, i ) + { + if ( !fTransformPos && Aig_ObjIsPo(pObj) ) + continue; + if ( pCnf->pVarNums[pObj->Id] >= 0 ) + pVarToPol[ pCnf->pVarNums[pObj->Id] ] = pObj->fPhase; + } + // transform literals + for ( i = 0; i < pCnf->nLiterals; i++ ) + { + iVar = lit_var(pCnf->pClauses[0][i]); + assert( iVar < pCnf->nVars ); + if ( pVarToPol[iVar] ) + pCnf->pClauses[0][i] = lit_neg( pCnf->pClauses[0][i] ); + } + ABC_FREE( pVarToPol ); +} + +/**Function************************************************************* + + Synopsis [Adds constraints for the two-input AND-gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cnf_DataAddXorClause( void * pSat, int iVarA, int iVarB, int iVarC ) +{ + lit Lits[3]; + assert( iVarA > 0 && iVarB > 0 && iVarC > 0 ); + + Lits[0] = toLitCond( iVarA, 1 ); + Lits[1] = toLitCond( iVarB, 1 ); + Lits[2] = toLitCond( iVarC, 1 ); + if ( !sat_solver_addclause( (sat_solver *)pSat, Lits, Lits + 3 ) ) + return 0; + + Lits[0] = toLitCond( iVarA, 1 ); + Lits[1] = toLitCond( iVarB, 0 ); + Lits[2] = toLitCond( iVarC, 0 ); + if ( !sat_solver_addclause( (sat_solver *)pSat, Lits, Lits + 3 ) ) + return 0; + + Lits[0] = toLitCond( iVarA, 0 ); + Lits[1] = toLitCond( iVarB, 1 ); + Lits[2] = toLitCond( iVarC, 0 ); + if ( !sat_solver_addclause( (sat_solver *)pSat, Lits, Lits + 3 ) ) + return 0; + + Lits[0] = toLitCond( iVarA, 0 ); + Lits[1] = toLitCond( iVarB, 0 ); + Lits[2] = toLitCond( iVarC, 1 ); + if ( !sat_solver_addclause( (sat_solver *)pSat, Lits, Lits + 3 ) ) + return 0; + + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/sat/cnf/cnfMap.c b/src/sat/cnf/cnfMap.c new file mode 100644 index 00000000..8907485e --- /dev/null +++ b/src/sat/cnf/cnfMap.c @@ -0,0 +1,362 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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 ); + pCut->uSign = 10 * 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( Aig_Obj_t *, 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 = ABC_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 = ABC_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 ); + ABC_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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/sat/cnf/cnfPost.c b/src/sat/cnf/cnfPost.c new file mode 100644 index 00000000..f7491889 --- /dev/null +++ b/src/sat/cnf/cnfPost.c @@ -0,0 +1,238 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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( (Cnf_Cut_t *)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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/sat/cnf/cnfUtil.c b/src/sat/cnf/cnfUtil.c new file mode 100644 index 00000000..236b6bfa --- /dev/null +++ b/src/sat/cnf/cnfUtil.c @@ -0,0 +1,238 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// 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( Aig_Obj_t *, 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( Aig_Obj_t *, vSuper, pLeaf, i ) + aArea += Cnf_ManScanMapping_rec( p, Aig_Regular(pLeaf), vMapped, fPreorder ); + Vec_PtrFree( vSuper ); + //////////////////////////// + pObj->fMarkB = 1; + } + else + { + pCutBest = (Cnf_Cut_t *)pObj->pData; +// assert( pCutBest->nFanins > 0 ); + 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; +} + +/**Function************************************************************* + + Synopsis [Returns the array of CI IDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Cnf_DataCollectCiSatNums( 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 [Returns the array of CI IDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Cnf_DataCollectCoSatNums( Cnf_Dat_t * pCnf, Aig_Man_t * p ) +{ + Vec_Int_t * vCoIds; + Aig_Obj_t * pObj; + int i; + vCoIds = Vec_IntAlloc( Aig_ManPoNum(p) ); + Aig_ManForEachPo( p, pObj, i ) + Vec_IntPush( vCoIds, pCnf->pVarNums[pObj->Id] ); + return vCoIds; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/sat/cnf/cnfWrite.c b/src/sat/cnf/cnfWrite.c new file mode 100644 index 00000000..54c28967 --- /dev/null +++ b/src/sat/cnf/cnfWrite.c @@ -0,0 +1,806 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Derives CNF mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Cnf_ManWriteCnfMapping( Cnf_Man_t * p, Vec_Ptr_t * vMapped ) +{ + Vec_Int_t * vResult; + Aig_Obj_t * pObj; + Cnf_Cut_t * pCut; + int i, k, nOffset; + nOffset = Aig_ManObjNumMax(p->pManAig); + vResult = Vec_IntStart( nOffset ); + Vec_PtrForEachEntry( Aig_Obj_t *, vMapped, pObj, i ) + { + assert( Aig_ObjIsNode(pObj) ); + pCut = Cnf_ObjBestCut( pObj ); + assert( pCut->nFanins < 5 ); + Vec_IntWriteEntry( vResult, Aig_ObjId(pObj), nOffset ); + Vec_IntPush( vResult, *Cnf_CutTruth(pCut) ); + for ( k = 0; k < pCut->nFanins; k++ ) + Vec_IntPush( vResult, pCut->pFanins[k] ); + for ( ; k < 4; k++ ) + Vec_IntPush( vResult, -1 ); + nOffset += 5; + } + return vResult; +} + + + +/**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 ) +{ + int fChangeVariableOrder = 0; // should be set to 0 to improve performance + 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( Aig_Obj_t *, 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 = ABC_CALLOC( Cnf_Dat_t, 1 ); + pCnf->pMan = p->pManAig; + pCnf->nLiterals = nLiterals; + pCnf->nClauses = nClauses; + pCnf->pClauses = ABC_ALLOC( int *, nClauses + 1 ); + pCnf->pClauses[0] = ABC_ALLOC( int, nLiterals ); + pCnf->pClauses[nClauses] = pCnf->pClauses[0] + nLiterals; + // create room for variable numbers + pCnf->pVarNums = ABC_ALLOC( int, Aig_ManObjNumMax(p->pManAig) ); +// memset( pCnf->pVarNums, 0xff, sizeof(int) * Aig_ManObjNumMax(p->pManAig) ); + for ( i = 0; i < Aig_ManObjNumMax(p->pManAig); i++ ) + pCnf->pVarNums[i] = -1; + + if ( !fChangeVariableOrder ) + { + // assign variables to the last (nOutputs) POs + Number = 1; + if ( nOutputs ) + { + if ( Aig_ManRegNum(p->pManAig) == 0 ) + { + assert( nOutputs == Aig_ManPoNum(p->pManAig) ); + Aig_ManForEachPo( p->pManAig, pObj, i ) + pCnf->pVarNums[pObj->Id] = Number++; + } + else + { + 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( Aig_Obj_t *, 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; + } + else + { + // assign variables to the last (nOutputs) POs + Number = Aig_ManObjNumMax(p->pManAig) + 1; + pCnf->nVars = Number + 1; + if ( nOutputs ) + { + if ( Aig_ManRegNum(p->pManAig) == 0 ) + { + assert( nOutputs == Aig_ManPoNum(p->pManAig) ); + Aig_ManForEachPo( p->pManAig, pObj, i ) + pCnf->pVarNums[pObj->Id] = Number--; + } + else + { + 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( Aig_Obj_t *, 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--; + assert( Number >= 0 ); + } + + // assign the clauses + vSopTemp = Vec_IntAlloc( 1 << 16 ); + pLits = pCnf->pClauses[0]; + pClas = pCnf->pClauses; + Vec_PtrForEachEntry( Aig_Obj_t *, 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 ); +//Cnf_DataPrint( pCnf, 1 ); + return pCnf; +} + + +/**Function************************************************************* + + Synopsis [Derives CNF for the mapping.] + + Description [Derives CNF with obj IDs as SAT vars and mapping of + objects into clauses (pObj2Clause and pObj2Count).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cnf_Dat_t * Cnf_ManWriteCnfOther( Cnf_Man_t * p, Vec_Ptr_t * vMapped ) +{ + 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; + + // count the number of literals and clauses + nLiterals = 1 + 4 * Aig_ManPoNum( p->pManAig ); + nClauses = 1 + 2 * Aig_ManPoNum( p->pManAig ); + Vec_PtrForEachEntry( Aig_Obj_t *, 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]); + } + } + + // allocate CNF + pCnf = ABC_CALLOC( Cnf_Dat_t, 1 ); + pCnf->pMan = p->pManAig; + pCnf->nLiterals = nLiterals; + pCnf->nClauses = nClauses; + pCnf->pClauses = ABC_ALLOC( int *, nClauses + 1 ); + pCnf->pClauses[0] = ABC_ALLOC( int, nLiterals ); + pCnf->pClauses[nClauses] = pCnf->pClauses[0] + nLiterals; + // create room for variable numbers + pCnf->pObj2Clause = ABC_ALLOC( int, Aig_ManObjNumMax(p->pManAig) ); + pCnf->pObj2Count = ABC_ALLOC( int, Aig_ManObjNumMax(p->pManAig) ); + for ( i = 0; i < Aig_ManObjNumMax(p->pManAig); i++ ) + pCnf->pObj2Clause[i] = pCnf->pObj2Count[i] = -1; + pCnf->nVars = Aig_ManObjNumMax(p->pManAig); + + // clear the PI counters + Aig_ManForEachPi( p->pManAig, pObj, i ) + pCnf->pObj2Count[pObj->Id] = 0; + + // assign the clauses + vSopTemp = Vec_IntAlloc( 1 << 16 ); + pLits = pCnf->pClauses[0]; + pClas = pCnf->pClauses; + Vec_PtrForEachEntry( Aig_Obj_t *, vMapped, pObj, i ) + { + // remember the starting clause + pCnf->pObj2Clause[pObj->Id] = pClas - pCnf->pClauses; + pCnf->pObj2Count[pObj->Id] = 0; + + // get the best cut + pCut = Cnf_ObjBestCut( pObj ); + // save variables of this cut + OutVar = pObj->Id; + for ( k = 0; k < (int)pCut->nFanins; k++ ) + { + pVars[k] = 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 ); + } + pCnf->pObj2Count[pObj->Id] += Vec_IntSize(vCover); + + // 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 ); + } + pCnf->pObj2Count[pObj->Id] += Vec_IntSize(vCover); + } + Vec_IntFree( vSopTemp ); + + // write the output literals + Aig_ManForEachPo( p->pManAig, pObj, i ) + { + // remember the starting clause + pCnf->pObj2Clause[pObj->Id] = pClas - pCnf->pClauses; + pCnf->pObj2Count[pObj->Id] = 2; + // get variables + OutVar = Aig_ObjFanin0(pObj)->Id; + PoVar = 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); + } + + // remember the starting clause + pCnf->pObj2Clause[Aig_ManConst1(p->pManAig)->Id] = pClas - pCnf->pClauses; + pCnf->pObj2Count[Aig_ManConst1(p->pManAig)->Id] = 1; + // write the constant literal + OutVar = Aig_ManConst1(p->pManAig)->Id; + *pClas++ = pLits; + *pLits++ = 2 * OutVar; + + // verify that the correct number of literals and clauses was written + assert( pLits - pCnf->pClauses[0] == nLiterals ); + assert( pClas - pCnf->pClauses == nClauses ); +//Cnf_DataPrint( pCnf, 1 ); + return pCnf; +} + + +/**Function************************************************************* + + Synopsis [Derives a simple CNF for the AIG.] + + Description [The last argument lists 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 = ABC_ALLOC( Cnf_Dat_t, 1 ); + memset( pCnf, 0, sizeof(Cnf_Dat_t) ); + pCnf->pMan = p; + pCnf->nLiterals = nLiterals; + pCnf->nClauses = nClauses; + pCnf->pClauses = ABC_ALLOC( int *, nClauses + 1 ); + pCnf->pClauses[0] = ABC_ALLOC( int, nLiterals ); + pCnf->pClauses[nClauses] = pCnf->pClauses[0] + nLiterals; + + // create room for variable numbers + pCnf->pVarNums = ABC_ALLOC( int, Aig_ManObjNumMax(p) ); +// memset( pCnf->pVarNums, 0xff, sizeof(int) * Aig_ManObjNumMax(p) ); + for ( i = 0; i < Aig_ManObjNumMax(p); i++ ) + pCnf->pVarNums[i] = -1; + // 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; +} + +/**Function************************************************************* + + Synopsis [Derives a simple CNF for backward retiming computation.] + + 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_DeriveSimpleForRetiming( Aig_Man_t * p ) +{ + 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) + 5 * Aig_ManPoNum(p); + nClauses = 1 + 3 * Aig_ManNodeNum(p) + 3 * Aig_ManPoNum(p); + + // allocate CNF + pCnf = ABC_ALLOC( Cnf_Dat_t, 1 ); + memset( pCnf, 0, sizeof(Cnf_Dat_t) ); + pCnf->pMan = p; + pCnf->nLiterals = nLiterals; + pCnf->nClauses = nClauses; + pCnf->pClauses = ABC_ALLOC( int *, nClauses + 1 ); + pCnf->pClauses[0] = ABC_ALLOC( int, nLiterals ); + pCnf->pClauses[nClauses] = pCnf->pClauses[0] + nLiterals; + + // create room for variable numbers + pCnf->pVarNums = ABC_ALLOC( int, Aig_ManObjNumMax(p) ); +// memset( pCnf->pVarNums, 0xff, sizeof(int) * Aig_ManObjNumMax(p) ); + for ( i = 0; i < Aig_ManObjNumMax(p); i++ ) + pCnf->pVarNums[i] = -1; + // assign variables to the last (nOutputs) POs + Number = 1; + 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; + // 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 ]; + 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); + // final clause (init-state is always 0 -> set the output to 0) + *pClas++ = pLits; + *pLits++ = 2 * PoVar + 1; + } + + // 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 /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/sat/cnf/cnf_.c b/src/sat/cnf/cnf_.c new file mode 100644 index 00000000..acf75093 --- /dev/null +++ b/src/sat/cnf/cnf_.c @@ -0,0 +1,53 @@ +/**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" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/sat/cnf/module.make b/src/sat/cnf/module.make new file mode 100644 index 00000000..880e9662 --- /dev/null +++ b/src/sat/cnf/module.make @@ -0,0 +1,9 @@ +SRC += src/sat/cnf/cnfCore.c \ + src/sat/cnf/cnfCut.c \ + src/sat/cnf/cnfData.c \ + src/sat/cnf/cnfFast.c \ + src/sat/cnf/cnfMan.c \ + src/sat/cnf/cnfMap.c \ + src/sat/cnf/cnfPost.c \ + src/sat/cnf/cnfUtil.c \ + src/sat/cnf/cnfWrite.c diff --git a/src/sat/csat/csat_apis.c b/src/sat/csat/csat_apis.c index 78ed2601..582dc1e7 100644 --- a/src/sat/csat/csat_apis.c +++ b/src/sat/csat/csat_apis.c @@ -16,11 +16,11 @@ ***********************************************************************/ -#include "abc.h" -#include "fraig.h" +#include "src/base/abc/abc.h" +#include "src/proof/fraig/fraig.h" #include "csat_apis.h" -#include "stmm.h" -#include "main.h" +#include "src/misc/st/stmm.h" +#include "src/base/main/main.h" ABC_NAMESPACE_IMPL_START diff --git a/src/sat/csat/csat_apis.h b/src/sat/csat/csat_apis.h index a6c1b18a..476e8c2c 100644 --- a/src/sat/csat/csat_apis.h +++ b/src/sat/csat/csat_apis.h @@ -16,8 +16,8 @@ ***********************************************************************/ -#ifndef __ABC_APIS_H__ -#define __ABC_APIS_H__ +#ifndef ABC__sat__csat__csat_apis_h +#define ABC__sat__csat__csat_apis_h //////////////////////////////////////////////////////////////////////// diff --git a/src/sat/fraig/fraig.h b/src/sat/fraig/fraig.h deleted file mode 100644 index 2b499967..00000000 --- a/src/sat/fraig/fraig.h +++ /dev/null @@ -1,260 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraig.h] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [External declarations of the FRAIG package.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - October 1, 2004] - - Revision [$Id: fraig.h,v 1.18 2005/07/08 01:01:30 alanmi Exp $] - -***********************************************************************/ - -#ifndef __FRAIG_H__ -#define __FRAIG_H__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Fraig_ManStruct_t_ Fraig_Man_t; -typedef struct Fraig_NodeStruct_t_ Fraig_Node_t; -typedef struct Fraig_NodeVecStruct_t_ Fraig_NodeVec_t; -typedef struct Fraig_HashTableStruct_t_ Fraig_HashTable_t; -typedef struct Fraig_ParamsStruct_t_ Fraig_Params_t; -typedef struct Fraig_PatternsStruct_t_ Fraig_Patterns_t; -typedef struct Prove_ParamsStruct_t_ Prove_Params_t; - -struct Fraig_ParamsStruct_t_ -{ - int nPatsRand; // the number of words of random simulation info - int nPatsDyna; // the number of words of dynamic simulation info - int nBTLimit; // the max number of backtracks to perform - int nSeconds; // the timeout for the final proof - int fFuncRed; // performs only one level hashing - int fFeedBack; // enables solver feedback - int fDist1Pats; // enables distance-1 patterns - int fDoSparse; // performs equiv tests for sparse functions - int fChoicing; // enables recording structural choices - int fTryProve; // tries to solve the final miter - int fVerbose; // the verbosiness flag - int fVerboseP; // the verbosiness flag (for proof reporting) - int fInternal; // is set to 1 for internal fraig calls - int nConfLimit; // the limit on the number of conflicts - ABC_INT64_T 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 - ABC_INT64_T nTotalBacktrackLimit; // global limit on the number of backtracks - ABC_INT64_T nTotalInspectLimit; // global limit on the number of clause inspects - // global resources applied - ABC_INT64_T nTotalBacktracksMade; // the total number of backtracks made - ABC_INT64_T nTotalInspectsMade; // the total number of inspects made -}; - -//////////////////////////////////////////////////////////////////////// -/// GLOBAL VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -// macros working with complemented attributes of the nodes -#define Fraig_IsComplement(p) (((int)((ABC_PTRUINT_T) (p) & 01))) -#define Fraig_Regular(p) ((Fraig_Node_t *)((ABC_PTRUINT_T)(p) & ~01)) -#define Fraig_Not(p) ((Fraig_Node_t *)((ABC_PTRUINT_T)(p) ^ 01)) -#define Fraig_NotCond(p,c) ((Fraig_Node_t *)((ABC_PTRUINT_T)(p) ^ (c))) - -// these are currently not used -#define Fraig_Ref(p) -#define Fraig_Deref(p) -#define Fraig_RecursiveDeref(p,c) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== fraigApi.c =============================================================*/ -extern Fraig_NodeVec_t * Fraig_ManReadVecInputs( Fraig_Man_t * p ); -extern Fraig_NodeVec_t * Fraig_ManReadVecOutputs( Fraig_Man_t * p ); -extern Fraig_NodeVec_t * Fraig_ManReadVecNodes( Fraig_Man_t * p ); -extern Fraig_Node_t ** Fraig_ManReadInputs ( Fraig_Man_t * p ); -extern Fraig_Node_t ** Fraig_ManReadOutputs( Fraig_Man_t * p ); -extern Fraig_Node_t ** Fraig_ManReadNodes( Fraig_Man_t * p ); -extern int Fraig_ManReadInputNum ( Fraig_Man_t * p ); -extern int Fraig_ManReadOutputNum( Fraig_Man_t * p ); -extern int Fraig_ManReadNodeNum( Fraig_Man_t * p ); -extern Fraig_Node_t * Fraig_ManReadConst1 ( Fraig_Man_t * p ); -extern Fraig_Node_t * Fraig_ManReadIthVar( Fraig_Man_t * p, int i ); -extern Fraig_Node_t * Fraig_ManReadIthNode( Fraig_Man_t * p, int i ); -extern char ** Fraig_ManReadInputNames( Fraig_Man_t * p ); -extern char ** Fraig_ManReadOutputNames( Fraig_Man_t * p ); -extern char * Fraig_ManReadVarsInt( Fraig_Man_t * p ); -extern char * Fraig_ManReadSat( Fraig_Man_t * p ); -extern int Fraig_ManReadFuncRed( Fraig_Man_t * p ); -extern int Fraig_ManReadFeedBack( Fraig_Man_t * p ); -extern int Fraig_ManReadDoSparse( Fraig_Man_t * p ); -extern int Fraig_ManReadChoicing( Fraig_Man_t * p ); -extern int Fraig_ManReadVerbose( Fraig_Man_t * p ); -extern int * Fraig_ManReadModel( Fraig_Man_t * p ); -extern int Fraig_ManReadPatternNumRandom( Fraig_Man_t * p ); -extern int Fraig_ManReadPatternNumDynamic( Fraig_Man_t * p ); -extern int Fraig_ManReadPatternNumDynamicFiltered( Fraig_Man_t * p ); -extern int Fraig_ManReadSatFails( Fraig_Man_t * p ); -extern int Fraig_ManReadConflicts( Fraig_Man_t * p ); -extern int Fraig_ManReadInspects( Fraig_Man_t * p ); - -extern void Fraig_ManSetFuncRed( Fraig_Man_t * p, int fFuncRed ); -extern void Fraig_ManSetFeedBack( Fraig_Man_t * p, int fFeedBack ); -extern void Fraig_ManSetDoSparse( Fraig_Man_t * p, int fDoSparse ); -extern void Fraig_ManSetChoicing( Fraig_Man_t * p, int fChoicing ); -extern void Fraig_ManSetTryProve( Fraig_Man_t * p, int fTryProve ); -extern void Fraig_ManSetVerbose( Fraig_Man_t * p, int fVerbose ); -extern void Fraig_ManSetTimeToGraph( Fraig_Man_t * p, int Time ); -extern void Fraig_ManSetTimeToNet( Fraig_Man_t * p, int Time ); -extern void Fraig_ManSetTimeTotal( Fraig_Man_t * p, int Time ); -extern void Fraig_ManSetOutputNames( Fraig_Man_t * p, char ** ppNames ); -extern void Fraig_ManSetInputNames( Fraig_Man_t * p, char ** ppNames ); -extern void Fraig_ManSetPo( Fraig_Man_t * p, Fraig_Node_t * pNode ); - -extern Fraig_Node_t * Fraig_NodeReadData0( Fraig_Node_t * p ); -extern Fraig_Node_t * Fraig_NodeReadData1( Fraig_Node_t * p ); -extern int Fraig_NodeReadNum( Fraig_Node_t * p ); -extern Fraig_Node_t * Fraig_NodeReadOne( Fraig_Node_t * p ); -extern Fraig_Node_t * Fraig_NodeReadTwo( Fraig_Node_t * p ); -extern Fraig_Node_t * Fraig_NodeReadNextE( Fraig_Node_t * p ); -extern Fraig_Node_t * Fraig_NodeReadRepr( Fraig_Node_t * p ); -extern int Fraig_NodeReadNumRefs( Fraig_Node_t * p ); -extern int Fraig_NodeReadNumFanouts( Fraig_Node_t * p ); -extern int Fraig_NodeReadSimInv( Fraig_Node_t * p ); -extern int Fraig_NodeReadNumOnes( Fraig_Node_t * p ); -extern unsigned * Fraig_NodeReadPatternsRandom( Fraig_Node_t * p ); -extern unsigned * Fraig_NodeReadPatternsDynamic( Fraig_Node_t * p ); - -extern void Fraig_NodeSetData0( Fraig_Node_t * p, Fraig_Node_t * pData ); -extern void Fraig_NodeSetData1( Fraig_Node_t * p, Fraig_Node_t * pData ); - -extern int Fraig_NodeIsConst( Fraig_Node_t * p ); -extern int Fraig_NodeIsVar( Fraig_Node_t * p ); -extern int Fraig_NodeIsAnd( Fraig_Node_t * p ); -extern int Fraig_NodeComparePhase( Fraig_Node_t * p1, Fraig_Node_t * p2 ); - -extern Fraig_Node_t * Fraig_NodeOr( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ); -extern Fraig_Node_t * Fraig_NodeAnd( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ); -extern Fraig_Node_t * Fraig_NodeOr( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ); -extern Fraig_Node_t * Fraig_NodeExor( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ); -extern Fraig_Node_t * Fraig_NodeMux( Fraig_Man_t * p, Fraig_Node_t * pNode, Fraig_Node_t * pNodeT, Fraig_Node_t * pNodeE ); -extern void Fraig_NodeSetChoice( Fraig_Man_t * pMan, Fraig_Node_t * pNodeOld, Fraig_Node_t * pNodeNew ); - -/*=== fraigMan.c =============================================================*/ -extern void Prove_ParamsSetDefault( Prove_Params_t * pParams ); -extern void Fraig_ParamsSetDefault( Fraig_Params_t * pParams ); -extern void Fraig_ParamsSetDefaultFull( Fraig_Params_t * pParams ); -extern Fraig_Man_t * Fraig_ManCreate( Fraig_Params_t * pParams ); -extern void Fraig_ManFree( Fraig_Man_t * pMan ); -extern void Fraig_ManPrintStats( Fraig_Man_t * p ); -extern Fraig_NodeVec_t * Fraig_ManGetSimInfo( Fraig_Man_t * p ); -extern int Fraig_ManCheckClauseUsingSimInfo( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2 ); -extern void Fraig_ManAddClause( Fraig_Man_t * p, Fraig_Node_t ** ppNodes, int nNodes ); - -/*=== fraigDfs.c =============================================================*/ -extern Fraig_NodeVec_t * Fraig_Dfs( Fraig_Man_t * pMan, int fEquiv ); -extern Fraig_NodeVec_t * Fraig_DfsOne( Fraig_Man_t * pMan, Fraig_Node_t * pNode, int fEquiv ); -extern Fraig_NodeVec_t * Fraig_DfsNodes( Fraig_Man_t * pMan, Fraig_Node_t ** ppNodes, int nNodes, int fEquiv ); -extern Fraig_NodeVec_t * Fraig_DfsReverse( Fraig_Man_t * pMan ); -extern int Fraig_CountNodes( Fraig_Man_t * pMan, int fEquiv ); -extern int Fraig_CheckTfi( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); -extern int Fraig_CountLevels( Fraig_Man_t * pMan ); - -/*=== fraigSat.c =============================================================*/ -extern int Fraig_NodesAreEqual( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit, int nTimeLimit ); -extern int Fraig_NodeIsEquivalent( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit, int nTimeLimit ); -extern void Fraig_ManProveMiter( Fraig_Man_t * p ); -extern int Fraig_ManCheckMiter( Fraig_Man_t * p ); -extern int Fraig_ManCheckClauseUsingSat( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit ); - -/*=== fraigVec.c ===============================================================*/ -extern Fraig_NodeVec_t * Fraig_NodeVecAlloc( int nCap ); -extern void Fraig_NodeVecFree( Fraig_NodeVec_t * p ); -extern Fraig_NodeVec_t * Fraig_NodeVecDup( Fraig_NodeVec_t * p ); -extern Fraig_Node_t ** Fraig_NodeVecReadArray( Fraig_NodeVec_t * p ); -extern int Fraig_NodeVecReadSize( Fraig_NodeVec_t * p ); -extern void Fraig_NodeVecGrow( Fraig_NodeVec_t * p, int nCapMin ); -extern void Fraig_NodeVecShrink( Fraig_NodeVec_t * p, int nSizeNew ); -extern void Fraig_NodeVecClear( Fraig_NodeVec_t * p ); -extern void Fraig_NodeVecPush( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ); -extern int Fraig_NodeVecPushUnique( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ); -extern void Fraig_NodeVecPushOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ); -extern int Fraig_NodeVecPushUniqueOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ); -extern void Fraig_NodeVecPushOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ); -extern int Fraig_NodeVecPushUniqueOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ); -extern Fraig_Node_t * Fraig_NodeVecPop( Fraig_NodeVec_t * p ); -extern void Fraig_NodeVecRemove( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ); -extern void Fraig_NodeVecWriteEntry( Fraig_NodeVec_t * p, int i, Fraig_Node_t * Entry ); -extern Fraig_Node_t * Fraig_NodeVecReadEntry( Fraig_NodeVec_t * p, int i ); -extern void Fraig_NodeVecSortByLevel( Fraig_NodeVec_t * p, int fIncreasing ); -extern void Fraig_NodeVecSortByNumber( Fraig_NodeVec_t * p ); - -/*=== fraigUtil.c ===============================================================*/ -extern void Fraig_ManMarkRealFanouts( Fraig_Man_t * p ); -extern int Fraig_ManCheckConsistency( Fraig_Man_t * p ); -extern int Fraig_GetMaxLevel( Fraig_Man_t * pMan ); -extern void Fraig_ManReportChoices( Fraig_Man_t * pMan ); -extern void Fraig_MappingSetChoiceLevels( Fraig_Man_t * pMan, int fMaximum ); -extern Fraig_NodeVec_t * Fraig_CollectSupergate( Fraig_Node_t * pNode, int fStopAtMux ); - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_END - - - -#endif diff --git a/src/sat/fraig/fraigApi.c b/src/sat/fraig/fraigApi.c deleted file mode 100644 index 6e0ab959..00000000 --- a/src/sat/fraig/fraigApi.c +++ /dev/null @@ -1,302 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraigApi.c] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [Access APIs for the FRAIG manager and node.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - October 1, 2004] - - Revision [$Id: fraigApi.c,v 1.2 2005/07/08 01:01:30 alanmi Exp $] - -***********************************************************************/ - -#include "fraigInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Access functions to read the data members of the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_NodeVec_t * Fraig_ManReadVecInputs( Fraig_Man_t * p ) { return p->vInputs; } -Fraig_NodeVec_t * Fraig_ManReadVecOutputs( Fraig_Man_t * p ) { return p->vOutputs; } -Fraig_NodeVec_t * Fraig_ManReadVecNodes( Fraig_Man_t * p ) { return p->vNodes; } -Fraig_Node_t ** Fraig_ManReadInputs ( Fraig_Man_t * p ) { return p->vInputs->pArray; } -Fraig_Node_t ** Fraig_ManReadOutputs( Fraig_Man_t * p ) { return p->vOutputs->pArray; } -Fraig_Node_t ** Fraig_ManReadNodes( Fraig_Man_t * p ) { return p->vNodes->pArray; } -int Fraig_ManReadInputNum ( Fraig_Man_t * p ) { return p->vInputs->nSize; } -int Fraig_ManReadOutputNum( Fraig_Man_t * p ) { return p->vOutputs->nSize; } -int Fraig_ManReadNodeNum( Fraig_Man_t * p ) { return p->vNodes->nSize; } -Fraig_Node_t * Fraig_ManReadConst1 ( Fraig_Man_t * p ) { return p->pConst1; } -Fraig_Node_t * Fraig_ManReadIthNode( Fraig_Man_t * p, int i ) { assert ( i < p->vNodes->nSize ); return p->vNodes->pArray[i]; } -char ** Fraig_ManReadInputNames( Fraig_Man_t * p ) { return p->ppInputNames; } -char ** Fraig_ManReadOutputNames( Fraig_Man_t * p ) { return p->ppOutputNames; } -char * Fraig_ManReadVarsInt( Fraig_Man_t * p ) { return (char *)p->vVarsInt; } -char * Fraig_ManReadSat( Fraig_Man_t * p ) { return (char *)p->pSat; } -int Fraig_ManReadFuncRed( Fraig_Man_t * p ) { return p->fFuncRed; } -int Fraig_ManReadFeedBack( Fraig_Man_t * p ) { return p->fFeedBack; } -int Fraig_ManReadDoSparse( Fraig_Man_t * p ) { return p->fDoSparse; } -int Fraig_ManReadChoicing( Fraig_Man_t * p ) { return p->fChoicing; } -int Fraig_ManReadVerbose( Fraig_Man_t * p ) { return p->fVerbose; } -int * Fraig_ManReadModel( Fraig_Man_t * p ) { return p->pModel; } -// returns the number of patterns used for random simulation (this number is fixed for the FRAIG run) -int Fraig_ManReadPatternNumRandom( Fraig_Man_t * p ) { return p->nWordsRand * 32; } -// returns the number of dynamic patterns accumulated at runtime (include SAT solver counter-examples and distance-1 patterns derived from them) -int Fraig_ManReadPatternNumDynamic( Fraig_Man_t * p ) { return p->iWordStart * 32; } -// returns the number of dynamic patterns proved useful to distinquish some FRAIG nodes (this number is more than 0 after the first garbage collection of patterns) -int Fraig_ManReadPatternNumDynamicFiltered( Fraig_Man_t * p ) { return p->iPatsPerm; } -// returns the number of times FRAIG package timed out -int Fraig_ManReadSatFails( Fraig_Man_t * p ) { return p->nSatFailsReal; } -// returns the number of conflicts in the SAT solver -int Fraig_ManReadConflicts( Fraig_Man_t * p ) { return p->pSat? Msat_SolverReadBackTracks(p->pSat) : 0; } -// returns the number of inspections in the SAT solver -int Fraig_ManReadInspects( Fraig_Man_t * p ) { return p->pSat? Msat_SolverReadInspects(p->pSat) : 0; } - -/**Function************************************************************* - - Synopsis [Access functions to set the data members of the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_ManSetFuncRed( Fraig_Man_t * p, int fFuncRed ) { p->fFuncRed = fFuncRed; } -void Fraig_ManSetFeedBack( Fraig_Man_t * p, int fFeedBack ) { p->fFeedBack = fFeedBack; } -void Fraig_ManSetDoSparse( Fraig_Man_t * p, int fDoSparse ) { p->fDoSparse = fDoSparse; } -void Fraig_ManSetChoicing( Fraig_Man_t * p, int fChoicing ) { p->fChoicing = fChoicing; } -void Fraig_ManSetTryProve( Fraig_Man_t * p, int fTryProve ) { p->fTryProve = fTryProve; } -void Fraig_ManSetVerbose( Fraig_Man_t * p, int fVerbose ) { p->fVerbose = fVerbose; } -void Fraig_ManSetTimeToGraph( Fraig_Man_t * p, int Time ) { p->timeToAig = Time; } -void Fraig_ManSetTimeToNet( Fraig_Man_t * p, int Time ) { p->timeToNet = Time; } -void Fraig_ManSetTimeTotal( Fraig_Man_t * p, int Time ) { p->timeTotal = Time; } -void Fraig_ManSetOutputNames( Fraig_Man_t * p, char ** ppNames ) { p->ppOutputNames = ppNames; } -void Fraig_ManSetInputNames( Fraig_Man_t * p, char ** ppNames ) { p->ppInputNames = ppNames; } - -/**Function************************************************************* - - Synopsis [Access functions to read the data members of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_NodeReadData0( Fraig_Node_t * p ) { return p->pData0; } -Fraig_Node_t * Fraig_NodeReadData1( Fraig_Node_t * p ) { return p->pData1; } -int Fraig_NodeReadNum( Fraig_Node_t * p ) { return p->Num; } -Fraig_Node_t * Fraig_NodeReadOne( Fraig_Node_t * p ) { assert (!Fraig_IsComplement(p)); return p->p1; } -Fraig_Node_t * Fraig_NodeReadTwo( Fraig_Node_t * p ) { assert (!Fraig_IsComplement(p)); return p->p2; } -Fraig_Node_t * Fraig_NodeReadNextE( Fraig_Node_t * p ) { return p->pNextE; } -Fraig_Node_t * Fraig_NodeReadRepr( Fraig_Node_t * p ) { return p->pRepr; } -int Fraig_NodeReadNumRefs( Fraig_Node_t * p ) { return p->nRefs; } -int Fraig_NodeReadNumFanouts( Fraig_Node_t * p ) { return p->nFanouts; } -int Fraig_NodeReadSimInv( Fraig_Node_t * p ) { return p->fInv; } -int Fraig_NodeReadNumOnes( Fraig_Node_t * p ) { return p->nOnes; } -// returns the pointer to the random simulation patterns (their number is returned by Fraig_ManReadPatternNumRandom) -// memory pointed to by this and the following procedure is maintained by the FRAIG package and exists as long as the package runs -unsigned * Fraig_NodeReadPatternsRandom( Fraig_Node_t * p ) { return p->puSimR; } -// returns the pointer to the dynamic simulation patterns (their number is returned by Fraig_ManReadPatternNumDynamic or Fraig_ManReadPatternNumDynamicFiltered) -// if the number of patterns is not evenly divisible by 32, the patterns beyond the given number contain garbage -unsigned * Fraig_NodeReadPatternsDynamic( Fraig_Node_t * p ) { return p->puSimD; } - -/**Function************************************************************* - - Synopsis [Access functions to set the data members of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeSetData0( Fraig_Node_t * p, Fraig_Node_t * pData ) { p->pData0 = pData; } -void Fraig_NodeSetData1( Fraig_Node_t * p, Fraig_Node_t * pData ) { p->pData1 = pData; } - -/**Function************************************************************* - - Synopsis [Checks the type of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeIsConst( Fraig_Node_t * p ) { return (Fraig_Regular(p))->Num == 0; } -int Fraig_NodeIsVar( Fraig_Node_t * p ) { return (Fraig_Regular(p))->NumPi >= 0; } -int Fraig_NodeIsAnd( Fraig_Node_t * p ) { return (Fraig_Regular(p))->NumPi < 0 && (Fraig_Regular(p))->Num > 0; } -int Fraig_NodeComparePhase( Fraig_Node_t * p1, Fraig_Node_t * p2 ) { assert( !Fraig_IsComplement(p1) ); assert( !Fraig_IsComplement(p2) ); return p1->fInv ^ p2->fInv; } - -/**Function************************************************************* - - Synopsis [Returns a new primary input node.] - - Description [If the node with this number does not exist, - create a new PI node with this number.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_ManReadIthVar( Fraig_Man_t * p, int i ) -{ - int k; - if ( i < 0 ) - { - printf( "Requesting a PI with a negative number\n" ); - return NULL; - } - // create the PIs to fill in the interval - if ( i >= p->vInputs->nSize ) - for ( k = p->vInputs->nSize; k <= i; k++ ) - Fraig_NodeCreatePi( p ); - return p->vInputs->pArray[i]; -} - -/**Function************************************************************* - - Synopsis [Creates a new PO node.] - - Description [This procedure may take a complemented node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_ManSetPo( Fraig_Man_t * p, Fraig_Node_t * pNode ) -{ - // internal node may be a PO two times - Fraig_Regular(pNode)->fNodePo = 1; - Fraig_NodeVecPush( p->vOutputs, pNode ); -} - -/**Function************************************************************* - - Synopsis [Perfoms the AND operation with functional hashing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_NodeAnd( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ) -{ - return Fraig_NodeAndCanon( p, p1, p2 ); -} - -/**Function************************************************************* - - Synopsis [Perfoms the OR operation with functional hashing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_NodeOr( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ) -{ - return Fraig_Not( Fraig_NodeAndCanon( p, Fraig_Not(p1), Fraig_Not(p2) ) ); -} - -/**Function************************************************************* - - Synopsis [Perfoms the EXOR operation with functional hashing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_NodeExor( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ) -{ - return Fraig_NodeMux( p, p1, Fraig_Not(p2), p2 ); -} - -/**Function************************************************************* - - Synopsis [Perfoms the MUX operation with functional hashing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_NodeMux( Fraig_Man_t * p, Fraig_Node_t * pC, Fraig_Node_t * pT, Fraig_Node_t * pE ) -{ - Fraig_Node_t * pAnd1, * pAnd2, * pRes; - pAnd1 = Fraig_NodeAndCanon( p, pC, pT ); Fraig_Ref( pAnd1 ); - pAnd2 = Fraig_NodeAndCanon( p, Fraig_Not(pC), pE ); Fraig_Ref( pAnd2 ); - pRes = Fraig_NodeOr( p, pAnd1, pAnd2 ); - Fraig_RecursiveDeref( p, pAnd1 ); - Fraig_RecursiveDeref( p, pAnd2 ); - Fraig_Deref( pRes ); - return pRes; -} - - -/**Function************************************************************* - - Synopsis [Sets the node to be equivalent to the given one.] - - Description [This procedure is a work-around for the equivalence check. - Does not verify the equivalence. Use at the user's risk.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeSetChoice( Fraig_Man_t * pMan, Fraig_Node_t * pNodeOld, Fraig_Node_t * pNodeNew ) -{ -// assert( pMan->fChoicing ); - pNodeNew->pNextE = pNodeOld->pNextE; - pNodeOld->pNextE = pNodeNew; - pNodeNew->pRepr = pNodeOld; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/sat/fraig/fraigCanon.c b/src/sat/fraig/fraigCanon.c deleted file mode 100644 index 47539db2..00000000 --- a/src/sat/fraig/fraigCanon.c +++ /dev/null @@ -1,223 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraigCanon.c] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [AND-node creation and elementary AND-operation.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - October 1, 2004] - - Revision [$Id: fraigCanon.c,v 1.4 2005/07/08 01:01:31 alanmi Exp $] - -***********************************************************************/ - -#include -#include "fraigInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [The internal AND operation for the two FRAIG nodes.] - - Description [This procedure is the core of the FRAIG package, because - it performs the two-step canonicization of FRAIG nodes. The first step - involves the lookup in the structural hash table (which hashes two ANDs - into a node that has them as fanins, if such a node exists). If the node - is not found in the structural hash table, an attempt is made to find a - functionally equivalent node in another hash table (which hashes the - simulation info into the nodes, which has this simulation info). Some - tricks used on the way are described in the comments to the code and - in the paper "FRAIGs: Functionally reduced AND-INV graphs".] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_NodeAndCanon( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2 ) -{ - Fraig_Node_t * pNodeNew, * pNodeOld, * pNodeRepr; - int fUseSatCheck; -// int RetValue; - - // check for trivial cases - if ( p1 == p2 ) - return p1; - if ( p1 == Fraig_Not(p2) ) - return Fraig_Not(pMan->pConst1); - if ( Fraig_NodeIsConst(p1) ) - { - if ( p1 == pMan->pConst1 ) - return p2; - return Fraig_Not(pMan->pConst1); - } - if ( Fraig_NodeIsConst(p2) ) - { - if ( p2 == pMan->pConst1 ) - return p1; - return Fraig_Not(pMan->pConst1); - } -/* - // check for less trivial cases - if ( Fraig_IsComplement(p1) ) - { - if ( RetValue = Fraig_NodeIsInSupergate( Fraig_Regular(p1), p2 ) ) - { - if ( RetValue == -1 ) - pMan->nImplies0++; - else - pMan->nImplies1++; - - if ( RetValue == -1 ) - return p2; - } - } - else - { - if ( RetValue = Fraig_NodeIsInSupergate( p1, p2 ) ) - { - if ( RetValue == 1 ) - pMan->nSimplifies1++; - else - pMan->nSimplifies0++; - - if ( RetValue == 1 ) - return p1; - return Fraig_Not(pMan->pConst1); - } - } - - if ( Fraig_IsComplement(p2) ) - { - if ( RetValue = Fraig_NodeIsInSupergate( Fraig_Regular(p2), p1 ) ) - { - if ( RetValue == -1 ) - pMan->nImplies0++; - else - pMan->nImplies1++; - - if ( RetValue == -1 ) - return p1; - } - } - else - { - if ( RetValue = Fraig_NodeIsInSupergate( p2, p1 ) ) - { - if ( RetValue == 1 ) - pMan->nSimplifies1++; - else - pMan->nSimplifies0++; - - if ( RetValue == 1 ) - return p2; - return Fraig_Not(pMan->pConst1); - } - } -*/ - // perform level-one structural hashing - if ( Fraig_HashTableLookupS( pMan, p1, p2, &pNodeNew ) ) // the node with these children is found - { - // if the existent node is part of the cone of unused logic - // (that is logic feeding the node which is equivalent to the given node) - // return the canonical representative of this node - // determine the phase of the given node, with respect to its canonical form - pNodeRepr = Fraig_Regular(pNodeNew)->pRepr; - if ( pMan->fFuncRed && pNodeRepr ) - return Fraig_NotCond( pNodeRepr, Fraig_IsComplement(pNodeNew) ^ Fraig_NodeComparePhase(Fraig_Regular(pNodeNew), pNodeRepr) ); - // otherwise, the node is itself a canonical representative, return it - return pNodeNew; - } - // the same node is not found, but the new one is created - - // if one level hashing is requested (without functionality hashing), return - if ( !pMan->fFuncRed ) - return pNodeNew; - - // check if the new node is unique using the simulation info - if ( pNodeNew->nOnes == 0 || pNodeNew->nOnes == (unsigned)pMan->nWordsRand * 32 ) - { - pMan->nSatZeros++; - if ( !pMan->fDoSparse ) // if we do not do sparse functions, skip - return pNodeNew; - // check the sparse function simulation hash table - pNodeOld = Fraig_HashTableLookupF0( pMan, pNodeNew ); - if ( pNodeOld == NULL ) // the node is unique (it is added to the table) - return pNodeNew; - } - else - { - // check the simulation hash table - pNodeOld = Fraig_HashTableLookupF( pMan, pNodeNew ); - if ( pNodeOld == NULL ) // the node is unique - return pNodeNew; - } - assert( pNodeOld->pRepr == 0 ); - // there is another node which looks the same according to simulation - - // use SAT to resolve the ambiguity - fUseSatCheck = (pMan->nInspLimit == 0 || Fraig_ManReadInspects(pMan) < pMan->nInspLimit); - if ( fUseSatCheck && Fraig_NodeIsEquivalent( pMan, pNodeOld, pNodeNew, pMan->nBTLimit, 1000000 ) ) - { - // set the node to be equivalent with this node - // to prevent loops, only set if the old node is not in the TFI of the new node - // the loop may happen in the following case: suppose - // NodeC = AND(NodeA, NodeB) and at the same time NodeA => NodeB - // in this case, NodeA and NodeC are functionally equivalent - // however, NodeA is a fanin of node NodeC (this leads to the loop) - // add the node to the list of equivalent nodes or dereference it - if ( pMan->fChoicing && !Fraig_CheckTfi( pMan, pNodeOld, pNodeNew ) ) - { - // if the old node is not in the TFI of the new node and choicing - // is enabled, add the new node to the list of equivalent ones - pNodeNew->pNextE = pNodeOld->pNextE; - pNodeOld->pNextE = pNodeNew; - } - // set the canonical representative of this node - pNodeNew->pRepr = pNodeOld; - // return the equivalent node - return Fraig_NotCond( pNodeOld, Fraig_NodeComparePhase(pNodeOld, pNodeNew) ); - } - - // now we add another member to this simulation class - if ( pNodeNew->nOnes == 0 || pNodeNew->nOnes == (unsigned)pMan->nWordsRand * 32 ) - { - Fraig_Node_t * pNodeTemp; - assert( pMan->fDoSparse ); - pNodeTemp = Fraig_HashTableLookupF0( pMan, pNodeNew ); -// assert( pNodeTemp == NULL ); -// Fraig_HashTableInsertF0( pMan, pNodeNew ); - } - else - { - pNodeNew->pNextD = pNodeOld->pNextD; - pNodeOld->pNextD = pNodeNew; - } - // return the new node - assert( pNodeNew->pRepr == 0 ); - return pNodeNew; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/sat/fraig/fraigChoice.c b/src/sat/fraig/fraigChoice.c deleted file mode 100644 index 21d4fe10..00000000 --- a/src/sat/fraig/fraigChoice.c +++ /dev/null @@ -1,246 +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" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// 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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/sat/fraig/fraigFanout.c b/src/sat/fraig/fraigFanout.c deleted file mode 100644 index 0e6c86f8..00000000 --- a/src/sat/fraig/fraigFanout.c +++ /dev/null @@ -1,180 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraigFanout.c] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [Procedures to manipulate fanouts of the FRAIG nodes.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - October 1, 2004] - - Revision [$Id: fraigFanout.c,v 1.5 2005/07/08 01:01:31 alanmi Exp $] - -***********************************************************************/ - -#include "fraigInt.h" - -ABC_NAMESPACE_IMPL_START - - -#ifdef FRAIG_ENABLE_FANOUTS - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Add the fanout to the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeAddFaninFanout( Fraig_Node_t * pFanin, Fraig_Node_t * pFanout ) -{ - Fraig_Node_t * pPivot; - - // pFanins is a fanin of pFanout - assert( !Fraig_IsComplement(pFanin) ); - assert( !Fraig_IsComplement(pFanout) ); - assert( Fraig_Regular(pFanout->p1) == pFanin || Fraig_Regular(pFanout->p2) == pFanin ); - - pPivot = pFanin->pFanPivot; - if ( pPivot == NULL ) - { - pFanin->pFanPivot = pFanout; - return; - } - - if ( Fraig_Regular(pPivot->p1) == pFanin ) - { - if ( Fraig_Regular(pFanout->p1) == pFanin ) - { - pFanout->pFanFanin1 = pPivot->pFanFanin1; - pPivot->pFanFanin1 = pFanout; - } - else // if ( Fraig_Regular(pFanout->p2) == pFanin ) - { - pFanout->pFanFanin2 = pPivot->pFanFanin1; - pPivot->pFanFanin1 = pFanout; - } - } - else // if ( Fraig_Regular(pPivot->p2) == pFanin ) - { - assert( Fraig_Regular(pPivot->p2) == pFanin ); - if ( Fraig_Regular(pFanout->p1) == pFanin ) - { - pFanout->pFanFanin1 = pPivot->pFanFanin2; - pPivot->pFanFanin2 = pFanout; - } - else // if ( Fraig_Regular(pFanout->p2) == pFanin ) - { - pFanout->pFanFanin2 = pPivot->pFanFanin2; - pPivot->pFanFanin2 = pFanout; - } - } -} - -/**Function************************************************************* - - Synopsis [Add the fanout to the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeRemoveFaninFanout( Fraig_Node_t * pFanin, Fraig_Node_t * pFanoutToRemove ) -{ - Fraig_Node_t * pFanout, * pFanout2, ** ppFanList; - // start the linked list of fanouts - ppFanList = &pFanin->pFanPivot; - // go through the fanouts - Fraig_NodeForEachFanoutSafe( pFanin, pFanout, pFanout2 ) - { - // skip the fanout-to-remove - if ( pFanout == pFanoutToRemove ) - continue; - // add useful fanouts to the list - *ppFanList = pFanout; - ppFanList = Fraig_NodeReadNextFanoutPlace( pFanin, pFanout ); - } - *ppFanList = NULL; -} - -/**Function************************************************************* - - Synopsis [Transfers fanout to a different node.] - - Description [Assumes that the other node currently has no fanouts.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeTransferFanout( Fraig_Node_t * pNodeFrom, Fraig_Node_t * pNodeTo ) -{ - Fraig_Node_t * pFanout; - assert( pNodeTo->pFanPivot == NULL ); - assert( pNodeTo->pFanFanin1 == NULL ); - assert( pNodeTo->pFanFanin2 == NULL ); - // go through the fanouts and update their fanins - Fraig_NodeForEachFanout( pNodeFrom, pFanout ) - { - if ( Fraig_Regular(pFanout->p1) == pNodeFrom ) - pFanout->p1 = Fraig_NotCond( pNodeTo, Fraig_IsComplement(pFanout->p1) ); - else if ( Fraig_Regular(pFanout->p2) == pNodeFrom ) - pFanout->p2 = Fraig_NotCond( pNodeTo, Fraig_IsComplement(pFanout->p2) ); - } - // move the pointers - pNodeTo->pFanPivot = pNodeFrom->pFanPivot; - pNodeTo->pFanFanin1 = pNodeFrom->pFanFanin1; - pNodeTo->pFanFanin2 = pNodeFrom->pFanFanin2; - pNodeFrom->pFanPivot = NULL; - pNodeFrom->pFanFanin1 = NULL; - pNodeFrom->pFanFanin2 = NULL; -} - -/**Function************************************************************* - - Synopsis [Returns the number of fanouts of a node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeGetFanoutNum( Fraig_Node_t * pNode ) -{ - Fraig_Node_t * pFanout; - int Counter = 0; - Fraig_NodeForEachFanout( pNode, pFanout ) - Counter++; - return Counter; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - -#endif - -ABC_NAMESPACE_IMPL_END - diff --git a/src/sat/fraig/fraigFeed.c b/src/sat/fraig/fraigFeed.c deleted file mode 100644 index 47f946e1..00000000 --- a/src/sat/fraig/fraigFeed.c +++ /dev/null @@ -1,913 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraigFeed.c] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [Procedures to support the solver feedback.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - October 1, 2004] - - Revision [$Id: fraigFeed.c,v 1.8 2005/07/08 01:01:31 alanmi Exp $] - -***********************************************************************/ - -#include "fraigInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Fraig_FeedBackPrepare( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars ); -static int Fraig_FeedBackInsert( Fraig_Man_t * p, int nVarsPi ); -static void Fraig_FeedBackVerify( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); - -static void Fraig_FeedBackCovering( Fraig_Man_t * p, Msat_IntVec_t * vPats ); -static Fraig_NodeVec_t * Fraig_FeedBackCoveringStart( Fraig_Man_t * pMan ); -static int Fraig_GetSmallestColumn( int * pHits, int nHits ); -static int Fraig_GetHittingPattern( unsigned * pSims, int nWords ); -static void Fraig_CancelCoveredColumns( Fraig_NodeVec_t * vColumns, int * pHits, int iPat ); -static void Fraig_FeedBackCheckTable( Fraig_Man_t * p ); -static void Fraig_FeedBackCheckTableF0( Fraig_Man_t * p ); -static void Fraig_ReallocateSimulationInfo( Fraig_Man_t * p ); - - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Initializes the feedback information.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_FeedBackInit( Fraig_Man_t * p ) -{ - p->vCones = Fraig_NodeVecAlloc( 500 ); - p->vPatsReal = Msat_IntVecAlloc( 1000 ); - p->pSimsReal = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); - memset( p->pSimsReal, 0, sizeof(unsigned) * p->nWordsDyna ); - p->pSimsTemp = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); - p->pSimsDiff = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); -} - -/**Function************************************************************* - - Synopsis [Processes the feedback from teh solver.] - - Description [Array pModel gives the value of each variable in the SAT - solver. Array vVars is the array of integer numbers of variables - involves in this conflict.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_FeedBack( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) -{ - int nVarsPi, nWords; - int i, clk = clock(); - - // get the number of PI vars in the feedback (also sets the PI values) - nVarsPi = Fraig_FeedBackPrepare( p, pModel, vVars ); - - // set the PI values - nWords = Fraig_FeedBackInsert( p, nVarsPi ); - assert( p->iWordStart + nWords <= p->nWordsDyna ); - - // resimulates the words from p->iWordStart to iWordStop - for ( i = 1; i < p->vNodes->nSize; i++ ) - if ( Fraig_NodeIsAnd(p->vNodes->pArray[i]) ) - Fraig_NodeSimulate( p->vNodes->pArray[i], p->iWordStart, p->iWordStart + nWords, 0 ); - - if ( p->fDoSparse ) - Fraig_TableRehashF0( p, 0 ); - - if ( !p->fChoicing ) - Fraig_FeedBackVerify( p, pOld, pNew ); - - // if there is no room left, compress the patterns - if ( p->iWordStart + nWords == p->nWordsDyna ) - p->iWordStart = Fraig_FeedBackCompress( p ); - else // otherwise, update the starting word - p->iWordStart += nWords; - -p->timeFeed += clock() - clk; -} - -/**Function************************************************************* - - Synopsis [Get the number and values of the PI variables.] - - Description [Returns the number of PI variables involved in this feedback. - Fills in the internal presence and value data for the primary inputs.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_FeedBackPrepare( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars ) -{ - Fraig_Node_t * pNode; - int i, nVars, nVarsPis, * pVars; - - // clean the presence flag for all PIs - for ( i = 0; i < p->vInputs->nSize; i++ ) - { - pNode = p->vInputs->pArray[i]; - pNode->fFeedUse = 0; - } - - // get the variables involved in the feedback - nVars = Msat_IntVecReadSize(vVars); - pVars = Msat_IntVecReadArray(vVars); - - // set the values for the present variables - nVarsPis = 0; - for ( i = 0; i < nVars; i++ ) - { - pNode = p->vNodes->pArray[ pVars[i] ]; - if ( !Fraig_NodeIsVar(pNode) ) - continue; - // set its value - pNode->fFeedUse = 1; - pNode->fFeedVal = !MSAT_LITSIGN(pModel[pVars[i]]); - nVarsPis++; - } - return nVarsPis; -} - -/**Function************************************************************* - - Synopsis [Inserts the new simulation patterns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_FeedBackInsert( Fraig_Man_t * p, int nVarsPi ) -{ - Fraig_Node_t * pNode; - int nWords, iPatFlip, nPatFlipLimit, i, w; - int fUseNoPats = 0; - int fUse2Pats = 0; - - // get the number of words - if ( fUse2Pats ) - nWords = FRAIG_NUM_WORDS( 2 * nVarsPi + 1 ); - else if ( fUseNoPats ) - nWords = 1; - else - nWords = FRAIG_NUM_WORDS( nVarsPi + 1 ); - // update the number of words if they do not fit into the simulation info - if ( nWords > p->nWordsDyna - p->iWordStart ) - nWords = p->nWordsDyna - p->iWordStart; - // determine the bound on the flipping bit - nPatFlipLimit = nWords * 32 - 2; - - // mark the real pattern - Msat_IntVecPush( p->vPatsReal, p->iWordStart * 32 ); - // record the real pattern - Fraig_BitStringSetBit( p->pSimsReal, p->iWordStart * 32 ); - - // set the values at the PIs - iPatFlip = 1; - for ( i = 0; i < p->vInputs->nSize; i++ ) - { - pNode = p->vInputs->pArray[i]; - for ( w = p->iWordStart; w < p->iWordStart + nWords; w++ ) - if ( !pNode->fFeedUse ) - pNode->puSimD[w] = FRAIG_RANDOM_UNSIGNED; - else if ( pNode->fFeedVal ) - pNode->puSimD[w] = FRAIG_FULL; - else // if ( !pNode->fFeedVal ) - pNode->puSimD[w] = 0; - - if ( fUse2Pats ) - { - // flip two patterns - if ( pNode->fFeedUse && 2 * iPatFlip < nPatFlipLimit ) - { - Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, 2 * iPatFlip - 1 ); - Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, 2 * iPatFlip ); - Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, 2 * iPatFlip + 1 ); - iPatFlip++; - } - } - else if ( fUseNoPats ) - { - } - else - { - // flip the diagonal - if ( pNode->fFeedUse && iPatFlip < nPatFlipLimit ) - { - Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, iPatFlip ); - iPatFlip++; - // Extra_PrintBinary( stdout, &pNode->puSimD, 45 ); printf( "\n" ); - } - } - // clean the use mask - pNode->fFeedUse = 0; - - // add the info to the D hash value of the PIs - for ( w = p->iWordStart; w < p->iWordStart + nWords; w++ ) - pNode->uHashD ^= pNode->puSimD[w] * s_FraigPrimes[w]; - - } - return nWords; -} - - -/**Function************************************************************* - - Synopsis [Checks that the SAT solver pattern indeed distinquishes the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_FeedBackVerify( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) -{ - int fValue1, fValue2, iPat; - iPat = Msat_IntVecReadEntry( p->vPatsReal, Msat_IntVecReadSize(p->vPatsReal)-1 ); - fValue1 = (Fraig_BitStringHasBit( pOld->puSimD, iPat )); - fValue2 = (Fraig_BitStringHasBit( pNew->puSimD, iPat )); -/* -Fraig_PrintNode( p, pOld ); -printf( "\n" ); -Fraig_PrintNode( p, pNew ); -printf( "\n" ); -*/ -// assert( fValue1 != fValue2 ); -} - -/**Function************************************************************* - - Synopsis [Compress the simulation patterns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_FeedBackCompress( Fraig_Man_t * p ) -{ - unsigned * pSims; - unsigned uHash; - int i, w, t, nPats, * pPats; - int fPerformChecks = (p->nBTLimit == -1); - - // solve the covering problem - if ( fPerformChecks ) - { - Fraig_FeedBackCheckTable( p ); - if ( p->fDoSparse ) - Fraig_FeedBackCheckTableF0( p ); - } - - // solve the covering problem - Fraig_FeedBackCovering( p, p->vPatsReal ); - - - // get the number of additional patterns - nPats = Msat_IntVecReadSize( p->vPatsReal ); - pPats = Msat_IntVecReadArray( p->vPatsReal ); - // get the new starting word - p->iWordStart = FRAIG_NUM_WORDS( p->iPatsPerm + nPats ); - - // set the simulation info for the PIs - for ( i = 0; i < p->vInputs->nSize; i++ ) - { - // get hold of the simulation info for this PI - pSims = p->vInputs->pArray[i]->puSimD; - // clean the storage for the new patterns - for ( w = p->iWordPerm; w < p->iWordStart; w++ ) - p->pSimsTemp[w] = 0; - // set the patterns - for ( t = 0; t < nPats; t++ ) - if ( Fraig_BitStringHasBit( pSims, pPats[t] ) ) - { - // check if this pattern falls into temporary storage - if ( p->iPatsPerm + t < p->iWordPerm * 32 ) - Fraig_BitStringSetBit( pSims, p->iPatsPerm + t ); - else - Fraig_BitStringSetBit( p->pSimsTemp, p->iPatsPerm + t ); - } - // copy the pattern - for ( w = p->iWordPerm; w < p->iWordStart; w++ ) - pSims[w] = p->pSimsTemp[w]; - // recompute the hashing info - uHash = 0; - for ( w = 0; w < p->iWordStart; w++ ) - uHash ^= pSims[w] * s_FraigPrimes[w]; - p->vInputs->pArray[i]->uHashD = uHash; - } - - // update info about the permanently stored patterns - p->iWordPerm = p->iWordStart; - p->iPatsPerm += nPats; - assert( p->iWordPerm == FRAIG_NUM_WORDS( p->iPatsPerm ) ); - - // resimulate and recompute the hash values - for ( i = 1; i < p->vNodes->nSize; i++ ) - if ( Fraig_NodeIsAnd(p->vNodes->pArray[i]) ) - { - p->vNodes->pArray[i]->uHashD = 0; - Fraig_NodeSimulate( p->vNodes->pArray[i], 0, p->iWordPerm, 0 ); - } - - // double-check that the nodes are still distinguished - if ( fPerformChecks ) - Fraig_FeedBackCheckTable( p ); - - // rehash the values in the F0 table - if ( p->fDoSparse ) - { - Fraig_TableRehashF0( p, 0 ); - if ( fPerformChecks ) - Fraig_FeedBackCheckTableF0( p ); - } - - // check if we need to resize the simulation info - // if less than FRAIG_WORDS_STORE words are left, reallocate simulation info - if ( p->iWordPerm + FRAIG_WORDS_STORE > p->nWordsDyna ) - Fraig_ReallocateSimulationInfo( p ); - - // set the real patterns - Msat_IntVecClear( p->vPatsReal ); - memset( p->pSimsReal, 0, sizeof(unsigned)*p->nWordsDyna ); - for ( w = 0; w < p->iWordPerm; w++ ) - p->pSimsReal[w] = FRAIG_FULL; - if ( p->iPatsPerm % 32 > 0 ) - p->pSimsReal[p->iWordPerm-1] = FRAIG_MASK( p->iPatsPerm % 32 ); -// printf( "The number of permanent words = %d.\n", p->iWordPerm ); - return p->iWordStart; -} - - - - -/**Function************************************************************* - - Synopsis [Checks the correctness of the functional simulation table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_FeedBackCovering( Fraig_Man_t * p, Msat_IntVec_t * vPats ) -{ - Fraig_NodeVec_t * vColumns; - unsigned * pSims; - int * pHits, iPat, iCol, i; - int nOnesTotal, nSolStarting; - int fVeryVerbose = 0; - - // collect the pairs to be distinguished - vColumns = Fraig_FeedBackCoveringStart( p ); - // collect the number of 1s in each simulation vector - nOnesTotal = 0; - pHits = ABC_ALLOC( int, vColumns->nSize ); - for ( i = 0; i < vColumns->nSize; i++ ) - { - pSims = (unsigned *)vColumns->pArray[i]; - pHits[i] = Fraig_BitStringCountOnes( pSims, p->iWordStart ); - nOnesTotal += pHits[i]; -// assert( pHits[i] > 0 ); - } - - // go through the patterns - nSolStarting = Msat_IntVecReadSize(vPats); - while ( (iCol = Fraig_GetSmallestColumn( pHits, vColumns->nSize )) != -1 ) - { - // find the pattern, which hits this column - iPat = Fraig_GetHittingPattern( (unsigned *)vColumns->pArray[iCol], p->iWordStart ); - // cancel the columns covered by this pattern - Fraig_CancelCoveredColumns( vColumns, pHits, iPat ); - // save the pattern - Msat_IntVecPush( vPats, iPat ); - } - - // free the set of columns - for ( i = 0; i < vColumns->nSize; i++ ) - Fraig_MemFixedEntryRecycle( p->mmSims, (char *)vColumns->pArray[i] ); - - // print stats related to the covering problem - if ( p->fVerbose && fVeryVerbose ) - { - printf( "%3d\\%3d\\%3d ", p->nWordsRand, p->nWordsDyna, p->iWordPerm ); - printf( "Col (pairs) = %5d. ", vColumns->nSize ); - printf( "Row (pats) = %5d. ", p->iWordStart * 32 ); - printf( "Dns = %6.2f %%. ", vColumns->nSize==0? 0.0 : 100.0 * nOnesTotal / vColumns->nSize / p->iWordStart / 32 ); - printf( "Sol = %3d (%3d). ", Msat_IntVecReadSize(vPats), nSolStarting ); - printf( "\n" ); - } - Fraig_NodeVecFree( vColumns ); - ABC_FREE( pHits ); -} - - -/**Function************************************************************* - - Synopsis [Checks the correctness of the functional simulation table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_NodeVec_t * Fraig_FeedBackCoveringStart( Fraig_Man_t * p ) -{ - Fraig_NodeVec_t * vColumns; - Fraig_HashTable_t * pT = p->pTableF; - Fraig_Node_t * pEntF, * pEntD; - unsigned * pSims; - unsigned * pUnsigned1, * pUnsigned2; - int i, k, m, w;//, nOnes; - - // start the set of columns - vColumns = Fraig_NodeVecAlloc( 100 ); - - // go through the pairs of nodes to be distinguished - for ( i = 0; i < pT->nBins; i++ ) - Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) - { - p->vCones->nSize = 0; - Fraig_TableBinForEachEntryD( pEntF, pEntD ) - Fraig_NodeVecPush( p->vCones, pEntD ); - if ( p->vCones->nSize == 1 ) - continue; - //////////////////////////////// bug fix by alanmi, September 14, 2006 - if ( p->vCones->nSize > 20 ) - continue; - //////////////////////////////// - - for ( k = 0; k < p->vCones->nSize; k++ ) - for ( m = k+1; m < p->vCones->nSize; m++ ) - { - if ( !Fraig_CompareSimInfoUnderMask( p->vCones->pArray[k], p->vCones->pArray[m], p->iWordStart, 0, p->pSimsReal ) ) - continue; - - // primary simulation patterns (counter-examples) cannot distinguish this pair - // get memory to store the feasible simulation patterns - pSims = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); - // find the pattern that distinguish this column, exept the primary ones - pUnsigned1 = p->vCones->pArray[k]->puSimD; - pUnsigned2 = p->vCones->pArray[m]->puSimD; - for ( w = 0; w < p->iWordStart; w++ ) - pSims[w] = (pUnsigned1[w] ^ pUnsigned2[w]) & ~p->pSimsReal[w]; - // store the pattern - Fraig_NodeVecPush( vColumns, (Fraig_Node_t *)pSims ); -// nOnes = Fraig_BitStringCountOnes(pSims, p->iWordStart); -// assert( nOnes > 0 ); - } - } - - // if the flag is not set, do not consider sparse nodes in p->pTableF0 - if ( !p->fDoSparse ) - return vColumns; - - // recalculate their hash values based on p->pSimsReal - pT = p->pTableF0; - for ( i = 0; i < pT->nBins; i++ ) - Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) - { - pSims = pEntF->puSimD; - pEntF->uHashD = 0; - for ( w = 0; w < p->iWordStart; w++ ) - pEntF->uHashD ^= (pSims[w] & p->pSimsReal[w]) * s_FraigPrimes[w]; - } - - // rehash the table using these values - Fraig_TableRehashF0( p, 1 ); - - // collect the classes of equivalent node pairs - for ( i = 0; i < pT->nBins; i++ ) - Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) - { - p->vCones->nSize = 0; - Fraig_TableBinForEachEntryD( pEntF, pEntD ) - Fraig_NodeVecPush( p->vCones, pEntD ); - if ( p->vCones->nSize == 1 ) - continue; - - // primary simulation patterns (counter-examples) cannot distinguish all these pairs - for ( k = 0; k < p->vCones->nSize; k++ ) - for ( m = k+1; m < p->vCones->nSize; m++ ) - { - // get memory to store the feasible simulation patterns - pSims = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); - // find the patterns that are not distinquished - pUnsigned1 = p->vCones->pArray[k]->puSimD; - pUnsigned2 = p->vCones->pArray[m]->puSimD; - for ( w = 0; w < p->iWordStart; w++ ) - pSims[w] = (pUnsigned1[w] ^ pUnsigned2[w]) & ~p->pSimsReal[w]; - // store the pattern - Fraig_NodeVecPush( vColumns, (Fraig_Node_t *)pSims ); -// nOnes = Fraig_BitStringCountOnes(pSims, p->iWordStart); -// assert( nOnes > 0 ); - } - } - return vColumns; -} - -/**Function************************************************************* - - Synopsis [Selects the column, which has the smallest number of hits.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_GetSmallestColumn( int * pHits, int nHits ) -{ - int i, iColMin = -1, nHitsMin = 1000000; - for ( i = 0; i < nHits; i++ ) - { - // skip covered columns - if ( pHits[i] == 0 ) - continue; - // take the column if it can only be covered by one pattern - if ( pHits[i] == 1 ) - return i; - // find the column, which requires the smallest number of patterns - if ( nHitsMin > pHits[i] ) - { - nHitsMin = pHits[i]; - iColMin = i; - } - } - return iColMin; -} - -/**Function************************************************************* - - Synopsis [Select the pattern, which hits this column.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_GetHittingPattern( unsigned * pSims, int nWords ) -{ - int i, b; - for ( i = 0; i < nWords; i++ ) - { - if ( pSims[i] == 0 ) - continue; - for ( b = 0; b < 32; b++ ) - if ( pSims[i] & (1 << b) ) - return i * 32 + b; - } - return -1; -} - -/**Function************************************************************* - - Synopsis [Cancel covered patterns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_CancelCoveredColumns( Fraig_NodeVec_t * vColumns, int * pHits, int iPat ) -{ - unsigned * pSims; - int i; - for ( i = 0; i < vColumns->nSize; i++ ) - { - pSims = (unsigned *)vColumns->pArray[i]; - if ( Fraig_BitStringHasBit( pSims, iPat ) ) - pHits[i] = 0; - } -} - - -/**Function************************************************************* - - Synopsis [Checks the correctness of the functional simulation table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_FeedBackCheckTable( Fraig_Man_t * p ) -{ - Fraig_HashTable_t * pT = p->pTableF; - Fraig_Node_t * pEntF, * pEntD; - int i, k, m, nPairs; - - nPairs = 0; - for ( i = 0; i < pT->nBins; i++ ) - Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) - { - p->vCones->nSize = 0; - Fraig_TableBinForEachEntryD( pEntF, pEntD ) - Fraig_NodeVecPush( p->vCones, pEntD ); - if ( p->vCones->nSize == 1 ) - continue; - for ( k = 0; k < p->vCones->nSize; k++ ) - for ( m = k+1; m < p->vCones->nSize; m++ ) - { - if ( Fraig_CompareSimInfo( p->vCones->pArray[k], p->vCones->pArray[m], p->iWordStart, 0 ) ) - printf( "Nodes %d and %d have the same D simulation info.\n", - p->vCones->pArray[k]->Num, p->vCones->pArray[m]->Num ); - nPairs++; - } - } -// printf( "\nThe total of %d node pairs have been verified.\n", nPairs ); -} - -/**Function************************************************************* - - Synopsis [Checks the correctness of the functional simulation table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_FeedBackCheckTableF0( Fraig_Man_t * p ) -{ - Fraig_HashTable_t * pT = p->pTableF0; - Fraig_Node_t * pEntF; - int i, k, m, nPairs; - - nPairs = 0; - for ( i = 0; i < pT->nBins; i++ ) - { - p->vCones->nSize = 0; - Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) - Fraig_NodeVecPush( p->vCones, pEntF ); - if ( p->vCones->nSize == 1 ) - continue; - for ( k = 0; k < p->vCones->nSize; k++ ) - for ( m = k+1; m < p->vCones->nSize; m++ ) - { - if ( Fraig_CompareSimInfo( p->vCones->pArray[k], p->vCones->pArray[m], p->iWordStart, 0 ) ) - printf( "Nodes %d and %d have the same D simulation info.\n", - p->vCones->pArray[k]->Num, p->vCones->pArray[m]->Num ); - nPairs++; - } - } -// printf( "\nThe total of %d node pairs have been verified.\n", nPairs ); -} - -/**Function************************************************************* - - Synopsis [Doubles the size of simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_ReallocateSimulationInfo( Fraig_Man_t * p ) -{ - Fraig_MemFixed_t * mmSimsNew; // new memory manager for simulation info - Fraig_Node_t * pNode; - unsigned * pSimsNew; - unsigned uSignOld; - int i; - - // allocate a new memory manager - p->nWordsDyna *= 2; - mmSimsNew = Fraig_MemFixedStart( sizeof(unsigned) * (p->nWordsRand + p->nWordsDyna) ); - - // set the new data for the constant node - pNode = p->pConst1; - pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); - pNode->puSimD = pNode->puSimR + p->nWordsRand; - memset( pNode->puSimR, 0, sizeof(unsigned) * p->nWordsRand ); - memset( pNode->puSimD, 0, sizeof(unsigned) * p->nWordsDyna ); - - // copy the simulation info of the PIs - for ( i = 0; i < p->vInputs->nSize; i++ ) - { - pNode = p->vInputs->pArray[i]; - // copy the simulation info - pSimsNew = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); - memmove( pSimsNew, pNode->puSimR, sizeof(unsigned) * (p->nWordsRand + p->iWordStart) ); - // attach the new info - pNode->puSimR = pSimsNew; - pNode->puSimD = pNode->puSimR + p->nWordsRand; - // signatures remain without changes - } - - // replace the manager to free up some memory - Fraig_MemFixedStop( p->mmSims, 0 ); - p->mmSims = mmSimsNew; - - // resimulate the internal nodes (this should lead to the same signatures) - for ( i = 1; i < p->vNodes->nSize; i++ ) - { - pNode = p->vNodes->pArray[i]; - if ( !Fraig_NodeIsAnd(pNode) ) - continue; - // allocate memory for the simulation info - pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); - pNode->puSimD = pNode->puSimR + p->nWordsRand; - // derive random simulation info - uSignOld = pNode->uHashR; - pNode->uHashR = 0; - Fraig_NodeSimulate( pNode, 0, p->nWordsRand, 1 ); - assert( uSignOld == pNode->uHashR ); - // derive dynamic simulation info - uSignOld = pNode->uHashD; - pNode->uHashD = 0; - Fraig_NodeSimulate( pNode, 0, p->iWordStart, 0 ); - assert( uSignOld == pNode->uHashD ); - } - - // realloc temporary storage - p->pSimsReal = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); - memset( p->pSimsReal, 0, sizeof(unsigned) * p->nWordsDyna ); - p->pSimsTemp = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); - p->pSimsDiff = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); -} - - -/**Function************************************************************* - - Synopsis [Generated trivial counter example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int * Fraig_ManAllocCounterExample( Fraig_Man_t * p ) -{ - int * pModel; - pModel = ABC_ALLOC( int, p->vInputs->nSize ); - memset( pModel, 0, sizeof(int) * p->vInputs->nSize ); - return pModel; -} - - -/**Function************************************************************* - - Synopsis [Saves the counter example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_ManSimulateBitNode_rec( Fraig_Man_t * p, Fraig_Node_t * pNode ) -{ - int Value0, Value1; - if ( Fraig_NodeIsTravIdCurrent( p, pNode ) ) - return pNode->fMark3; - Fraig_NodeSetTravIdCurrent( p, pNode ); - Value0 = Fraig_ManSimulateBitNode_rec( p, Fraig_Regular(pNode->p1) ); - Value1 = Fraig_ManSimulateBitNode_rec( p, Fraig_Regular(pNode->p2) ); - Value0 ^= Fraig_IsComplement(pNode->p1); - Value1 ^= Fraig_IsComplement(pNode->p2); - pNode->fMark3 = Value0 & Value1; - return pNode->fMark3; -} - -/**Function************************************************************* - - Synopsis [Simulates one bit.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_ManSimulateBitNode( Fraig_Man_t * p, Fraig_Node_t * pNode, int * pModel ) -{ - int fCompl, RetValue, i; - // set the PI values - Fraig_ManIncrementTravId( p ); - for ( i = 0; i < p->vInputs->nSize; i++ ) - { - Fraig_NodeSetTravIdCurrent( p, p->vInputs->pArray[i] ); - p->vInputs->pArray[i]->fMark3 = pModel[i]; - } - // perform the traversal - fCompl = Fraig_IsComplement(pNode); - RetValue = Fraig_ManSimulateBitNode_rec( p, Fraig_Regular(pNode) ); - return fCompl ^ RetValue; -} - - -/**Function************************************************************* - - Synopsis [Saves the counter example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int * Fraig_ManSaveCounterExample( Fraig_Man_t * p, Fraig_Node_t * pNode ) -{ - int * pModel; - int iPattern; - int i, fCompl; - - // the node can be complemented - fCompl = Fraig_IsComplement(pNode); - // because we compare with constant 0, p->pConst1 should also be complemented - fCompl = !fCompl; - - // derive the model - pModel = Fraig_ManAllocCounterExample( p ); - iPattern = Fraig_FindFirstDiff( p->pConst1, Fraig_Regular(pNode), fCompl, p->nWordsRand, 1 ); - if ( iPattern >= 0 ) - { - for ( i = 0; i < p->vInputs->nSize; i++ ) - if ( Fraig_BitStringHasBit( p->vInputs->pArray[i]->puSimR, iPattern ) ) - pModel[i] = 1; -/* -printf( "SAT solver's pattern:\n" ); -for ( i = 0; i < p->vInputs->nSize; i++ ) - printf( "%d", pModel[i] ); -printf( "\n" ); -*/ - assert( Fraig_ManSimulateBitNode( p, pNode, pModel ) ); - return pModel; - } - iPattern = Fraig_FindFirstDiff( p->pConst1, Fraig_Regular(pNode), fCompl, p->iWordStart, 0 ); - if ( iPattern >= 0 ) - { - for ( i = 0; i < p->vInputs->nSize; i++ ) - if ( Fraig_BitStringHasBit( p->vInputs->pArray[i]->puSimD, iPattern ) ) - pModel[i] = 1; -/* -printf( "SAT solver's pattern:\n" ); -for ( i = 0; i < p->vInputs->nSize; i++ ) - printf( "%d", pModel[i] ); -printf( "\n" ); -*/ - assert( Fraig_ManSimulateBitNode( p, pNode, pModel ) ); - return pModel; - } - ABC_FREE( pModel ); - return NULL; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/sat/fraig/fraigInt.h b/src/sat/fraig/fraigInt.h deleted file mode 100644 index 7cc2194a..00000000 --- a/src/sat/fraig/fraigInt.h +++ /dev/null @@ -1,434 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraigInt.h] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [Internal declarations of the FRAIG package.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - October 1, 2004] - - Revision [$Id: fraigInt.h,v 1.15 2005/07/08 01:01:31 alanmi Exp $] - -***********************************************************************/ - -#ifndef __FRAIG_INT_H__ -#define __FRAIG_INT_H__ - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include - -#include "abc_global.h" -#include "fraig.h" -#include "msat.h" - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -/* - The AIG node policy: - - Each node has its main number (pNode->Num) - This is the number of this node in the array of all nodes and its SAT variable number - - The PI nodes are stored along with other nodes - Additionally, PI nodes have a PI number, by which they are stored in the PI node array - - The constant node is has number 0 and is also stored in the array -*/ - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -// enable this macro to support the fanouts -#define FRAIG_ENABLE_FANOUTS -#define FRAIG_PATTERNS_RANDOM 2048 // should not be less than 128 and more than 32768 (2^15) -#define FRAIG_PATTERNS_DYNAMIC 2048 // should not be less than 256 and more than 32768 (2^15) -#define FRAIG_MAX_PRIMES 1024 // the maximum number of primes used for hashing - -// this parameter determines when simulation info is extended -// it will be extended when the free storage in the dynamic simulation -// info is less or equal to this number of words (FRAIG_WORDS_STORE) -// this is done because if the free storage for dynamic simulation info -// is not sufficient, computation becomes inefficient -#define FRAIG_WORDS_STORE 5 - -// the bit masks -#define FRAIG_MASK(n) ((~((unsigned)0)) >> (32-(n))) -#define FRAIG_FULL (~((unsigned)0)) -#define FRAIG_NUM_WORDS(n) (((n)>>5) + (((n)&31) > 0)) - -// generating random unsigned (#define RAND_MAX 0x7fff) -#define FRAIG_RANDOM_UNSIGNED ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand())) - -// macros to get hold of the bits in a bit string -#define Fraig_BitStringSetBit(p,i) ((p)[(i)>>5] |= (1<<((i) & 31))) -#define Fraig_BitStringXorBit(p,i) ((p)[(i)>>5] ^= (1<<((i) & 31))) -#define Fraig_BitStringHasBit(p,i) (((p)[(i)>>5] & (1<<((i) & 31))) > 0) - -// macros to get hold of the bits in the support info -//#define Fraig_NodeSetVarStr(p,i) (Fraig_Regular(p)->pSuppStr[((i)%FRAIG_SUPP_SIGN)>>5] |= (1<<(((i)%FRAIG_SUPP_SIGN) & 31))) -//#define Fraig_NodeHasVarStr(p,i) ((Fraig_Regular(p)->pSuppStr[((i)%FRAIG_SUPP_SIGN)>>5] & (1<<(((i)%FRAIG_SUPP_SIGN) & 31))) > 0) -#define Fraig_NodeSetVarStr(p,i) Fraig_BitStringSetBit(Fraig_Regular(p)->pSuppStr,i) -#define Fraig_NodeHasVarStr(p,i) Fraig_BitStringHasBit(Fraig_Regular(p)->pSuppStr,i) - -// copied from "extra.h" for stand-aloneness -#define Fraig_PrintTime(a,t) printf( "%s = ", (a) ); printf( "%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC) ) - -#define Fraig_HashKey2(a,b,TSIZE) (((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b) * 12582917) % TSIZE) -//#define Fraig_HashKey2(a,b,TSIZE) (( ((unsigned)(a)->Num * 19) ^ ((unsigned)(b)->Num * 1999) ) % TSIZE) -//#define Fraig_HashKey2(a,b,TSIZE) ( ((unsigned)((a)->Num + (b)->Num) * ((a)->Num + (b)->Num + 1) / 2) % TSIZE) -// the other two hash functions give bad distribution of hash chain lengths (not clear why) - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Fraig_MemFixed_t_ Fraig_MemFixed_t; - -// the mapping manager -struct Fraig_ManStruct_t_ -{ - // the AIG nodes - Fraig_NodeVec_t * vInputs; // the array of primary inputs - Fraig_NodeVec_t * vNodes; // the array of all nodes, including primary inputs - Fraig_NodeVec_t * vOutputs; // the array of primary outputs (some internal nodes) - Fraig_Node_t * pConst1; // the pointer to the constant node (vNodes->pArray[0]) - - // info about the original circuit - char ** ppInputNames; // the primary input names - char ** ppOutputNames; // the primary output names - - // various hash-tables - Fraig_HashTable_t * pTableS; // hashing by structure - Fraig_HashTable_t * pTableF; // hashing by simulation info - Fraig_HashTable_t * pTableF0; // hashing by simulation info (sparse functions) - - // parameters - int nWordsRand; // the number of words of random simulation info - int nWordsDyna; // the number of words of dynamic simulation info - int nBTLimit; // the max number of backtracks to perform - int nSeconds; // the runtime limit for the miter proof - int fFuncRed; // performs only one level hashing - int fFeedBack; // enables solver feedback - int fDist1Pats; // enables solver feedback - int fDoSparse; // performs equiv tests for sparse functions - int fChoicing; // enables recording structural choices - int fTryProve; // tries to solve the final miter - int fVerbose; // the verbosiness flag - int fVerboseP; // the verbosiness flag - ABC_INT64_T nInspLimit; // the inspection limit - - int nTravIds; // the traversal counter - int nTravIds2; // the traversal counter - - // info related to the solver feedback - int iWordStart; // the first word to use for simulation - int iWordPerm; // the number of words stored permanently - int iPatsPerm; // the number of patterns stored permanently - Fraig_NodeVec_t * vCones; // the temporary array of internal variables - Msat_IntVec_t * vPatsReal; // the array of real pattern numbers - unsigned * pSimsReal; // used for simulation patterns - unsigned * pSimsDiff; // used for simulation patterns - unsigned * pSimsTemp; // used for simulation patterns - - // the support information - int nSuppWords; - unsigned ** pSuppS; - unsigned ** pSuppF; - - // the memory managers - Fraig_MemFixed_t * mmNodes; // the memory manager for nodes - Fraig_MemFixed_t * mmSims; // the memory manager for simulation info - - // solving the SAT problem - Msat_Solver_t * pSat; // the SAT solver - Msat_IntVec_t * vProj; // the temporary array of projection vars - int nSatNums; // the counter of SAT variables - int * pModel; // the assignment, which satisfies the miter - // these arrays belong to the solver - Msat_IntVec_t * vVarsInt; // the temporary array of variables - Msat_ClauseVec_t * vAdjacents; // the temporary storage for connectivity - Msat_IntVec_t * vVarsUsed; // the array marking vars appearing in the cone - - // various statistic variables - int nSatCalls; // the number of times equivalence checking was called - int nSatProof; // the number of times a proof was found - int nSatCounter; // the number of times a counter example was found - int nSatFails; // the number of times the SAT solver failed to complete due to resource limit or prediction - int nSatFailsReal; // the number of times the SAT solver failed to complete due to resource limit - - int nSatCallsImp; // the number of times equivalence checking was called - int nSatProofImp; // the number of times a proof was found - int nSatCounterImp;// the number of times a counter example was found - int nSatFailsImp; // the number of times the SAT solver failed to complete - - int nSatZeros; // the number of times the simulation vector is zero - int nSatSupps; // the number of times the support info was useful - int nRefErrors; // the number of ref counting errors - int nImplies; // the number of implication cases - int nSatImpls; // the number of implication SAT calls - int nVarsClauses; // the number of variables with clauses - int nSimplifies0; - int nSimplifies1; - int nImplies0; - int nImplies1; - - // runtime statistics - int timeToAig; // time to transfer to the mapping structure - int timeSims; // time to compute k-feasible cuts - int timeTrav; // time to traverse the network - int timeFeed; // time for solver feedback (recording and resimulating) - int timeImply; // time to analyze implications - int timeSat; // time to compute the truth table for each cut - int timeToNet; // time to transfer back to the network - int timeTotal; // the total mapping time - int time1; // time to perform one task - int time2; // time to perform another task - int time3; // time to perform another task - int time4; // time to perform another task -}; - -// the mapping node -struct Fraig_NodeStruct_t_ -{ - // various numbers associated with the node - int Num; // the unique number (SAT var number) of this node - int NumPi; // if the node is a PI, this is its variable number - int Level; // the level of the node - int nRefs; // the number of references of the node - int TravId; // the traversal ID (use to avoid cleaning marks) - int TravId2; // the traversal ID (use to avoid cleaning marks) - - // general information about the node - unsigned fInv : 1; // the mark to show that simulation info is complemented - unsigned fNodePo : 1; // the mark used for primary outputs - unsigned fClauses : 1; // the clauses for this node are loaded - unsigned fMark0 : 1; // the mark used for traversals - unsigned fMark1 : 1; // the mark used for traversals - unsigned fMark2 : 1; // the mark used for traversals - unsigned fMark3 : 1; // the mark used for traversals - unsigned fFeedUse : 1; // the presence of the variable in the feedback - unsigned fFeedVal : 1; // the value of the variable in the feedback - unsigned fFailTfo : 1; // the node is in the TFO of the failed SAT run - unsigned nFanouts : 2; // the indicator of fanouts (none, one, or many) - unsigned nOnes : 20; // the number of 1's in the random sim info - - // the children of the node - Fraig_Node_t * p1; // the first child - Fraig_Node_t * p2; // the second child - Fraig_NodeVec_t * vFanins; // the fanins of the supergate rooted at this node -// Fraig_NodeVec_t * vFanouts; // the fanouts of the supergate rooted at this node - - // various linked lists - Fraig_Node_t * pNextS; // the next node in the structural hash table - Fraig_Node_t * pNextF; // the next node in the functional (simulation) hash table - Fraig_Node_t * pNextD; // the next node in the list of nodes based on dynamic simulation - Fraig_Node_t * pNextE; // the next structural choice (functionally-equivalent node) - Fraig_Node_t * pRepr; // the canonical functional representative of the node - - // simulation data - unsigned uHashR; // the hash value for random information - unsigned uHashD; // the hash value for dynamic information - unsigned * puSimR; // the simulation information (random) - unsigned * puSimD; // the simulation information (dynamic) - - // misc information - Fraig_Node_t * pData0; // temporary storage for the corresponding network node - Fraig_Node_t * pData1; // temporary storage for the corresponding network node - -#ifdef FRAIG_ENABLE_FANOUTS - // representation of node's fanouts - Fraig_Node_t * pFanPivot; // the first fanout of this node - Fraig_Node_t * pFanFanin1; // the next fanout of p1 - Fraig_Node_t * pFanFanin2; // the next fanout of p2 -#endif -}; - -// the vector of nodes -struct Fraig_NodeVecStruct_t_ -{ - int nCap; // the number of allocated entries - int nSize; // the number of entries in the array - Fraig_Node_t ** pArray; // the array of nodes -}; - -// the hash table -struct Fraig_HashTableStruct_t_ -{ - Fraig_Node_t ** pBins; // the table bins - int nBins; // the size of the table - int nEntries; // the total number of entries in the table -}; - -// getting hold of the next fanout of the node -#define Fraig_NodeReadNextFanout( pNode, pFanout ) \ - ( ( pFanout == NULL )? NULL : \ - ((Fraig_Regular((pFanout)->p1) == (pNode))? \ - (pFanout)->pFanFanin1 : (pFanout)->pFanFanin2) ) -// getting hold of the place where the next fanout will be attached -#define Fraig_NodeReadNextFanoutPlace( pNode, pFanout ) \ - ( (Fraig_Regular((pFanout)->p1) == (pNode))? \ - &(pFanout)->pFanFanin1 : &(pFanout)->pFanFanin2 ) -// iterator through the fanouts of the node -#define Fraig_NodeForEachFanout( pNode, pFanout ) \ - for ( pFanout = (pNode)->pFanPivot; pFanout; \ - pFanout = Fraig_NodeReadNextFanout(pNode, pFanout) ) -// safe iterator through the fanouts of the node -#define Fraig_NodeForEachFanoutSafe( pNode, pFanout, pFanout2 ) \ - for ( pFanout = (pNode)->pFanPivot, \ - pFanout2 = Fraig_NodeReadNextFanout(pNode, pFanout); \ - pFanout; \ - pFanout = pFanout2, \ - pFanout2 = Fraig_NodeReadNextFanout(pNode, pFanout) ) - -// iterators through the entries in the linked lists of nodes -// the list of nodes in the structural hash table -#define Fraig_TableBinForEachEntryS( pBin, pEnt ) \ - for ( pEnt = pBin; \ - pEnt; \ - pEnt = pEnt->pNextS ) -#define Fraig_TableBinForEachEntrySafeS( pBin, pEnt, pEnt2 ) \ - for ( pEnt = pBin, \ - pEnt2 = pEnt? pEnt->pNextS: NULL; \ - pEnt; \ - pEnt = pEnt2, \ - pEnt2 = pEnt? pEnt->pNextS: NULL ) -// the list of nodes in the functional (simulation) hash table -#define Fraig_TableBinForEachEntryF( pBin, pEnt ) \ - for ( pEnt = pBin; \ - pEnt; \ - pEnt = pEnt->pNextF ) -#define Fraig_TableBinForEachEntrySafeF( pBin, pEnt, pEnt2 ) \ - for ( pEnt = pBin, \ - pEnt2 = pEnt? pEnt->pNextF: NULL; \ - pEnt; \ - pEnt = pEnt2, \ - pEnt2 = pEnt? pEnt->pNextF: NULL ) -// the list of nodes with the same simulation and different functionality -#define Fraig_TableBinForEachEntryD( pBin, pEnt ) \ - for ( pEnt = pBin; \ - pEnt; \ - pEnt = pEnt->pNextD ) -#define Fraig_TableBinForEachEntrySafeD( pBin, pEnt, pEnt2 ) \ - for ( pEnt = pBin, \ - pEnt2 = pEnt? pEnt->pNextD: NULL; \ - pEnt; \ - pEnt = pEnt2, \ - pEnt2 = pEnt? pEnt->pNextD: NULL ) -// the list of nodes with the same functionality -#define Fraig_TableBinForEachEntryE( pBin, pEnt ) \ - for ( pEnt = pBin; \ - pEnt; \ - pEnt = pEnt->pNextE ) -#define Fraig_TableBinForEachEntrySafeE( pBin, pEnt, pEnt2 ) \ - for ( pEnt = pBin, \ - pEnt2 = pEnt? pEnt->pNextE: NULL; \ - pEnt; \ - pEnt = pEnt2, \ - pEnt2 = pEnt? pEnt->pNextE: NULL ) - -//////////////////////////////////////////////////////////////////////// -/// GLOBAL VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== fraigCanon.c =============================================================*/ -extern Fraig_Node_t * Fraig_NodeAndCanon( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2 ); -/*=== fraigFanout.c =============================================================*/ -extern void Fraig_NodeAddFaninFanout( Fraig_Node_t * pFanin, Fraig_Node_t * pFanout ); -extern void Fraig_NodeRemoveFaninFanout( Fraig_Node_t * pFanin, Fraig_Node_t * pFanoutToRemove ); -extern int Fraig_NodeGetFanoutNum( Fraig_Node_t * pNode ); -/*=== fraigFeed.c =============================================================*/ -extern void Fraig_FeedBackInit( Fraig_Man_t * p ); -extern void Fraig_FeedBack( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); -extern void Fraig_FeedBackTest( Fraig_Man_t * p ); -extern int Fraig_FeedBackCompress( Fraig_Man_t * p ); -extern int * Fraig_ManAllocCounterExample( Fraig_Man_t * p ); -extern int * Fraig_ManSaveCounterExample( Fraig_Man_t * p, Fraig_Node_t * pNode ); -/*=== fraigMan.c =============================================================*/ -extern void Fraig_ManCreateSolver( Fraig_Man_t * p ); -/*=== fraigMem.c =============================================================*/ -extern Fraig_MemFixed_t * Fraig_MemFixedStart( int nEntrySize ); -extern void Fraig_MemFixedStop( Fraig_MemFixed_t * p, int fVerbose ); -extern char * Fraig_MemFixedEntryFetch( Fraig_MemFixed_t * p ); -extern void Fraig_MemFixedEntryRecycle( Fraig_MemFixed_t * p, char * pEntry ); -extern void Fraig_MemFixedRestart( Fraig_MemFixed_t * p ); -extern int Fraig_MemFixedReadMemUsage( Fraig_MemFixed_t * p ); -/*=== fraigNode.c =============================================================*/ -extern Fraig_Node_t * Fraig_NodeCreateConst( Fraig_Man_t * p ); -extern Fraig_Node_t * Fraig_NodeCreatePi( Fraig_Man_t * p ); -extern Fraig_Node_t * Fraig_NodeCreate( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ); -extern void Fraig_NodeSimulate( Fraig_Node_t * pNode, int iWordStart, int iWordStop, int fUseRand ); -/*=== fraigPrime.c =============================================================*/ -extern int s_FraigPrimes[FRAIG_MAX_PRIMES]; -extern unsigned int Cudd_PrimeFraig( unsigned int p ); -/*=== fraigSat.c ===============================================================*/ -extern int Fraig_NodeIsImplication( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit ); -/*=== fraigTable.c =============================================================*/ -extern Fraig_HashTable_t * Fraig_HashTableCreate( int nSize ); -extern void Fraig_HashTableFree( Fraig_HashTable_t * p ); -extern int Fraig_HashTableLookupS( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2, Fraig_Node_t ** ppNodeRes ); -extern Fraig_Node_t * Fraig_HashTableLookupF( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); -extern Fraig_Node_t * Fraig_HashTableLookupF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); -extern void Fraig_HashTableInsertF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); -extern int Fraig_CompareSimInfo( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand ); -extern int Fraig_CompareSimInfoUnderMask( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask ); -extern int Fraig_FindFirstDiff( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int fCompl, int iWordLast, int fUseRand ); -extern void Fraig_CollectXors( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask ); -extern void Fraig_TablePrintStatsS( Fraig_Man_t * pMan ); -extern void Fraig_TablePrintStatsF( Fraig_Man_t * pMan ); -extern void Fraig_TablePrintStatsF0( Fraig_Man_t * pMan ); -extern int Fraig_TableRehashF0( Fraig_Man_t * pMan, int fLinkEquiv ); -/*=== fraigUtil.c ===============================================================*/ -extern int Fraig_NodeCountPis( Msat_IntVec_t * vVars, int nVarsPi ); -extern int Fraig_NodeCountSuppVars( Fraig_Man_t * p, Fraig_Node_t * pNode, int fSuppStr ); -extern int Fraig_NodesCompareSupps( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); -extern int Fraig_NodeAndSimpleCase_rec( Fraig_Node_t * pOld, Fraig_Node_t * pNew ); -extern int Fraig_NodeIsExorType( Fraig_Node_t * pNode ); -extern void Fraig_ManSelectBestChoice( Fraig_Man_t * p ); -extern int Fraig_BitStringCountOnes( unsigned * pString, int nWords ); -extern void Fraig_PrintBinary( FILE * pFile, unsigned * pSign, int nBits ); -extern int Fraig_NodeIsExorType( Fraig_Node_t * pNode ); -extern int Fraig_NodeIsExor( Fraig_Node_t * pNode ); -extern int Fraig_NodeIsMuxType( Fraig_Node_t * pNode ); -extern Fraig_Node_t * Fraig_NodeRecognizeMux( Fraig_Node_t * pNode, Fraig_Node_t ** ppNodeT, Fraig_Node_t ** ppNodeE ); -extern int Fraig_ManCountExors( Fraig_Man_t * pMan ); -extern int Fraig_ManCountMuxes( Fraig_Man_t * pMan ); -extern int Fraig_NodeSimsContained( Fraig_Man_t * pMan, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2 ); -extern int Fraig_NodeIsInSupergate( Fraig_Node_t * pOld, Fraig_Node_t * pNew ); -extern Fraig_NodeVec_t * Fraig_CollectSupergate( Fraig_Node_t * pNode, int fStopAtMux ); -extern int Fraig_CountPis( Fraig_Man_t * p, Msat_IntVec_t * vVarNums ); -extern void Fraig_ManIncrementTravId( Fraig_Man_t * pMan ); -extern void Fraig_NodeSetTravIdCurrent( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); -extern int Fraig_NodeIsTravIdCurrent( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); -extern int Fraig_NodeIsTravIdPrevious( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); -/*=== fraigVec.c ===============================================================*/ -extern void Fraig_NodeVecSortByRefCount( Fraig_NodeVec_t * p ); - - - -ABC_NAMESPACE_HEADER_END - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/sat/fraig/fraigMan.c b/src/sat/fraig/fraigMan.c deleted file mode 100644 index ba08d793..00000000 --- a/src/sat/fraig/fraigMan.c +++ /dev/null @@ -1,545 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraigMan.c] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [Implementation of the FRAIG manager.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - October 1, 2004] - - Revision [$Id: fraigMan.c,v 1.11 2005/07/08 01:01:31 alanmi Exp $] - -***********************************************************************/ - -#include "fraigInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -int timeSelect; -int timeAssign; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Sets the default parameters of the package.] - - Description [This set of parameters is tuned for equivalence checking.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Prove_ParamsSetDefault( Prove_Params_t * pParams ) -{ - // clean the parameter structure - memset( pParams, 0, sizeof(Prove_Params_t) ); - // general parameters - pParams->fUseFraiging = 1; // enables fraiging - pParams->fUseRewriting = 1; // enables rewriting - pParams->fUseBdds = 0; // enables BDD construction when other methods fail - pParams->fVerbose = 0; // prints verbose stats - // iterations - pParams->nItersMax = 6; // the number of iterations - // mitering - pParams->nMiteringLimitStart = 5000; // 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: %.2f\n", pParams->nFraigingLimitMulti ); - printf( "Multiplicative coeficient for fraiging: %.2f\n", pParams->nRewritingLimitMulti ); - printf( "BDD size limit for bailing out: %d\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: %lld\n", pParams->nTotalBacktrackLimit ); - printf( "Total inspection limit: %lld\n", pParams->nTotalInspectLimit ); - printf( "Parameter dump complete.\n" ); -} - -/**Function************************************************************* - - Synopsis [Sets the default parameters of the package.] - - Description [This set of parameters is tuned for equivalence checking.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_ParamsSetDefault( Fraig_Params_t * pParams ) -{ - memset( pParams, 0, sizeof(Fraig_Params_t) ); - pParams->nPatsRand = FRAIG_PATTERNS_RANDOM; // the number of words of random simulation info - pParams->nPatsDyna = FRAIG_PATTERNS_DYNAMIC; // the number of words of dynamic simulation info - pParams->nBTLimit = 99; // the max number of backtracks to perform - pParams->nSeconds = 20; // the max number of seconds to solve the miter - pParams->fFuncRed = 1; // performs only one level hashing - pParams->fFeedBack = 1; // enables solver feedback - pParams->fDist1Pats = 1; // enables distance-1 patterns - pParams->fDoSparse = 0; // performs equiv tests for sparse functions - pParams->fChoicing = 0; // enables recording structural choices - pParams->fTryProve = 1; // tries to solve the final miter - pParams->fVerbose = 0; // the verbosiness flag - pParams->fVerboseP = 0; // the verbose flag for reporting the proof - pParams->fInternal = 0; // the flag indicates the internal run - pParams->nConfLimit = 0; // the limit on the number of conflicts - pParams->nInspLimit = 0; // the limit on the number of inspections -} - -/**Function************************************************************* - - Synopsis [Sets the default parameters of the package.] - - Description [This set of parameters is tuned for complete FRAIGing.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_ParamsSetDefaultFull( Fraig_Params_t * pParams ) -{ - memset( pParams, 0, sizeof(Fraig_Params_t) ); - pParams->nPatsRand = FRAIG_PATTERNS_RANDOM; // the number of words of random simulation info - pParams->nPatsDyna = FRAIG_PATTERNS_DYNAMIC; // the number of words of dynamic simulation info - pParams->nBTLimit = -1; // the max number of backtracks to perform - pParams->nSeconds = 20; // the max number of seconds to solve the miter - pParams->fFuncRed = 1; // performs only one level hashing - pParams->fFeedBack = 1; // enables solver feedback - pParams->fDist1Pats = 1; // enables distance-1 patterns - pParams->fDoSparse = 1; // performs equiv tests for sparse functions - pParams->fChoicing = 0; // enables recording structural choices - pParams->fTryProve = 0; // tries to solve the final miter - pParams->fVerbose = 0; // the verbosiness flag - pParams->fVerboseP = 0; // the verbose flag for reporting the proof - pParams->fInternal = 0; // the flag indicates the internal run - pParams->nConfLimit = 0; // the limit on the number of conflicts - pParams->nInspLimit = 0; // the limit on the number of inspections -} - -/**Function************************************************************* - - Synopsis [Creates the new FRAIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Man_t * Fraig_ManCreate( Fraig_Params_t * pParams ) -{ - Fraig_Params_t Params; - Fraig_Man_t * p; - - // set the random seed for simulation -// srand( 0xFEEDDEAF ); - srand( 0xDEADCAFE ); - - // set parameters for equivalence checking - if ( pParams == NULL ) - Fraig_ParamsSetDefault( pParams = &Params ); - // adjust the amount of simulation info - if ( pParams->nPatsRand < 128 ) - pParams->nPatsRand = 128; - if ( pParams->nPatsRand > 32768 ) - pParams->nPatsRand = 32768; - if ( pParams->nPatsDyna < 128 ) - pParams->nPatsDyna = 128; - if ( pParams->nPatsDyna > 32768 ) - pParams->nPatsDyna = 32768; - // if reduction is not performed, allocate minimum simulation info - if ( !pParams->fFuncRed ) - pParams->nPatsRand = pParams->nPatsDyna = 128; - - // start the manager - p = ABC_ALLOC( Fraig_Man_t, 1 ); - memset( p, 0, sizeof(Fraig_Man_t) ); - - // set the default parameters - p->nWordsRand = FRAIG_NUM_WORDS( pParams->nPatsRand ); // the number of words of random simulation info - p->nWordsDyna = FRAIG_NUM_WORDS( pParams->nPatsDyna ); // the number of patterns for dynamic simulation info - p->nBTLimit = pParams->nBTLimit; // -1 means infinite backtrack limit - p->nSeconds = pParams->nSeconds; // the timeout for the final miter - p->fFuncRed = pParams->fFuncRed; // enables functional reduction (otherwise, only one-level hashing is performed) - p->fFeedBack = pParams->fFeedBack; // enables solver feedback (the use of counter-examples in simulation) - p->fDist1Pats = pParams->fDist1Pats; // enables solver feedback (the use of counter-examples in simulation) - p->fDoSparse = pParams->fDoSparse; // performs equivalence checking for sparse functions (whose sim-info is 0) - p->fChoicing = pParams->fChoicing; // disable accumulation of structural choices (keeps only the first choice) - p->fTryProve = pParams->fTryProve; // disable accumulation of structural choices (keeps only the first choice) - p->fVerbose = pParams->fVerbose; // disable verbose output - p->fVerboseP = pParams->fVerboseP; // disable verbose output - p->nInspLimit = pParams->nInspLimit; // the limit on the number of inspections - - // start memory managers - p->mmNodes = Fraig_MemFixedStart( sizeof(Fraig_Node_t) ); - p->mmSims = Fraig_MemFixedStart( sizeof(unsigned) * (p->nWordsRand + p->nWordsDyna) ); - // allocate node arrays - p->vInputs = Fraig_NodeVecAlloc( 1000 ); // the array of primary inputs - p->vOutputs = Fraig_NodeVecAlloc( 1000 ); // the array of primary outputs - p->vNodes = Fraig_NodeVecAlloc( 1000 ); // the array of internal nodes - // start the tables - p->pTableS = Fraig_HashTableCreate( 1000 ); // hashing by structure - p->pTableF = Fraig_HashTableCreate( 1000 ); // hashing by function - p->pTableF0 = Fraig_HashTableCreate( 1000 ); // hashing by function (for sparse functions) - // create the constant node - p->pConst1 = Fraig_NodeCreateConst( p ); - // initialize SAT solver feedback data structures - Fraig_FeedBackInit( p ); - // initialize other variables - p->vProj = Msat_IntVecAlloc( 10 ); - p->nTravIds = 1; - p->nTravIds2 = 1; - return p; -} - -/**Function************************************************************* - - Synopsis [Deallocates the mapping manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_ManFree( Fraig_Man_t * p ) -{ - int i; - if ( p->fVerbose ) - { - if ( p->fChoicing ) Fraig_ManReportChoices( p ); - Fraig_ManPrintStats( p ); -// Fraig_TablePrintStatsS( p ); -// Fraig_TablePrintStatsF( p ); -// Fraig_TablePrintStatsF0( p ); - } - - for ( i = 0; i < p->vNodes->nSize; i++ ) - if ( p->vNodes->pArray[i]->vFanins ) - { - Fraig_NodeVecFree( p->vNodes->pArray[i]->vFanins ); - p->vNodes->pArray[i]->vFanins = NULL; - } - - if ( p->vInputs ) Fraig_NodeVecFree( p->vInputs ); - if ( p->vNodes ) Fraig_NodeVecFree( p->vNodes ); - if ( p->vOutputs ) Fraig_NodeVecFree( p->vOutputs ); - - if ( p->pTableS ) Fraig_HashTableFree( p->pTableS ); - if ( p->pTableF ) Fraig_HashTableFree( p->pTableF ); - if ( p->pTableF0 ) Fraig_HashTableFree( p->pTableF0 ); - - if ( p->pSat ) Msat_SolverFree( p->pSat ); - if ( p->vProj ) Msat_IntVecFree( p->vProj ); - if ( p->vCones ) Fraig_NodeVecFree( p->vCones ); - if ( p->vPatsReal ) Msat_IntVecFree( p->vPatsReal ); - if ( p->pModel ) ABC_FREE( p->pModel ); - - Fraig_MemFixedStop( p->mmNodes, 0 ); - Fraig_MemFixedStop( p->mmSims, 0 ); - - if ( p->pSuppS ) - { - ABC_FREE( p->pSuppS[0] ); - ABC_FREE( p->pSuppS ); - } - if ( p->pSuppF ) - { - ABC_FREE( p->pSuppF[0] ); - ABC_FREE( p->pSuppF ); - } - - ABC_FREE( p->ppOutputNames ); - ABC_FREE( p->ppInputNames ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Prepares the SAT solver to run on the two nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_ManCreateSolver( Fraig_Man_t * p ) -{ - extern int timeSelect; - extern int timeAssign; - assert( p->pSat == NULL ); - // allocate data for SAT solving - p->pSat = Msat_SolverAlloc( 500, 1, 1, 1, 1, 0 ); - p->vVarsInt = Msat_SolverReadConeVars( p->pSat ); - p->vAdjacents = Msat_SolverReadAdjacents( p->pSat ); - p->vVarsUsed = Msat_SolverReadVarsUsed( p->pSat ); - timeSelect = 0; - timeAssign = 0; -} - - -/**Function************************************************************* - - Synopsis [Deallocates the mapping manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_ManPrintStats( Fraig_Man_t * p ) -{ - double nMemory; - nMemory = ((double)(p->vInputs->nSize + p->vNodes->nSize) * - (sizeof(Fraig_Node_t) + sizeof(unsigned)*(p->nWordsRand + p->nWordsDyna) /*+ p->nSuppWords*sizeof(unsigned)*/))/(1<<20); - printf( "Words: Random = %d. Dynamic = %d. Used = %d. Memory = %0.2f Mb.\n", - p->nWordsRand, p->nWordsDyna, p->iWordPerm, nMemory ); - printf( "Proof = %d. Counter-example = %d. Fail = %d. FailReal = %d. Zero = %d.\n", - p->nSatProof, p->nSatCounter, p->nSatFails, p->nSatFailsReal, p->nSatZeros ); - printf( "Nodes: Final = %d. Total = %d. Mux = %d. (Exor = %d.) ClaVars = %d.\n", - Fraig_CountNodes(p,0), p->vNodes->nSize, Fraig_ManCountMuxes(p), Fraig_ManCountExors(p), p->nVarsClauses ); - if ( p->pSat ) Msat_SolverPrintStats( p->pSat ); - Fraig_PrintTime( "AIG simulation ", p->timeSims ); - Fraig_PrintTime( "AIG traversal ", p->timeTrav ); - Fraig_PrintTime( "Solver feedback ", p->timeFeed ); - Fraig_PrintTime( "SAT solving ", p->timeSat ); - Fraig_PrintTime( "Network update ", p->timeToNet ); - Fraig_PrintTime( "TOTAL RUNTIME ", p->timeTotal ); - if ( p->time1 > 0 ) { Fraig_PrintTime( "time1", p->time1 ); } - if ( p->time2 > 0 ) { Fraig_PrintTime( "time2", p->time2 ); } - if ( p->time3 > 0 ) { Fraig_PrintTime( "time3", p->time3 ); } - if ( p->time4 > 0 ) { Fraig_PrintTime( "time4", p->time4 ); } -// ABC_PRT( "Selection ", timeSelect ); -// ABC_PRT( "Assignment", timeAssign ); - fflush( stdout ); -} - -/**Function************************************************************* - - Synopsis [Allocates simulation information for all nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_NodeVec_t * Fraig_UtilInfoAlloc( int nSize, int nWords, int fClean ) -{ - Fraig_NodeVec_t * vInfo; - unsigned * pUnsigned; - int i; - assert( nSize > 0 && nWords > 0 ); - vInfo = Fraig_NodeVecAlloc( nSize ); - pUnsigned = ABC_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 /// -//////////////////////////////////////////////////////////////////////// - -ABC_NAMESPACE_IMPL_END - diff --git a/src/sat/fraig/fraigMem.c b/src/sat/fraig/fraigMem.c deleted file mode 100644 index ef52765e..00000000 --- a/src/sat/fraig/fraigMem.c +++ /dev/null @@ -1,251 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraigMem.c] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [Fixed-size-entry memory manager for the FRAIG package.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - October 1, 2004] - - Revision [$Id: fraigMem.c,v 1.4 2005/07/08 01:01:31 alanmi Exp $] - -***********************************************************************/ - -#include "fraigInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -struct Fraig_MemFixed_t_ -{ - // information about individual entries - int nEntrySize; // the size of one entry - int nEntriesAlloc; // the total number of entries allocated - int nEntriesUsed; // the number of entries in use - int nEntriesMax; // the max number of entries in use - char * pEntriesFree; // the linked list of free entries - - // this is where the memory is stored - int nChunkSize; // the size of one chunk - int nChunksAlloc; // the maximum number of memory chunks - int nChunks; // the current number of memory chunks - char ** pChunks; // the allocated memory - - // statistics - int nMemoryUsed; // memory used in the allocated entries - int nMemoryAlloc; // memory allocated -}; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the internal memory manager.] - - Description [Can only work with entry size at least 4 byte long.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_MemFixed_t * Fraig_MemFixedStart( int nEntrySize ) -{ - Fraig_MemFixed_t * p; - - p = ABC_ALLOC( Fraig_MemFixed_t, 1 ); - memset( p, 0, sizeof(Fraig_MemFixed_t) ); - - p->nEntrySize = nEntrySize; - p->nEntriesAlloc = 0; - p->nEntriesUsed = 0; - p->pEntriesFree = NULL; - - if ( nEntrySize * (1 << 10) < (1<<16) ) - p->nChunkSize = (1 << 10); - else - p->nChunkSize = (1<<16) / nEntrySize; - if ( p->nChunkSize < 8 ) - p->nChunkSize = 8; - - p->nChunksAlloc = 64; - p->nChunks = 0; - p->pChunks = ABC_ALLOC( char *, p->nChunksAlloc ); - - p->nMemoryUsed = 0; - p->nMemoryAlloc = 0; - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the internal memory manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_MemFixedStop( Fraig_MemFixed_t * p, int fVerbose ) -{ - int i; - if ( p == NULL ) - return; - if ( fVerbose ) - { - printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n", - p->nEntrySize, p->nChunkSize, p->nChunks ); - printf( " Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n", - p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc ); - } - for ( i = 0; i < p->nChunks; i++ ) - ABC_FREE( p->pChunks[i] ); - ABC_FREE( p->pChunks ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Extracts one entry from the memory manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Fraig_MemFixedEntryFetch( Fraig_MemFixed_t * p ) -{ - char * pTemp; - int i; - - // check if there are still free entries - if ( p->nEntriesUsed == p->nEntriesAlloc ) - { // need to allocate more entries - assert( p->pEntriesFree == NULL ); - if ( p->nChunks == p->nChunksAlloc ) - { - p->nChunksAlloc *= 2; - p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); - } - p->pEntriesFree = ABC_ALLOC( char, p->nEntrySize * p->nChunkSize ); - p->nMemoryAlloc += p->nEntrySize * p->nChunkSize; - // transform these entries into a linked list - pTemp = p->pEntriesFree; - for ( i = 1; i < p->nChunkSize; i++ ) - { - *((char **)pTemp) = pTemp + p->nEntrySize; - pTemp += p->nEntrySize; - } - // set the last link - *((char **)pTemp) = NULL; - // add the chunk to the chunk storage - p->pChunks[ p->nChunks++ ] = p->pEntriesFree; - // add to the number of entries allocated - p->nEntriesAlloc += p->nChunkSize; - } - // incrememt the counter of used entries - p->nEntriesUsed++; - if ( p->nEntriesMax < p->nEntriesUsed ) - p->nEntriesMax = p->nEntriesUsed; - // return the first entry in the free entry list - pTemp = p->pEntriesFree; - p->pEntriesFree = *((char **)pTemp); - return pTemp; -} - -/**Function************************************************************* - - Synopsis [Returns one entry into the memory manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_MemFixedEntryRecycle( Fraig_MemFixed_t * p, char * pEntry ) -{ - // decrement the counter of used entries - p->nEntriesUsed--; - // add the entry to the linked list of free entries - *((char **)pEntry) = p->pEntriesFree; - p->pEntriesFree = pEntry; -} - -/**Function************************************************************* - - Synopsis [Frees all associated memory and resets the manager.] - - Description [Relocates all the memory except the first chunk.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_MemFixedRestart( Fraig_MemFixed_t * p ) -{ - int i; - char * pTemp; - - // deallocate all chunks except the first one - for ( i = 1; i < p->nChunks; i++ ) - ABC_FREE( p->pChunks[i] ); - p->nChunks = 1; - // transform these entries into a linked list - pTemp = p->pChunks[0]; - for ( i = 1; i < p->nChunkSize; i++ ) - { - *((char **)pTemp) = pTemp + p->nEntrySize; - pTemp += p->nEntrySize; - } - // set the last link - *((char **)pTemp) = NULL; - // set the free entry list - p->pEntriesFree = p->pChunks[0]; - // set the correct statistics - p->nMemoryAlloc = p->nEntrySize * p->nChunkSize; - p->nMemoryUsed = 0; - p->nEntriesAlloc = p->nChunkSize; - p->nEntriesUsed = 0; -} - -/**Function************************************************************* - - Synopsis [Reports the memory usage.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_MemFixedReadMemUsage( Fraig_MemFixed_t * p ) -{ - return p->nMemoryAlloc; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/sat/fraig/fraigNode.c b/src/sat/fraig/fraigNode.c deleted file mode 100644 index 9f95cd46..00000000 --- a/src/sat/fraig/fraigNode.c +++ /dev/null @@ -1,318 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraigNode.c] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [Implementation of the FRAIG node.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - October 1, 2004] - - Revision [$Id: fraigNode.c,v 1.3 2005/07/08 01:01:32 alanmi Exp $] - -***********************************************************************/ - -#include "fraigInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// returns the complemented attribute of the node -#define Fraig_NodeIsSimComplement(p) (Fraig_IsComplement(p)? !(Fraig_Regular(p)->fInv) : (p)->fInv) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates the constant 1 node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_NodeCreateConst( Fraig_Man_t * p ) -{ - Fraig_Node_t * pNode; - - // create the node - pNode = (Fraig_Node_t *)Fraig_MemFixedEntryFetch( p->mmNodes ); - memset( pNode, 0, sizeof(Fraig_Node_t) ); - - // assign the number and add to the array of nodes - pNode->Num = p->vNodes->nSize; - Fraig_NodeVecPush( p->vNodes, pNode ); - pNode->NumPi = -1; // this is not a PI, so its number is -1 - pNode->Level = 0; // just like a PI, it has 0 level - pNode->nRefs = 1; // it is a persistent node, which comes referenced - pNode->fInv = 1; // the simulation info is complemented - - // create the simulation info - pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); - pNode->puSimD = pNode->puSimR + p->nWordsRand; - memset( pNode->puSimR, 0, sizeof(unsigned) * p->nWordsRand ); - memset( pNode->puSimD, 0, sizeof(unsigned) * p->nWordsDyna ); - - // count the number of ones in the simulation vector - pNode->nOnes = p->nWordsRand * sizeof(unsigned) * 8; - - // insert it into the hash table - Fraig_HashTableLookupF0( p, pNode ); - return pNode; -} - -/**Function************************************************************* - - Synopsis [Creates a primary input node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_NodeCreatePi( Fraig_Man_t * p ) -{ - Fraig_Node_t * pNode, * pNodeRes; - int i, clk; - - // create the node - pNode = (Fraig_Node_t *)Fraig_MemFixedEntryFetch( p->mmNodes ); - memset( pNode, 0, sizeof(Fraig_Node_t) ); - pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); - pNode->puSimD = pNode->puSimR + p->nWordsRand; - memset( pNode->puSimD, 0, sizeof(unsigned) * p->nWordsDyna ); - - // assign the number and add to the array of nodes - pNode->Num = p->vNodes->nSize; - Fraig_NodeVecPush( p->vNodes, pNode ); - - // assign the PI number and add to the array of primary inputs - pNode->NumPi = p->vInputs->nSize; - Fraig_NodeVecPush( p->vInputs, pNode ); - - pNode->Level = 0; // PI has 0 level - pNode->nRefs = 1; // it is a persistent node, which comes referenced - pNode->fInv = 0; // the simulation info of the PI is not complemented - - // derive the simulation info for the new node -clk = clock(); - // set the random simulation info for the primary input - pNode->uHashR = 0; - for ( i = 0; i < p->nWordsRand; i++ ) - { - // generate the simulation info - pNode->puSimR[i] = FRAIG_RANDOM_UNSIGNED; - // for reasons that take very long to explain, it makes sense to have (0000000...) - // pattern in the set (this helps if we need to return the counter-examples) - if ( i == 0 ) - pNode->puSimR[i] <<= 1; - // compute the hash key - pNode->uHashR ^= pNode->puSimR[i] * s_FraigPrimes[i]; - } - // count the number of ones in the simulation vector - pNode->nOnes = Fraig_BitStringCountOnes( pNode->puSimR, p->nWordsRand ); - - // set the systematic simulation info for the primary input - pNode->uHashD = 0; - for ( i = 0; i < p->iWordStart; i++ ) - { - // generate the simulation info - pNode->puSimD[i] = FRAIG_RANDOM_UNSIGNED; - // compute the hash key - pNode->uHashD ^= pNode->puSimD[i] * s_FraigPrimes[i]; - } -p->timeSims += clock() - clk; - - // insert it into the hash table - pNodeRes = Fraig_HashTableLookupF( p, pNode ); - assert( pNodeRes == NULL ); - // add to the runtime of simulation - return pNode; -} - -/**Function************************************************************* - - Synopsis [Creates a new node.] - - Description [This procedure should be called to create the constant - node and the PI nodes first.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_NodeCreate( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ) -{ - Fraig_Node_t * pNode; - int clk; - - // create the node - pNode = (Fraig_Node_t *)Fraig_MemFixedEntryFetch( p->mmNodes ); - memset( pNode, 0, sizeof(Fraig_Node_t) ); - - // assign the children - pNode->p1 = p1; Fraig_Ref(p1); Fraig_Regular(p1)->nRefs++; - pNode->p2 = p2; Fraig_Ref(p2); Fraig_Regular(p2)->nRefs++; - - // assign the number and add to the array of nodes - pNode->Num = p->vNodes->nSize; - Fraig_NodeVecPush( p->vNodes, pNode ); - - // assign the PI number - pNode->NumPi = -1; - - // compute the level of this node - pNode->Level = 1 + ABC_MAX(Fraig_Regular(p1)->Level, Fraig_Regular(p2)->Level); - pNode->fInv = Fraig_NodeIsSimComplement(p1) & Fraig_NodeIsSimComplement(p2); - pNode->fFailTfo = Fraig_Regular(p1)->fFailTfo | Fraig_Regular(p2)->fFailTfo; - - // derive the simulation info -clk = clock(); - // allocate memory for the simulation info - pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); - pNode->puSimD = pNode->puSimR + p->nWordsRand; - // derive random simulation info - pNode->uHashR = 0; - Fraig_NodeSimulate( pNode, 0, p->nWordsRand, 1 ); - // derive dynamic simulation info - pNode->uHashD = 0; - Fraig_NodeSimulate( pNode, 0, p->iWordStart, 0 ); - // count the number of ones in the random simulation info - pNode->nOnes = Fraig_BitStringCountOnes( pNode->puSimR, p->nWordsRand ); - if ( pNode->fInv ) - pNode->nOnes = p->nWordsRand * 32 - pNode->nOnes; - // add to the runtime of simulation -p->timeSims += clock() - clk; - -#ifdef FRAIG_ENABLE_FANOUTS - // create the fanout info - Fraig_NodeAddFaninFanout( Fraig_Regular(p1), pNode ); - Fraig_NodeAddFaninFanout( Fraig_Regular(p2), pNode ); -#endif - return pNode; -} - - -/**Function************************************************************* - - Synopsis [Simulates the node.] - - Description [Simulates the random or dynamic simulation info through - the node. Uses phases of the children to determine their real simulation - info. Uses phase of the node to determine the way its simulation info - is stored. The resulting info is guaranteed to be 0 for the first pattern.] - - SideEffects [This procedure modified the hash value of the simulation info.] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeSimulate( Fraig_Node_t * pNode, int iWordStart, int iWordStop, int fUseRand ) -{ - unsigned * pSims, * pSims1, * pSims2; - unsigned uHash; - int fCompl, fCompl1, fCompl2, i; - - assert( !Fraig_IsComplement(pNode) ); - - // get hold of the simulation information - pSims = fUseRand? pNode->puSimR : pNode->puSimD; - pSims1 = fUseRand? Fraig_Regular(pNode->p1)->puSimR : Fraig_Regular(pNode->p1)->puSimD; - pSims2 = fUseRand? Fraig_Regular(pNode->p2)->puSimR : Fraig_Regular(pNode->p2)->puSimD; - - // get complemented attributes of the children using their random info - fCompl = pNode->fInv; - fCompl1 = Fraig_NodeIsSimComplement(pNode->p1); - fCompl2 = Fraig_NodeIsSimComplement(pNode->p2); - - // simulate - uHash = 0; - if ( fCompl1 && fCompl2 ) - { - if ( fCompl ) - for ( i = iWordStart; i < iWordStop; i++ ) - { - pSims[i] = (pSims1[i] | pSims2[i]); - uHash ^= pSims[i] * s_FraigPrimes[i]; - } - else - for ( i = iWordStart; i < iWordStop; i++ ) - { - pSims[i] = ~(pSims1[i] | pSims2[i]); - uHash ^= pSims[i] * s_FraigPrimes[i]; - } - } - else if ( fCompl1 && !fCompl2 ) - { - if ( fCompl ) - for ( i = iWordStart; i < iWordStop; i++ ) - { - pSims[i] = (pSims1[i] | ~pSims2[i]); - uHash ^= pSims[i] * s_FraigPrimes[i]; - } - else - for ( i = iWordStart; i < iWordStop; i++ ) - { - pSims[i] = (~pSims1[i] & pSims2[i]); - uHash ^= pSims[i] * s_FraigPrimes[i]; - } - } - else if ( !fCompl1 && fCompl2 ) - { - if ( fCompl ) - for ( i = iWordStart; i < iWordStop; i++ ) - { - pSims[i] = (~pSims1[i] | pSims2[i]); - uHash ^= pSims[i] * s_FraigPrimes[i]; - } - else - for ( i = iWordStart; i < iWordStop; i++ ) - { - pSims[i] = (pSims1[i] & ~pSims2[i]); - uHash ^= pSims[i] * s_FraigPrimes[i]; - } - } - else // if ( !fCompl1 && !fCompl2 ) - { - if ( fCompl ) - for ( i = iWordStart; i < iWordStop; i++ ) - { - pSims[i] = ~(pSims1[i] & pSims2[i]); - uHash ^= pSims[i] * s_FraigPrimes[i]; - } - else - for ( i = iWordStart; i < iWordStop; i++ ) - { - pSims[i] = (pSims1[i] & pSims2[i]); - uHash ^= pSims[i] * s_FraigPrimes[i]; - } - } - - if ( fUseRand ) - pNode->uHashR ^= uHash; - else - pNode->uHashD ^= uHash; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - -ABC_NAMESPACE_IMPL_END - diff --git a/src/sat/fraig/fraigPrime.c b/src/sat/fraig/fraigPrime.c deleted file mode 100644 index 42a079fd..00000000 --- a/src/sat/fraig/fraigPrime.c +++ /dev/null @@ -1,149 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraigPrime.c] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [The table of the first 1000 primes.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - October 1, 2004] - - Revision [$Id: fraigPrime.c,v 1.4 2005/07/08 01:01:32 alanmi Exp $] - -***********************************************************************/ - -#include "fraigInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// The 1,024 smallest prime numbers used to compute the hash value -// http://www.math.utah.edu/~alfeld/math/primelist.html -int s_FraigPrimes[FRAIG_MAX_PRIMES] = { 2, 3, 5, -7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, -101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, -193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, -293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, -409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, -521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, -641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, -757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, -881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, -1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, -1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, -1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, -1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, -1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, -1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, -1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, -1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, -1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, -1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, -2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, -2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, -2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, -2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, -2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, -2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, -2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, -2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, -2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, -3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, -3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, -3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, -3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, -3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, -3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, -3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, -3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, -3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, -4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, -4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, -4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, -4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, -4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, -4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, -4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, -4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, -5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, -5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, -5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, -5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, -5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, -5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, -5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, -5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, -6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, -6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, -6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, -6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, -6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, -6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, -6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, -6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, -6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, -7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, -7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, -7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, -7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, -7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, -7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, -7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, -8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123, -8147, 8161 }; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function******************************************************************** - - Synopsis [Returns the next prime >= p.] - - Description [Copied from CUDD, for stand-aloneness.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -unsigned int Cudd_PrimeFraig( unsigned int p) -{ - int i,pn; - - p--; - do { - p++; - if (p&1) { - pn = 1; - i = 3; - while ((unsigned) (i * i) <= p) { - if (p % i == 0) { - pn = 0; - break; - } - i += 2; - } - } else { - pn = 0; - } - } while (!pn); - return(p); - -} /* end of Cudd_Prime */ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/sat/fraig/fraigSat.c b/src/sat/fraig/fraigSat.c deleted file mode 100644 index b96bc5a1..00000000 --- a/src/sat/fraig/fraigSat.c +++ /dev/null @@ -1,1459 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraigSat.c] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [Proving functional equivalence using SAT.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - October 1, 2004] - - Revision [$Id: fraigSat.c,v 1.10 2005/07/08 01:01:32 alanmi Exp $] - -***********************************************************************/ - -#include -#include "fraigInt.h" -#include "msatInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Fraig_OrderVariables( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); -static void Fraig_SetupAdjacent( Fraig_Man_t * pMan, Msat_IntVec_t * vConeVars ); -static void Fraig_SetupAdjacentMark( Fraig_Man_t * pMan, Msat_IntVec_t * vConeVars ); -static void Fraig_PrepareCones( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); -static void Fraig_PrepareCones_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); - -static void Fraig_SupergateAddClauses( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper ); -static void Fraig_SupergateAddClausesExor( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); -static void Fraig_SupergateAddClausesMux( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); -//static void Fraig_DetectFanoutFreeCone( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); -static void Fraig_DetectFanoutFreeConeMux( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); -static void Fraig_SetActivity( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); - -// The lesson learned seems to be that variable should be in reverse topological order -// from the output of the miter. The ordering of adjacency lists is very important. -// The best way seems to be fanins followed by fanouts. Slight changes to this order -// leads to big degradation in quality. - -static int nMuxes; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Checks equivalence of two nodes.] - - Description [Returns 1 iff the nodes are equivalent.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodesAreEqual( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit, int nTimeLimit ) -{ - if ( pNode1 == pNode2 ) - return 1; - if ( pNode1 == Fraig_Not(pNode2) ) - return 0; - return Fraig_NodeIsEquivalent( p, Fraig_Regular(pNode1), Fraig_Regular(pNode2), nBTLimit, nTimeLimit ); -} - -/**Function************************************************************* - - Synopsis [Tries to prove the final miter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_ManProveMiter( Fraig_Man_t * p ) -{ - Fraig_Node_t * pNode; - int i, clk; - - if ( !p->fTryProve ) - return; - - clk = clock(); - // consider all outputs of the multi-output miter - for ( i = 0; i < p->vOutputs->nSize; i++ ) - { - pNode = Fraig_Regular(p->vOutputs->pArray[i]); - // skip already constant nodes - if ( pNode == p->pConst1 ) - continue; - // skip nodes that are different according to simulation - if ( !Fraig_CompareSimInfo( pNode, p->pConst1, p->nWordsRand, 1 ) ) - continue; - if ( Fraig_NodeIsEquivalent( p, p->pConst1, pNode, -1, p->nSeconds ) ) - { - if ( Fraig_IsComplement(p->vOutputs->pArray[i]) ^ Fraig_NodeComparePhase(p->pConst1, pNode) ) - p->vOutputs->pArray[i] = Fraig_Not(p->pConst1); - else - p->vOutputs->pArray[i] = p->pConst1; - } - } - if ( p->fVerboseP ) - { -// ABC_PRT( "Final miter proof time", clock() - clk ); - } -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the miter is unsat; 0 if sat; -1 if undecided.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_ManCheckMiter( Fraig_Man_t * p ) -{ - Fraig_Node_t * pNode; - int i; - ABC_FREE( p->pModel ); - for ( i = 0; i < p->vOutputs->nSize; i++ ) - { - // get the output node (it can be complemented!) - pNode = p->vOutputs->pArray[i]; - // if the miter is constant 0, the problem is UNSAT - if ( pNode == Fraig_Not(p->pConst1) ) - continue; - // consider the special case when the miter is constant 1 - if ( pNode == p->pConst1 ) - { - // in this case, any counter example will do to distinquish it from constant 0 - // here we pick the counter example composed of all zeros - p->pModel = Fraig_ManAllocCounterExample( p ); - return 0; - } - // save the counter example - p->pModel = Fraig_ManSaveCounterExample( p, pNode ); - // if the model is not found, return undecided - if ( p->pModel == NULL ) - return -1; - else - return 0; - } - return 1; -} - - -/**Function************************************************************* - - Synopsis [Returns 1 if pOld is in the TFI of pNew.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_MarkTfi_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) -{ - // skip the visited node - if ( pNode->TravId == pMan->nTravIds ) - return 0; - pNode->TravId = pMan->nTravIds; - // skip the PI node - if ( pNode->NumPi >= 0 ) - return 1; - // check the children - return Fraig_MarkTfi_rec( pMan, Fraig_Regular(pNode->p1) ) + - Fraig_MarkTfi_rec( pMan, Fraig_Regular(pNode->p2) ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if pOld is in the TFI of pNew.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_MarkTfi2_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) -{ - // skip the visited node - if ( pNode->TravId == pMan->nTravIds ) - return 0; - // skip the boundary node - if ( pNode->TravId == pMan->nTravIds-1 ) - { - pNode->TravId = pMan->nTravIds; - return 1; - } - pNode->TravId = pMan->nTravIds; - // skip the PI node - if ( pNode->NumPi >= 0 ) - return 1; - // check the children - return Fraig_MarkTfi2_rec( pMan, Fraig_Regular(pNode->p1) ) + - Fraig_MarkTfi2_rec( pMan, Fraig_Regular(pNode->p2) ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if pOld is in the TFI of pNew.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_MarkTfi3_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) -{ - // skip the visited node - if ( pNode->TravId == pMan->nTravIds ) - return 1; - // skip the boundary node - if ( pNode->TravId == pMan->nTravIds-1 ) - { - pNode->TravId = pMan->nTravIds; - return 1; - } - pNode->TravId = pMan->nTravIds; - // skip the PI node - if ( pNode->NumPi >= 0 ) - return 0; - // check the children - return Fraig_MarkTfi3_rec( pMan, Fraig_Regular(pNode->p1) ) * - Fraig_MarkTfi3_rec( pMan, Fraig_Regular(pNode->p2) ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_VarsStudy( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) -{ - int NumPis, NumCut, fContain; - - // mark the TFI of pNew - p->nTravIds++; - NumPis = Fraig_MarkTfi_rec( p, pNew ); - printf( "(%d)(%d,%d):", NumPis, pOld->Level, pNew->Level ); - - // check if the old is in the TFI - if ( pOld->TravId == p->nTravIds ) - { - printf( "* " ); - return; - } - - // count the boundary of nodes in pOld - p->nTravIds++; - NumCut = Fraig_MarkTfi2_rec( p, pOld ); - printf( "%d", NumCut ); - - // check if the new is contained in the old's support - p->nTravIds++; - fContain = Fraig_MarkTfi3_rec( p, pNew ); - printf( "%c ", fContain? '+':'-' ); -} - - -/**Function************************************************************* - - Synopsis [Checks whether two nodes are functinally equivalent.] - - Description [The flag (fComp) tells whether the nodes to be checked - are in the opposite polarity. The second flag (fSkipZeros) tells whether - the checking should be performed if the simulation vectors are zeros. - Returns 1 if the nodes are equivalent; 0 othewise.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeIsEquivalent( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit, int nTimeLimit ) -{ - int RetValue, RetValue1, i, fComp, clk; - int fVerbose = 0; - int fSwitch = 0; - - // make sure the nodes are not complemented - assert( !Fraig_IsComplement(pNew) ); - assert( !Fraig_IsComplement(pOld) ); - assert( pNew != pOld ); - - // if at least one of the nodes is a failed node, perform adjustments: - // if the backtrack limit is small, simply skip this node - // if the backtrack limit is > 10, take the quare root of the limit - if ( nBTLimit > 0 && (pOld->fFailTfo || pNew->fFailTfo) ) - { - p->nSatFails++; -// return 0; -// if ( nBTLimit > 10 ) -// nBTLimit /= 10; - if ( nBTLimit <= 10 ) - return 0; - nBTLimit = (int)sqrt((double)nBTLimit); -// fSwitch = 1; - } - - p->nSatCalls++; - - // make sure the solver is allocated and has enough variables - if ( p->pSat == NULL ) - Fraig_ManCreateSolver( p ); - // make sure the SAT solver has enough variables - for ( i = Msat_SolverReadVarNum(p->pSat); i < p->vNodes->nSize; i++ ) - Msat_SolverAddVar( p->pSat, p->vNodes->pArray[i]->Level ); - - - -/* - { - Fraig_Node_t * ppNodes[2] = { pOld, pNew }; - extern void Fraig_MappingShowNodes( Fraig_Man_t * pMan, Fraig_Node_t ** ppRoots, int nRoots, char * pFileName ); - Fraig_MappingShowNodes( p, ppNodes, 2, "temp_aig" ); - } -*/ - - nMuxes = 0; - - - // get the logic cone -clk = clock(); -// Fraig_VarsStudy( p, pOld, pNew ); - Fraig_OrderVariables( p, pOld, pNew ); -// Fraig_PrepareCones( p, pOld, pNew ); -p->timeTrav += clock() - clk; - -// printf( "The number of MUXes detected = %d (%5.2f %% of logic). ", nMuxes, 300.0*nMuxes/(p->vNodes->nSize - p->vInputs->nSize) ); -// ABC_PRT( "Time", clock() - clk ); - -if ( fVerbose ) - printf( "%d(%d) - ", Fraig_CountPis(p,p->vVarsInt), Msat_IntVecReadSize(p->vVarsInt) ); - - - // prepare variable activity - Fraig_SetActivity( p, pOld, pNew ); - - // get the complemented attribute - fComp = Fraig_NodeComparePhase( pOld, pNew ); -//Msat_SolverPrintClauses( p->pSat ); - - //////////////////////////////////////////// - // prepare the solver to run incrementally on these variables -//clk = clock(); - Msat_SolverPrepare( p->pSat, p->vVarsInt ); -//p->time3 += clock() - clk; - - - // solve under assumptions - // A = 1; B = 0 OR A = 1; B = 1 - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 0) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, !fComp) ); - -//Msat_SolverWriteDimacs( p->pSat, "temp_fraig.cnf" ); - - // run the solver -clk = clock(); - RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, nTimeLimit ); -p->timeSat += clock() - clk; - - if ( RetValue1 == MSAT_FALSE ) - { -//p->time1 += clock() - clk; - -if ( fVerbose ) -{ -// printf( "unsat %d ", Msat_SolverReadBackTracks(p->pSat) ); -//ABC_PRT( "time", clock() - clk ); -} - - // add the clause - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 1) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, fComp) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); - // continue solving the other implication - } - else if ( RetValue1 == MSAT_TRUE ) - { -//p->time2 += clock() - clk; - -if ( fVerbose ) -{ -// printf( "sat %d ", Msat_SolverReadBackTracks(p->pSat) ); -//ABC_PRT( "time", clock() - clk ); -} - - // record the counter example - Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pOld, pNew ); - -// if ( pOld->fFailTfo || pNew->fFailTfo ) -// printf( "*" ); -// printf( "s(%d)", pNew->Level ); - if ( fSwitch ) - printf( "s(%d)", pNew->Level ); - p->nSatCounter++; - return 0; - } - else // if ( RetValue1 == MSAT_UNKNOWN ) - { -p->time3 += clock() - clk; - -// if ( pOld->fFailTfo || pNew->fFailTfo ) -// printf( "*" ); -// printf( "T(%d)", pNew->Level ); - - // mark the node as the failed node - if ( pOld != p->pConst1 ) - pOld->fFailTfo = 1; - pNew->fFailTfo = 1; -// p->nSatFails++; - if ( fSwitch ) - printf( "T(%d)", pNew->Level ); - p->nSatFailsReal++; - return 0; - } - - // if the old node was constant 0, we already know the answer - if ( pOld == p->pConst1 ) - return 1; - - //////////////////////////////////////////// - // prepare the solver to run incrementally -//clk = clock(); - Msat_SolverPrepare( p->pSat, p->vVarsInt ); -//p->time3 += clock() - clk; - // solve under assumptions - // A = 0; B = 1 OR A = 0; B = 0 - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 1) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, fComp) ); - // run the solver -clk = clock(); - RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, nTimeLimit ); -p->timeSat += clock() - clk; - - if ( RetValue1 == MSAT_FALSE ) - { -//p->time1 += clock() - clk; - -if ( fVerbose ) -{ -// printf( "unsat %d ", Msat_SolverReadBackTracks(p->pSat) ); -//ABC_PRT( "time", clock() - clk ); -} - - // add the clause - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 0) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, !fComp) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); - // continue solving the other implication - } - else if ( RetValue1 == MSAT_TRUE ) - { -//p->time2 += clock() - clk; - -if ( fVerbose ) -{ -// printf( "sat %d ", Msat_SolverReadBackTracks(p->pSat) ); -//ABC_PRT( "time", clock() - clk ); -} - - // record the counter example - Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pOld, pNew ); - p->nSatCounter++; - -// if ( pOld->fFailTfo || pNew->fFailTfo ) -// printf( "*" ); -// printf( "s(%d)", pNew->Level ); - if ( fSwitch ) - printf( "s(%d)", pNew->Level ); - return 0; - } - else // if ( RetValue1 == MSAT_UNKNOWN ) - { -p->time3 += clock() - clk; - -// if ( pOld->fFailTfo || pNew->fFailTfo ) -// printf( "*" ); -// printf( "T(%d)", pNew->Level ); - if ( fSwitch ) - printf( "T(%d)", pNew->Level ); - - // mark the node as the failed node - pOld->fFailTfo = 1; - pNew->fFailTfo = 1; -// p->nSatFails++; - p->nSatFailsReal++; - return 0; - } - - // return SAT proof - p->nSatProof++; - -// if ( pOld->fFailTfo || pNew->fFailTfo ) -// printf( "*" ); -// printf( "u(%d)", pNew->Level ); - - if ( fSwitch ) - printf( "u(%d)", pNew->Level ); - - return 1; -} - - -/**Function************************************************************* - - Synopsis [Checks whether pOld => pNew.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeIsImplication( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit ) -{ - int RetValue, RetValue1, i, fComp, clk; - int fVerbose = 0; - - // make sure the nodes are not complemented - assert( !Fraig_IsComplement(pNew) ); - assert( !Fraig_IsComplement(pOld) ); - assert( pNew != pOld ); - - p->nSatCallsImp++; - - // make sure the solver is allocated and has enough variables - if ( p->pSat == NULL ) - Fraig_ManCreateSolver( p ); - // make sure the SAT solver has enough variables - for ( i = Msat_SolverReadVarNum(p->pSat); i < p->vNodes->nSize; i++ ) - Msat_SolverAddVar( p->pSat, p->vNodes->pArray[i]->Level ); - - // get the logic cone -clk = clock(); - Fraig_OrderVariables( p, pOld, pNew ); -// Fraig_PrepareCones( p, pOld, pNew ); -p->timeTrav += clock() - clk; - -if ( fVerbose ) - printf( "%d(%d) - ", Fraig_CountPis(p,p->vVarsInt), Msat_IntVecReadSize(p->vVarsInt) ); - - - // get the complemented attribute - fComp = Fraig_NodeComparePhase( pOld, pNew ); -//Msat_SolverPrintClauses( p->pSat ); - - //////////////////////////////////////////// - // prepare the solver to run incrementally on these variables -//clk = clock(); - Msat_SolverPrepare( p->pSat, p->vVarsInt ); -//p->time3 += clock() - clk; - - // solve under assumptions - // A = 1; B = 0 OR A = 1; B = 1 - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 0) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, !fComp) ); - // run the solver -clk = clock(); - RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, 1000000 ); -p->timeSat += clock() - clk; - - if ( RetValue1 == MSAT_FALSE ) - { -//p->time1 += clock() - clk; - -if ( fVerbose ) -{ -// printf( "unsat %d ", Msat_SolverReadBackTracks(p->pSat) ); -//ABC_PRT( "time", clock() - clk ); -} - - // add the clause - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 1) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, fComp) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); -// p->nSatProofImp++; - return 1; - } - else if ( RetValue1 == MSAT_TRUE ) - { -//p->time2 += clock() - clk; - -if ( fVerbose ) -{ -// printf( "sat %d ", Msat_SolverReadBackTracks(p->pSat) ); -//ABC_PRT( "time", clock() - clk ); -} - // record the counter example - Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pOld, pNew ); - p->nSatCounterImp++; - return 0; - } - else // if ( RetValue1 == MSAT_UNKNOWN ) - { -p->time3 += clock() - clk; - p->nSatFailsImp++; - return 0; - } -} - -/**Function************************************************************* - - Synopsis [Prepares the SAT solver to run on the two nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_ManCheckClauseUsingSat( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit ) -{ - Fraig_Node_t * pNode1R, * pNode2R; - int RetValue, RetValue1, i, clk; - int fVerbose = 0; - - pNode1R = Fraig_Regular(pNode1); - pNode2R = Fraig_Regular(pNode2); - assert( pNode1R != pNode2R ); - - // make sure the solver is allocated and has enough variables - if ( p->pSat == NULL ) - Fraig_ManCreateSolver( p ); - // make sure the SAT solver has enough variables - for ( i = Msat_SolverReadVarNum(p->pSat); i < p->vNodes->nSize; i++ ) - Msat_SolverAddVar( p->pSat, p->vNodes->pArray[i]->Level ); - - // get the logic cone -clk = clock(); - Fraig_OrderVariables( p, pNode1R, pNode2R ); -// Fraig_PrepareCones( p, pNode1R, pNode2R ); -p->timeTrav += clock() - clk; - - //////////////////////////////////////////// - // prepare the solver to run incrementally on these variables -//clk = clock(); - Msat_SolverPrepare( p->pSat, p->vVarsInt ); -//p->time3 += clock() - clk; - - // solve under assumptions - // A = 1; B = 0 OR A = 1; B = 1 - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1R->Num, !Fraig_IsComplement(pNode1)) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2R->Num, !Fraig_IsComplement(pNode2)) ); - // run the solver -clk = clock(); - RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, 1000000 ); -p->timeSat += clock() - clk; - - if ( RetValue1 == MSAT_FALSE ) - { -//p->time1 += clock() - clk; - -if ( fVerbose ) -{ -// printf( "unsat %d ", Msat_SolverReadBackTracks(p->pSat) ); -//ABC_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) ); -//ABC_PRT( "time", clock() - clk ); -} - // record the counter example -// Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pNode1R, pNode2R ); - p->nSatCounterImp++; - return 0; - } - else // if ( RetValue1 == MSAT_UNKNOWN ) - { -p->time3 += clock() - clk; - p->nSatFailsImp++; - return 0; - } -} - - -/**Function************************************************************* - - Synopsis [Prepares the SAT solver to run on the two nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_PrepareCones( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) -{ -// Msat_IntVec_t * vAdjs; -// int * pVars, nVars, i, k; - int nVarsAlloc; - - assert( pOld != pNew ); - assert( !Fraig_IsComplement(pOld) ); - assert( !Fraig_IsComplement(pNew) ); - // clean the variables - nVarsAlloc = Msat_IntVecReadSize(pMan->vVarsUsed); - Msat_IntVecFill( pMan->vVarsUsed, nVarsAlloc, 0 ); - Msat_IntVecClear( pMan->vVarsInt ); - - pMan->nTravIds++; - Fraig_PrepareCones_rec( pMan, pNew ); - Fraig_PrepareCones_rec( pMan, pOld ); - - -/* - nVars = Msat_IntVecReadSize( pMan->vVarsInt ); - pVars = Msat_IntVecReadArray( pMan->vVarsInt ); - for ( i = 0; i < nVars; i++ ) - { - // process its connections - vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] ); - printf( "%d=%d { ", pVars[i], Msat_IntVecReadSize(vAdjs) ); - for ( k = 0; k < Msat_IntVecReadSize(vAdjs); k++ ) - printf( "%d ", Msat_IntVecReadEntry(vAdjs,k) ); - printf( "}\n" ); - - } - i = 0; -*/ -} - -/**Function************************************************************* - - Synopsis [Traverses the cone, collects the numbers and adds the clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_PrepareCones_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) -{ - Fraig_Node_t * pFanin; - Msat_IntVec_t * vAdjs; - int fUseMuxes = 1, i; - int fItIsTime; - - // skip if the node is aleady visited - assert( !Fraig_IsComplement(pNode) ); - if ( pNode->TravId == pMan->nTravIds ) - return; - pNode->TravId = pMan->nTravIds; - - // collect the node's number (closer to reverse topological order) - Msat_IntVecPush( pMan->vVarsInt, pNode->Num ); - Msat_IntVecWriteEntry( pMan->vVarsUsed, pNode->Num, 1 ); - if ( !Fraig_NodeIsAnd( pNode ) ) - return; - - // if the node does not have fanins, create them - fItIsTime = 0; - if ( pNode->vFanins == NULL ) - { - fItIsTime = 1; - // create the fanins of the supergate - assert( pNode->fClauses == 0 ); - if ( fUseMuxes && Fraig_NodeIsMuxType(pNode) ) - { - pNode->vFanins = Fraig_NodeVecAlloc( 4 ); - Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p1) ); - Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p2) ); - Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p1) ); - Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p2) ); - Fraig_SupergateAddClausesMux( pMan, pNode ); - } - else - { - pNode->vFanins = Fraig_CollectSupergate( pNode, fUseMuxes ); - Fraig_SupergateAddClauses( pMan, pNode, pNode->vFanins ); - } - assert( pNode->vFanins->nSize > 1 ); - pNode->fClauses = 1; - pMan->nVarsClauses++; - - // add fanins - vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pNode->Num ); - assert( Msat_IntVecReadSize( vAdjs ) == 0 ); - for ( i = 0; i < pNode->vFanins->nSize; i++ ) - { - pFanin = Fraig_Regular(pNode->vFanins->pArray[i]); - Msat_IntVecPush( vAdjs, pFanin->Num ); - } - } - - // recursively visit the fanins - for ( i = 0; i < pNode->vFanins->nSize; i++ ) - Fraig_PrepareCones_rec( pMan, Fraig_Regular(pNode->vFanins->pArray[i]) ); - - if ( fItIsTime ) - { - // recursively visit the fanins - for ( i = 0; i < pNode->vFanins->nSize; i++ ) - { - pFanin = Fraig_Regular(pNode->vFanins->pArray[i]); - vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pFanin->Num ); - Msat_IntVecPush( vAdjs, pNode->Num ); - } - } -} - -/**Function************************************************************* - - Synopsis [Collect variables using their proximity from the nodes.] - - Description [This procedure creates a variable order based on collecting - first the nodes that are the closest to the given two target nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_OrderVariables( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) -{ - Fraig_Node_t * pNode, * pFanin; - int i, k, Number, fUseMuxes = 1; - int nVarsAlloc; - - assert( pOld != pNew ); - assert( !Fraig_IsComplement(pOld) ); - assert( !Fraig_IsComplement(pNew) ); - - pMan->nTravIds++; - - // clean the variables - nVarsAlloc = Msat_IntVecReadSize(pMan->vVarsUsed); - Msat_IntVecFill( pMan->vVarsUsed, nVarsAlloc, 0 ); - Msat_IntVecClear( pMan->vVarsInt ); - - // add the first node - Msat_IntVecPush( pMan->vVarsInt, pOld->Num ); - Msat_IntVecWriteEntry( pMan->vVarsUsed, pOld->Num, 1 ); - pOld->TravId = pMan->nTravIds; - - // add the second node - Msat_IntVecPush( pMan->vVarsInt, pNew->Num ); - Msat_IntVecWriteEntry( pMan->vVarsUsed, pNew->Num, 1 ); - pNew->TravId = pMan->nTravIds; - - // create the variable order - for ( i = 0; i < Msat_IntVecReadSize(pMan->vVarsInt); i++ ) - { - // get the new node on the frontier - Number = Msat_IntVecReadEntry(pMan->vVarsInt, i); - pNode = pMan->vNodes->pArray[Number]; - if ( !Fraig_NodeIsAnd(pNode) ) - continue; - - // if the node does not have fanins, create them - if ( pNode->vFanins == NULL ) - { - // create the fanins of the supergate - assert( pNode->fClauses == 0 ); - // detecting a fanout-free cone (experiment only) -// Fraig_DetectFanoutFreeCone( pMan, pNode ); - - if ( fUseMuxes && Fraig_NodeIsMuxType(pNode) ) - { - pNode->vFanins = Fraig_NodeVecAlloc( 4 ); - Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p1) ); - Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p2) ); - Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p1) ); - Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p2) ); - Fraig_SupergateAddClausesMux( pMan, pNode ); -// Fraig_DetectFanoutFreeConeMux( pMan, pNode ); - - nMuxes++; - } - else - { - pNode->vFanins = Fraig_CollectSupergate( pNode, fUseMuxes ); - Fraig_SupergateAddClauses( pMan, pNode, pNode->vFanins ); - } - assert( pNode->vFanins->nSize > 1 ); - pNode->fClauses = 1; - pMan->nVarsClauses++; - - pNode->fMark2 = 1; // goes together with Fraig_SetupAdjacentMark() - } - - // explore the implication fanins of pNode - for ( k = 0; k < pNode->vFanins->nSize; k++ ) - { - pFanin = Fraig_Regular(pNode->vFanins->pArray[k]); - if ( pFanin->TravId == pMan->nTravIds ) // already collected - continue; - // collect and mark - Msat_IntVecPush( pMan->vVarsInt, pFanin->Num ); - Msat_IntVecWriteEntry( pMan->vVarsUsed, pFanin->Num, 1 ); - pFanin->TravId = pMan->nTravIds; - } - } - - // set up the adjacent variable information -// Fraig_SetupAdjacent( pMan, pMan->vVarsInt ); - Fraig_SetupAdjacentMark( pMan, pMan->vVarsInt ); -} - - - -/**Function************************************************************* - - Synopsis [Set up the adjacent variable information.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_SetupAdjacent( Fraig_Man_t * pMan, Msat_IntVec_t * vConeVars ) -{ - Fraig_Node_t * pNode, * pFanin; - Msat_IntVec_t * vAdjs; - int * pVars, nVars, i, k; - - // clean the adjacents for the variables - nVars = Msat_IntVecReadSize( vConeVars ); - pVars = Msat_IntVecReadArray( vConeVars ); - for ( i = 0; i < nVars; i++ ) - { - // process its connections - vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] ); - Msat_IntVecClear( vAdjs ); - - pNode = pMan->vNodes->pArray[pVars[i]]; - if ( !Fraig_NodeIsAnd(pNode) ) - continue; - - // add fanins - vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] ); - for ( k = 0; k < pNode->vFanins->nSize; k++ ) -// for ( k = pNode->vFanins->nSize - 1; k >= 0; k-- ) - { - pFanin = Fraig_Regular(pNode->vFanins->pArray[k]); - Msat_IntVecPush( vAdjs, pFanin->Num ); -// Msat_IntVecPushUniqueOrder( vAdjs, pFanin->Num ); - } - } - // add the fanouts - for ( i = 0; i < nVars; i++ ) - { - pNode = pMan->vNodes->pArray[pVars[i]]; - if ( !Fraig_NodeIsAnd(pNode) ) - continue; - - // add the edges - for ( k = 0; k < pNode->vFanins->nSize; k++ ) -// for ( k = pNode->vFanins->nSize - 1; k >= 0; k-- ) - { - pFanin = Fraig_Regular(pNode->vFanins->pArray[k]); - vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pFanin->Num ); - Msat_IntVecPush( vAdjs, pNode->Num ); -// Msat_IntVecPushUniqueOrder( vAdjs, pFanin->Num ); - } - } -} - - -/**Function************************************************************* - - Synopsis [Set up the adjacent variable information.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_SetupAdjacentMark( Fraig_Man_t * pMan, Msat_IntVec_t * vConeVars ) -{ - Fraig_Node_t * pNode, * pFanin; - Msat_IntVec_t * vAdjs; - int * pVars, nVars, i, k; - - // clean the adjacents for the variables - nVars = Msat_IntVecReadSize( vConeVars ); - pVars = Msat_IntVecReadArray( vConeVars ); - for ( i = 0; i < nVars; i++ ) - { - pNode = pMan->vNodes->pArray[pVars[i]]; - if ( pNode->fMark2 == 0 ) - continue; -// pNode->fMark2 = 0; - - // process its connections -// vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] ); -// Msat_IntVecClear( vAdjs ); - - if ( !Fraig_NodeIsAnd(pNode) ) - continue; - - // add fanins - vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] ); - for ( k = 0; k < pNode->vFanins->nSize; k++ ) -// for ( k = pNode->vFanins->nSize - 1; k >= 0; k-- ) - { - pFanin = Fraig_Regular(pNode->vFanins->pArray[k]); - Msat_IntVecPush( vAdjs, pFanin->Num ); -// Msat_IntVecPushUniqueOrder( vAdjs, pFanin->Num ); - } - } - // add the fanouts - for ( i = 0; i < nVars; i++ ) - { - pNode = pMan->vNodes->pArray[pVars[i]]; - if ( pNode->fMark2 == 0 ) - continue; - pNode->fMark2 = 0; - - if ( !Fraig_NodeIsAnd(pNode) ) - continue; - - // add the edges - for ( k = 0; k < pNode->vFanins->nSize; k++ ) -// for ( k = pNode->vFanins->nSize - 1; k >= 0; k-- ) - { - pFanin = Fraig_Regular(pNode->vFanins->pArray[k]); - vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pFanin->Num ); - Msat_IntVecPush( vAdjs, pNode->Num ); -// Msat_IntVecPushUniqueOrder( vAdjs, pFanin->Num ); - } - } -} - - - - -/**Function************************************************************* - - Synopsis [Adds clauses to the solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_SupergateAddClauses( Fraig_Man_t * p, Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper ) -{ - int fComp1, RetValue, nVars, Var, Var1, i; - - assert( Fraig_NodeIsAnd( pNode ) ); - nVars = Msat_SolverReadVarNum(p->pSat); - - Var = pNode->Num; - assert( Var < nVars ); - for ( i = 0; i < vSuper->nSize; i++ ) - { - // get the predecessor nodes - // get the complemented attributes of the nodes - fComp1 = Fraig_IsComplement(vSuper->pArray[i]); - // determine the variable numbers - Var1 = Fraig_Regular(vSuper->pArray[i])->Num; - // check that the variables are in the SAT manager - assert( Var1 < nVars ); - - // suppose the AND-gate is A * B = C - // add !A => !C or A + !C - // fprintf( pFile, "%d %d 0%c", Var1, -Var, 10 ); - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(Var1, fComp1) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(Var, 1) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); - } - - // add A & B => C or !A + !B + C -// fprintf( pFile, "%d %d %d 0%c", -Var1, -Var2, Var, 10 ); - Msat_IntVecClear( p->vProj ); - for ( i = 0; i < vSuper->nSize; i++ ) - { - // get the predecessor nodes - // get the complemented attributes of the nodes - fComp1 = Fraig_IsComplement(vSuper->pArray[i]); - // determine the variable numbers - Var1 = Fraig_Regular(vSuper->pArray[i])->Num; - - // add this variable to the array - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(Var1, !fComp1) ); - } - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(Var, 0) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); -} - -/**Function************************************************************* - - Synopsis [Adds clauses to the solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_SupergateAddClausesExor( Fraig_Man_t * p, Fraig_Node_t * pNode ) -{ - Fraig_Node_t * pNode1, * pNode2; - int fComp, RetValue; - - assert( !Fraig_IsComplement( pNode ) ); - assert( Fraig_NodeIsExorType( pNode ) ); - // get nodes - pNode1 = Fraig_Regular(Fraig_Regular(pNode->p1)->p1); - pNode2 = Fraig_Regular(Fraig_Regular(pNode->p1)->p2); - // get the complemented attribute of the EXOR/NEXOR gate - fComp = Fraig_NodeIsExor( pNode ); // 1 if EXOR, 0 if NEXOR - - // create four clauses - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, fComp) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1->Num, fComp) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2->Num, fComp) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, fComp) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1->Num, !fComp) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2->Num, !fComp) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, !fComp) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1->Num, fComp) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2->Num, !fComp) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, !fComp) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1->Num, !fComp) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2->Num, fComp) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); -} - -/**Function************************************************************* - - Synopsis [Adds clauses to the solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_SupergateAddClausesMux( Fraig_Man_t * p, Fraig_Node_t * pNode ) -{ - Fraig_Node_t * pNodeI, * pNodeT, * pNodeE; - int RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE; - - assert( !Fraig_IsComplement( pNode ) ); - assert( Fraig_NodeIsMuxType( pNode ) ); - // get nodes (I = if, T = then, E = else) - pNodeI = Fraig_NodeRecognizeMux( pNode, &pNodeT, &pNodeE ); - // get the variable numbers - VarF = pNode->Num; - VarI = pNodeI->Num; - VarT = Fraig_Regular(pNodeT)->Num; - VarE = Fraig_Regular(pNodeE)->Num; - // get the complementation flags - fCompT = Fraig_IsComplement(pNodeT); - fCompE = Fraig_IsComplement(pNodeE); - - // f = ITE(i, t, e) - - // i' + t' + f - // i' + t + f' - // i + e' + f - // i + e + f' - - // create four clauses - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarI, 1) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT, 1^fCompT) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 0) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarI, 1) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT, 0^fCompT) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 1) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarI, 0) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE, 1^fCompE) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 0) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarI, 0) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE, 0^fCompE) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 1) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); - - // two additional clauses - // t' & e' -> f' - // t & e -> f - - // t + e + f' - // t' + e' + f - - if ( VarT == VarE ) - { -// assert( fCompT == !fCompE ); - return; - } - - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT, 0^fCompT) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE, 0^fCompE) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 1) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT, 1^fCompT) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE, 1^fCompE) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 0) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); - -} - - - - - -/**Function************************************************************* - - Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_DetectFanoutFreeCone_rec( Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper, Fraig_NodeVec_t * vInside, int fFirst ) -{ - // make the pointer regular - pNode = Fraig_Regular(pNode); - // if the new node is complemented or a PI, another gate begins - if ( (!fFirst && pNode->nRefs > 1) || Fraig_NodeIsVar(pNode) ) - { - Fraig_NodeVecPushUnique( vSuper, pNode ); - return; - } - // go through the branches - Fraig_DetectFanoutFreeCone_rec( pNode->p1, vSuper, vInside, 0 ); - Fraig_DetectFanoutFreeCone_rec( pNode->p2, vSuper, vInside, 0 ); - // add the node - Fraig_NodeVecPushUnique( vInside, pNode ); -} - -/**Function************************************************************* - - Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -/* -void Fraig_DetectFanoutFreeCone( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) -{ - Fraig_NodeVec_t * vFanins; - Fraig_NodeVec_t * vInside; - int nCubes; - extern int Fraig_CutSopCountCubes( Fraig_Man_t * pMan, Fraig_NodeVec_t * vFanins, Fraig_NodeVec_t * vInside ); - - vFanins = Fraig_NodeVecAlloc( 8 ); - vInside = Fraig_NodeVecAlloc( 8 ); - - Fraig_DetectFanoutFreeCone_rec( pNode, vFanins, vInside, 1 ); - assert( vInside->pArray[vInside->nSize-1] == pNode ); - - nCubes = Fraig_CutSopCountCubes( pMan, vFanins, vInside ); - -printf( "%d(%d)", vFanins->nSize, nCubes ); - Fraig_NodeVecFree( vFanins ); - Fraig_NodeVecFree( vInside ); -} -*/ - - - -/**Function************************************************************* - - Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_DetectFanoutFreeConeMux_rec( Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper, Fraig_NodeVec_t * vInside, int fFirst ) -{ - // make the pointer regular - pNode = Fraig_Regular(pNode); - // if the new node is complemented or a PI, another gate begins - if ( (!fFirst && pNode->nRefs > 1) || Fraig_NodeIsVar(pNode) || !Fraig_NodeIsMuxType(pNode) ) - { - Fraig_NodeVecPushUnique( vSuper, pNode ); - return; - } - // go through the branches - Fraig_DetectFanoutFreeConeMux_rec( Fraig_Regular(pNode->p1)->p1, vSuper, vInside, 0 ); - Fraig_DetectFanoutFreeConeMux_rec( Fraig_Regular(pNode->p1)->p2, vSuper, vInside, 0 ); - Fraig_DetectFanoutFreeConeMux_rec( Fraig_Regular(pNode->p2)->p1, vSuper, vInside, 0 ); - Fraig_DetectFanoutFreeConeMux_rec( Fraig_Regular(pNode->p2)->p2, vSuper, vInside, 0 ); - // add the node - Fraig_NodeVecPushUnique( vInside, pNode ); -} - -/**Function************************************************************* - - Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_DetectFanoutFreeConeMux( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) -{ - Fraig_NodeVec_t * vFanins; - Fraig_NodeVec_t * vInside; - int nCubes; - extern int Fraig_CutSopCountCubes( Fraig_Man_t * pMan, Fraig_NodeVec_t * vFanins, Fraig_NodeVec_t * vInside ); - - vFanins = Fraig_NodeVecAlloc( 8 ); - vInside = Fraig_NodeVecAlloc( 8 ); - - Fraig_DetectFanoutFreeConeMux_rec( pNode, vFanins, vInside, 1 ); - assert( vInside->pArray[vInside->nSize-1] == pNode ); - -// nCubes = Fraig_CutSopCountCubes( pMan, vFanins, vInside ); - nCubes = 0; - -printf( "%d(%d)", vFanins->nSize, nCubes ); - Fraig_NodeVecFree( vFanins ); - Fraig_NodeVecFree( vInside ); -} - - - -/**Function************************************************************* - - Synopsis [Collect variables using their proximity from the nodes.] - - Description [This procedure creates a variable order based on collecting - first the nodes that are the closest to the given two target nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_SetActivity( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) -{ - Fraig_Node_t * pNode; - int i, Number, MaxLevel; - float * pFactors = Msat_SolverReadFactors(pMan->pSat); - if ( pFactors == NULL ) - return; - MaxLevel = ABC_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 /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/sat/fraig/fraigTable.c b/src/sat/fraig/fraigTable.c deleted file mode 100644 index 79ab7ffc..00000000 --- a/src/sat/fraig/fraigTable.c +++ /dev/null @@ -1,662 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraigTable.c] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [Structural and functional hash tables.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - October 1, 2004] - - Revision [$Id: fraigTable.c,v 1.7 2005/07/08 01:01:34 alanmi Exp $] - -***********************************************************************/ - -#include "fraigInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Fraig_TableResizeS( Fraig_HashTable_t * p ); -static void Fraig_TableResizeF( Fraig_HashTable_t * p, int fUseSimR ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_HashTable_t * Fraig_HashTableCreate( int nSize ) -{ - Fraig_HashTable_t * p; - // allocate the table - p = ABC_ALLOC( Fraig_HashTable_t, 1 ); - memset( p, 0, sizeof(Fraig_HashTable_t) ); - // allocate and clean the bins - p->nBins = Cudd_PrimeFraig(nSize); - p->pBins = ABC_ALLOC( Fraig_Node_t *, p->nBins ); - memset( p->pBins, 0, sizeof(Fraig_Node_t *) * p->nBins ); - return p; -} - -/**Function************************************************************* - - Synopsis [Deallocates the supergate hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_HashTableFree( Fraig_HashTable_t * p ) -{ - ABC_FREE( p->pBins ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Looks up an entry in the structural hash table.] - - Description [If the entry with the same children does not exists, - creates it, inserts it into the table, and returns 0. If the entry - with the same children exists, finds it, and return 1. In both cases, - the new/old entry is returned in ppNodeRes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_HashTableLookupS( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2, Fraig_Node_t ** ppNodeRes ) -{ - Fraig_HashTable_t * p = pMan->pTableS; - Fraig_Node_t * pEnt; - unsigned Key; - - // order the arguments - if ( Fraig_Regular(p1)->Num > Fraig_Regular(p2)->Num ) - pEnt = p1, p1 = p2, p2 = pEnt; - - Key = Fraig_HashKey2( p1, p2, p->nBins ); - Fraig_TableBinForEachEntryS( p->pBins[Key], pEnt ) - if ( pEnt->p1 == p1 && pEnt->p2 == p2 ) - { - *ppNodeRes = pEnt; - return 1; - } - // check if it is a good time for table resizing - if ( p->nEntries >= 2 * p->nBins ) - { - Fraig_TableResizeS( p ); - Key = Fraig_HashKey2( p1, p2, p->nBins ); - } - // create the new node - pEnt = Fraig_NodeCreate( pMan, p1, p2 ); - // add the node to the corresponding linked list in the table - pEnt->pNextS = p->pBins[Key]; - p->pBins[Key] = pEnt; - *ppNodeRes = pEnt; - p->nEntries++; - return 0; -} - - -/**Function************************************************************* - - Synopsis [Insert the entry in the functional hash table.] - - Description [If the entry with the same key exists, return it right away. - If the entry with the same key does not exists, inserts it and returns NULL. ] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_HashTableLookupF( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) -{ - Fraig_HashTable_t * p = pMan->pTableF; - Fraig_Node_t * pEnt, * pEntD; - unsigned Key; - - // go through the hash table entries - Key = pNode->uHashR % p->nBins; - Fraig_TableBinForEachEntryF( p->pBins[Key], pEnt ) - { - // if their simulation info differs, skip - if ( !Fraig_CompareSimInfo( pNode, pEnt, pMan->nWordsRand, 1 ) ) - continue; - // equivalent up to the complement - Fraig_TableBinForEachEntryD( pEnt, pEntD ) - { - // if their simulation info differs, skip - if ( !Fraig_CompareSimInfo( pNode, pEntD, pMan->iWordStart, 0 ) ) - continue; - // found a simulation-equivalent node - return pEntD; - } - // did not find a simulation equivalent node - // add the node to the corresponding linked list - pNode->pNextD = pEnt->pNextD; - pEnt->pNextD = pNode; - // return NULL, because there is no functional equivalence in this case - return NULL; - } - - // check if it is a good time for table resizing - if ( p->nEntries >= 2 * p->nBins ) - { - Fraig_TableResizeF( p, 1 ); - Key = pNode->uHashR % p->nBins; - } - - // add the node to the corresponding linked list in the table - pNode->pNextF = p->pBins[Key]; - p->pBins[Key] = pNode; - p->nEntries++; - // return NULL, because there is no functional equivalence in this case - return NULL; -} - -/**Function************************************************************* - - Synopsis [Insert the entry in the functional hash table.] - - Description [If the entry with the same key exists, return it right away. - If the entry with the same key does not exists, inserts it and returns NULL. ] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_HashTableLookupF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) -{ - Fraig_HashTable_t * p = pMan->pTableF0; - Fraig_Node_t * pEnt; - unsigned Key; - - // go through the hash table entries - Key = pNode->uHashD % p->nBins; - Fraig_TableBinForEachEntryF( p->pBins[Key], pEnt ) - { - // if their simulation info differs, skip - if ( !Fraig_CompareSimInfo( pNode, pEnt, pMan->iWordStart, 0 ) ) - continue; - // found a simulation-equivalent node - return pEnt; - } - - // check if it is a good time for table resizing - if ( p->nEntries >= 2 * p->nBins ) - { - Fraig_TableResizeF( p, 0 ); - Key = pNode->uHashD % p->nBins; - } - - // add the node to the corresponding linked list in the table - pNode->pNextF = p->pBins[Key]; - p->pBins[Key] = pNode; - p->nEntries++; - // return NULL, because there is no functional equivalence in this case - return NULL; -} - -/**Function************************************************************* - - Synopsis [Insert the entry in the functional hash table.] - - Description [Unconditionally add the node to the corresponding - linked list in the table.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_HashTableInsertF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) -{ - Fraig_HashTable_t * p = pMan->pTableF0; - unsigned Key = pNode->uHashD % p->nBins; - - pNode->pNextF = p->pBins[Key]; - p->pBins[Key] = pNode; - p->nEntries++; -} - - -/**Function************************************************************* - - Synopsis [Resizes the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_TableResizeS( Fraig_HashTable_t * p ) -{ - Fraig_Node_t ** pBinsNew; - Fraig_Node_t * pEnt, * pEnt2; - int nBinsNew, Counter, i, clk; - unsigned Key; - -clk = clock(); - // get the new table size - nBinsNew = Cudd_PrimeFraig(2 * p->nBins); - // allocate a new array - pBinsNew = ABC_ALLOC( Fraig_Node_t *, nBinsNew ); - memset( pBinsNew, 0, sizeof(Fraig_Node_t *) * nBinsNew ); - // rehash the entries from the old table - Counter = 0; - for ( i = 0; i < p->nBins; i++ ) - Fraig_TableBinForEachEntrySafeS( p->pBins[i], pEnt, pEnt2 ) - { - Key = Fraig_HashKey2( pEnt->p1, pEnt->p2, nBinsNew ); - pEnt->pNextS = pBinsNew[Key]; - pBinsNew[Key] = pEnt; - Counter++; - } - assert( Counter == p->nEntries ); -// printf( "Increasing the structural table size from %6d to %6d. ", p->nBins, nBinsNew ); -// ABC_PRT( "Time", clock() - clk ); - // replace the table and the parameters - ABC_FREE( p->pBins ); - p->pBins = pBinsNew; - p->nBins = nBinsNew; -} - -/**Function************************************************************* - - Synopsis [Resizes the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_TableResizeF( Fraig_HashTable_t * p, int fUseSimR ) -{ - Fraig_Node_t ** pBinsNew; - Fraig_Node_t * pEnt, * pEnt2; - int nBinsNew, Counter, i, clk; - unsigned Key; - -clk = clock(); - // get the new table size - nBinsNew = Cudd_PrimeFraig(2 * p->nBins); - // allocate a new array - pBinsNew = ABC_ALLOC( Fraig_Node_t *, nBinsNew ); - memset( pBinsNew, 0, sizeof(Fraig_Node_t *) * nBinsNew ); - // rehash the entries from the old table - Counter = 0; - for ( i = 0; i < p->nBins; i++ ) - Fraig_TableBinForEachEntrySafeF( p->pBins[i], pEnt, pEnt2 ) - { - if ( fUseSimR ) - Key = pEnt->uHashR % nBinsNew; - else - Key = pEnt->uHashD % nBinsNew; - pEnt->pNextF = pBinsNew[Key]; - pBinsNew[Key] = pEnt; - Counter++; - } - assert( Counter == p->nEntries ); -// printf( "Increasing the functional table size from %6d to %6d. ", p->nBins, nBinsNew ); -// ABC_PRT( "Time", clock() - clk ); - // replace the table and the parameters - ABC_FREE( p->pBins ); - p->pBins = pBinsNew; - p->nBins = nBinsNew; -} - - -/**Function************************************************************* - - Synopsis [Compares two pieces of simulation info.] - - Description [Returns 1 if they are equal.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_CompareSimInfo( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand ) -{ - int i; - assert( !Fraig_IsComplement(pNode1) ); - assert( !Fraig_IsComplement(pNode2) ); - if ( fUseRand ) - { - // if their signatures differ, skip - if ( pNode1->uHashR != pNode2->uHashR ) - return 0; - // check the simulation info - for ( i = 0; i < iWordLast; i++ ) - if ( pNode1->puSimR[i] != pNode2->puSimR[i] ) - return 0; - } - else - { - // if their signatures differ, skip - if ( pNode1->uHashD != pNode2->uHashD ) - return 0; - // check the simulation info - for ( i = 0; i < iWordLast; i++ ) - if ( pNode1->puSimD[i] != pNode2->puSimD[i] ) - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Find the number of the different pattern.] - - Description [Returns -1 if there is no such pattern] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_FindFirstDiff( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int fCompl, int iWordLast, int fUseRand ) -{ - int i, v; - assert( !Fraig_IsComplement(pNode1) ); - assert( !Fraig_IsComplement(pNode2) ); - // take into account possible internal complementation - fCompl ^= pNode1->fInv; - fCompl ^= pNode2->fInv; - // find the pattern - if ( fCompl ) - { - if ( fUseRand ) - { - for ( i = 0; i < iWordLast; i++ ) - if ( pNode1->puSimR[i] != ~pNode2->puSimR[i] ) - for ( v = 0; v < 32; v++ ) - if ( (pNode1->puSimR[i] ^ ~pNode2->puSimR[i]) & (1 << v) ) - return i * 32 + v; - } - else - { - for ( i = 0; i < iWordLast; i++ ) - if ( pNode1->puSimD[i] != ~pNode2->puSimD[i] ) - for ( v = 0; v < 32; v++ ) - if ( (pNode1->puSimD[i] ^ ~pNode2->puSimD[i]) & (1 << v) ) - return i * 32 + v; - } - } - else - { - if ( fUseRand ) - { - for ( i = 0; i < iWordLast; i++ ) - if ( pNode1->puSimR[i] != pNode2->puSimR[i] ) - for ( v = 0; v < 32; v++ ) - if ( (pNode1->puSimR[i] ^ pNode2->puSimR[i]) & (1 << v) ) - return i * 32 + v; - } - else - { - for ( i = 0; i < iWordLast; i++ ) - if ( pNode1->puSimD[i] != pNode2->puSimD[i] ) - for ( v = 0; v < 32; v++ ) - if ( (pNode1->puSimD[i] ^ pNode2->puSimD[i]) & (1 << v) ) - return i * 32 + v; - } - } - return -1; -} - -/**Function************************************************************* - - Synopsis [Compares two pieces of simulation info.] - - Description [Returns 1 if they are equal.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_CompareSimInfoUnderMask( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask ) -{ - unsigned * pSims1, * pSims2; - int i; - assert( !Fraig_IsComplement(pNode1) ); - assert( !Fraig_IsComplement(pNode2) ); - // get hold of simulation info - pSims1 = fUseRand? pNode1->puSimR : pNode1->puSimD; - pSims2 = fUseRand? pNode2->puSimR : pNode2->puSimD; - // check the simulation info - for ( i = 0; i < iWordLast; i++ ) - if ( (pSims1[i] & puMask[i]) != (pSims2[i] & puMask[i]) ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Compares two pieces of simulation info.] - - Description [Returns 1 if they are equal.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_CollectXors( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask ) -{ - unsigned * pSims1, * pSims2; - int i; - assert( !Fraig_IsComplement(pNode1) ); - assert( !Fraig_IsComplement(pNode2) ); - // get hold of simulation info - pSims1 = fUseRand? pNode1->puSimR : pNode1->puSimD; - pSims2 = fUseRand? pNode2->puSimR : pNode2->puSimD; - // check the simulation info - for ( i = 0; i < iWordLast; i++ ) - puMask[i] = ( pSims1[i] ^ pSims2[i] ); -} - - -/**Function************************************************************* - - Synopsis [Prints stats of the structural table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_TablePrintStatsS( Fraig_Man_t * pMan ) -{ - Fraig_HashTable_t * pT = pMan->pTableS; - Fraig_Node_t * pNode; - int i, Counter; - - printf( "Structural table. Table size = %d. Number of entries = %d.\n", pT->nBins, pT->nEntries ); - for ( i = 0; i < pT->nBins; i++ ) - { - Counter = 0; - Fraig_TableBinForEachEntryS( pT->pBins[i], pNode ) - Counter++; - if ( Counter > 1 ) - { - printf( "%d ", Counter ); - if ( Counter > 50 ) - printf( "{%d} ", i ); - } - } - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Prints stats of the structural table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_TablePrintStatsF( Fraig_Man_t * pMan ) -{ - Fraig_HashTable_t * pT = pMan->pTableF; - Fraig_Node_t * pNode; - int i, Counter; - - printf( "Functional table. Table size = %d. Number of entries = %d.\n", pT->nBins, pT->nEntries ); - for ( i = 0; i < pT->nBins; i++ ) - { - Counter = 0; - Fraig_TableBinForEachEntryF( pT->pBins[i], pNode ) - Counter++; - if ( Counter > 1 ) - printf( "{%d} ", Counter ); - } - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Prints stats of the structural table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_TablePrintStatsF0( Fraig_Man_t * pMan ) -{ - Fraig_HashTable_t * pT = pMan->pTableF0; - Fraig_Node_t * pNode; - int i, Counter; - - printf( "Zero-node table. Table size = %d. Number of entries = %d.\n", pT->nBins, pT->nEntries ); - for ( i = 0; i < pT->nBins; i++ ) - { - Counter = 0; - Fraig_TableBinForEachEntryF( pT->pBins[i], pNode ) - Counter++; - if ( Counter == 0 ) - continue; -/* - printf( "\nBin = %4d : Number of entries = %4d\n", i, Counter ); - Fraig_TableBinForEachEntryF( pT->pBins[i], pNode ) - printf( "Node %5d. Hash = %10d.\n", pNode->Num, pNode->uHashD ); -*/ - } - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Rehashes the table after the simulation info has changed.] - - Description [Assumes that the hash values have been updated after performing - additional simulation. Rehashes the table using the new hash values. - Uses pNextF to link the entries in the bins. Uses pNextD to link the entries - with identical hash values. Returns 1 if the identical entries have been found. - Note that identical hash values may mean that the simulation data is different.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_TableRehashF0( Fraig_Man_t * pMan, int fLinkEquiv ) -{ - Fraig_HashTable_t * pT = pMan->pTableF0; - Fraig_Node_t ** pBinsNew; - Fraig_Node_t * pEntF, * pEntF2, * pEnt, * pEntD2, * pEntN; - int ReturnValue, Counter, i; - unsigned Key; - - // allocate a new array of bins - pBinsNew = ABC_ALLOC( Fraig_Node_t *, pT->nBins ); - memset( pBinsNew, 0, sizeof(Fraig_Node_t *) * pT->nBins ); - - // rehash the entries in the table - // go through all the nodes in the F-lists (and possible in D-lists, if used) - Counter = 0; - ReturnValue = 0; - for ( i = 0; i < pT->nBins; i++ ) - Fraig_TableBinForEachEntrySafeF( pT->pBins[i], pEntF, pEntF2 ) - Fraig_TableBinForEachEntrySafeD( pEntF, pEnt, pEntD2 ) - { - // decide where to put entry pEnt - Key = pEnt->uHashD % pT->nBins; - if ( fLinkEquiv ) - { - // go through the entries in the new bin - Fraig_TableBinForEachEntryF( pBinsNew[Key], pEntN ) - { - // if they have different values skip - if ( pEnt->uHashD != pEntN->uHashD ) - continue; - // they have the same hash value, add pEnt to the D-list pEnt3 - pEnt->pNextD = pEntN->pNextD; - pEntN->pNextD = pEnt; - ReturnValue = 1; - Counter++; - break; - } - if ( pEntN != NULL ) // already linked - continue; - // we did not find equal entry - } - // link the new entry - pEnt->pNextF = pBinsNew[Key]; - pBinsNew[Key] = pEnt; - pEnt->pNextD = NULL; - Counter++; - } - assert( Counter == pT->nEntries ); - // replace the table and the parameters - ABC_FREE( pT->pBins ); - pT->pBins = pBinsNew; - return ReturnValue; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/sat/fraig/fraigUtil.c b/src/sat/fraig/fraigUtil.c deleted file mode 100644 index 0d4cdfaf..00000000 --- a/src/sat/fraig/fraigUtil.c +++ /dev/null @@ -1,1039 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraigUtil.c] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [Various utilities.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - October 1, 2004] - - Revision [$Id: fraigUtil.c,v 1.15 2005/07/08 01:01:34 alanmi Exp $] - -***********************************************************************/ - -#include "fraigInt.h" -#include - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int bit_count[256] = { - 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 -}; - -static void Fraig_Dfs_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_NodeVec_t * vNodes, int fEquiv ); -static int Fraig_CheckTfi_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_Node_t * pOld ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes the DFS ordering of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_NodeVec_t * Fraig_Dfs( Fraig_Man_t * pMan, int fEquiv ) -{ - Fraig_NodeVec_t * vNodes; - int i; - pMan->nTravIds++; - vNodes = Fraig_NodeVecAlloc( 100 ); - for ( i = 0; i < pMan->vOutputs->nSize; i++ ) - Fraig_Dfs_rec( pMan, Fraig_Regular(pMan->vOutputs->pArray[i]), vNodes, fEquiv ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Computes the DFS ordering of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_NodeVec_t * Fraig_DfsOne( Fraig_Man_t * pMan, Fraig_Node_t * pNode, int fEquiv ) -{ - Fraig_NodeVec_t * vNodes; - pMan->nTravIds++; - vNodes = Fraig_NodeVecAlloc( 100 ); - Fraig_Dfs_rec( pMan, Fraig_Regular(pNode), vNodes, fEquiv ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Computes the DFS ordering of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_NodeVec_t * Fraig_DfsNodes( Fraig_Man_t * pMan, Fraig_Node_t ** ppNodes, int nNodes, int fEquiv ) -{ - Fraig_NodeVec_t * vNodes; - int i; - pMan->nTravIds++; - vNodes = Fraig_NodeVecAlloc( 100 ); - for ( i = 0; i < nNodes; i++ ) - Fraig_Dfs_rec( pMan, Fraig_Regular(ppNodes[i]), vNodes, fEquiv ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Recursively computes the DFS ordering of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_Dfs_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_NodeVec_t * vNodes, int fEquiv ) -{ - assert( !Fraig_IsComplement(pNode) ); - // skip the visited node - if ( pNode->TravId == pMan->nTravIds ) - return; - pNode->TravId = pMan->nTravIds; - // visit the transitive fanin - if ( Fraig_NodeIsAnd(pNode) ) - { - Fraig_Dfs_rec( pMan, Fraig_Regular(pNode->p1), vNodes, fEquiv ); - Fraig_Dfs_rec( pMan, Fraig_Regular(pNode->p2), vNodes, fEquiv ); - } - if ( fEquiv && pNode->pNextE ) - Fraig_Dfs_rec( pMan, pNode->pNextE, vNodes, fEquiv ); - // save the node - Fraig_NodeVecPush( vNodes, pNode ); -} - -/**Function************************************************************* - - Synopsis [Computes the DFS ordering of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_CountNodes( Fraig_Man_t * pMan, int fEquiv ) -{ - Fraig_NodeVec_t * vNodes; - int RetValue; - vNodes = Fraig_Dfs( pMan, fEquiv ); - RetValue = vNodes->nSize; - Fraig_NodeVecFree( vNodes ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if pOld is in the TFI of pNew.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_CheckTfi( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) -{ - assert( !Fraig_IsComplement(pOld) ); - assert( !Fraig_IsComplement(pNew) ); - pMan->nTravIds++; - return Fraig_CheckTfi_rec( pMan, pNew, pOld ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if pOld is in the TFI of pNew.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_CheckTfi_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_Node_t * pOld ) -{ - // check the trivial cases - if ( pNode == NULL ) - return 0; - if ( pNode->Num < pOld->Num && !pMan->fChoicing ) - return 0; - if ( pNode == pOld ) - return 1; - // skip the visited node - if ( pNode->TravId == pMan->nTravIds ) - return 0; - pNode->TravId = pMan->nTravIds; - // check the children - if ( Fraig_CheckTfi_rec( pMan, Fraig_Regular(pNode->p1), pOld ) ) - return 1; - if ( Fraig_CheckTfi_rec( pMan, Fraig_Regular(pNode->p2), pOld ) ) - return 1; - // check equivalent nodes - return Fraig_CheckTfi_rec( pMan, pNode->pNextE, pOld ); -} - - -/**Function************************************************************* - - Synopsis [Returns 1 if pOld is in the TFI of pNew.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_CheckTfi2( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) -{ - Fraig_NodeVec_t * vNodes; - int RetValue; - vNodes = Fraig_DfsOne( pMan, pNew, 1 ); - RetValue = (pOld->TravId == pMan->nTravIds); - Fraig_NodeVecFree( vNodes ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Sets the number of fanouts (none, one, or many).] - - Description [This procedure collects the nodes reachable from - the POs of the AIG and sets the type of fanout counter (none, one, - or many) for each node. This procedure is useful to determine - fanout-free cones of AND-nodes, which is helpful for rebalancing - the AIG (see procedure Fraig_ManRebalance, or something like that).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_ManMarkRealFanouts( Fraig_Man_t * p ) -{ - Fraig_NodeVec_t * vNodes; - Fraig_Node_t * pNodeR; - int i; - // collect the nodes reachable - vNodes = Fraig_Dfs( p, 0 ); - // clean the fanouts field - for ( i = 0; i < vNodes->nSize; i++ ) - { - vNodes->pArray[i]->nFanouts = 0; - vNodes->pArray[i]->pData0 = NULL; - } - // mark reachable nodes by setting the two-bit counter pNode->nFans - for ( i = 0; i < vNodes->nSize; i++ ) - { - pNodeR = Fraig_Regular(vNodes->pArray[i]->p1); - if ( pNodeR && ++pNodeR->nFanouts == 3 ) - pNodeR->nFanouts = 2; - pNodeR = Fraig_Regular(vNodes->pArray[i]->p2); - if ( pNodeR && ++pNodeR->nFanouts == 3 ) - pNodeR->nFanouts = 2; - } - Fraig_NodeVecFree( vNodes ); -} - -/**Function************************************************************* - - Synopsis [Creates the constant 1 node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_BitStringCountOnes( unsigned * pString, int nWords ) -{ - unsigned char * pSuppBytes = (unsigned char *)pString; - int i, nOnes, nBytes = sizeof(unsigned) * nWords; - // count the number of ones in the simulation vector - for ( i = nOnes = 0; i < nBytes; i++ ) - nOnes += bit_count[pSuppBytes[i]]; - return nOnes; -} - -/**Function************************************************************* - - Synopsis [Verify one useful property.] - - Description [This procedure verifies one useful property. After - the FRAIG construction with choice nodes is over, each primary node - should have fanins that are primary nodes. The primary nodes is the - one that does not have pNode->pRepr set to point to another node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_ManCheckConsistency( Fraig_Man_t * p ) -{ - Fraig_Node_t * pNode; - Fraig_NodeVec_t * pVec; - int i; - pVec = Fraig_Dfs( p, 0 ); - for ( i = 0; i < pVec->nSize; i++ ) - { - pNode = pVec->pArray[i]; - if ( Fraig_NodeIsVar(pNode) ) - { - if ( pNode->pRepr ) - printf( "Primary input %d is a secondary node.\n", pNode->Num ); - } - else if ( Fraig_NodeIsConst(pNode) ) - { - if ( pNode->pRepr ) - printf( "Constant 1 %d is a secondary node.\n", pNode->Num ); - } - else - { - if ( pNode->pRepr ) - printf( "Internal node %d is a secondary node.\n", pNode->Num ); - if ( Fraig_Regular(pNode->p1)->pRepr ) - printf( "Internal node %d has first fanin %d that is a secondary node.\n", - pNode->Num, Fraig_Regular(pNode->p1)->Num ); - if ( Fraig_Regular(pNode->p2)->pRepr ) - printf( "Internal node %d has second fanin %d that is a secondary node.\n", - pNode->Num, Fraig_Regular(pNode->p2)->Num ); - } - } - Fraig_NodeVecFree( pVec ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Prints the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_PrintNode( Fraig_Man_t * p, Fraig_Node_t * pNode ) -{ - Fraig_NodeVec_t * vNodes; - Fraig_Node_t * pTemp; - int fCompl1, fCompl2, i; - - vNodes = Fraig_DfsOne( p, pNode, 0 ); - for ( i = 0; i < vNodes->nSize; i++ ) - { - pTemp = vNodes->pArray[i]; - if ( Fraig_NodeIsVar(pTemp) ) - { - printf( "%3d : PI ", pTemp->Num ); - Fraig_PrintBinary( stdout, (unsigned *)&pTemp->puSimR, 20 ); - printf( " " ); - Fraig_PrintBinary( stdout, (unsigned *)&pTemp->puSimD, 20 ); - printf( " %d\n", pTemp->fInv ); - continue; - } - - fCompl1 = Fraig_IsComplement(pTemp->p1); - fCompl2 = Fraig_IsComplement(pTemp->p2); - printf( "%3d : %c%3d %c%3d ", pTemp->Num, - (fCompl1? '-':'+'), Fraig_Regular(pTemp->p1)->Num, - (fCompl2? '-':'+'), Fraig_Regular(pTemp->p2)->Num ); - Fraig_PrintBinary( stdout, (unsigned *)&pTemp->puSimR, 20 ); - printf( " " ); - Fraig_PrintBinary( stdout, (unsigned *)&pTemp->puSimD, 20 ); - printf( " %d\n", pTemp->fInv ); - } - Fraig_NodeVecFree( vNodes ); -} - -/**Function************************************************************* - - Synopsis [Prints the bit string.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_PrintBinary( FILE * pFile, unsigned * pSign, int nBits ) -{ - int Remainder, nWords; - int w, i; - - Remainder = (nBits%(sizeof(unsigned)*8)); - nWords = (nBits/(sizeof(unsigned)*8)) + (Remainder>0); - - for ( w = nWords-1; w >= 0; w-- ) - for ( i = ((w == nWords-1 && Remainder)? Remainder-1: 31); i >= 0; i-- ) - fprintf( pFile, "%c", '0' + (int)((pSign[w] & (1< 0) ); - -// fprintf( pFile, "\n" ); -} - -/**Function************************************************************* - - Synopsis [Sets up the mask.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_GetMaxLevel( Fraig_Man_t * pMan ) -{ - int nLevelMax, i; - nLevelMax = 0; - for ( i = 0; i < pMan->vOutputs->nSize; i++ ) - nLevelMax = nLevelMax > Fraig_Regular(pMan->vOutputs->pArray[i])->Level? - nLevelMax : Fraig_Regular(pMan->vOutputs->pArray[i])->Level; - return nLevelMax; -} - -/**Function************************************************************* - - Synopsis [Analyses choice nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_MappingUpdateLevel_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, int fMaximum ) -{ - Fraig_Node_t * pTemp; - int Level1, Level2, LevelE; - assert( !Fraig_IsComplement(pNode) ); - if ( !Fraig_NodeIsAnd(pNode) ) - return pNode->Level; - // skip the visited node - if ( pNode->TravId == pMan->nTravIds ) - return pNode->Level; - pNode->TravId = pMan->nTravIds; - // compute levels of the children nodes - Level1 = Fraig_MappingUpdateLevel_rec( pMan, Fraig_Regular(pNode->p1), fMaximum ); - Level2 = Fraig_MappingUpdateLevel_rec( pMan, Fraig_Regular(pNode->p2), fMaximum ); - pNode->Level = 1 + ABC_MAX( Level1, Level2 ); - if ( pNode->pNextE ) - { - LevelE = Fraig_MappingUpdateLevel_rec( pMan, pNode->pNextE, fMaximum ); - if ( fMaximum ) - { - if ( pNode->Level < LevelE ) - pNode->Level = LevelE; - } - else - { - if ( pNode->Level > LevelE ) - pNode->Level = LevelE; - } - // set the level of all equivalent nodes to be the same minimum - if ( pNode->pRepr == NULL ) // the primary node - for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE ) - pTemp->Level = pNode->Level; - } - return pNode->Level; -} - -/**Function************************************************************* - - Synopsis [Resets the levels of the nodes in the choice graph.] - - Description [Makes the level of the choice nodes to be equal to the - maximum of the level of the nodes in the equivalence class. This way - sorting by level leads to the reverse topological order, which is - needed for the required time computation.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_MappingSetChoiceLevels( Fraig_Man_t * pMan, int fMaximum ) -{ - int i; - pMan->nTravIds++; - for ( i = 0; i < pMan->vOutputs->nSize; i++ ) - Fraig_MappingUpdateLevel_rec( pMan, Fraig_Regular(pMan->vOutputs->pArray[i]), fMaximum ); -} - -/**Function************************************************************* - - Synopsis [Reports statistics on choice nodes.] - - Description [The number of choice nodes is the number of primary nodes, - which has pNextE set to a pointer. The number of choices is the number - of entries in the equivalent-node lists of the primary nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_ManReportChoices( Fraig_Man_t * pMan ) -{ - Fraig_Node_t * pNode, * pTemp; - int nChoiceNodes, nChoices; - int i, LevelMax1, LevelMax2; - - // report the number of levels - LevelMax1 = Fraig_GetMaxLevel( pMan ); - Fraig_MappingSetChoiceLevels( pMan, 0 ); - LevelMax2 = Fraig_GetMaxLevel( pMan ); - - // report statistics about choices - nChoiceNodes = nChoices = 0; - for ( i = 0; i < pMan->vNodes->nSize; i++ ) - { - pNode = pMan->vNodes->pArray[i]; - if ( pNode->pRepr == NULL && pNode->pNextE != NULL ) - { // this is a choice node = the primary node that has equivalent nodes - nChoiceNodes++; - for ( pTemp = pNode; pTemp; pTemp = pTemp->pNextE ) - nChoices++; - } - } - printf( "Maximum level: Original = %d. Reduced due to choices = %d.\n", LevelMax1, LevelMax2 ); - printf( "Choice stats: Choice nodes = %d. Total choices = %d.\n", nChoiceNodes, nChoices ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the node is the root of EXOR/NEXOR gate.] - - Description [The node can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeIsExorType( Fraig_Node_t * pNode ) -{ - Fraig_Node_t * pNode1, * pNode2; - // make the node regular (it does not matter for EXOR/NEXOR) - pNode = Fraig_Regular(pNode); - // if the node or its children are not ANDs or not compl, this cannot be EXOR type - if ( !Fraig_NodeIsAnd(pNode) ) - return 0; - if ( !Fraig_NodeIsAnd(pNode->p1) || !Fraig_IsComplement(pNode->p1) ) - return 0; - if ( !Fraig_NodeIsAnd(pNode->p2) || !Fraig_IsComplement(pNode->p2) ) - return 0; - - // get children - pNode1 = Fraig_Regular(pNode->p1); - pNode2 = Fraig_Regular(pNode->p2); - assert( pNode1->Num < pNode2->Num ); - - // compare grandchildren - return pNode1->p1 == Fraig_Not(pNode2->p1) && pNode1->p2 == Fraig_Not(pNode2->p2); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] - - Description [The node can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeIsMuxType( Fraig_Node_t * pNode ) -{ - Fraig_Node_t * pNode1, * pNode2; - - // make the node regular (it does not matter for EXOR/NEXOR) - pNode = Fraig_Regular(pNode); - // if the node or its children are not ANDs or not compl, this cannot be EXOR type - if ( !Fraig_NodeIsAnd(pNode) ) - return 0; - if ( !Fraig_NodeIsAnd(pNode->p1) || !Fraig_IsComplement(pNode->p1) ) - return 0; - if ( !Fraig_NodeIsAnd(pNode->p2) || !Fraig_IsComplement(pNode->p2) ) - return 0; - - // get children - pNode1 = Fraig_Regular(pNode->p1); - pNode2 = Fraig_Regular(pNode->p2); - assert( pNode1->Num < pNode2->Num ); - - // compare grandchildren - // node is an EXOR/NEXOR - if ( pNode1->p1 == Fraig_Not(pNode2->p1) && pNode1->p2 == Fraig_Not(pNode2->p2) ) - return 1; - - // otherwise the node is MUX iff it has a pair of equal grandchildren - return pNode1->p1 == Fraig_Not(pNode2->p1) || - pNode1->p1 == Fraig_Not(pNode2->p2) || - pNode1->p2 == Fraig_Not(pNode2->p1) || - pNode1->p2 == Fraig_Not(pNode2->p2); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the node is EXOR, 0 if it is NEXOR.] - - Description [The node should be EXOR type and not complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeIsExor( Fraig_Node_t * pNode ) -{ - Fraig_Node_t * pNode1; - assert( !Fraig_IsComplement(pNode) ); - assert( Fraig_NodeIsExorType(pNode) ); - assert( Fraig_IsComplement(pNode->p1) ); - // get children - pNode1 = Fraig_Regular(pNode->p1); - return Fraig_IsComplement(pNode1->p1) == Fraig_IsComplement(pNode1->p2); -} - -/**Function************************************************************* - - Synopsis [Recognizes what nodes are control and data inputs of a MUX.] - - Description [If the node is a MUX, returns the control variable C. - Assigns nodes T and E to be the then and else variables of the MUX. - Node C is never complemented. Nodes T and E can be complemented. - This function also recognizes EXOR/NEXOR gates as MUXes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_NodeRecognizeMux( Fraig_Node_t * pNode, Fraig_Node_t ** ppNodeT, Fraig_Node_t ** ppNodeE ) -{ - Fraig_Node_t * pNode1, * pNode2; - assert( !Fraig_IsComplement(pNode) ); - assert( Fraig_NodeIsMuxType(pNode) ); - // get children - pNode1 = Fraig_Regular(pNode->p1); - pNode2 = Fraig_Regular(pNode->p2); - // find the control variable - if ( pNode1->p1 == Fraig_Not(pNode2->p1) ) - { - if ( Fraig_IsComplement(pNode1->p1) ) - { // pNode2->p1 is positive phase of C - *ppNodeT = Fraig_Not(pNode2->p2); - *ppNodeE = Fraig_Not(pNode1->p2); - return pNode2->p1; - } - else - { // pNode1->p1 is positive phase of C - *ppNodeT = Fraig_Not(pNode1->p2); - *ppNodeE = Fraig_Not(pNode2->p2); - return pNode1->p1; - } - } - else if ( pNode1->p1 == Fraig_Not(pNode2->p2) ) - { - if ( Fraig_IsComplement(pNode1->p1) ) - { // pNode2->p2 is positive phase of C - *ppNodeT = Fraig_Not(pNode2->p1); - *ppNodeE = Fraig_Not(pNode1->p2); - return pNode2->p2; - } - else - { // pNode1->p1 is positive phase of C - *ppNodeT = Fraig_Not(pNode1->p2); - *ppNodeE = Fraig_Not(pNode2->p1); - return pNode1->p1; - } - } - else if ( pNode1->p2 == Fraig_Not(pNode2->p1) ) - { - if ( Fraig_IsComplement(pNode1->p2) ) - { // pNode2->p1 is positive phase of C - *ppNodeT = Fraig_Not(pNode2->p2); - *ppNodeE = Fraig_Not(pNode1->p1); - return pNode2->p1; - } - else - { // pNode1->p2 is positive phase of C - *ppNodeT = Fraig_Not(pNode1->p1); - *ppNodeE = Fraig_Not(pNode2->p2); - return pNode1->p2; - } - } - else if ( pNode1->p2 == Fraig_Not(pNode2->p2) ) - { - if ( Fraig_IsComplement(pNode1->p2) ) - { // pNode2->p2 is positive phase of C - *ppNodeT = Fraig_Not(pNode2->p1); - *ppNodeE = Fraig_Not(pNode1->p1); - return pNode2->p2; - } - else - { // pNode1->p2 is positive phase of C - *ppNodeT = Fraig_Not(pNode1->p1); - *ppNodeE = Fraig_Not(pNode2->p1); - return pNode1->p2; - } - } - assert( 0 ); // this is not MUX - return NULL; -} - -/**Function************************************************************* - - Synopsis [Counts the number of EXOR type nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_ManCountExors( Fraig_Man_t * pMan ) -{ - int i, nExors; - nExors = 0; - for ( i = 0; i < pMan->vNodes->nSize; i++ ) - nExors += Fraig_NodeIsExorType( pMan->vNodes->pArray[i] ); - return nExors; - -} - -/**Function************************************************************* - - Synopsis [Counts the number of EXOR type nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_ManCountMuxes( Fraig_Man_t * pMan ) -{ - int i, nMuxes; - nMuxes = 0; - for ( i = 0; i < pMan->vNodes->nSize; i++ ) - nMuxes += Fraig_NodeIsMuxType( pMan->vNodes->pArray[i] ); - return nMuxes; - -} - -/**Function************************************************************* - - Synopsis [Returns 1 if siminfo of Node1 is contained in siminfo of Node2.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeSimsContained( Fraig_Man_t * pMan, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2 ) -{ - unsigned * pUnsigned1, * pUnsigned2; - int i; - - // compare random siminfo - pUnsigned1 = pNode1->puSimR; - pUnsigned2 = pNode2->puSimR; - for ( i = 0; i < pMan->nWordsRand; i++ ) - if ( pUnsigned1[i] & ~pUnsigned2[i] ) - return 0; - - // compare systematic siminfo - pUnsigned1 = pNode1->puSimD; - pUnsigned2 = pNode2->puSimD; - for ( i = 0; i < pMan->iWordStart; i++ ) - if ( pUnsigned1[i] & ~pUnsigned2[i] ) - return 0; - - return 1; -} - -/**Function************************************************************* - - Synopsis [Count the number of PI variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_CountPis( Fraig_Man_t * p, Msat_IntVec_t * vVarNums ) -{ - int * pVars, nVars, i, Counter; - - nVars = Msat_IntVecReadSize(vVarNums); - pVars = Msat_IntVecReadArray(vVarNums); - Counter = 0; - for ( i = 0; i < nVars; i++ ) - Counter += Fraig_NodeIsVar( p->vNodes->pArray[pVars[i]] ); - return Counter; -} - - - -/**Function************************************************************* - - Synopsis [Counts the number of EXOR type nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_ManPrintRefs( Fraig_Man_t * pMan ) -{ - Fraig_NodeVec_t * vPivots; - Fraig_Node_t * pNode, * pNode2; - int i, k, Counter, nProved; - int clk; - - vPivots = Fraig_NodeVecAlloc( 1000 ); - for ( i = 0; i < pMan->vNodes->nSize; i++ ) - { - pNode = pMan->vNodes->pArray[i]; - - if ( pNode->nOnes == 0 || pNode->nOnes == (unsigned)pMan->nWordsRand * 32 ) - continue; - - if ( pNode->nRefs > 5 ) - { - Fraig_NodeVecPush( vPivots, pNode ); -// printf( "Node %6d : nRefs = %2d Level = %3d.\n", pNode->Num, pNode->nRefs, pNode->Level ); - } - } - printf( "Total nodes = %d. Referenced nodes = %d.\n", pMan->vNodes->nSize, vPivots->nSize ); - -clk = clock(); - // count implications - Counter = nProved = 0; - for ( i = 0; i < vPivots->nSize; i++ ) - for ( k = i+1; k < vPivots->nSize; k++ ) - { - pNode = vPivots->pArray[i]; - pNode2 = vPivots->pArray[k]; - if ( Fraig_NodeSimsContained( pMan, pNode, pNode2 ) ) - { - if ( Fraig_NodeIsImplication( pMan, pNode, pNode2, -1 ) ) - nProved++; - Counter++; - } - else if ( Fraig_NodeSimsContained( pMan, pNode2, pNode ) ) - { - if ( Fraig_NodeIsImplication( pMan, pNode2, pNode, -1 ) ) - nProved++; - Counter++; - } - } - printf( "Number of candidate pairs = %d. Proved = %d.\n", Counter, nProved ); -//ABC_PRT( "Time", clock() - clk ); - return 0; -} - - -/**Function************************************************************* - - Synopsis [Checks if pNew exists among the implication fanins of pOld.] - - Description [If pNew is an implication fanin of pOld, returns 1. - If Fraig_Not(pNew) is an implication fanin of pOld, return -1. - Otherwise returns 0.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeIsInSupergate( Fraig_Node_t * pOld, Fraig_Node_t * pNew ) -{ - int RetValue1, RetValue2; - if ( Fraig_Regular(pOld) == Fraig_Regular(pNew) ) - return (pOld == pNew)? 1 : -1; - if ( Fraig_IsComplement(pOld) || Fraig_NodeIsVar(pOld) ) - return 0; - RetValue1 = Fraig_NodeIsInSupergate( pOld->p1, pNew ); - RetValue2 = Fraig_NodeIsInSupergate( pOld->p2, pNew ); - if ( RetValue1 == -1 || RetValue2 == -1 ) - return -1; - if ( RetValue1 == 1 || RetValue2 == 1 ) - return 1; - return 0; -} - - -/**Function************************************************************* - - Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_CollectSupergate_rec( Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper, int fFirst, int fStopAtMux ) -{ - // if the new node is complemented or a PI, another gate begins -// if ( Fraig_IsComplement(pNode) || Fraig_NodeIsVar(pNode) || Fraig_NodeIsMuxType(pNode) ) - if ( (!fFirst && Fraig_Regular(pNode)->nRefs > 1) || - Fraig_IsComplement(pNode) || Fraig_NodeIsVar(pNode) || - (fStopAtMux && Fraig_NodeIsMuxType(pNode)) ) - { - Fraig_NodeVecPushUnique( vSuper, pNode ); - return; - } - // go through the branches - Fraig_CollectSupergate_rec( pNode->p1, vSuper, 0, fStopAtMux ); - Fraig_CollectSupergate_rec( pNode->p2, vSuper, 0, fStopAtMux ); -} - -/**Function************************************************************* - - Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_NodeVec_t * Fraig_CollectSupergate( Fraig_Node_t * pNode, int fStopAtMux ) -{ - Fraig_NodeVec_t * vSuper; - vSuper = Fraig_NodeVecAlloc( 8 ); - Fraig_CollectSupergate_rec( pNode, vSuper, 1, fStopAtMux ); - return vSuper; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_ManIncrementTravId( Fraig_Man_t * pMan ) -{ - pMan->nTravIds2++; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeSetTravIdCurrent( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) -{ - pNode->TravId2 = pMan->nTravIds2; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeIsTravIdCurrent( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) -{ - return pNode->TravId2 == pMan->nTravIds2; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeIsTravIdPrevious( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) -{ - return pNode->TravId2 == pMan->nTravIds2 - 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/sat/fraig/fraigVec.c b/src/sat/fraig/fraigVec.c deleted file mode 100644 index 25d50bf3..00000000 --- a/src/sat/fraig/fraigVec.c +++ /dev/null @@ -1,550 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraigVec.c] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [Vector of FRAIG nodes.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - October 1, 2004] - - Revision [$Id: fraigVec.c,v 1.7 2005/07/08 01:01:34 alanmi Exp $] - -***********************************************************************/ - -#include "fraigInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_NodeVec_t * Fraig_NodeVecAlloc( int nCap ) -{ - Fraig_NodeVec_t * p; - p = ABC_ALLOC( Fraig_NodeVec_t, 1 ); - if ( nCap > 0 && nCap < 8 ) - nCap = 8; - p->nSize = 0; - p->nCap = nCap; - p->pArray = p->nCap? ABC_ALLOC( Fraig_Node_t *, p->nCap ) : NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeVecFree( Fraig_NodeVec_t * p ) -{ - ABC_FREE( p->pArray ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Duplicates the integer array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_NodeVec_t * Fraig_NodeVecDup( Fraig_NodeVec_t * pVec ) -{ - Fraig_NodeVec_t * p; - p = ABC_ALLOC( Fraig_NodeVec_t, 1 ); - p->nSize = pVec->nSize; - p->nCap = pVec->nCap; - p->pArray = p->nCap? ABC_ALLOC( Fraig_Node_t *, p->nCap ) : NULL; - memcpy( p->pArray, pVec->pArray, sizeof(Fraig_Node_t *) * pVec->nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t ** Fraig_NodeVecReadArray( Fraig_NodeVec_t * p ) -{ - return p->pArray; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeVecReadSize( Fraig_NodeVec_t * p ) -{ - return p->nSize; -} - -/**Function************************************************************* - - Synopsis [Resizes the vector to the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeVecGrow( Fraig_NodeVec_t * p, int nCapMin ) -{ - if ( p->nCap >= nCapMin ) - return; - p->pArray = ABC_REALLOC( Fraig_Node_t *, p->pArray, nCapMin ); - p->nCap = nCapMin; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeVecShrink( Fraig_NodeVec_t * p, int nSizeNew ) -{ - assert( p->nSize >= nSizeNew ); - p->nSize = nSizeNew; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeVecClear( Fraig_NodeVec_t * p ) -{ - p->nSize = 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeVecPush( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ) -{ - if ( p->nSize == p->nCap ) - { - if ( p->nCap < 16 ) - Fraig_NodeVecGrow( p, 16 ); - else - Fraig_NodeVecGrow( p, 2 * p->nCap ); - } - p->pArray[p->nSize++] = Entry; -} - -/**Function************************************************************* - - Synopsis [Add the element while ensuring uniqueness.] - - Description [Returns 1 if the element was found, and 0 if it was new. ] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeVecPushUnique( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == Entry ) - return 1; - Fraig_NodeVecPush( p, Entry ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Inserts a new node in the order by arrival times.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeVecPushOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ) -{ - Fraig_Node_t * pNode1, * pNode2; - int i; - Fraig_NodeVecPush( p, pNode ); - // find the p of the node - for ( i = p->nSize-1; i > 0; i-- ) - { - pNode1 = p->pArray[i ]; - pNode2 = p->pArray[i-1]; - if ( pNode1 >= pNode2 ) - break; - p->pArray[i ] = pNode2; - p->pArray[i-1] = pNode1; - } -} - -/**Function************************************************************* - - Synopsis [Add the element while ensuring uniqueness in the order.] - - Description [Returns 1 if the element was found, and 0 if it was new. ] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeVecPushUniqueOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == pNode ) - return 1; - Fraig_NodeVecPushOrder( p, pNode ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Inserts a new node in the order by arrival times.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeVecPushOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ) -{ - Fraig_Node_t * pNode1, * pNode2; - int i; - Fraig_NodeVecPush( p, pNode ); - // find the p of the node - for ( i = p->nSize-1; i > 0; i-- ) - { - pNode1 = p->pArray[i ]; - pNode2 = p->pArray[i-1]; - if ( Fraig_Regular(pNode1)->Level <= Fraig_Regular(pNode2)->Level ) - break; - p->pArray[i ] = pNode2; - p->pArray[i-1] = pNode1; - } -} - -/**Function************************************************************* - - Synopsis [Add the element while ensuring uniqueness in the order.] - - Description [Returns 1 if the element was found, and 0 if it was new. ] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeVecPushUniqueOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == pNode ) - return 1; - Fraig_NodeVecPushOrderByLevel( p, pNode ); - return 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_NodeVecPop( Fraig_NodeVec_t * p ) -{ - return p->pArray[--p->nSize]; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeVecRemove( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == Entry ) - break; - assert( i < p->nSize ); - for ( i++; i < p->nSize; i++ ) - p->pArray[i-1] = p->pArray[i]; - p->nSize--; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeVecWriteEntry( Fraig_NodeVec_t * p, int i, Fraig_Node_t * Entry ) -{ - assert( i >= 0 && i < p->nSize ); - p->pArray[i] = Entry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_NodeVecReadEntry( Fraig_NodeVec_t * p, int i ) -{ - assert( i >= 0 && i < p->nSize ); - return p->pArray[i]; -} - -/**Function************************************************************* - - Synopsis [Comparison procedure for two clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeVecCompareLevelsIncreasing( Fraig_Node_t ** pp1, Fraig_Node_t ** pp2 ) -{ - int Level1 = Fraig_Regular(*pp1)->Level; - int Level2 = Fraig_Regular(*pp2)->Level; - if ( Level1 < Level2 ) - return -1; - if ( Level1 > Level2 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Comparison procedure for two clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeVecCompareLevelsDecreasing( Fraig_Node_t ** pp1, Fraig_Node_t ** pp2 ) -{ - int Level1 = Fraig_Regular(*pp1)->Level; - int Level2 = Fraig_Regular(*pp2)->Level; - if ( Level1 > Level2 ) - return -1; - if ( Level1 < Level2 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Comparison procedure for two clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeVecCompareNumbers( Fraig_Node_t ** pp1, Fraig_Node_t ** pp2 ) -{ - int Num1 = Fraig_Regular(*pp1)->Num; - int Num2 = Fraig_Regular(*pp2)->Num; - if ( Num1 < Num2 ) - return -1; - if ( Num1 > Num2 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Comparison procedure for two clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeVecCompareRefCounts( Fraig_Node_t ** pp1, Fraig_Node_t ** pp2 ) -{ - int nRefs1 = Fraig_Regular(*pp1)->nRefs; - int nRefs2 = Fraig_Regular(*pp2)->nRefs; - - if ( nRefs1 < nRefs2 ) - return -1; - if ( nRefs1 > nRefs2 ) - return 1; - - nRefs1 = Fraig_Regular(*pp1)->Level; - nRefs2 = Fraig_Regular(*pp2)->Level; - - if ( nRefs1 < nRefs2 ) - return -1; - if ( nRefs1 > nRefs2 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Sorting the entries by their integer value.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeVecSortByLevel( Fraig_NodeVec_t * p, int fIncreasing ) -{ - if ( fIncreasing ) - qsort( (void *)p->pArray, p->nSize, sizeof(Fraig_Node_t *), - (int (*)(const void *, const void *)) Fraig_NodeVecCompareLevelsIncreasing ); - else - qsort( (void *)p->pArray, p->nSize, sizeof(Fraig_Node_t *), - (int (*)(const void *, const void *)) Fraig_NodeVecCompareLevelsDecreasing ); -} - -/**Function************************************************************* - - Synopsis [Sorting the entries by their integer value.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeVecSortByNumber( Fraig_NodeVec_t * p ) -{ - qsort( (void *)p->pArray, p->nSize, sizeof(Fraig_Node_t *), - (int (*)(const void *, const void *)) Fraig_NodeVecCompareNumbers ); -} - -/**Function************************************************************* - - Synopsis [Sorting the entries by their integer value.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeVecSortByRefCount( Fraig_NodeVec_t * p ) -{ - qsort( (void *)p->pArray, p->nSize, sizeof(Fraig_Node_t *), - (int (*)(const void *, const void *)) Fraig_NodeVecCompareRefCounts ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - -ABC_NAMESPACE_IMPL_END - diff --git a/src/sat/fraig/module.make b/src/sat/fraig/module.make deleted file mode 100644 index cc6eb9d3..00000000 --- a/src/sat/fraig/module.make +++ /dev/null @@ -1,12 +0,0 @@ -SRC += src/sat/fraig/fraigApi.c \ - src/sat/fraig/fraigCanon.c \ - src/sat/fraig/fraigFanout.c \ - src/sat/fraig/fraigFeed.c \ - src/sat/fraig/fraigMan.c \ - src/sat/fraig/fraigMem.c \ - src/sat/fraig/fraigNode.c \ - src/sat/fraig/fraigPrime.c \ - src/sat/fraig/fraigSat.c \ - src/sat/fraig/fraigTable.c \ - src/sat/fraig/fraigUtil.c \ - src/sat/fraig/fraigVec.c diff --git a/src/sat/lsat/solver.h b/src/sat/lsat/solver.h index a50c4abe..2baff658 100644 --- a/src/sat/lsat/solver.h +++ b/src/sat/lsat/solver.h @@ -18,8 +18,8 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************************************/ -#ifndef Minisat_solver_h -#define Minisat_solver_h +#ifndef ABC__sat__lsat__solver_h +#define ABC__sat__lsat__solver_h ABC_NAMESPACE_HEADER_START diff --git a/src/sat/msat/msat.h b/src/sat/msat/msat.h index 6dc68cf8..4830b12e 100644 --- a/src/sat/msat/msat.h +++ b/src/sat/msat/msat.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __MSAT_H__ -#define __MSAT_H__ +#ifndef ABC__sat__msat__msat_h +#define ABC__sat__msat__msat_h //////////////////////////////////////////////////////////////////////// diff --git a/src/sat/msat/msatInt.h b/src/sat/msat/msatInt.h index b4b5ff77..58baa7b4 100644 --- a/src/sat/msat/msatInt.h +++ b/src/sat/msat/msatInt.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __MSAT_INT_H__ -#define __MSAT_INT_H__ +#ifndef ABC__sat__msat__msatInt_h +#define ABC__sat__msat__msatInt_h //////////////////////////////////////////////////////////////////////// @@ -33,7 +33,7 @@ #include #include -#include "abc_global.h" +#include "src/misc/util/abc_global.h" #include "msat.h" ABC_NAMESPACE_HEADER_START diff --git a/src/sat/pdr/module.make b/src/sat/pdr/module.make deleted file mode 100644 index 5cf4491c..00000000 --- a/src/sat/pdr/module.make +++ /dev/null @@ -1,8 +0,0 @@ -SRC += src/sat/pdr/pdr.c \ - src/sat/pdr/pdrCnf.c \ - src/sat/pdr/pdrCore.c \ - src/sat/pdr/pdrInv.c \ - src/sat/pdr/pdrMan.c \ - src/sat/pdr/pdrSat.c \ - src/sat/pdr/pdrTsim.c \ - src/sat/pdr/pdrUtil.c diff --git a/src/sat/pdr/pdr.c b/src/sat/pdr/pdr.c deleted file mode 100644 index 6bdf75b5..00000000 --- a/src/sat/pdr/pdr.c +++ /dev/null @@ -1,53 +0,0 @@ -/**CFile**************************************************************** - - FileName [pdr.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Netlist representation.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - November 20, 2010.] - - Revision [$Id: pdr.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "pdrInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/sat/pdr/pdr.h b/src/sat/pdr/pdr.h deleted file mode 100644 index 03854509..00000000 --- a/src/sat/pdr/pdr.h +++ /dev/null @@ -1,79 +0,0 @@ -/**CFile**************************************************************** - - FileName [pdr.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Property driven reachability.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - November 20, 2010.] - - Revision [$Id: pdr.h,v 1.00 2010/11/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __PDR_H__ -#define __PDR_H__ - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Pdr_Par_t_ Pdr_Par_t; -struct Pdr_Par_t_ -{ - int iOutput; // zero-based number of primary output to solve - int nRecycle; // limit on vars for recycling - int nFrameMax; // limit on frame count - int nConfLimit; // limit on SAT solver conflicts - int nTimeOut; // timeout in seconds - int fTwoRounds; // use two rounds for generalization - int fMonoCnf; // monolythic CNF - int fDumpInv; // dump inductive invariant - int fShortest; // forces bug traces to be shortest - int fSkipGeneral; // skips expensive generalization step - int fVerbose; // verbose output - int fVeryVerbose; // very verbose output - int iFrame; // explored up to this frame -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== pdrCore.c ==========================================================*/ -extern void Pdr_ManSetDefaultParams( Pdr_Par_t * pPars ); -extern int Pdr_ManSolve( Aig_Man_t * p, Pdr_Par_t * pPars, Abc_Cex_t ** ppCex ); - - -ABC_NAMESPACE_HEADER_END - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/sat/pdr/pdrClass.c b/src/sat/pdr/pdrClass.c deleted file mode 100644 index 3e990958..00000000 --- a/src/sat/pdr/pdrClass.c +++ /dev/null @@ -1,223 +0,0 @@ -/**CFile**************************************************************** - - FileName [pdrClass.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Property driven reachability.] - - Synopsis [Equivalence classes of register outputs.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - November 20, 2010.] - - Revision [$Id: pdrClass.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "pdrInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs duplication with the variable map.] - - Description [Var map contains -1 if const0 and otherwise.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Pdr_ManRehashWithMap( Aig_Man_t * pAig, Vec_Int_t * vMap ) -{ - Aig_Man_t * pFrames; - Aig_Obj_t * pObj; - int i, iReg; - assert( Vec_IntSize(vMap) == Aig_ManRegNum(pAig) ); - // start the fraig package - pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) ); - pFrames->pName = Aig_UtilStrsav( pAig->pName ); - pFrames->pSpec = Aig_UtilStrsav( pAig->pSpec ); - // create CI mapping - Aig_ManCleanData( pAig ); - Aig_ManConst1(pAig)->pData = Aig_ManConst1(pFrames); - Aig_ManForEachPi( pAig, pObj, i ) - pObj->pData = Aig_ObjCreatePi(pFrames); - Saig_ManForEachLo( pAig, pObj, i ) - { - iReg = Vec_IntEntry(vMap, i); - if ( iReg == -1 ) - pObj->pData = Aig_ManConst0(pFrames); - else - pObj->pData = Saig_ManLo(pAig, iReg)->pData; - } - // add internal nodes of this frame - Aig_ManForEachNode( pAig, pObj, i ) - pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - // add output nodes - Aig_ManForEachPo( pAig, pObj, i ) - pObj->pData = Aig_ObjCreatePo( pFrames, Aig_ObjChild0Copy(pObj) ); - // finish off - Aig_ManCleanup( pFrames ); - Aig_ManSetRegNum( pFrames, Aig_ManRegNum(pAig) ); - return pFrames; -} - -/**Function************************************************************* - - Synopsis [Creates mapping of registers.] - - Description [Var map contains -1 if const0 and otherwise.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Pdr_ManCreateMap( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - Vec_Int_t * vMap; - int * pLit2Id, Lit, i; - pLit2Id = ABC_ALLOC( int, Aig_ManObjNumMax(p) * 2 ); - for ( i = 0; i < Aig_ManObjNumMax(p) * 2; i++ ) - pLit2Id[i] = -1; - vMap = Vec_IntAlloc( Aig_ManRegNum(p) ); - Saig_ManForEachLi( p, pObj, i ) - { - if ( Aig_ObjChild0(pObj) == Aig_ManConst0(p) ) - { - Vec_IntPush( vMap, -1 ); - continue; - } - Lit = 2 * Aig_ObjFaninId0(pObj) + Aig_ObjFaninC0(pObj); - if ( pLit2Id[Lit] < 0 ) // the first time - pLit2Id[Lit] = i; - Vec_IntPush( vMap, pLit2Id[Lit] ); - } - ABC_FREE( pLit2Id ); - return vMap; -} - -/**Function************************************************************* - - Synopsis [Counts reduced registers.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pdr_ManCountMap( Vec_Int_t * vMap ) -{ - int i, Entry, Counter = 0; - Vec_IntForEachEntry( vMap, Entry, i ) - if ( Entry != i ) - Counter++; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts reduced registers.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pdr_ManPrintMap( Vec_Int_t * vMap ) -{ - Vec_Int_t * vMarks; - int f, i, iClass, Entry, Counter = 0; - printf( " Consts: " ); - Vec_IntForEachEntry( vMap, Entry, i ) - if ( Entry == -1 ) - printf( "%d ", i ); - printf( "\n" ); - vMarks = Vec_IntAlloc( 100 ); - Vec_IntForEachEntry( vMap, iClass, f ) - { - if ( iClass == -1 ) - continue; - if ( iClass == f ) - continue; - // check previous classes - if ( Vec_IntFind( vMarks, iClass ) >= 0 ) - continue; - Vec_IntPush( vMarks, iClass ); - // print class - printf( " Class %d : ", iClass ); - Vec_IntForEachEntry( vMap, Entry, i ) - if ( Entry == iClass ) - printf( "%d ", i ); - printf( "\n" ); - } - Vec_IntFree( vMarks ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pdr_ManEquivClasses( Aig_Man_t * pAig ) -{ - Vec_Int_t * vMap; - Aig_Man_t * pTemp; - int f, nFrames = 100; - assert( Saig_ManRegNum(pAig) > 0 ); - // start the map - vMap = Vec_IntAlloc( 0 ); - Vec_IntFill( vMap, Aig_ManRegNum(pAig), -1 ); - // iterate and print changes - for ( f = 0; f < nFrames; f++ ) - { - // implement variable map - pTemp = Pdr_ManRehashWithMap( pAig, vMap ); - // report the result - printf( "F =%4d : Total = %6d. Nodes = %6d. RedRegs = %6d. Prop = %s\n", - f+1, Aig_ManNodeNum(pAig), Aig_ManNodeNum(pTemp), Pdr_ManCountMap(vMap), - Aig_ObjChild0(Aig_ManPo(pTemp,0)) == Aig_ManConst0(pTemp) ? "proof" : "unknown" ); - // recreate the map - Pdr_ManPrintMap( vMap ); - Vec_IntFree( vMap ); - vMap = Pdr_ManCreateMap( pTemp ); - Aig_ManStop( pTemp ); - if ( Pdr_ManCountMap(vMap) == 0 ) - break; - } - Vec_IntFree( vMap ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/sat/pdr/pdrCnf.c b/src/sat/pdr/pdrCnf.c deleted file mode 100644 index fddd292b..00000000 --- a/src/sat/pdr/pdrCnf.c +++ /dev/null @@ -1,357 +0,0 @@ -/**CFile**************************************************************** - - FileName [pdrCnf.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Property driven reachability.] - - Synopsis [CNF computation on demand.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - November 20, 2010.] - - Revision [$Id: pdrCnf.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "pdrInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/* - The CNF (p->pCnf2) is expressed in terms of object IDs. - Each node in the CNF is marked if it has clauses (p->pCnf2->pObj2Count[Id] > 0). - Each node in the CNF has the first clause (p->pCnf2->pObj2Clause) - and the number of clauses (p->pCnf2->pObj2Count). - Each node used in a CNF of any timeframe has its SAT var recorded. - Each frame has a reserve mapping of SAT variables into ObjIds. -*/ - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns SAT variable of the given object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Pdr_ObjSatVar1( Pdr_Man_t * p, int k, Aig_Obj_t * pObj ) -{ - return p->pCnf1->pVarNums[ Aig_ObjId(pObj) ]; -} - -/**Function************************************************************* - - Synopsis [Returns SAT variable of the given object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Pdr_ObjSatVar2FindOrAdd( Pdr_Man_t * p, int k, Aig_Obj_t * pObj ) -{ - assert( p->pCnf2->pObj2Count[Aig_ObjId(pObj)] >= 0 ); - if ( p->pvId2Vars[Aig_ObjId(pObj)] == NULL ) - p->pvId2Vars[Aig_ObjId(pObj)] = Vec_IntStart( 16 ); - if ( Vec_IntGetEntry( p->pvId2Vars[Aig_ObjId(pObj)], k ) == 0 ) - { - sat_solver * pSat = Pdr_ManSolver(p, k); - Vec_Int_t * vVar2Ids = (Vec_Int_t *)Vec_PtrEntry(p->vVar2Ids, k); - int iVarNew = Vec_IntSize( vVar2Ids ); - assert( iVarNew > 0 ); - Vec_IntPush( vVar2Ids, Aig_ObjId(pObj) ); - Vec_IntWriteEntry( p->pvId2Vars[Aig_ObjId(pObj)], k, iVarNew ); - sat_solver_setnvars( pSat, iVarNew + 1 ); - if ( k == 0 && Saig_ObjIsLo(p->pAig, pObj) ) // initialize the register output - { - int Lit = toLitCond( iVarNew, 1 ); - int RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 ); - assert( RetValue == 1 ); - sat_solver_compress( pSat ); - } - } - return Vec_IntEntry( p->pvId2Vars[Aig_ObjId(pObj)], k ); -} - -/**Function************************************************************* - - Synopsis [Recursively adds CNF for the given object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pdr_ObjSatVar2( Pdr_Man_t * p, int k, Aig_Obj_t * pObj ) -{ - sat_solver * pSat; - Vec_Int_t * vLits; - Vec_Int_t * vVar2Ids = (Vec_Int_t *)Vec_PtrEntry(p->vVar2Ids, k); - int nVarCount = Vec_IntSize(vVar2Ids); - int iVarThis = Pdr_ObjSatVar2FindOrAdd( p, k, pObj ); - int * pLit, i, iVar, nClauses, iFirstClause, RetValue; - if ( nVarCount == Vec_IntSize(vVar2Ids) ) - return iVarThis; - assert( nVarCount + 1 == Vec_IntSize(vVar2Ids) ); - if ( Aig_ObjIsPi(pObj) ) - return iVarThis; - nClauses = p->pCnf2->pObj2Count[Aig_ObjId(pObj)]; - iFirstClause = p->pCnf2->pObj2Clause[Aig_ObjId(pObj)]; - assert( nClauses > 0 ); - pSat = Pdr_ManSolver(p, k); - vLits = Vec_IntAlloc( 16 ); - for ( i = iFirstClause; i < iFirstClause + nClauses; i++ ) - { - Vec_IntClear( vLits ); - for ( pLit = p->pCnf2->pClauses[i]; pLit < p->pCnf2->pClauses[i+1]; pLit++ ) - { - iVar = Pdr_ObjSatVar2( p, k, Aig_ManObj(p->pAig, lit_var(*pLit)) ); - Vec_IntPush( vLits, toLitCond( iVar, lit_sign(*pLit) ) ); - } - RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits)+Vec_IntSize(vLits) ); - assert( RetValue ); - } - Vec_IntFree( vLits ); - return iVarThis; -} - -/**Function************************************************************* - - Synopsis [Returns SAT variable of the given object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pdr_ObjSatVar( Pdr_Man_t * p, int k, Aig_Obj_t * pObj ) -{ - if ( p->pPars->fMonoCnf ) - return Pdr_ObjSatVar1( p, k, pObj ); - else - return Pdr_ObjSatVar2( p, k, pObj ); -} - - -/**Function************************************************************* - - Synopsis [Returns register number for the given SAT variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Pdr_ObjRegNum1( Pdr_Man_t * p, int k, int iSatVar ) -{ - int RegId; - assert( iSatVar >= 0 ); - // consider the case of auxiliary variable - if ( iSatVar >= p->pCnf1->nVars ) - return -1; - // consider the case of register output - RegId = Vec_IntEntry( p->vVar2Reg, iSatVar ); - assert( RegId >= 0 && RegId < Aig_ManRegNum(p->pAig) ); - return RegId; -} - -/**Function************************************************************* - - Synopsis [Returns register number for the given SAT variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Pdr_ObjRegNum2( Pdr_Man_t * p, int k, int iSatVar ) -{ - Aig_Obj_t * pObj; - int ObjId; - Vec_Int_t * vVar2Ids = (Vec_Int_t *)Vec_PtrEntry(p->vVar2Ids, k); - assert( iSatVar > 0 && iSatVar < Vec_IntSize(vVar2Ids) ); - ObjId = Vec_IntEntry( vVar2Ids, iSatVar ); - if ( ObjId == -1 ) // activation variable - return -1; - pObj = Aig_ManObj( p->pAig, ObjId ); - if ( Saig_ObjIsLi( p->pAig, pObj ) ) - return Aig_ObjPioNum(pObj)-Saig_ManPoNum(p->pAig); - assert( 0 ); // should be called for register inputs only - return -1; -} - -/**Function************************************************************* - - Synopsis [Returns register number for the given SAT variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pdr_ObjRegNum( Pdr_Man_t * p, int k, int iSatVar ) -{ - if ( p->pPars->fMonoCnf ) - return Pdr_ObjRegNum1( p, k, iSatVar ); - else - return Pdr_ObjRegNum2( p, k, iSatVar ); -} - - -/**Function************************************************************* - - Synopsis [Returns the index of unused SAT variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pdr_ManFreeVar( Pdr_Man_t * p, int k ) -{ - if ( p->pPars->fMonoCnf ) - return sat_solver_nvars( Pdr_ManSolver(p, k) ); - else - { - Vec_Int_t * vVar2Ids = (Vec_Int_t *)Vec_PtrEntry( p->vVar2Ids, k ); - Vec_IntPush( vVar2Ids, -1 ); - return Vec_IntSize( vVar2Ids ) - 1; - } -} - -/**Function************************************************************* - - Synopsis [Creates SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline sat_solver * Pdr_ManNewSolver1( sat_solver * pSat, Pdr_Man_t * p, int k, int fInit ) -{ - Aig_Obj_t * pObj; - int i; - assert( pSat ); - if ( p->pCnf1 == NULL ) - { - int nRegs = p->pAig->nRegs; - p->pAig->nRegs = Aig_ManPoNum(p->pAig); - p->pCnf1 = Cnf_Derive( p->pAig, Aig_ManPoNum(p->pAig) ); - p->pAig->nRegs = nRegs; - assert( p->vVar2Reg == NULL ); - p->vVar2Reg = Vec_IntStartFull( p->pCnf1->nVars ); - Saig_ManForEachLi( p->pAig, pObj, i ) - Vec_IntWriteEntry( p->vVar2Reg, Pdr_ObjSatVar(p, k, pObj), i ); - } - pSat = (sat_solver *)Cnf_DataWriteIntoSolverInt( pSat, p->pCnf1, 1, fInit ); - sat_solver_set_runtime_limit( pSat, p->timeToStop ); - return pSat; -} - -/**Function************************************************************* - - Synopsis [Creates SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline sat_solver * Pdr_ManNewSolver2( sat_solver * pSat, Pdr_Man_t * p, int k, int fInit ) -{ - Vec_Int_t * vVar2Ids; - int i, Entry; - assert( pSat ); - if ( p->pCnf2 == NULL ) - { - p->pCnf2 = Cnf_DeriveOther( p->pAig ); - p->pvId2Vars = ABC_CALLOC( Vec_Int_t *, Aig_ManObjNumMax(p->pAig) ); - p->vVar2Ids = Vec_PtrAlloc( 256 ); - } - // update the variable mapping - vVar2Ids = (Vec_Int_t *)Vec_PtrGetEntry( p->vVar2Ids, k ); - if ( vVar2Ids == NULL ) - { - vVar2Ids = Vec_IntAlloc( 500 ); - Vec_PtrWriteEntry( p->vVar2Ids, k, vVar2Ids ); - } - Vec_IntForEachEntry( vVar2Ids, Entry, i ) - { - if ( Entry == -1 ) - continue; - assert( Vec_IntEntry( p->pvId2Vars[Entry], k ) > 0 ); - Vec_IntWriteEntry( p->pvId2Vars[Entry], k, 0 ); - } - Vec_IntClear( vVar2Ids ); - Vec_IntPush( vVar2Ids, -1 ); - // start the SAT solver -// pSat = sat_solver_new(); - sat_solver_setnvars( pSat, 500 ); - sat_solver_set_runtime_limit( pSat, p->timeToStop ); - return pSat; -} - -/**Function************************************************************* - - Synopsis [Creates SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -sat_solver * Pdr_ManNewSolver( sat_solver * pSat, Pdr_Man_t * p, int k, int fInit ) -{ - assert( pSat != NULL ); - if ( p->pPars->fMonoCnf ) - return Pdr_ManNewSolver1( pSat, p, k, fInit ); - else - return Pdr_ManNewSolver2( pSat, p, k, fInit ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/sat/pdr/pdrCore.c b/src/sat/pdr/pdrCore.c deleted file mode 100644 index 025ada06..00000000 --- a/src/sat/pdr/pdrCore.c +++ /dev/null @@ -1,722 +0,0 @@ -/**CFile**************************************************************** - - FileName [pdrCore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Property driven reachability.] - - Synopsis [Core procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - November 20, 2010.] - - Revision [$Id: pdrCore.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "pdrInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns 1 if the state could be blocked.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pdr_ManSetDefaultParams( Pdr_Par_t * pPars ) -{ - memset( pPars, 0, sizeof(Pdr_Par_t) ); - pPars->iOutput = -1; // zero-based output number - pPars->nRecycle = 300; // limit on vars for recycling - pPars->nFrameMax = 5000; // limit on number of timeframes - pPars->nTimeOut = 0; // timeout in seconds - pPars->nConfLimit = 100000; // limit on SAT solver conflicts - pPars->fTwoRounds = 0; // use two rounds for generalization - pPars->fMonoCnf = 0; // monolythic CNF - pPars->fDumpInv = 0; // dump inductive invariant - pPars->fShortest = 0; // forces bug traces to be shortest - pPars->fVerbose = 0; // verbose output - pPars->fVeryVerbose = 0; // very verbose output - pPars->iFrame = -1; // explored up to this frame -} - -/**Function************************************************************* - - Synopsis [Reduces clause using analyzeFinal.] - - Description [Assumes that the SAT solver just terminated an UNSAT call.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Pdr_Set_t * Pdr_ManReduceClause( Pdr_Man_t * p, int k, Pdr_Set_t * pCube ) -{ - Pdr_Set_t * pCubeMin; - Vec_Int_t * vLits; - int i, Entry, nCoreLits, * pCoreLits; - // get relevant SAT literals - nCoreLits = sat_solver_final(Pdr_ManSolver(p, k), &pCoreLits); - // translate them into register literals and remove auxiliary - vLits = Pdr_ManLitsToCube( p, k, pCoreLits, nCoreLits ); - // skip if there is no improvement - if ( Vec_IntSize(vLits) == pCube->nLits ) - return NULL; - assert( Vec_IntSize(vLits) < pCube->nLits ); - // if the cube overlaps with init, add any literal - Vec_IntForEachEntry( vLits, Entry, i ) - if ( lit_sign(Entry) == 0 ) // positive literal - break; - if ( i == Vec_IntSize(vLits) ) // only negative literals - { - // add the first positive literal - for ( i = 0; i < pCube->nLits; i++ ) - if ( lit_sign(pCube->Lits[i]) == 0 ) // positive literal - { - Vec_IntPush( vLits, pCube->Lits[i] ); - break; - } - assert( i < pCube->nLits ); - } - // generate a starting cube - pCubeMin = Pdr_SetCreateSubset( pCube, Vec_IntArray(vLits), Vec_IntSize(vLits) ); - assert( !Pdr_SetIsInit(pCubeMin, -1) ); -/* - // make sure the cube works - { - int RetValue; - RetValue = Pdr_ManCheckCube( p, k, pCubeMin, NULL, 0 ); - assert( RetValue ); - } -*/ - return pCubeMin; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the state could be blocked.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pdr_ManPushClauses( Pdr_Man_t * p ) -{ - Pdr_Set_t * pTemp, * pCubeK, * pCubeK1; - Vec_Ptr_t * vArrayK, * vArrayK1; - int i, j, k, m, RetValue = 0, RetValue2, kMax = Vec_PtrSize(p->vSolvers)-1; - int Counter = 0; - int clk = clock(); - Vec_VecForEachLevelStartStop( p->vClauses, vArrayK, k, 1, kMax ) - { - Vec_PtrSort( vArrayK, (int (*)(void))Pdr_SetCompare ); - vArrayK1 = Vec_VecEntry( p->vClauses, k+1 ); - Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCubeK, j ) - { - Counter++; - - // remove cubes in the same frame that are contained by pCubeK - Vec_PtrForEachEntryStart( Pdr_Set_t *, vArrayK, pTemp, m, j+1 ) - { - if ( !Pdr_SetContains( pTemp, pCubeK ) ) // pCubeK contains pTemp - continue; - Pdr_SetDeref( pTemp ); - Vec_PtrWriteEntry( vArrayK, m, Vec_PtrEntryLast(vArrayK) ); - Vec_PtrPop(vArrayK); - m--; - } - - // check if the clause can be moved to the next frame - RetValue2 = Pdr_ManCheckCube( p, k, pCubeK, NULL, 0 ); - if ( RetValue2 == -1 ) - return -1; - if ( !RetValue2 ) - continue; - - { - Pdr_Set_t * pCubeMin; - pCubeMin = Pdr_ManReduceClause( p, k, pCubeK ); - if ( pCubeMin != NULL ) - { -// printf( "%d ", pCubeK->nLits - pCubeMin->nLits ); - Pdr_SetDeref( pCubeK ); - pCubeK = pCubeMin; - } - } - - // if it can be moved, add it to the next frame - Pdr_ManSolverAddClause( p, k+1, pCubeK ); - // check if the clause subsumes others - Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK1, pCubeK1, i ) - { - if ( !Pdr_SetContains( pCubeK1, pCubeK ) ) // pCubeK contains pCubeK1 - continue; - Pdr_SetDeref( pCubeK1 ); - Vec_PtrWriteEntry( vArrayK1, i, Vec_PtrEntryLast(vArrayK1) ); - Vec_PtrPop(vArrayK1); - i--; - } - // add the last clause - Vec_PtrPush( vArrayK1, pCubeK ); - Vec_PtrWriteEntry( vArrayK, j, Vec_PtrEntryLast(vArrayK) ); - Vec_PtrPop(vArrayK); - j--; - } - if ( Vec_PtrSize(vArrayK) == 0 ) - RetValue = 1; - } - - // clean up the last one - vArrayK = Vec_VecEntry( p->vClauses, kMax ); - Vec_PtrSort( vArrayK, (int (*)(void))Pdr_SetCompare ); - Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCubeK, j ) - { - // remove cubes in the same frame that are contained by pCubeK - Vec_PtrForEachEntryStart( Pdr_Set_t *, vArrayK, pTemp, m, j+1 ) - { - if ( !Pdr_SetContains( pTemp, pCubeK ) ) // pCubeK contains pTemp - continue; -/* - printf( "===\n" ); - Pdr_SetPrint( stdout, pCubeK, Aig_ManRegNum(p->pAig), NULL ); - printf( "\n" ); - Pdr_SetPrint( stdout, pTemp, Aig_ManRegNum(p->pAig), NULL ); - printf( "\n" ); -*/ - Pdr_SetDeref( pTemp ); - Vec_PtrWriteEntry( vArrayK, m, Vec_PtrEntryLast(vArrayK) ); - Vec_PtrPop(vArrayK); - m--; - } - } - p->tPush += clock() - clk; - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the clause is contained in higher clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pdr_ManCheckContainment( Pdr_Man_t * p, int k, Pdr_Set_t * pSet ) -{ - Pdr_Set_t * pThis; - Vec_Ptr_t * vArrayK; - int i, j, kMax = Vec_PtrSize(p->vSolvers)-1; - Vec_VecForEachLevelStartStop( p->vClauses, vArrayK, i, k, kMax+1 ) - Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pThis, j ) - if ( Pdr_SetContains( pSet, pThis ) ) - return 1; - return 0; -} - - -/**Function************************************************************* - - Synopsis [Sorts literals by priority.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int * Pdr_ManSortByPriority( Pdr_Man_t * p, Pdr_Set_t * pCube ) -{ - int * pPrios = Vec_IntArray(p->vPrio); - int * pArray = p->pOrder; - int temp, i, j, best_i, nSize = pCube->nLits; - // initialize variable order - for ( i = 0; i < nSize; i++ ) - pArray[i] = i; - for ( i = 0; i < nSize-1; i++ ) - { - best_i = i; - for ( j = i+1; j < nSize; j++ ) -// if ( pArray[j] < pArray[best_i] ) - if ( pPrios[pCube->Lits[pArray[j]]>>1] < pPrios[pCube->Lits[pArray[best_i]]>>1] ) - best_i = j; - temp = pArray[i]; - pArray[i] = pArray[best_i]; - pArray[best_i] = temp; - } -/* - for ( i = 0; i < pCube->nLits; i++ ) - printf( "%2d : %5d %5d %5d\n", i, pArray[i], pCube->Lits[pArray[i]]>>1, pPrios[pCube->Lits[pArray[i]]>>1] ); - printf( "\n" ); -*/ - return pArray; -} - - -/**Function************************************************************* - - Synopsis [Returns 1 if the state could be blocked.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pdr_ManGeneralize( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, Pdr_Set_t ** ppPred, Pdr_Set_t ** ppCubeMin ) -{ - Pdr_Set_t * pCubeMin, * pCubeTmp = NULL; - int i, j, n, Lit, RetValue, clk = clock(); - int * pOrder; - // if there is no induction, return - *ppCubeMin = NULL; - RetValue = Pdr_ManCheckCube( p, k, pCube, ppPred, p->pPars->nConfLimit ); - if ( RetValue == -1 ) - return -1; - if ( RetValue == 0 ) - { - p->tGeneral += clock() - clk; - return 0; - } - - // reduce clause using assumptions -// pCubeMin = Pdr_SetDup( pCube ); - pCubeMin = Pdr_ManReduceClause( p, k, pCube ); - if ( pCubeMin == NULL ) - pCubeMin = Pdr_SetDup( pCube ); - - // perform generalization - if ( !p->pPars->fSkipGeneral ) - { - // sort literals by their occurences - pOrder = Pdr_ManSortByPriority( p, pCubeMin ); - // try removing literals - for ( j = 0; j < pCubeMin->nLits; j++ ) - { - // use ordering - // i = j; - i = pOrder[j]; - - // check init state - assert( pCubeMin->Lits[i] != -1 ); - if ( Pdr_SetIsInit(pCubeMin, i) ) - continue; - // try removing this literal - Lit = pCubeMin->Lits[i]; pCubeMin->Lits[i] = -1; - RetValue = Pdr_ManCheckCube( p, k, pCubeMin, NULL, p->pPars->nConfLimit ); - if ( RetValue == -1 ) - { - Pdr_SetDeref( pCubeMin ); - return -1; - } - pCubeMin->Lits[i] = Lit; - if ( RetValue == 0 ) - continue; - - // remove j-th entry - for ( n = j; n < pCubeMin->nLits-1; n++ ) - pOrder[n] = pOrder[n+1]; - j--; - - // success - update the cube - pCubeMin = Pdr_SetCreateFrom( pCubeTmp = pCubeMin, i ); - Pdr_SetDeref( pCubeTmp ); - assert( pCubeMin->nLits > 0 ); - i--; - - // get the ordering by decreasing priorit - pOrder = Pdr_ManSortByPriority( p, pCubeMin ); - } - - if ( p->pPars->fTwoRounds ) - for ( j = 0; j < pCubeMin->nLits; j++ ) - { - // use ordering - // i = j; - i = pOrder[j]; - - // check init state - assert( pCubeMin->Lits[i] != -1 ); - if ( Pdr_SetIsInit(pCubeMin, i) ) - continue; - // try removing this literal - Lit = pCubeMin->Lits[i]; pCubeMin->Lits[i] = -1; - RetValue = Pdr_ManCheckCube( p, k, pCubeMin, NULL, p->pPars->nConfLimit ); - if ( RetValue == -1 ) - { - Pdr_SetDeref( pCubeMin ); - return -1; - } - pCubeMin->Lits[i] = Lit; - if ( RetValue == 0 ) - continue; - - // remove j-th entry - for ( n = j; n < pCubeMin->nLits-1; n++ ) - pOrder[n] = pOrder[n+1]; - j--; - - // success - update the cube - pCubeMin = Pdr_SetCreateFrom( pCubeTmp = pCubeMin, i ); - Pdr_SetDeref( pCubeTmp ); - assert( pCubeMin->nLits > 0 ); - i--; - - // get the ordering by decreasing priorit - pOrder = Pdr_ManSortByPriority( p, pCubeMin ); - } - } - - assert( ppCubeMin != NULL ); - *ppCubeMin = pCubeMin; - p->tGeneral += clock() - clk; - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the state could be blocked.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pdr_ManBlockCube( Pdr_Man_t * p, Pdr_Set_t * pCube ) -{ - Pdr_Obl_t * pThis; - Pdr_Set_t * pPred, * pCubeMin; - int i, k, RetValue, Prio = ABC_INFINITY, Counter = 0; - int kMax = Vec_PtrSize(p->vSolvers)-1, clk; - p->nBlocks++; - // create first proof obligation - assert( p->pQueue == NULL ); - pThis = Pdr_OblStart( kMax, Prio--, pCube, NULL ); // consume ref - Pdr_QueuePush( p, pThis ); - // try to solve it recursively - while ( !Pdr_QueueIsEmpty(p) ) - { - Counter++; - pThis = Pdr_QueueHead( p ); - if ( pThis->iFrame == 0 ) - return 0; // SAT - pThis = Pdr_QueuePop( p ); - assert( pThis->iFrame > 0 ); - assert( !Pdr_SetIsInit(pThis->pState, -1) ); - - clk = clock(); - if ( Pdr_ManCheckContainment( p, pThis->iFrame, pThis->pState ) ) - { - p->tContain += clock() - clk; - Pdr_OblDeref( pThis ); - continue; - } - p->tContain += clock() - clk; - - // check if the cube is already contained - RetValue = Pdr_ManCheckCubeCs( p, pThis->iFrame, pThis->pState ); - if ( RetValue == -1 ) // cube is blocked by clauses in this frame - { - Pdr_OblDeref( pThis ); - return -1; - } - if ( RetValue ) // cube is blocked by clauses in this frame - { - Pdr_OblDeref( pThis ); - continue; - } - - // check if the cube holds with relative induction - pCubeMin = NULL; - RetValue = Pdr_ManGeneralize( p, pThis->iFrame-1, pThis->pState, &pPred, &pCubeMin ); - if ( RetValue == -1 ) - { - Pdr_OblDeref( pThis ); - return -1; - } - if ( RetValue ) // cube is blocked inductively in this frame - { - assert( pCubeMin != NULL ); - - // k is the last frame where pCubeMin holds - k = pThis->iFrame; - - // check other frames - assert( pPred == NULL ); - for ( k = pThis->iFrame; k < kMax; k++ ) - if ( !Pdr_ManCheckCube( p, k, pCubeMin, NULL, 0 ) ) - break; - - // add new clause - if ( p->pPars->fVeryVerbose ) - { - printf( "Adding cube " ); - Pdr_SetPrint( stdout, pCubeMin, Aig_ManRegNum(p->pAig), NULL ); - printf( " to frame %d.\n", k ); - } - // set priority flops - for ( i = 0; i < pCubeMin->nLits; i++ ) - { - assert( pCubeMin->Lits[i] >= 0 ); - assert( (pCubeMin->Lits[i] / 2) < Aig_ManRegNum(p->pAig) ); - Vec_IntAddToEntry( p->vPrio, pCubeMin->Lits[i] / 2, 1 ); - } - - Vec_VecPush( p->vClauses, k, pCubeMin ); // consume ref - p->nCubes++; - // add clause - for ( i = 1; i <= k; i++ ) - Pdr_ManSolverAddClause( p, i, pCubeMin ); - // schedule proof obligation - if ( k < kMax && !p->pPars->fShortest ) - { - pThis->iFrame = k+1; - pThis->prio = Prio--; - Pdr_QueuePush( p, pThis ); - } - else - { - Pdr_OblDeref( pThis ); - } - } - else - { - assert( pCubeMin == NULL ); - assert( pPred != NULL ); - pThis->prio = Prio--; - Pdr_QueuePush( p, pThis ); - - pThis = Pdr_OblStart( pThis->iFrame-1, Prio--, pPred, Pdr_OblRef(pThis) ); - Pdr_QueuePush( p, pThis ); - } - - // check the timeout - if ( p->timeToStop && time(NULL) > p->timeToStop ) - return -1; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pdr_ManSolveInt( Pdr_Man_t * p ) -{ - int fPrintClauses = 0; - Pdr_Set_t * pCube; - int k, RetValue = -1; - int clkTotal = clock(); - int clkStart = clock(); - p->timeToStop = p->pPars->nTimeOut ? time(NULL) + p->pPars->nTimeOut : 0; - assert( Vec_PtrSize(p->vSolvers) == 0 ); - // create the first timeframe - Pdr_ManCreateSolver( p, (k = 0) ); - while ( 1 ) - { - p->nFrames = k; - assert( k == Vec_PtrSize(p->vSolvers)-1 ); - RetValue = Pdr_ManCheckCube( p, k, NULL, &pCube, p->pPars->nConfLimit ); - if ( RetValue == -1 ) - { - if ( p->pPars->fVerbose ) - Pdr_ManPrintProgress( p, 1, clock() - clkStart ); - printf( "Reached conflict limit (%d).\n", p->pPars->nConfLimit ); - p->pPars->iFrame = k; - return -1; - } - if ( RetValue == 0 ) - { - RetValue = Pdr_ManBlockCube( p, pCube ); - if ( RetValue == -1 ) - { - if ( p->pPars->fVerbose ) - Pdr_ManPrintProgress( p, 1, clock() - clkStart ); - printf( "Reached conflict limit (%d).\n", p->pPars->nConfLimit ); - p->pPars->iFrame = k; - return -1; - } - if ( RetValue == 0 ) - { - if ( fPrintClauses ) - { - printf( "*** Clauses after frame %d:\n", k ); - Pdr_ManPrintClauses( p, 0 ); - } - if ( p->pPars->fVerbose ) - Pdr_ManPrintProgress( p, 1, clock() - clkStart ); - p->pPars->iFrame = k; - return 0; // SAT - } - } - else - { - if ( p->pPars->fVerbose ) - Pdr_ManPrintProgress( p, 1, clock() - clkStart ); - // open a new timeframe - assert( pCube == NULL ); - Pdr_ManSetPropertyOutput( p, k ); - Pdr_ManCreateSolver( p, ++k ); - if ( fPrintClauses ) - { - printf( "*** Clauses after frame %d:\n", k ); - Pdr_ManPrintClauses( p, 0 ); - } - // push clauses into this timeframe - RetValue = Pdr_ManPushClauses( p ); - if ( RetValue == -1 ) - { - if ( p->pPars->fVerbose ) - Pdr_ManPrintProgress( p, 1, clock() - clkStart ); - printf( "Reached conflict limit (%d).\n", p->pPars->nConfLimit ); - p->pPars->iFrame = k; - return -1; - } - if ( RetValue ) - { - if ( p->pPars->fVerbose ) - Pdr_ManPrintProgress( p, 1, clock() - clkStart ); - Pdr_ManReportInvariant( p ); - Pdr_ManVerifyInvariant( p ); - p->pPars->iFrame = k; - return 1; // UNSAT - } - if ( p->pPars->fVerbose ) - Pdr_ManPrintProgress( p, 0, clock() - clkStart ); - clkStart = clock(); - } - - // check the timeout - if ( p->timeToStop && time(NULL) > p->timeToStop ) - { - if ( fPrintClauses ) - { - printf( "*** Clauses after frame %d:\n", k ); - Pdr_ManPrintClauses( p, 0 ); - } - if ( p->pPars->fVerbose ) - Pdr_ManPrintProgress( p, 1, clock() - clkStart ); - printf( "Reached timeout (%d seconds).\n", p->pPars->nTimeOut ); - p->pPars->iFrame = k; - return -1; - } - if ( p->pPars->nFrameMax && k >= p->pPars->nFrameMax ) - { - if ( p->pPars->fVerbose ) - Pdr_ManPrintProgress( p, 1, clock() - clkStart ); - printf( "Reached limit on the number of timeframes (%d).\n", p->pPars->nFrameMax ); - p->pPars->iFrame = k; - return -1; - } - } - return RetValue; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pdr_ManSolve_( Aig_Man_t * pAig, Pdr_Par_t * pPars, Vec_Int_t ** pvPrioInit, Abc_Cex_t ** ppCex ) -{ - Pdr_Man_t * p; - int RetValue; - int clk = clock(); - p = Pdr_ManStart( pAig, pPars, pvPrioInit? *pvPrioInit : NULL ); - RetValue = Pdr_ManSolveInt( p ); - *ppCex = RetValue ? NULL : Pdr_ManDeriveCex( p ); - if ( p->pPars->fDumpInv ) - Pdr_ManDumpClauses( p, (char *)"inv.pla", RetValue==1 ); - -// if ( *ppCex && pPars->fVerbose ) -// printf( "Found counter-example in frame %d after exploring %d frames.\n", -// (*ppCex)->iFrame, p->nFrames ); - p->tTotal += clock() - clk; - if ( pvPrioInit ) - { - *pvPrioInit = p->vPrio; - p->vPrio = NULL; - } - Pdr_ManStop( p ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pdr_ManSolve( Aig_Man_t * pAig, Pdr_Par_t * pPars, Abc_Cex_t ** ppCex ) -{ -/* - Vec_Int_t * vPrioInit = NULL; - int RetValue, nTimeOut; - if ( pPars->nTimeOut > 0 ) - return Pdr_ManSolve_( pAig, pPars, NULL, ppCex ); - nTimeOut = pPars->nTimeOut; - pPars->nTimeOut = 10; - RetValue = Pdr_ManSolve_( pAig, pPars, &vPrioInit, ppCex ); - pPars->nTimeOut = nTimeOut; - if ( RetValue == -1 ) - RetValue = Pdr_ManSolve_( pAig, pPars, &vPrioInit, ppCex ); - Vec_IntFree( vPrioInit ); - return RetValue; -*/ - return Pdr_ManSolve_( pAig, pPars, NULL, ppCex ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/sat/pdr/pdrInt.h b/src/sat/pdr/pdrInt.h deleted file mode 100644 index f49ee7d0..00000000 --- a/src/sat/pdr/pdrInt.h +++ /dev/null @@ -1,198 +0,0 @@ -/**CFile**************************************************************** - - FileName [pdrInt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Property driven reachability.] - - Synopsis [Internal declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - November 20, 2010.] - - Revision [$Id: pdrInt.h,v 1.00 2010/11/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __PDR_INT_H__ -#define __PDR_INT_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "saig.h" -#include "cnf.h" -#include "satSolver.h" -#include "pdr.h" - -ABC_NAMESPACE_HEADER_START - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Pdr_Set_t_ Pdr_Set_t; -struct Pdr_Set_t_ -{ - word Sign; // signature - int nRefs; // ref counter - int nTotal; // total literals - int nLits; // num flop literals - int Lits[0]; -}; - -typedef struct Pdr_Obl_t_ Pdr_Obl_t; -struct Pdr_Obl_t_ -{ - int iFrame; // time frame - int prio; // priority - int nRefs; // reference counter - Pdr_Set_t * pState; // state cube - Pdr_Obl_t * pNext; // next one - Pdr_Obl_t * pLink; // queue link -}; - -typedef struct Pdr_Man_t_ Pdr_Man_t; -struct Pdr_Man_t_ -{ - // input problem - Pdr_Par_t * pPars; // parameters - Aig_Man_t * pAig; // user's AIG - // static CNF representation - Cnf_Dat_t * pCnf1; // CNF for this AIG - Vec_Int_t * vVar2Reg; // mapping of SAT var into registers - // dynamic CNF representation - Cnf_Dat_t * pCnf2; // CNF for this AIG - Vec_Int_t** pvId2Vars; // for each used ObjId, maps frame into SAT var - Vec_Ptr_t * vVar2Ids; // for each used frame, maps SAT var into ObjId - // data representation - Vec_Ptr_t * vSolvers; // SAT solvers - Vec_Vec_t * vClauses; // clauses by timeframe - Pdr_Obl_t * pQueue; // proof obligations - int * pOrder; // ordering of the lits - Vec_Int_t * vActVars; // the counter of activation variables - // internal use - Vec_Int_t * vPrio; // priority flops - Vec_Int_t * vLits; // array of literals - Vec_Int_t * vCiObjs; // cone leaves - Vec_Int_t * vCoObjs; // cone roots - Vec_Int_t * vCiVals; // cone leaf values - Vec_Int_t * vCoVals; // cone root values - Vec_Int_t * vNodes; // cone nodes - Vec_Int_t * vUndo; // cone undos - Vec_Int_t * vVisits; // intermediate - Vec_Int_t * vCi2Rem; // CIs to be removed - Vec_Int_t * vRes; // final result - Vec_Int_t * vSuppLits; // support literals - Pdr_Set_t * pCubeJust; // justification - // statistics - int nBlocks; // the number of times blockState was called - int nObligs; // the number of proof obligations derived - int nCubes; // the number of cubes derived - int nCalls; // the number of SAT calls - int nCallsS; // the number of SAT calls (sat) - int nCallsU; // the number of SAT calls (unsat) - int nStarts; // the number of SAT solver restarts - int nFrames; // frames explored - int nCasesSS; - int nCasesSU; - int nCasesUS; - int nCasesUU; - // runtime - int timeStart; - int timeToStop; - // time stats - int tSat; - int tSatSat; - int tSatUnsat; - int tGeneral; - int tPush; - int tTsim; - int tContain; - int tCnf; - int tTotal; -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline sat_solver * Pdr_ManSolver( Pdr_Man_t * p, int k ) { return (sat_solver *)Vec_PtrEntry(p->vSolvers, k); } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== pdrCex.c ==========================================================*/ -extern Abc_Cex_t * Pdr_ManDeriveCex( Pdr_Man_t * p ); -/*=== pdrCnf.c ==========================================================*/ -extern int Pdr_ObjSatVar( Pdr_Man_t * p, int k, Aig_Obj_t * pObj ); -extern int Pdr_ObjRegNum( Pdr_Man_t * p, int k, int iSatVar ); -extern int Pdr_ManFreeVar( Pdr_Man_t * p, int k ); -extern sat_solver * Pdr_ManNewSolver( sat_solver * pSat, Pdr_Man_t * p, int k, int fInit ); -/*=== pdrCore.c ==========================================================*/ -extern int Pdr_ManCheckContainment( Pdr_Man_t * p, int k, Pdr_Set_t * pSet ); -/*=== pdrInv.c ==========================================================*/ -extern void Pdr_ManPrintProgress( Pdr_Man_t * p, int fClose, int Time ); -extern void Pdr_ManPrintClauses( Pdr_Man_t * p, int kStart ); -extern void Pdr_ManDumpClauses( Pdr_Man_t * p, char * pFileName, int fProved ); -extern void Pdr_ManReportInvariant( Pdr_Man_t * p ); -extern void Pdr_ManVerifyInvariant( Pdr_Man_t * p ); -/*=== pdrMan.c ==========================================================*/ -extern Pdr_Man_t * Pdr_ManStart( Aig_Man_t * pAig, Pdr_Par_t * pPars, Vec_Int_t * vPrioInit ); -extern void Pdr_ManStop( Pdr_Man_t * p ); -extern Abc_Cex_t * Pdr_ManDeriveCex( Pdr_Man_t * p ); -/*=== pdrSat.c ==========================================================*/ -extern sat_solver * Pdr_ManCreateSolver( Pdr_Man_t * p, int k ); -extern sat_solver * Pdr_ManFetchSolver( Pdr_Man_t * p, int k ); -extern void Pdr_ManSetPropertyOutput( Pdr_Man_t * p, int k ); -extern Vec_Int_t * Pdr_ManCubeToLits( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, int fCompl, int fNext ); -extern Vec_Int_t * Pdr_ManLitsToCube( Pdr_Man_t * p, int k, int * pArray, int nArray ); -extern void Pdr_ManSolverAddClause( Pdr_Man_t * p, int k, Pdr_Set_t * pCube ); -extern void Pdr_ManCollectValues( Pdr_Man_t * p, int k, Vec_Int_t * vObjIds, Vec_Int_t * vValues ); -extern int Pdr_ManCheckCubeCs( Pdr_Man_t * p, int k, Pdr_Set_t * pCube ); -extern int Pdr_ManCheckCube( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, Pdr_Set_t ** ppPred, int nConfLimit ); -/*=== pdrTsim.c ==========================================================*/ -extern Pdr_Set_t * Pdr_ManTernarySim( Pdr_Man_t * p, int k, Pdr_Set_t * pCube ); -/*=== pdrUtil.c ==========================================================*/ -extern Pdr_Set_t * Pdr_SetAlloc( int nSize ); -extern Pdr_Set_t * Pdr_SetCreate( Vec_Int_t * vLits, Vec_Int_t * vPiLits ); -extern Pdr_Set_t * Pdr_SetCreateFrom( Pdr_Set_t * pSet, int iRemove ); -extern Pdr_Set_t * Pdr_SetCreateSubset( Pdr_Set_t * pSet, int * pLits, int nLits ); -extern Pdr_Set_t * Pdr_SetDup( Pdr_Set_t * pSet ); -extern Pdr_Set_t * Pdr_SetRef( Pdr_Set_t * p ); -extern void Pdr_SetDeref( Pdr_Set_t * p ); -extern int Pdr_SetContains( Pdr_Set_t * pOld, Pdr_Set_t * pNew ); -extern int Pdr_SetContainsSimple( Pdr_Set_t * pOld, Pdr_Set_t * pNew ); -extern int Pdr_SetIsInit( Pdr_Set_t * p, int iRemove ); -extern void Pdr_SetPrint( FILE * pFile, Pdr_Set_t * p, int nRegs, Vec_Int_t * vFlopCounts ); -extern int Pdr_SetCompare( Pdr_Set_t ** pp1, Pdr_Set_t ** pp2 ); -extern Pdr_Obl_t * Pdr_OblStart( int k, int prio, Pdr_Set_t * pState, Pdr_Obl_t * pNext ); -extern Pdr_Obl_t * Pdr_OblRef( Pdr_Obl_t * p ); -extern void Pdr_OblDeref( Pdr_Obl_t * p ); -extern int Pdr_QueueIsEmpty( Pdr_Man_t * p ); -extern Pdr_Obl_t * Pdr_QueueHead( Pdr_Man_t * p ); -extern Pdr_Obl_t * Pdr_QueuePop( Pdr_Man_t * p ); -extern void Pdr_QueuePush( Pdr_Man_t * p, Pdr_Obl_t * pObl ); -extern void Pdr_QueuePrint( Pdr_Man_t * p ); -extern void Pdr_QueueStop( Pdr_Man_t * p ); -extern int Pdr_ManCubeJust( Pdr_Man_t * p, int k, Pdr_Set_t * pCube ); - -ABC_NAMESPACE_HEADER_END - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/sat/pdr/pdrInv.c b/src/sat/pdr/pdrInv.c deleted file mode 100644 index 2f630e28..00000000 --- a/src/sat/pdr/pdrInv.c +++ /dev/null @@ -1,376 +0,0 @@ -/**CFile**************************************************************** - - FileName [pdrInv.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Property driven reachability.] - - Synopsis [Invariant computation, printing, verification.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - November 20, 2010.] - - Revision [$Id: pdrInv.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" // for Abc_NtkCollectCioNames() -#include "main.h" // for Abc_FrameReadGlobalFrame() - -#include "pdrInt.h" -#include "extra.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pdr_ManPrintProgress( Pdr_Man_t * p, int fClose, int Time ) -{ - static int PastSize; - Vec_Ptr_t * vVec; - int i, ThisSize, Length, LengthStart; - if ( Vec_PtrSize(p->vSolvers) < 2 ) - return; - // count the total length of the printout - Length = 0; - Vec_VecForEachLevel( p->vClauses, vVec, i ) - Length += 1 + Extra_Base10Log(Vec_PtrSize(vVec)+1); - // determine the starting point - LengthStart = ABC_MAX( 0, Length - 70 ); - printf( "%3d :", Vec_PtrSize(p->vSolvers)-1 ); - ThisSize = 6; - if ( LengthStart > 0 ) - { - printf( " ..." ); - ThisSize += 4; - } - Length = 0; - Vec_VecForEachLevel( p->vClauses, vVec, i ) - { - if ( Length < LengthStart ) - { - Length += 1 + Extra_Base10Log(Vec_PtrSize(vVec)+1); - continue; - } - printf( " %d", Vec_PtrSize(vVec) ); - Length += 1 + Extra_Base10Log(Vec_PtrSize(vVec)+1); - ThisSize += 1 + Extra_Base10Log(Vec_PtrSize(vVec)+1); - } - if ( fClose ) - { - for ( i = 0; i < PastSize - ThisSize; i++ ) - printf( " " ); - printf( "\n" ); - } - else - { - printf( "\r" ); - PastSize = ThisSize; - } -// printf(" %.2f sec", (float)(Time)/(float)(CLOCKS_PER_SEC)); -} - -/**Function************************************************************* - - Synopsis [Counts how many times each flop appears in the set of cubes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Pdr_ManCountFlops( Pdr_Man_t * p, Vec_Ptr_t * vCubes ) -{ - Vec_Int_t * vFlopCount; - Pdr_Set_t * pCube; - int i, n; - vFlopCount = Vec_IntStart( Aig_ManRegNum(p->pAig) ); - Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i ) - for ( n = 0; n < pCube->nLits; n++ ) - { - assert( pCube->Lits[n] >= 0 && pCube->Lits[n] < 2*Aig_ManRegNum(p->pAig) ); - Vec_IntAddToEntry( vFlopCount, pCube->Lits[n] >> 1, 1 ); - } - return vFlopCount; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pdr_ManFindInvariantStart( Pdr_Man_t * p ) -{ - Vec_Ptr_t * vArrayK; - int k, kMax = Vec_PtrSize(p->vSolvers)-1; - Vec_VecForEachLevelStartStop( p->vClauses, vArrayK, k, 1, kMax+1 ) - if ( Vec_PtrSize(vArrayK) == 0 ) - return k; -// return -1; - // if there is no starting point (as in case of SAT or undecided), return the last frame -// printf( "The last timeframe contains %d clauses.\n", Vec_PtrSize(Vec_VecEntry(p->vClauses, kMax)) ); - return kMax; -} - -/**Function************************************************************* - - Synopsis [Counts the number of variables used in the clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Pdr_ManCollectCubes( Pdr_Man_t * p, int kStart ) -{ - Vec_Ptr_t * vResult; - Vec_Ptr_t * vArrayK; - Pdr_Set_t * pSet; - int i, j; - vResult = Vec_PtrAlloc( 100 ); - Vec_VecForEachLevelStart( p->vClauses, vArrayK, i, kStart ) - Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pSet, j ) - Vec_PtrPush( vResult, pSet ); - return vResult; -} - -/**Function************************************************************* - - Synopsis [Counts the number of variables used in the clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pdr_ManCountVariables( Pdr_Man_t * p, int kStart ) -{ - Vec_Int_t * vFlopCounts; - Vec_Ptr_t * vCubes; - int i, Entry, Counter = 0; - vCubes = Pdr_ManCollectCubes( p, kStart ); - vFlopCounts = Pdr_ManCountFlops( p, vCubes ); - Vec_IntForEachEntry( vFlopCounts, Entry, i ) - Counter += (Entry > 0); - Vec_IntFreeP( &vFlopCounts ); - Vec_PtrFree( vCubes ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pdr_ManPrintClauses( Pdr_Man_t * p, int kStart ) -{ - Vec_Ptr_t * vArrayK; - Pdr_Set_t * pCube; - int i, k, Counter = 0; - Vec_VecForEachLevelStart( p->vClauses, vArrayK, k, kStart ) - { - Vec_PtrSort( vArrayK, (int (*)(void))Pdr_SetCompare ); - Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCube, i ) - { - printf( "C=%4d. F=%4d ", Counter++, k ); - Pdr_SetPrint( stdout, pCube, Aig_ManRegNum(p->pAig), NULL ); - printf( "\n" ); - } - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pdr_ManDumpClauses( Pdr_Man_t * p, char * pFileName, int fProved ) -{ - int fUseSupp = 1; - FILE * pFile; - Vec_Int_t * vFlopCounts; - Vec_Ptr_t * vCubes; - Pdr_Set_t * pCube; - char ** pNamesCi; - int i, kStart; - // create file - pFile = fopen( pFileName, "w" ); - if ( pFile == NULL ) - { - printf( "Cannot open file \"%s\" for writing invariant.\n", pFileName ); - return; - } - // collect cubes - kStart = Pdr_ManFindInvariantStart( p ); - vCubes = Pdr_ManCollectCubes( p, kStart ); - Vec_PtrSort( vCubes, (int (*)(void))Pdr_SetCompare ); - // collect variable appearances - vFlopCounts = fUseSupp ? Pdr_ManCountFlops( p, vCubes ) : NULL; - // output the header - if ( fProved ) - fprintf( pFile, "# Inductive invariant for \"%s\"\n", p->pAig->pName ); - else - fprintf( pFile, "# Clauses of the last timeframe for \"%s\"\n", p->pAig->pName ); - fprintf( pFile, "# generated by PDR in ABC on %s\n", Aig_TimeStamp() ); - fprintf( pFile, ".i %d\n", fUseSupp ? Pdr_ManCountVariables(p, kStart) : Aig_ManRegNum(p->pAig) ); - fprintf( pFile, ".o 1\n" ); - fprintf( pFile, ".p %d\n", Vec_PtrSize(vCubes) ); - // output flop names - pNamesCi = Abc_NtkCollectCioNames( Abc_FrameReadNtk( Abc_FrameReadGlobalFrame() ), 0 ); - if ( pNamesCi ) - { - fprintf( pFile, ".ilb" ); - for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ ) - if ( !fUseSupp || Vec_IntEntry( vFlopCounts, i ) ) - fprintf( pFile, " %s", pNamesCi[Saig_ManPiNum(p->pAig) + i] ); - fprintf( pFile, "\n" ); - ABC_FREE( pNamesCi ); - fprintf( pFile, ".ob inv\n" ); - } - // output cubes - Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i ) - { - Pdr_SetPrint( pFile, pCube, Aig_ManRegNum(p->pAig), vFlopCounts ); - fprintf( pFile, " 1\n" ); - } - fprintf( pFile, ".e\n\n" ); - fclose( pFile ); - Vec_IntFreeP( &vFlopCounts ); - Vec_PtrFree( vCubes ); - if ( fProved ) - printf( "Inductive invariant was written into file \"%s\".\n", pFileName ); - else - printf( "Clauses of the last timeframe were written into file \"%s\".\n", pFileName ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pdr_ManReportInvariant( Pdr_Man_t * p ) -{ - Vec_Ptr_t * vCubes; - int kStart = Pdr_ManFindInvariantStart( p ); - vCubes = Pdr_ManCollectCubes( p, kStart ); - printf( "Invariant F[%d] : %d clauses with %d flops (out of %d)\n", - kStart, Vec_PtrSize(vCubes), Pdr_ManCountVariables(p, kStart), Aig_ManRegNum(p->pAig) ); - Vec_PtrFree( vCubes ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pdr_ManVerifyInvariant( Pdr_Man_t * p ) -{ - sat_solver * pSat; - Vec_Int_t * vLits; - Vec_Ptr_t * vCubes; - Pdr_Set_t * pCube; - int i, kStart, kThis, RetValue, Counter = 0, clk = clock(); - // collect cubes used in the inductive invariant - kStart = Pdr_ManFindInvariantStart( p ); - vCubes = Pdr_ManCollectCubes( p, kStart ); - // create solver with the cubes - kThis = Vec_PtrSize(p->vSolvers); - pSat = Pdr_ManCreateSolver( p, kThis ); - // add the property output - Pdr_ManSetPropertyOutput( p, kThis ); - // add the clauses - Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i ) - { - vLits = Pdr_ManCubeToLits( p, kThis, pCube, 1, 0 ); - RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ); - assert( RetValue ); - sat_solver_compress( pSat ); - } - // check each clause - Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i ) - { - vLits = Pdr_ManCubeToLits( p, kThis, pCube, 0, 1 ); - RetValue = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), 0, 0, 0, 0 ); - if ( RetValue != l_False ) - { - printf( "Verification of clause %d failed.\n", i ); - Counter++; - } - } - if ( Counter ) - printf( "Verification of %d clauses has failed.\n", Counter ); - else - { - printf( "Verification of invariant with %d clauses was successful. ", Vec_PtrSize(vCubes) ); - Abc_PrintTime( 1, "Time", clock() - clk ); - } -// sat_solver_delete( pSat ); - Vec_PtrFree( vCubes ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/sat/pdr/pdrMan.c b/src/sat/pdr/pdrMan.c deleted file mode 100644 index 95a38efb..00000000 --- a/src/sat/pdr/pdrMan.c +++ /dev/null @@ -1,194 +0,0 @@ -/**CFile**************************************************************** - - FileName [pdrMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Property driven reachability.] - - Synopsis [Manager procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - November 20, 2010.] - - Revision [$Id: pdrMan.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "pdrInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Pdr_Man_t * Pdr_ManStart( Aig_Man_t * pAig, Pdr_Par_t * pPars, Vec_Int_t * vPrioInit ) -{ - Pdr_Man_t * p; - p = ABC_CALLOC( Pdr_Man_t, 1 ); - p->pPars = pPars; - p->pAig = pAig; - p->vSolvers = Vec_PtrAlloc( 0 ); - p->vClauses = Vec_VecAlloc( 0 ); - p->pQueue = NULL; - p->pOrder = ABC_ALLOC( int, Aig_ManRegNum(pAig) ); - p->vActVars = Vec_IntAlloc( 256 ); - // internal use - p->vPrio = vPrioInit ? vPrioInit : Vec_IntStart( Aig_ManRegNum(pAig) ); // priority flops - p->vLits = Vec_IntAlloc( 100 ); // array of literals - p->vCiObjs = Vec_IntAlloc( 100 ); // cone leaves - p->vCoObjs = Vec_IntAlloc( 100 ); // cone roots - p->vCiVals = Vec_IntAlloc( 100 ); // cone leaf values - p->vCoVals = Vec_IntAlloc( 100 ); // cone root values - p->vNodes = Vec_IntAlloc( 100 ); // cone nodes - p->vUndo = Vec_IntAlloc( 100 ); // cone undos - p->vVisits = Vec_IntAlloc( 100 ); // intermediate - p->vCi2Rem = Vec_IntAlloc( 100 ); // CIs to be removed - p->vRes = Vec_IntAlloc( 100 ); // final result - p->vSuppLits= Vec_IntAlloc( 100 ); // support literals - p->pCubeJust= Pdr_SetAlloc( Saig_ManRegNum(pAig) ); - // additional AIG data-members - if ( pAig->pFanData == NULL ) - Aig_ManFanoutStart( pAig ); - if ( pAig->pTerSimData == NULL ) - pAig->pTerSimData = ABC_CALLOC( unsigned, 1 + (Aig_ManObjNumMax(pAig) / 16) ); - p->timeStart = clock(); - return p; -} - -/**Function************************************************************* - - Synopsis [Frees manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pdr_ManStop( Pdr_Man_t * p ) -{ - Pdr_Set_t * pCla; - sat_solver * pSat; - int i, k; - Aig_ManCleanMarkAB( p->pAig ); - if ( p->pPars->fVerbose ) - { - printf( "Block =%5d Oblig =%6d Clause =%6d Call =%6d (sat=%.1f%%) Start =%4d\n", - p->nBlocks, p->nObligs, p->nCubes, p->nCalls, 100.0 * p->nCallsS / p->nCalls, p->nStarts ); - ABC_PRTP( "SAT solving", p->tSat, p->tTotal ); - ABC_PRTP( " unsat ", p->tSatUnsat, p->tTotal ); - ABC_PRTP( " sat ", p->tSatSat, p->tTotal ); - ABC_PRTP( "Generalize ", p->tGeneral, p->tTotal ); - ABC_PRTP( "Push clause", p->tPush, p->tTotal ); - ABC_PRTP( "Ternary sim", p->tTsim, p->tTotal ); - ABC_PRTP( "Containment", p->tContain, p->tTotal ); - ABC_PRTP( "CNF compute", p->tCnf, p->tTotal ); - ABC_PRTP( "TOTAL ", p->tTotal, p->tTotal ); - } -// printf( "SS =%6d. SU =%6d. US =%6d. UU =%6d.\n", p->nCasesSS, p->nCasesSU, p->nCasesUS, p->nCasesUU ); - Vec_PtrForEachEntry( sat_solver *, p->vSolvers, pSat, i ) - sat_solver_delete( pSat ); - Vec_PtrFree( p->vSolvers ); - Vec_VecForEachEntry( Pdr_Set_t *, p->vClauses, pCla, i, k ) - Pdr_SetDeref( pCla ); - Vec_VecFree( p->vClauses ); - Pdr_QueueStop( p ); - ABC_FREE( p->pOrder ); - Vec_IntFree( p->vActVars ); - // static CNF - Cnf_DataFree( p->pCnf1 ); - Vec_IntFreeP( &p->vVar2Reg ); - // dynamic CNF - Cnf_DataFree( p->pCnf2 ); - if ( p->pvId2Vars ) - for ( i = 0; i < Aig_ManObjNumMax(p->pAig); i++ ) - Vec_IntFreeP( &p->pvId2Vars[i] ); - ABC_FREE( p->pvId2Vars ); - Vec_VecFreeP( (Vec_Vec_t **)&p->vVar2Ids ); - // internal use - Vec_IntFreeP( &p->vPrio ); // priority flops - Vec_IntFree( p->vLits ); // array of literals - Vec_IntFree( p->vCiObjs ); // cone leaves - Vec_IntFree( p->vCoObjs ); // cone roots - Vec_IntFree( p->vCiVals ); // cone leaf values - Vec_IntFree( p->vCoVals ); // cone root values - Vec_IntFree( p->vNodes ); // cone nodes - Vec_IntFree( p->vUndo ); // cone undos - Vec_IntFree( p->vVisits ); // intermediate - Vec_IntFree( p->vCi2Rem ); // CIs to be removed - Vec_IntFree( p->vRes ); // final result - Vec_IntFree( p->vSuppLits ); // support literals - ABC_FREE( p->pCubeJust ); - // additional AIG data-members - if ( p->pAig->pFanData != NULL ) - Aig_ManFanoutStop( p->pAig ); - if ( p->pAig->pTerSimData != NULL ) - ABC_FREE( p->pAig->pTerSimData ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Derives counter-example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Cex_t * Pdr_ManDeriveCex( Pdr_Man_t * p ) -{ - Abc_Cex_t * pCex; - Pdr_Obl_t * pObl; - int i, f, Lit, nFrames = 0; - // count the number of frames - for ( pObl = p->pQueue; pObl; pObl = pObl->pNext ) - nFrames++; - // create the counter-example - pCex = Abc_CexAlloc( Aig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), nFrames ); - pCex->iPo = (p->pPars->iOutput==-1)? 0 : p->pPars->iOutput; - pCex->iFrame = nFrames-1; - for ( pObl = p->pQueue, f = 0; pObl; pObl = pObl->pNext, f++ ) - for ( i = pObl->pState->nLits; i < pObl->pState->nTotal; i++ ) - { - Lit = pObl->pState->Lits[i]; - if ( lit_sign(Lit) ) - continue; - assert( lit_var(Lit) < pCex->nPis ); - Aig_InfoSetBit( pCex->pData, pCex->nRegs + f * pCex->nPis + lit_var(Lit) ); - } - assert( f == nFrames ); - return pCex; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/sat/pdr/pdrSat.c b/src/sat/pdr/pdrSat.c deleted file mode 100644 index cc4c2b1b..00000000 --- a/src/sat/pdr/pdrSat.c +++ /dev/null @@ -1,373 +0,0 @@ -/**CFile**************************************************************** - - FileName [pdrSat.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Property driven reachability.] - - Synopsis [SAT solver procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - November 20, 2010.] - - Revision [$Id: pdrSat.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "pdrInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates new SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -sat_solver * Pdr_ManCreateSolver( Pdr_Man_t * p, int k ) -{ - sat_solver * pSat; - assert( Vec_PtrSize(p->vSolvers) == k ); - assert( Vec_VecSize(p->vClauses) == k ); - assert( Vec_IntSize(p->vActVars) == k ); - // create new solver - pSat = sat_solver_new(); - pSat = Pdr_ManNewSolver( pSat, p, k, (int)(k == 0) ); - Vec_PtrPush( p->vSolvers, pSat ); - Vec_VecExpand( p->vClauses, k ); - Vec_IntPush( p->vActVars, 0 ); - // add property cone - Pdr_ObjSatVar( p, k, Aig_ManPo(p->pAig, (p->pPars->iOutput==-1)?0:p->pPars->iOutput ) ); - return pSat; -} - -/**Function************************************************************* - - Synopsis [Returns old or restarted solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -sat_solver * Pdr_ManFetchSolver( Pdr_Man_t * p, int k ) -{ - sat_solver * pSat; - Vec_Ptr_t * vArrayK; - Pdr_Set_t * pCube; - int i, j; - pSat = Pdr_ManSolver(p, k); - if ( Vec_IntEntry(p->vActVars, k) < p->pPars->nRecycle ) - return pSat; - assert( k < Vec_PtrSize(p->vSolvers) - 1 ); - p->nStarts++; -// sat_solver_delete( pSat ); -// pSat = sat_solver_new(); - sat_solver_rollback( pSat ); - // create new SAT solver - pSat = Pdr_ManNewSolver( pSat, p, k, (int)(k == 0) ); - // write new SAT solver - Vec_PtrWriteEntry( p->vSolvers, k, pSat ); - Vec_IntWriteEntry( p->vActVars, k, 0 ); - // set the property output - Pdr_ManSetPropertyOutput( p, k ); - // add the clauses - Vec_VecForEachLevelStart( p->vClauses, vArrayK, i, k ) - Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCube, j ) - Pdr_ManSolverAddClause( p, k, pCube ); - return pSat; -} - -/**Function************************************************************* - - Synopsis [Converts SAT variables into register IDs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Pdr_ManLitsToCube( Pdr_Man_t * p, int k, int * pArray, int nArray ) -{ - int i, RegId; - Vec_IntClear( p->vLits ); - for ( i = 0; i < nArray; i++ ) - { - RegId = Pdr_ObjRegNum( p, k, lit_var(pArray[i]) ); - if ( RegId == -1 ) - continue; - assert( RegId >= 0 && RegId < Aig_ManRegNum(p->pAig) ); - Vec_IntPush( p->vLits, toLitCond(RegId, !lit_sign(pArray[i])) ); - } - assert( Vec_IntSize(p->vLits) >= 0 && Vec_IntSize(p->vLits) <= nArray ); - return p->vLits; -} - -/**Function************************************************************* - - Synopsis [Converts the cube in terms of RO numbers into array of CNF literals.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Pdr_ManCubeToLits( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, int fCompl, int fNext ) -{ - Aig_Obj_t * pObj; - int i, iVar, iVarMax = 0; - int clk = clock(); - Vec_IntClear( p->vLits ); - for ( i = 0; i < pCube->nLits; i++ ) - { - if ( pCube->Lits[i] == -1 ) - continue; - if ( fNext ) - pObj = Saig_ManLi( p->pAig, lit_var(pCube->Lits[i]) ); - else - pObj = Saig_ManLo( p->pAig, lit_var(pCube->Lits[i]) ); - iVar = Pdr_ObjSatVar( p, k, pObj ); assert( iVar >= 0 ); - iVarMax = ABC_MAX( iVarMax, iVar ); - Vec_IntPush( p->vLits, toLitCond( iVar, fCompl ^ lit_sign(pCube->Lits[i]) ) ); - } -// sat_solver_setnvars( Pdr_ManSolver(p, k), iVarMax + 1 ); - p->tCnf += clock() - clk; - return p->vLits; -} - -/**Function************************************************************* - - Synopsis [Sets the property output to 0 (sat) forever.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pdr_ManSetPropertyOutput( Pdr_Man_t * p, int k ) -{ - sat_solver * pSat; - int Lit, RetValue; - pSat = Pdr_ManSolver(p, k); - Lit = toLitCond( Pdr_ObjSatVar(p, k, Aig_ManPo(p->pAig, (p->pPars->iOutput==-1)?0:p->pPars->iOutput)), 1 ); // neg literal - RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 ); - assert( RetValue == 1 ); - sat_solver_compress( pSat ); -} - -/**Function************************************************************* - - Synopsis [Adds one clause in terms of ROs to the k-th SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pdr_ManSolverAddClause( Pdr_Man_t * p, int k, Pdr_Set_t * pCube ) -{ - sat_solver * pSat; - Vec_Int_t * vLits; - int RetValue; - pSat = Pdr_ManSolver(p, k); - vLits = Pdr_ManCubeToLits( p, k, pCube, 1, 0 ); - RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ); - assert( RetValue == 1 ); - sat_solver_compress( pSat ); -} - -/**Function************************************************************* - - Synopsis [Collects values of the RO/RI variables in k-th SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pdr_ManCollectValues( Pdr_Man_t * p, int k, Vec_Int_t * vObjIds, Vec_Int_t * vValues ) -{ - sat_solver * pSat; - Aig_Obj_t * pObj; - int iVar, i; - Vec_IntClear( vValues ); - pSat = Pdr_ManSolver(p, k); - Aig_ManForEachObjVec( vObjIds, p->pAig, pObj, i ) - { - iVar = Pdr_ObjSatVar( p, k, pObj ); assert( iVar >= 0 ); - Vec_IntPush( vValues, sat_solver_var_value(pSat, iVar) ); - } -} - -/**Function************************************************************* - - Synopsis [Checks if the cube holds (UNSAT) in the given timeframe.] - - Description [Return 1/0 if cube or property are proved to hold/fail - in k-th timeframe. Returns the predecessor bad state in ppPred.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pdr_ManCheckCubeCs( Pdr_Man_t * p, int k, Pdr_Set_t * pCube ) -{ - sat_solver * pSat; - Vec_Int_t * vLits; - int RetValue; - pSat = Pdr_ManFetchSolver( p, k ); - vLits = Pdr_ManCubeToLits( p, k, pCube, 0, 0 ); - RetValue = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), 0, 0, 0, 0 ); - if ( RetValue == l_Undef ) - return -1; - return (RetValue == l_False); -} - -/**Function************************************************************* - - Synopsis [Checks if the cube holds (UNSAT) in the given timeframe.] - - Description [Return 1/0 if cube or property are proved to hold/fail - in k-th timeframe. Returns the predecessor bad state in ppPred.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pdr_ManCheckCube( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, Pdr_Set_t ** ppPred, int nConfLimit ) -{ - int fUseLit = 1; - int fLitUsed = 0; - sat_solver * pSat; - Vec_Int_t * vLits; - int Lit, RetValue, clk; - p->nCalls++; - pSat = Pdr_ManFetchSolver( p, k ); - if ( pCube == NULL ) // solve the property - { - clk = clock(); - Lit = toLit( Pdr_ObjSatVar(p, k, Aig_ManPo(p->pAig, (p->pPars->iOutput==-1)?0:p->pPars->iOutput)) ); // pos literal (property fails) - RetValue = sat_solver_solve( pSat, &Lit, &Lit + 1, nConfLimit, 0, 0, 0 ); - if ( RetValue == l_Undef ) - return -1; - } - else // check relative containment in terms of next states - { - if ( fUseLit ) - { - fLitUsed = 1; - Vec_IntAddToEntry( p->vActVars, k, 1 ); - // add the cube in terms of current state variables - vLits = Pdr_ManCubeToLits( p, k, pCube, 1, 0 ); - // add activation literal - Lit = toLit( Pdr_ManFreeVar(p, k) ); - // add activation literal - Vec_IntPush( vLits, Lit ); - RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ); - assert( RetValue == 1 ); - sat_solver_compress( pSat ); - // create assumptions - vLits = Pdr_ManCubeToLits( p, k, pCube, 0, 1 ); - // add activation literal - Vec_IntPush( vLits, lit_neg(Lit) ); - } - else - vLits = Pdr_ManCubeToLits( p, k, pCube, 0, 1 ); - - // solve - clk = clock(); - RetValue = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), nConfLimit, 0, 0, 0 ); - if ( RetValue == l_Undef ) - return -1; -/* - if ( RetValue == l_True ) - { - int RetValue2 = Pdr_ManCubeJust( p, k, pCube ); - if ( RetValue2 ) - p->nCasesSS++; - else - p->nCasesSU++; - } - else - { - int RetValue2 = Pdr_ManCubeJust( p, k, pCube ); - if ( RetValue2 ) - p->nCasesUS++; - else - p->nCasesUU++; - } -*/ - } - clk = clock() - clk; - p->tSat += clk; - assert( RetValue != l_Undef ); - if ( RetValue == l_False ) - { - p->tSatUnsat += clk; - p->nCallsU++; - if ( ppPred ) - *ppPred = NULL; - RetValue = 1; - } - else // if ( RetValue == l_True ) - { - p->tSatSat += clk; - p->nCallsS++; - if ( ppPred ) - *ppPred = Pdr_ManTernarySim( p, k, pCube ); - RetValue = 0; - } - -/* // for some reason, it does not work... - if ( fLitUsed ) - { - int RetValue; - Lit = lit_neg(Lit); - RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 ); - assert( RetValue == 1 ); - sat_solver_compress( pSat ); - } -*/ - return RetValue; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/sat/pdr/pdrTsim.c b/src/sat/pdr/pdrTsim.c deleted file mode 100644 index 6fec1605..00000000 --- a/src/sat/pdr/pdrTsim.c +++ /dev/null @@ -1,450 +0,0 @@ -/**CFile**************************************************************** - - FileName [pdrTsim.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Property driven reachability.] - - Synopsis [Ternary simulation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - November 20, 2010.] - - Revision [$Id: pdrTsim.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "pdrInt.h" - -ABC_NAMESPACE_IMPL_START - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define PDR_ZER 1 -#define PDR_ONE 2 -#define PDR_UND 3 - -static inline int Pdr_ManSimInfoNot( int Value ) -{ - if ( Value == PDR_ZER ) - return PDR_ONE; - if ( Value == PDR_ONE ) - return PDR_ZER; - return PDR_UND; -} - -static inline int Pdr_ManSimInfoAnd( int Value0, int Value1 ) -{ - if ( Value0 == PDR_ZER || Value1 == PDR_ZER ) - return PDR_ZER; - if ( Value0 == PDR_ONE && Value1 == PDR_ONE ) - return PDR_ONE; - return PDR_UND; -} - -static inline int Pdr_ManSimInfoGet( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - return 3 & (p->pTerSimData[Aig_ObjId(pObj) >> 4] >> ((Aig_ObjId(pObj) & 15) << 1)); -} - -static inline void Pdr_ManSimInfoSet( Aig_Man_t * p, Aig_Obj_t * pObj, int Value ) -{ - assert( Value >= PDR_ZER && Value <= PDR_UND ); - Value ^= Pdr_ManSimInfoGet( p, pObj ); - p->pTerSimData[Aig_ObjId(pObj) >> 4] ^= (Value << ((Aig_ObjId(pObj) & 15) << 1)); -} - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Marks the TFI cone and collects CIs and nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pdr_ManCollectCone_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vCiObjs, Vec_Int_t * vNodes ) -{ - assert( !Aig_IsComplement(pObj) ); - if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) - return; - Aig_ObjSetTravIdCurrent(pAig, pObj); - if ( Aig_ObjIsPi(pObj) ) - { - Vec_IntPush( vCiObjs, Aig_ObjId(pObj) ); - return; - } - Pdr_ManCollectCone_rec( pAig, Aig_ObjFanin0(pObj), vCiObjs, vNodes ); - if ( Aig_ObjIsPo(pObj) ) - return; - Pdr_ManCollectCone_rec( pAig, Aig_ObjFanin1(pObj), vCiObjs, vNodes ); - Vec_IntPush( vNodes, Aig_ObjId(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Marks the TFI cone and collects CIs and nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pdr_ManCollectCone( Aig_Man_t * pAig, Vec_Int_t * vCoObjs, Vec_Int_t * vCiObjs, Vec_Int_t * vNodes ) -{ - Aig_Obj_t * pObj; - int i; - Vec_IntClear( vCiObjs ); - Vec_IntClear( vNodes ); - Aig_ManIncrementTravId( pAig ); - Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) ); - Aig_ManForEachObjVec( vCoObjs, pAig, pObj, i ) - Pdr_ManCollectCone_rec( pAig, pObj, vCiObjs, vNodes ); -} - -/**Function************************************************************* - - Synopsis [Performs ternary simulation for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pdr_ManExtendOneEval( Aig_Man_t * pAig, Aig_Obj_t * pObj ) -{ - int Value0, Value1, Value; - Value0 = Pdr_ManSimInfoGet( pAig, Aig_ObjFanin0(pObj) ); - if ( Aig_ObjFaninC0(pObj) ) - Value0 = Pdr_ManSimInfoNot( Value0 ); - if ( Aig_ObjIsPo(pObj) ) - { - Pdr_ManSimInfoSet( pAig, pObj, Value0 ); - return Value0; - } - assert( Aig_ObjIsNode(pObj) ); - Value1 = Pdr_ManSimInfoGet( pAig, Aig_ObjFanin1(pObj) ); - if ( Aig_ObjFaninC1(pObj) ) - Value1 = Pdr_ManSimInfoNot( Value1 ); - Value = Pdr_ManSimInfoAnd( Value0, Value1 ); - Pdr_ManSimInfoSet( pAig, pObj, Value ); - return Value; -} - -/**Function************************************************************* - - Synopsis [Performs ternary simulation for one design.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pdr_ManSimDataInit( Aig_Man_t * pAig, - Vec_Int_t * vCiObjs, Vec_Int_t * vCiVals, Vec_Int_t * vNodes, - Vec_Int_t * vCoObjs, Vec_Int_t * vCoVals, Vec_Int_t * vCi2Rem ) -{ - Aig_Obj_t * pObj; - int i; - // set the CI values - Pdr_ManSimInfoSet( pAig, Aig_ManConst1(pAig), PDR_ONE ); - Aig_ManForEachObjVec( vCiObjs, pAig, pObj, i ) - Pdr_ManSimInfoSet( pAig, pObj, (Vec_IntEntry(vCiVals, i)?PDR_ONE:PDR_ZER) ); - // set the FOs to remove - if ( vCi2Rem != NULL ) - Aig_ManForEachObjVec( vCi2Rem, pAig, pObj, i ) - Pdr_ManSimInfoSet( pAig, pObj, PDR_UND ); - // perform ternary simulation - Aig_ManForEachObjVec( vNodes, pAig, pObj, i ) - Pdr_ManExtendOneEval( pAig, pObj ); - // transfer results to the output - Aig_ManForEachObjVec( vCoObjs, pAig, pObj, i ) - Pdr_ManExtendOneEval( pAig, pObj ); - // check the results - Aig_ManForEachObjVec( vCoObjs, pAig, pObj, i ) - if ( Pdr_ManSimInfoGet( pAig, pObj ) != (Vec_IntEntry(vCoVals, i)?PDR_ONE:PDR_ZER) ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Tries to assign ternary value to one of the CIs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pdr_ManExtendOne( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vUndo, Vec_Int_t * vVis ) -{ - Aig_Obj_t * pFanout; - int i, k, iFanout, Value, Value2; - assert( Saig_ObjIsLo(pAig, pObj) ); - assert( Aig_ObjIsTravIdCurrent(pAig, pObj) ); - // save original value - Value = Pdr_ManSimInfoGet( pAig, pObj ); - assert( Value == PDR_ZER || Value == PDR_ONE ); - Vec_IntPush( vUndo, Aig_ObjId(pObj) ); - Vec_IntPush( vUndo, Value ); - // update original value - Pdr_ManSimInfoSet( pAig, pObj, PDR_UND ); - // traverse - Vec_IntClear( vVis ); - Vec_IntPush( vVis, Aig_ObjId(pObj) ); - Aig_ManForEachObjVec( vVis, pAig, pObj, i ) - { - Aig_ObjForEachFanout( pAig, pObj, pFanout, iFanout, k ) - { - if ( !Aig_ObjIsTravIdCurrent(pAig, pFanout) ) - continue; - assert( Aig_ObjId(pObj) < Aig_ObjId(pFanout) ); - Value = Pdr_ManSimInfoGet( pAig, pFanout ); - if ( Value == PDR_UND ) - continue; - Value2 = Pdr_ManExtendOneEval( pAig, pFanout ); - if ( Value2 == Value ) - continue; - assert( Value2 == PDR_UND ); - Vec_IntPush( vUndo, Aig_ObjId(pFanout) ); - Vec_IntPush( vUndo, Value ); - if ( Aig_ObjIsPo(pFanout) ) - return 0; - assert( Aig_ObjIsNode(pFanout) ); - Vec_IntPushOrder( vVis, Aig_ObjId(pFanout) ); - } - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Undoes the partial results of ternary simulation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pdr_ManExtendUndo( Aig_Man_t * pAig, Vec_Int_t * vUndo ) -{ - Aig_Obj_t * pObj; - int i, Value; - Aig_ManForEachObjVec( vUndo, pAig, pObj, i ) - { - Value = Vec_IntEntry(vUndo, ++i); - assert( Pdr_ManSimInfoGet(pAig, pObj) == PDR_UND ); - Pdr_ManSimInfoSet( pAig, pObj, Value ); - } -} - -/**Function************************************************************* - - Synopsis [Derives the resulting cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pdr_ManDeriveResult( Aig_Man_t * pAig, Vec_Int_t * vCiObjs, Vec_Int_t * vCiVals, Vec_Int_t * vCi2Rem, Vec_Int_t * vRes, Vec_Int_t * vPiLits ) -{ - Aig_Obj_t * pObj; - int i, Lit; - // mark removed flop outputs - Aig_ManIncrementTravId( pAig ); - Aig_ManForEachObjVec( vCi2Rem, pAig, pObj, i ) - { - assert( Saig_ObjIsLo( pAig, pObj ) ); - Aig_ObjSetTravIdCurrent(pAig, pObj); - } - // collect flop outputs that are not marked - Vec_IntClear( vRes ); - Vec_IntClear( vPiLits ); - Aig_ManForEachObjVec( vCiObjs, pAig, pObj, i ) - { - if ( Saig_ObjIsPi(pAig, pObj) ) - { - Lit = toLitCond( Aig_ObjPioNum(pObj), (Vec_IntEntry(vCiVals, i) == 0) ); - Vec_IntPush( vPiLits, Lit ); - continue; - } - assert( Saig_ObjIsLo(pAig, pObj) ); - if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) - continue; - Lit = toLitCond( Aig_ObjPioNum(pObj) - Saig_ManPiNum(pAig), (Vec_IntEntry(vCiVals, i) == 0) ); - Vec_IntPush( vRes, Lit ); - } - if ( Vec_IntSize(vRes) == 0 ) - Vec_IntPush(vRes, 0); -} - -/**Function************************************************************* - - Synopsis [Derives the resulting cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pdr_ManPrintCex( Aig_Man_t * pAig, Vec_Int_t * vCiObjs, Vec_Int_t * vCiVals, Vec_Int_t * vCi2Rem ) -{ - Aig_Obj_t * pObj; - int i; - char * pBuff = ABC_ALLOC( char, Aig_ManPiNum(pAig)+1 ); - for ( i = 0; i < Aig_ManPiNum(pAig); i++ ) - pBuff[i] = '-'; - pBuff[i] = 0; - Aig_ManForEachObjVec( vCiObjs, pAig, pObj, i ) - pBuff[Aig_ObjPioNum(pObj)] = (Vec_IntEntry(vCiVals, i)? '1':'0'); - if ( vCi2Rem ) - Aig_ManForEachObjVec( vCi2Rem, pAig, pObj, i ) - pBuff[Aig_ObjPioNum(pObj)] = 'x'; - printf( "%s\n", pBuff ); - ABC_FREE( pBuff ); -} - -/**Function************************************************************* - - Synopsis [Shrinks values using ternary simulation.] - - Description [The cube contains the set of flop index literals which, - when converted into a clause and applied to the combinational outputs, - led to a satisfiable SAT run in frame k (values stored in the SAT solver). - If the cube is NULL, it is assumed that the first property output was - asserted and failed. - The resulting array is a set of flop index literals that asserts the COs. - Priority contains 0 for i-th entry if the i-th FF is desirable to remove.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Pdr_Set_t * Pdr_ManTernarySim( Pdr_Man_t * p, int k, Pdr_Set_t * pCube ) -{ - Vec_Int_t * vPrio = p->vPrio; // priority flops (flop indices) - Vec_Int_t * vPiLits = p->vLits; // array of literals (0/1 PI values) - Vec_Int_t * vCiObjs = p->vCiObjs; // cone leaves (CI obj IDs) - Vec_Int_t * vCoObjs = p->vCoObjs; // cone roots (CO obj IDs) - Vec_Int_t * vCiVals = p->vCiVals; // cone leaf values (0/1 CI values) - Vec_Int_t * vCoVals = p->vCoVals; // cone root values (0/1 CO values) - Vec_Int_t * vNodes = p->vNodes; // cone nodes (node obj IDs) - Vec_Int_t * vUndo = p->vUndo; // cone undos (node obj IDs) - Vec_Int_t * vVisits = p->vVisits; // intermediate (obj IDs) - Vec_Int_t * vCi2Rem = p->vCi2Rem; // CIs to be removed (CI obj IDs) - Vec_Int_t * vRes = p->vRes; // final result (flop literals) - Aig_Obj_t * pObj; - int i, Entry, RetValue; - int clk = clock(); - - // collect CO objects - Vec_IntClear( vCoObjs ); - if ( pCube == NULL ) // the target is the property output - Vec_IntPush( vCoObjs, Aig_ObjId(Aig_ManPo(p->pAig, (p->pPars->iOutput==-1)?0:p->pPars->iOutput)) ); - else // the target is the cube - { - for ( i = 0; i < pCube->nLits; i++ ) - { - if ( pCube->Lits[i] == -1 ) - continue; - pObj = Saig_ManLi(p->pAig, (pCube->Lits[i] >> 1)); - Vec_IntPush( vCoObjs, Aig_ObjId(pObj) ); - } - } -if ( p->pPars->fVeryVerbose ) -{ -printf( "Trying to justify cube " ); -if ( pCube ) - Pdr_SetPrint( stdout, pCube, Aig_ManRegNum(p->pAig), NULL ); -else - printf( "" ); -printf( " in frame %d.\n", k ); -} - - // collect CI objects - Pdr_ManCollectCone( p->pAig, vCoObjs, vCiObjs, vNodes ); - // collect values - Pdr_ManCollectValues( p, k, vCiObjs, vCiVals ); - Pdr_ManCollectValues( p, k, vCoObjs, vCoVals ); - // simulate for the first time -if ( p->pPars->fVeryVerbose ) -Pdr_ManPrintCex( p->pAig, vCiObjs, vCiVals, NULL ); - RetValue = Pdr_ManSimDataInit( p->pAig, vCiObjs, vCiVals, vNodes, vCoObjs, vCoVals, NULL ); - assert( RetValue ); - - // try removing high-priority flops - Vec_IntClear( vCi2Rem ); - Aig_ManForEachObjVec( vCiObjs, p->pAig, pObj, i ) - { - if ( !Saig_ObjIsLo( p->pAig, pObj ) ) - continue; - Entry = Aig_ObjPioNum(pObj) - Saig_ManPiNum(p->pAig); - if ( vPrio != NULL && Vec_IntEntry( vPrio, Entry ) != 0 ) - continue; - Vec_IntClear( vUndo ); - if ( Pdr_ManExtendOne( p->pAig, pObj, vUndo, vVisits ) ) - Vec_IntPush( vCi2Rem, Aig_ObjId(pObj) ); - else - Pdr_ManExtendUndo( p->pAig, vUndo ); - } - // try removing low-priority flops - Aig_ManForEachObjVec( vCiObjs, p->pAig, pObj, i ) - { - if ( !Saig_ObjIsLo( p->pAig, pObj ) ) - continue; - Entry = Aig_ObjPioNum(pObj) - Saig_ManPiNum(p->pAig); - if ( vPrio == NULL || Vec_IntEntry( vPrio, Entry ) == 0 ) - continue; - Vec_IntClear( vUndo ); - if ( Pdr_ManExtendOne( p->pAig, pObj, vUndo, vVisits ) ) - Vec_IntPush( vCi2Rem, Aig_ObjId(pObj) ); - else - Pdr_ManExtendUndo( p->pAig, vUndo ); - } -if ( p->pPars->fVeryVerbose ) -Pdr_ManPrintCex( p->pAig, vCiObjs, vCiVals, vCi2Rem ); - RetValue = Pdr_ManSimDataInit( p->pAig, vCiObjs, vCiVals, vNodes, vCoObjs, vCoVals, vCi2Rem ); - assert( RetValue ); - - // derive the set of resulting registers - Pdr_ManDeriveResult( p->pAig, vCiObjs, vCiVals, vCi2Rem, vRes, vPiLits ); - assert( Vec_IntSize(vRes) > 0 ); - p->tTsim += clock() - clk; - return Pdr_SetCreate( vRes, vPiLits ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/sat/pdr/pdrUtil.c b/src/sat/pdr/pdrUtil.c deleted file mode 100644 index 1107aec7..00000000 --- a/src/sat/pdr/pdrUtil.c +++ /dev/null @@ -1,719 +0,0 @@ -/**CFile**************************************************************** - - FileName [pdrUtil.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Property driven reachability.] - - Synopsis [Various utilities.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - November 20, 2010.] - - Revision [$Id: pdrUtil.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "pdrInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Pdr_Set_t * Pdr_SetAlloc( int nSize ) -{ - Pdr_Set_t * p; - assert( nSize >= 0 && nSize < (1<<30) ); - p = (Pdr_Set_t *)ABC_CALLOC( char, sizeof(Pdr_Set_t) + nSize * sizeof(int) ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Pdr_Set_t * Pdr_SetCreate( Vec_Int_t * vLits, Vec_Int_t * vPiLits ) -{ - Pdr_Set_t * p; - int i; - assert( Vec_IntSize(vLits) + Vec_IntSize(vPiLits) < (1<<30) ); - p = (Pdr_Set_t *)ABC_ALLOC( char, sizeof(Pdr_Set_t) + (Vec_IntSize(vLits) + Vec_IntSize(vPiLits)) * sizeof(int) ); - p->nLits = Vec_IntSize(vLits); - p->nTotal = Vec_IntSize(vLits) + Vec_IntSize(vPiLits); - p->nRefs = 1; - p->Sign = 0; - for ( i = 0; i < p->nLits; i++ ) - { - p->Lits[i] = Vec_IntEntry(vLits, i); - p->Sign |= ((word)1 << (p->Lits[i] % 63)); - } - Vec_IntSelectSort( p->Lits, p->nLits ); -/* - for ( i = 0; i < p->nLits; i++ ) - printf( "%d ", p->Lits[i] ); - printf( "\n" ); -*/ - // remember PI literals - for ( i = p->nLits; i < p->nTotal; i++ ) - p->Lits[i] = Vec_IntEntry(vPiLits, i-p->nLits); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Pdr_Set_t * Pdr_SetCreateFrom( Pdr_Set_t * pSet, int iRemove ) -{ - Pdr_Set_t * p; - int i, k = 0; - assert( iRemove >= 0 && iRemove < pSet->nLits ); - p = (Pdr_Set_t *)ABC_ALLOC( char, sizeof(Pdr_Set_t) + (pSet->nTotal - 1) * sizeof(int) ); - p->nLits = pSet->nLits - 1; - p->nTotal = pSet->nTotal - 1; - p->nRefs = 1; - p->Sign = 0; - for ( i = 0; i < pSet->nTotal; i++ ) - { - if ( i == iRemove ) - continue; - p->Lits[k++] = pSet->Lits[i]; - if ( i >= pSet->nLits ) - continue; - p->Sign |= ((word)1 << (pSet->Lits[i] % 63)); - } - assert( k == p->nTotal ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Pdr_Set_t * Pdr_SetCreateSubset( Pdr_Set_t * pSet, int * pLits, int nLits ) -{ - Pdr_Set_t * p; - int i, k = 0; - assert( nLits >= 0 && nLits <= pSet->nLits ); - p = (Pdr_Set_t *)ABC_ALLOC( char, sizeof(Pdr_Set_t) + (nLits + pSet->nTotal - pSet->nLits) * sizeof(int) ); - p->nLits = nLits; - p->nTotal = nLits + pSet->nTotal - pSet->nLits; - p->nRefs = 1; - p->Sign = 0; - for ( i = 0; i < nLits; i++ ) - { - assert( pLits[i] >= 0 ); - p->Lits[k++] = pLits[i]; - p->Sign |= ((word)1 << (pLits[i] % 63)); - } - Vec_IntSelectSort( p->Lits, p->nLits ); - for ( i = pSet->nLits; i < pSet->nTotal; i++ ) - p->Lits[k++] = pSet->Lits[i]; - assert( k == p->nTotal ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Pdr_Set_t * Pdr_SetDup( Pdr_Set_t * pSet ) -{ - Pdr_Set_t * p; - int i; - p = (Pdr_Set_t *)ABC_ALLOC( char, sizeof(Pdr_Set_t) + pSet->nTotal * sizeof(int) ); - p->nLits = pSet->nLits; - p->nTotal = pSet->nTotal; - p->nRefs = 1; - p->Sign = pSet->Sign; - for ( i = 0; i < pSet->nTotal; i++ ) - p->Lits[i] = pSet->Lits[i]; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Pdr_Set_t * Pdr_SetRef( Pdr_Set_t * p ) -{ - p->nRefs++; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pdr_SetDeref( Pdr_Set_t * p ) -{ - if ( --p->nRefs == 0 ) - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pdr_SetPrint( FILE * pFile, Pdr_Set_t * p, int nRegs, Vec_Int_t * vFlopCounts ) -{ - char * pBuff; - int i, k, Entry; - pBuff = ABC_ALLOC( char, nRegs + 1 ); - for ( i = 0; i < nRegs; i++ ) - pBuff[i] = '-'; - pBuff[i] = 0; - for ( i = 0; i < p->nLits; i++ ) - { - if ( p->Lits[i] == -1 ) - continue; - pBuff[lit_var(p->Lits[i])] = (lit_sign(p->Lits[i])? '0':'1'); - } - if ( vFlopCounts ) - { - // skip some literals - k = 0; - Vec_IntForEachEntry( vFlopCounts, Entry, i ) - if ( Entry ) - pBuff[k++] = pBuff[i]; - pBuff[k] = 0; - } - fprintf( pFile, "%s", pBuff ); - ABC_FREE( pBuff ); -} - -/**Function************************************************************* - - Synopsis [Return 1 if pOld set-theoretically contains pNew.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pdr_SetContains( Pdr_Set_t * pOld, Pdr_Set_t * pNew ) -{ - int * pOldInt, * pNewInt; - assert( pOld->nLits > 0 ); - assert( pNew->nLits > 0 ); - if ( pOld->nLits < pNew->nLits ) - return 0; - if ( (pOld->Sign & pNew->Sign) != pNew->Sign ) - return 0; - pOldInt = pOld->Lits + pOld->nLits - 1; - pNewInt = pNew->Lits + pNew->nLits - 1; - while ( pNew->Lits <= pNewInt ) - { - if ( pOld->Lits > pOldInt ) - return 0; - assert( *pNewInt != -1 ); - assert( *pOldInt != -1 ); - if ( *pNewInt == *pOldInt ) - pNewInt--, pOldInt--; - else if ( *pNewInt < *pOldInt ) - pOldInt--; - else - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Return 1 if pOld set-theoretically contains pNew.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pdr_SetContainsSimple( Pdr_Set_t * pOld, Pdr_Set_t * pNew ) -{ - int * pOldInt, * pNewInt; - assert( pOld->nLits > 0 ); - assert( pNew->nLits > 0 ); - pOldInt = pOld->Lits + pOld->nLits - 1; - pNewInt = pNew->Lits + pNew->nLits - 1; - while ( pNew->Lits <= pNewInt ) - { - assert( *pOldInt != -1 ); - if ( *pNewInt == -1 ) - { - pNewInt--; - continue; - } - if ( pOld->Lits > pOldInt ) - return 0; - assert( *pNewInt != -1 ); - assert( *pOldInt != -1 ); - if ( *pNewInt == *pOldInt ) - pNewInt--, pOldInt--; - else if ( *pNewInt < *pOldInt ) - pOldInt--; - else - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Return 1 if the state cube contains init state (000...0).] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pdr_SetIsInit( Pdr_Set_t * pCube, int iRemove ) -{ - int i; - for ( i = 0; i < pCube->nLits; i++ ) - { - assert( pCube->Lits[i] != -1 ); - if ( i == iRemove ) - continue; - if ( lit_sign( pCube->Lits[i] ) == 0 ) - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pdr_SetCompare( Pdr_Set_t ** pp1, Pdr_Set_t ** pp2 ) -{ - Pdr_Set_t * p1 = *pp1; - Pdr_Set_t * p2 = *pp2; - int i; - for ( i = 0; i < p1->nLits && i < p2->nLits; i++ ) - { - if ( p1->Lits[i] > p2->Lits[i] ) - return -1; - if ( p1->Lits[i] < p2->Lits[i] ) - return 1; - } - if ( i == p1->nLits && i < p2->nLits ) - return -1; - if ( i < p1->nLits && i == p2->nLits ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Pdr_Obl_t * Pdr_OblStart( int k, int prio, Pdr_Set_t * pState, Pdr_Obl_t * pNext ) -{ - Pdr_Obl_t * p; - p = ABC_ALLOC( Pdr_Obl_t, 1 ); - p->iFrame = k; - p->prio = prio; - p->nRefs = 1; - p->pState = pState; - p->pNext = pNext; - p->pLink = NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Pdr_Obl_t * Pdr_OblRef( Pdr_Obl_t * p ) -{ - p->nRefs++; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pdr_OblDeref( Pdr_Obl_t * p ) -{ - if ( --p->nRefs == 0 ) - { - if ( p->pNext ) - Pdr_OblDeref( p->pNext ); - Pdr_SetDeref( p->pState ); - ABC_FREE( p ); - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pdr_QueueIsEmpty( Pdr_Man_t * p ) -{ - return p->pQueue == NULL; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Pdr_Obl_t * Pdr_QueueHead( Pdr_Man_t * p ) -{ - return p->pQueue; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Pdr_Obl_t * Pdr_QueuePop( Pdr_Man_t * p ) -{ - Pdr_Obl_t * pRes = p->pQueue; - if ( p->pQueue == NULL ) - return NULL; - p->pQueue = p->pQueue->pLink; - Pdr_OblDeref( pRes ); - return pRes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pdr_QueuePush( Pdr_Man_t * p, Pdr_Obl_t * pObl ) -{ - Pdr_Obl_t * pTemp, ** ppPrev; - p->nObligs++; - Pdr_OblRef( pObl ); - if ( p->pQueue == NULL ) - { - p->pQueue = pObl; - return; - } - for ( ppPrev = &p->pQueue, pTemp = p->pQueue; pTemp; ppPrev = &pTemp->pLink, pTemp = pTemp->pLink ) - if ( pTemp->iFrame > pObl->iFrame || (pTemp->iFrame == pObl->iFrame && pTemp->prio > pObl->prio) ) - break; - *ppPrev = pObl; - pObl->pLink = pTemp; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pdr_QueuePrint( Pdr_Man_t * p ) -{ - Pdr_Obl_t * pObl; - for ( pObl = p->pQueue; pObl; pObl = pObl->pLink ) - printf( "Frame = %2d. Prio = %8d.\n", pObl->iFrame, pObl->prio ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pdr_QueueStop( Pdr_Man_t * p ) -{ - Pdr_Obl_t * pObl; - while ( !Pdr_QueueIsEmpty(p) ) - { - pObl = Pdr_QueuePop(p); - Pdr_OblDeref( pObl ); - } - p->pQueue = NULL; -} - - -#define PDR_VAL0 1 -#define PDR_VAL1 2 -#define PDR_VALX 3 - -/**Function************************************************************* - - Synopsis [Returns value (0 or 1) or X if unassigned.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Pdr_ObjSatValue( Aig_Man_t * pAig, Aig_Obj_t * pNode, int fCompl ) -{ - if ( Aig_ObjIsTravIdCurrent(pAig, pNode) ) - return (pNode->fMarkA ^ fCompl) ? PDR_VAL1 : PDR_VAL0; - return PDR_VALX; -} - -/**Function************************************************************* - - Synopsis [Recursively searched for a satisfying assignment.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pdr_NtkFindSatAssign_rec( Aig_Man_t * pAig, Aig_Obj_t * pNode, int Value, Pdr_Set_t * pCube, int Heur ) -{ - int Value0, Value1; - if ( Aig_ObjIsConst1(pNode) ) - return 1; - if ( Aig_ObjIsTravIdCurrent(pAig, pNode) ) - return ((int)pNode->fMarkA == Value); - Aig_ObjSetTravIdCurrent(pAig, pNode); - pNode->fMarkA = Value; - if ( Aig_ObjIsPi(pNode) ) - { -// if ( vSuppLits ) -// Vec_IntPush( vSuppLits, Aig_Var2Lit( Aig_ObjPioNum(pNode), !Value ) ); - if ( Saig_ObjIsLo(pAig, pNode) ) - { -// pCube->Lits[pCube->nLits++] = Aig_Var2Lit( Aig_ObjPioNum(pNode) - Saig_ManPiNum(pAig), !Value ); - pCube->Lits[pCube->nLits++] = Aig_Var2Lit( Aig_ObjPioNum(pNode) - Saig_ManPiNum(pAig), Value ); - pCube->Sign |= ((word)1 << (pCube->Lits[pCube->nLits-1] % 63)); - } - return 1; - } - assert( Aig_ObjIsNode(pNode) ); - // propagation - if ( Value ) - { - if ( !Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin0(pNode), !Aig_ObjFaninC0(pNode), pCube, Heur) ) - return 0; - return Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin1(pNode), !Aig_ObjFaninC1(pNode), pCube, Heur); - } - // justification - Value0 = Pdr_ObjSatValue( pAig, Aig_ObjFanin0(pNode), Aig_ObjFaninC0(pNode) ); - if ( Value0 == PDR_VAL0 ) - return 1; - Value1 = Pdr_ObjSatValue( pAig, Aig_ObjFanin1(pNode), Aig_ObjFaninC1(pNode) ); - if ( Value1 == PDR_VAL0 ) - return 1; - if ( Value0 == PDR_VAL1 && Value1 == PDR_VAL1 ) - return 0; - if ( Value0 == PDR_VAL1 ) - return Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin1(pNode), Aig_ObjFaninC1(pNode), pCube, Heur); - if ( Value1 == PDR_VAL1 ) - return Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin0(pNode), Aig_ObjFaninC0(pNode), pCube, Heur); - assert( Value0 == PDR_VALX && Value1 == PDR_VALX ); - // decision making -// if ( rand() % 10 == Heur ) - if ( Aig_ObjId(pNode) % 4 == Heur ) - return Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin1(pNode), Aig_ObjFaninC1(pNode), pCube, Heur); - else - return Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin0(pNode), Aig_ObjFaninC0(pNode), pCube, Heur); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if SAT assignment is found; 0 otherwise.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pdr_ManCubeJust( Pdr_Man_t * p, int k, Pdr_Set_t * pCube ) -{ - Aig_Obj_t * pNode; - int i, v, fCompl; -// return 0; - for ( i = 0; i < 4; i++ ) - { - // derive new assignment - p->pCubeJust->nLits = 0; - p->pCubeJust->Sign = 0; - Aig_ManIncrementTravId( p->pAig ); - for ( v = 0; v < pCube->nLits; v++ ) - { - if ( pCube->Lits[v] == -1 ) - continue; - pNode = Saig_ManLi( p->pAig, lit_var(pCube->Lits[v]) ); - fCompl = lit_sign(pCube->Lits[v]) ^ Aig_ObjFaninC0(pNode); - if ( !Pdr_NtkFindSatAssign_rec( p->pAig, Aig_ObjFanin0(pNode), !fCompl, p->pCubeJust, i ) ) - break; - } - if ( v < pCube->nLits ) - continue; - // figure this out!!! - if ( p->pCubeJust->nLits == 0 ) - continue; - // successfully derived new assignment - Vec_IntSelectSort( p->pCubeJust->Lits, p->pCubeJust->nLits ); - // check assignment against this cube - if ( Pdr_SetContainsSimple( p->pCubeJust, pCube ) ) - continue; -//printf( "\n" ); -//Pdr_SetPrint( stdout, pCube, Saig_ManRegNum(p->pAig), NULL ); printf( "\n" ); -//Pdr_SetPrint( stdout, p->pCubeJust, Saig_ManRegNum(p->pAig), NULL ); printf( "\n" ); - // check assignment against the clauses - if ( Pdr_ManCheckContainment( p, k, p->pCubeJust ) ) - continue; - // find good assignment - return 1; - } - return 0; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/sat/proof/pr.c b/src/sat/proof/pr.c index 0da16eaf..45bc2e33 100644 --- a/src/sat/proof/pr.c +++ b/src/sat/proof/pr.c @@ -25,7 +25,7 @@ #include //#include "vec.h" -#include "abc_global.h" +#include "src/misc/util/abc_global.h" #include "pr.h" ABC_NAMESPACE_IMPL_START diff --git a/src/sat/proof/pr.h b/src/sat/proof/pr.h index 9088c89b..b060b52b 100644 --- a/src/sat/proof/pr.h +++ b/src/sat/proof/pr.h @@ -18,8 +18,8 @@ ***********************************************************************/ -#ifndef __PR_H__ -#define __PR_H__ +#ifndef ABC__sat__proof__pr_h +#define ABC__sat__proof__pr_h #ifdef _WIN32 diff --git a/src/sat/psat/m114p.h b/src/sat/psat/m114p.h index 9319d918..12f98135 100644 --- a/src/sat/psat/m114p.h +++ b/src/sat/psat/m114p.h @@ -1,7 +1,7 @@ // C-language header for MiniSat 1.14p -#ifndef m114p_h -#define m114p_h +#ifndef ABC__sat__psat__m114p_h +#define ABC__sat__psat__m114p_h #include "m114p_types.h" diff --git a/src/sat/psat/m114p_types.h b/src/sat/psat/m114p_types.h index 29d70a87..770cd417 100644 --- a/src/sat/psat/m114p_types.h +++ b/src/sat/psat/m114p_types.h @@ -1,7 +1,7 @@ // C-language header for MiniSat 1.14p -#ifndef m114p_types_h -#define m114p_types_h +#ifndef ABC__sat__psat__m114p_types_h +#define ABC__sat__psat__m114p_types_h ABC_NAMESPACE_HEADER_START diff --git a/src/template.c b/src/template.c index 17d33424..8b799151 100644 --- a/src/template.c +++ b/src/template.c @@ -18,7 +18,7 @@ ***********************************************************************/ -#include "aig.h" +#include "aig/aig/aig.h" ABC_NAMESPACE_IMPL_START -- cgit v1.2.3